1 /*
2  *  CVS: $Id: GameObject.java,v 1.13 2004/07/25 19:07:20 marcus Exp $
3  * 
4  *  This file is part of JZuul.
5  *
6  *  JZuul is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10 *
11 *  JZuul is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with Zuul; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 * 
20 *  Copyrigth 2004 by marcus, leh
21 * 
22 */
23
24package org.jzuul.engine;
25
26import java.text.MessageFormat;
27import java.util.Map;
28
29import org.jdom.Element;
30import org.jzuul.engine.exceptions.NoSuchEventException;
31
32/**
33 * Die Zentale Oberklasse für Characters und Items
34 * 
35 * 
36 * @version $Revision: 1.13 $
37  */
38public abstract class GameObject implements EventListener {
39    /**
40     * Die Beschreibung des Objektes (für "inspect")
41     */
42    protected String desc;
43    
44    /**
45     * Der Name des Objektes
46     */
47    protected String name;
48    
49    /**
50     * Ist das GameObject nehmbar (für "take")
51     */
52    protected boolean takeable;
53    
54    /**
55     * Kann man das GameObject benutzen (für "use")
56     */
57    protected boolean useable;
58    
59    /**
60     * Den Platz den das GameObject im Inventar einnimmt
61     */
62    protected int size;
63    
64    /**
65     * Soll das GameObject nach dem Benutzen aus dem Inventar entfernt werden 
66     */
67    protected boolean deleteOnUse = false;
68    
69    /**
70     * Targets die das GameObject zuweisen kann
71     */
72    protected TargetList targets;
73    
74    /**
75     * Die EventHandler für dieses GameObject
76     */
77    protected EventHandler[] events;
78
79    /**
80     * Der Konstruktor der von Unterklassen aufgerufen wird
81     * 
82     * @param name  der Name des GameObjects
83     */
84    public GameObject(String name) {
85        this.name = name.toLowerCase();
86        this.targets = new TargetList();
87        this.events = new EventHandler[Event.COUNT];
88    }
89
90    /**
91     * Die Größe (der Platz) den ein Objekt im Inventory einnimmt
92     * 
93     * @return die Größe
94     */
95    public int getSize() {
96        return this.size;
97    }
98
99    /**
00     * Accessor für den Namen
01     * 
02     * @return  der Name des GameObjects
03     */
04    public String getName() {
05        return this.name;
06    }
07
08    /**
09     * Holt die Beschreibung, wenn die GameObject.desc nicht gesetzt ist wird sie aus dem Namen gebildet. 
10     * 
11     * @return die Beschreibung des GameObject
12     */
13    public String getDescription() {
14        if (this.desc == null) {
15            Object[] formatArgs = { this.getName() };
16            return MessageFormat.format(Messages.getString("GAMEOBJECT_DEFAULT_DESCRIPTION"), formatArgs); //$NON-NLS-1$
17        } else {
18            return this.desc;
19        }
20    }
21
22    /**
23     * Setzt die Beschreibung
24     * @param desc  die neue Beschreibung des Gegenstands
25     */
26    public void setDescription(String desc) {
27        if (desc == null) throw new IllegalArgumentException("The description must not be null"); //$NON-NLS-1$
28        this.desc = desc;
29    }
30
31    /**
32     * Setzt den Namen.
33     * Vorsicht: die Gegenstände werden auch intern über diesen Namen verwaltet (warum eigentlich?) daher
34     * sollte der Name nicht geändert werden. 
35     * 
36     * @param name der neue Name eines Objektes
37     */
38    public void setName(String name) {
39        if (name == null) { throw new IllegalArgumentException(); }
40        this.name = name.toLowerCase();
41    }
42
43    /**
44     * Kann der Spieler das GameObject aufheben
45     * 
46     * @return  true wenn man es aufheben kann, false sonst
47     */
48    public boolean isTakeable() {
49        return this.takeable;
50    }
51
52    /**
53     * Setzt die Benutzbarkeit eines GameObjects
54     * 
55     * @param value true falls man es mit use benutzen kann, false sonst
56     */
57    public void setUsability(boolean value) {
58        this.useable = value;
59    }
60
61    /**
62     * Kann der Spieler das GameObject benutzen?
63     * 
64     * @return true wenn man es benutzen kann, false sonst
65     */
66    public boolean isUsable() {
67        return this.useable;
68    }
69
70    /**
71     * Ist das GameObject ein Character Objekt?
72     * 
73     * @return  true wenn das Objekt eine instanz von Character ist, false sonst
74     */
75    public boolean isCharacter() {
76        return false;
77    }
78
79    /**
80     * Ist das GameObject eine instanz von Item
81     * 
82     * @return  true wenn das Objekt eine Instanz von Item ist, false sonst
83     */
84    public boolean isItem() {
85        return false;
86    }
87
88    /**
89     * Wandelt das Objekt in ein JDOM XML Element
90     * 
91     * @return  ein JDOM XML Element
92     */
93    public abstract Element toElement();
94
95    /**
96     * Setzt die Nehmbarkeit des GameObjects
97     * 
98     * @param takeable  true wenn man es aufheben können soll, sonst false
99     */
00    public void setTakeable(boolean takeable) {
01        this.takeable = takeable;
02    }
03
04    /**
05     * Setzt die Größe (den Platz im Inventar) des GameObject
06     * 
07     * @param size
08     */
09    public void setSize(int size) {
10        if (size < 0) { throw new IllegalArgumentException("Size must be bigger than 0, is " + size); } //$NON-NLS-1$
11        this.size = size;
12    }
13    
14    /**
15     * Setzt ob das GameObject nach der Benutzung aus dem Inventar gelöscht werden soll
16     * 
17     * @param delete    soll es nach "use" gelöscht werden?
18     */
19    public void setDeleteOnUse(boolean delete) {
20        Engine.debug("New state of deleteonuse for " + name + ":" + delete,1); //$NON-NLS-1$ //$NON-NLS-2$
21        this.deleteOnUse = delete;
22    }
23
24    /**
25     * Setzt eine Eigenschaft über einen Hashkey.
26     * Im Moment wird nur "description" unterstützt, was setDescription aufruft
27     * 
28     * @param properties    eine Map mit den zu änderndern Eigenschaften
29     */
30    public void setProperties(Map properties) {
31        if (properties.containsKey("description")) { //$NON-NLS-1$
32            this.desc = (String)properties.get("description"); //$NON-NLS-1$
33        } else {
34            Engine.debug("Call to set unsuported property in GameObject",1); //$NON-NLS-1$
35        }
36    }
37
38    /**
39     * Zugriff auf die TargetList eines GameObjects
40     * 
41     * @return  die mit dem GameObject assozierte TargetList
42     */
43    public TargetList getTargetList() {
44        return this.targets;
45    }
46
47    /**
48     * Führt ein event aus. 
49     * 
50     * @param id    Die Id des Events
51     * @see org.jzuul.engine.Event
52     * @see org.jzuul.engine.EventHandler
53     */
54    public void doEvent(int id) {
55        if (id >= Event.COUNT || id < 0) throw new IllegalArgumentException("Id is not valid: " + id); //$NON-NLS-1$
56        if (id!=0) Engine.debug(getName() + " got event " + id,1); //$NON-NLS-1$
57        if (events[id] != null) {
58            events[id].execute(this);
59        } else {
60            if (id!=0) Engine.debug(getName() + " has no event handler for id " + id,1); //$NON-NLS-1$
61        }
62    }
63    
64    /**
65     * Setzt einen EventHandler
66     * 
67     * @param eventName der Name des Events
68     * @param handler           das EventHandler Objekt
69     * @see org.jzuul.engine.EventHandler
70     * @see org.jzuul.engine.Event
71     */
72    public void setHandler(String eventName, EventHandler handler) {
73        if (eventName == null || handler == null) {
74            Engine.debug("Tryed to set a null handler (name=" + eventName + ", handler=" + handler + ")",1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
75            return;
76        }
77        int id = Event.fromString(eventName);
78        handler.setOwner(this.getName());
79        if (id > -1) {
80        events[id] = handler;
81        } else {
82            throw new NoSuchEventException("The event " + eventName + " is unknown"); //$NON-NLS-1$ //$NON-NLS-2$
83        }
84    }
85        
86    /**
87     * Kopiert die Eigenschaften dieses GameObjects in das übergeben GameObject.
88     * Wird von Character.clone und Item.clone benutzt
89     * 
90     * @param obj   das Objekt dessen eigenschaften mit dem aktuellen gesynct werden sollen
91     */ 
92    protected void cloneInto(GameObject obj) {
93        obj.name = this.name;
94        obj.desc = this.desc;
95        obj.takeable = this.takeable;
96        obj.useable = this.useable;
97        obj.size = this.size;
98        obj.deleteOnUse = this.deleteOnUse;
99        obj.targets = this.targets.copy();
00        //NOTE I don't know wether this is correct or not, because events is a array of objects
01        obj.events = this.events;
02    }
03
04    abstract public GameObject copy();
05
06}
07