/*
* Copyright (C) 2012 maartenl
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package mmud.database.entities.characters;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import mmud.Attributes;
import mmud.Constants;
import mmud.Utils;
import mmud.database.entities.Ownage;
import mmud.database.entities.game.Admin;
import mmud.database.entities.game.Attribute;
import mmud.database.entities.game.AttributeWrangler;
import mmud.database.entities.game.Charattribute;
import mmud.database.entities.game.DisplayInterface;
import mmud.database.entities.game.Room;
import mmud.database.entities.items.Item;
import mmud.database.entities.items.ItemWrangler;
import mmud.database.enums.Alignment;
import mmud.database.enums.Appetite;
import mmud.database.enums.God;
import mmud.database.enums.Health;
import mmud.database.enums.Movement;
import mmud.database.enums.Sex;
import mmud.database.enums.Sobriety;
import mmud.database.enums.Wearing;
import static mmud.database.enums.Wearing.ABOUT_BODY;
import static mmud.database.enums.Wearing.FLOATING_NEARBY;
import static mmud.database.enums.Wearing.ON_ARMS;
import static mmud.database.enums.Wearing.ON_EARS;
import static mmud.database.enums.Wearing.ON_EYES;
import static mmud.database.enums.Wearing.ON_FEET;
import static mmud.database.enums.Wearing.ON_HANDS;
import static mmud.database.enums.Wearing.ON_HEAD;
import static mmud.database.enums.Wearing.ON_LEFT_FINGER;
import static mmud.database.enums.Wearing.ON_LEFT_WRIST;
import static mmud.database.enums.Wearing.ON_LEGS;
import static mmud.database.enums.Wearing.ON_NECK;
import static mmud.database.enums.Wearing.ON_RIGHT_FINGER;
import static mmud.database.enums.Wearing.ON_RIGHT_WRIST;
import static mmud.database.enums.Wearing.ON_TORSO;
import static mmud.database.enums.Wearing.ON_WAIST;
import mmud.database.enums.Wielding;
import mmud.exceptions.ItemException;
import mmud.exceptions.MoneyException;
import mmud.exceptions.MudException;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;
/**
* A character in the game. Might be both a bot, a shopkeeper, a user, or an
* administrator. Note: it contains a filter annotation which is EclipseLink
* specific.
*
* @author maartenl
*/
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "god",
discriminatorType = DiscriminatorType.INTEGER)
@Table(name = "mm_usertable")
@NamedQueries(
{
@NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p")
,
@NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE lower(p.name) = lower(:name)")
})
abstract public class Person implements Serializable, AttributeWrangler, DisplayInterface, ItemWrangler, Ownage
{
private static final Logger itsLog = java.util.logging.Logger.getLogger(Person.class.getName());
private static final long serialVersionUID = 1L;
public static final String EMPTY_LOG = "";
@Id
@Basic(optional = false)
@NotNull
@Size(min = 3, max = 20)
@Column(name = "name")
@Pattern(regexp = Constants.NAME_REGEXP, message = Constants.NAME_MESSAGE)
private String name;
@Size(max = 254)
@Column(name = "title")
private String title;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 50)
@Column(name = "race")
private String race;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 6)
@Column(name = "sex")
private String sex = "male";
@Size(max = 20)
@Column(name = "age")
private String age;
@Size(max = 20)
@Column(name = "height")
private String height;
@Size(max = 40)
@Column(name = "width")
private String width;
@Size(max = 40)
@Column(name = "complexion")
private String complexion;
@Size(max = 40)
@Column(name = "eyes")
private String eyes;
@Size(max = 40)
@Column(name = "face")
private String face;
@Size(max = 40)
@Column(name = "hair")
private String hair;
@Size(max = 40)
@Column(name = "beard")
private String beard;
@Size(max = 40)
@Column(name = "arm")
private String arm;
@Size(max = 40)
@Column(name = "leg")
private String leg;
@Column(name = "copper")
private Integer copper;
@JoinColumn(name = "room", nullable = false, referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@NotNull
private Room room;
@Column(name = "whimpy")
private Integer wimpy;
@Column(name = "experience")
private Integer experience;
@Size(max = 20)
// TODO recursion into the same table
@Column(name = "fightingwho")
private String fightingwho;
@Column(name = "sleep")
private Boolean sleep;
@Column(name = "fightable")
private Integer fightable;
@Column(name = "vitals")
private Integer vitals;
@Column(name = "fysically")
private Integer fysically;
@Column(name = "mentally")
private Integer mentally;
@Column(name = "drinkstats")
private Integer drinkstats;
@Column(name = "eatstats")
private Integer eatstats;
@Column(name = "active")
private Integer active;
@Column(name = "birth")
@Temporal(TemporalType.TIMESTAMP)
private Date birth;
@Column(name = "god", insertable = false, updatable = false)
private Integer god;
@Column(name = "strength")
private Integer strength;
@Column(name = "intelligence")
private Integer intelligence;
@Column(name = "dexterity")
private Integer dexterity;
@Column(name = "constitution")
private Integer constitution;
@Column(name = "wisdom")
private Integer wisdom;
@Column(name = "practises")
private Integer practises;
@Column(name = "training")
private Integer training;
@Column(name = "bandage")
private Integer bandage;
@Column(name = "alignment")
private Integer alignment;
@Column(name = "manastats")
private Integer manastats;
@Column(name = "movementstats")
private Integer movementstats;
@Column(name = "maxmana")
private Integer maxmana;
@Column(name = "maxmove")
private Integer maxmove;
@Column(name = "maxvital")
private Integer maxvital;
@Column(name = "jumpmana")
private Integer jumpmana;
@Column(name = "jumpmove")
private Integer jumpmove;
@Column(name = "jumpvital")
private Integer jumpvital;
@Basic(optional = false)
@NotNull
@Column(name = "creation_date")
@Temporal(TemporalType.TIMESTAMP)
private Date creation;
@Lob
@Size(max = 65535)
@Column(name = "notes")
private String notes;
@Lob
@Size(max = 65535)
@Column(name = "currentstate")
private String state;
@JoinColumn(name = "owner", referencedColumnName = "name")
@ManyToOne(fetch = FetchType.LAZY)
private Admin owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "belongsto", orphanRemoval = true)
private Set<Item> items = new HashSet<>();
@Transient
private File theLogfile = null;
@Transient
private StringBuffer theLog = null;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "person", orphanRemoval = true)
private Set<Charattribute> attributes = new HashSet<>();
@JoinColumn(name = "wieldleft", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wieldleft;
@JoinColumn(name = "wieldright", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wieldright;
@JoinColumn(name = "wieldboth", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wieldboth;
@JoinColumn(name = "wearhead", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearhead;
@JoinColumn(name = "wearneck", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearneck;
@JoinColumn(name = "weartorso", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item weartorso;
@JoinColumn(name = "weararms", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item weararms;
@JoinColumn(name = "wearleftwrist", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearleftwrist;
@JoinColumn(name = "wearrightwrist", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearrightwrist;
@JoinColumn(name = "wearleftfinger", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearleftfinger;
@JoinColumn(name = "wearrightfinger", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearrightfinger;
@JoinColumn(name = "wearfeet", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearfeet;
@JoinColumn(name = "wearhands", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearhands;
@JoinColumn(name = "wearfloatingnearby", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearfloatingnearby;
@JoinColumn(name = "wearwaist", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearwaist;
@JoinColumn(name = "wearlegs", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearlegs;
@JoinColumn(name = "weareyes", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item weareyes;
@JoinColumn(name = "wearears", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearears;
@JoinColumn(name = "wearaboutbody", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY)
private Item wearaboutbody;
public Person()
{
this.copper = 0; // no money
this.wimpy = 0; // no coward, either
this.experience = 0; // no experience points to speak of
this.fightingwho = null; // not fighting anybody
this.sleep = false;
this.fightable = 0;
this.vitals = MAX_VITALS;
this.fysically = 100;
this.mentally = 100;
this.drinkstats = 0;
this.eatstats = 0;
this.active = 0;
this.birth = new Date();
this.god = God.DEFAULT_USER.getValue();
this.strength = 0;
this.intelligence = 0;
this.dexterity = 0;
this.constitution = 0;
this.wisdom = 0;
this.practises = 0;
this.training = 0;
this.bandage = 0;
this.alignment = 0;
this.manastats = 100;
this.movementstats = 0;
this.maxmana = 11999;
this.maxmove = 11999;
this.maxvital = MAX_VITALS;
this.jumpmana = 1;
this.jumpmove = 1;
this.jumpvital = 1;
this.creation = new Date();
this.notes = null;
this.state = null;
}
public static final int MAX_VITALS = 11999;
/**
* returns the name of the character.
*
* @return String containing the name
*/
public String getName()
{
return name;
}
/**
* Sets the name of the person. Should contain only alphabetical characters,
* but has to have at least size of 3.
*
* @param name the (new) name.
* @throws MudException if the name is not allowed.
*/
public void setName(String name) throws MudException
{
this.name = name;
}
/**
* returns the title of the character.
*
* @return String containing the title
*/
public String getTitle()
{
return title;
}
/**
* sets the title of the character.
*
* @param title String containing the title
*/
public void setTitle(String title)
{
this.title = title;
}
/**
* returns the race of the character.
*
* @return String containing the race
*/
public String getRace()
{
return race;
}
public void setRace(String race)
{
this.race = race;
}
/**
* returns what gender the character is.
*
* @return Sex containing either male or female.
*/
public Sex getSex()
{
return Sex.createFromString(sex);
}
public void setSex(Sex sex)
{
this.sex = sex.toString();
}
/**
* returns the age of the character.
*
* @return String containing the age
*/
public String getAge()
{
return age;
}
public void setAge(String age)
{
this.age = age;
}
/**
* returns the length of the character.
*
* @return String containing the length
*/
public String getHeight()
{
return height;
}
public void setHeight(String height)
{
this.height = height;
}
/**
* returns the width of the character.
*
* @return String containing the width
*/
public String getWidth()
{
return width;
}
public void setWidth(String width)
{
this.width = width;
}
/**
* returns the complexion of the character.
*
* @return String containing the complexion
*/
public String getComplexion()
{
return complexion;
}
public void setComplexion(String complexion)
{
this.complexion = complexion;
}
/**
* returns the eyes of the character.
*
* @return String containing the eyes
*/
public String getEyes()
{
return eyes;
}
public void setEyes(String eyes)
{
this.eyes = eyes;
}
/**
* returns the face of the character.
*
* @return String containing the face
*/
public String getFace()
{
return face;
}
public void setFace(String face)
{
this.face = face;
}
/**
* returns the hair of the character.
*
* @return String containing the hair
*/
public String getHair()
{
return hair;
}
public void setHair(String hair)
{
this.hair = hair;
}
/**
* returns the beard of the character.
*
* @return String containing the beard
*/
public String getBeard()
{
return beard;
}
public void setBeard(String beard)
{
this.beard = beard;
}
/**
* returns the arms of the character.
*
* @return String containing the arms
*/
public String getArm()
{
return arm;
}
public void setArm(String arm)
{
this.arm = arm;
}
/**
* returns the legs of the character.
*
* @return String containing the legs
*/
public String getLeg()
{
return leg;
}
public void setLeg(String leg)
{
this.leg = leg;
}
/**
* Returns the amount of money a character has (in coppers). Basically 10
* coppers is 1 silver, and 10 silvers is 1 gold.
*
* @return Integer with the amount of coppers.
*/
public Integer getCopper()
{
return copper;
}
/**
* @see #getCopper()
* @return Integer with the amount of coppers
*/
public Integer getMoney()
{
return getCopper();
}
protected void setCopper(Integer copper)
{
this.copper = copper;
}
/**
* returns in which Room the character is.
*
* @return Room the room that the character is currently occupying
*/
public Room getRoom()
{
return room;
}
/**
* sets the room of the character.
*
* @param room the new current room of the character
*/
public void setRoom(Room room)
{
this.room = room;
}
/**
* get the setting for when to flee the fight.
*
* @return integer containing the setting
*/
public Health getWimpy()
{
return Health.get(wimpy);
}
/**
* sets the wimpy of the character.
*
* @param wimpy Health enum containing the wimpy
* @see #getWimpy()
*/
public void setWimpy(Health wimpy)
{
if (wimpy == null)
{
this.wimpy = null;
return;
}
this.wimpy = wimpy.getOrdinalValue();
}
/**
* Returns the level of the character.
*
* @return integer.
*/
public int getLevel()
{
if (experience == null)
{
experience = 0;
}
return experience / 1000;
}
/**
* Returns the experience of the character.
*
* @return integer between 0 and 1000. The closer to 1000 is the closer to
* the next level.
*/
public int getExperience()
{
if (experience == null)
{
experience = 0;
}
return experience % 1000;
}
public String getFightingwho()
{
return fightingwho;
}
public void setFightingwho(String fightingwho)
{
this.fightingwho = fightingwho;
}
/**
* returns whether or not the character is asleep.
*
* @return boolean, true if character is asleep.
*/
public Boolean getSleep()
{
if (sleep == null)
{
return false;
}
return sleep;
}
/**
* sets the sleep status of the character.
*
* @param sleep boolean containing the sleep status
*/
public void setSleep(Boolean sleep)
{
this.sleep = sleep;
}
/**
* Indicates if this person can be fought with by other
* persons/users/players.
*
* @return true if can be fought with, false otherwise.
*/
public Boolean getFightable()
{
return fightable == null ? false : fightable != 0;
}
/**
* @param fightable Indicates if this person can be fought with by other
* persons/users/players.
* @see #getFightable()
*/
public void setFightable(Boolean fightable)
{
if (fightable == null)
{
this.fightable = 0;
return;
}
this.fightable = (fightable ? 1 : 0);
}
public Integer getVitals()
{
if (vitals == null)
{
vitals = 11999;
}
return vitals;
}
public void increaseHealth(Integer vitals)
{
if (vitals < 0)
{
return;
}
this.vitals += vitals;
this.vitals = this.vitals % 12000;
}
public void decreaseHealth(Integer vitals)
{
if (vitals >= 12000)
{
return;
}
this.vitals -= vitals;
if (this.vitals < 0)
{
this.vitals = 0;
}
}
public Health getHealth()
{
return Health.get(getVitals());
}
public boolean isDead()
{
return getVitals() == 0;
}
public Integer getFysically()
{
return fysically;
}
public void setFysically(Integer fysically)
{
this.fysically = fysically;
}
public Integer getMentally()
{
return mentally;
}
public void setMentally(Integer mentally)
{
this.mentally = mentally;
}
public Integer getDrinkstats()
{
return drinkstats;
}
public void setDrinkstats(Integer drinkstats)
{
this.drinkstats = drinkstats;
}
public Integer getEatstats()
{
return eatstats;
}
public void setEatstats(Integer eatstats)
{
this.eatstats = eatstats;
}
/**
* Can tell you if a person is playing the game or not.
*
* @return boolean, true if the person is playing, false otherwise.
*/
public boolean isActive()
{
if (active == null)
{
return false;
}
return active.equals(1);
}
/**
* Make a person actively playing the game (or not).
*
* @param active boolean, true if he's playing, false otherwise.
*/
public void setActive(Boolean active)
{
if (active == null)
{
this.active = null;
}
this.active = active ? 1 : 0;
}
public Date getBirth()
{
return birth;
}
public void setBirth(Date birth)
{
this.birth = birth;
}
public God getGod()
{
return God.get(god);
}
public Integer getStrength()
{
return strength;
}
public void setStrength(Integer strength)
{
this.strength = strength;
}
public Integer getIntelligence()
{
return intelligence;
}
public void setIntelligence(Integer intelligence)
{
this.intelligence = intelligence;
}
public Integer getDexterity()
{
return dexterity;
}
public void setDexterity(Integer dexterity)
{
this.dexterity = dexterity;
}
public Integer getConstitution()
{
return constitution;
}
public void setConstitution(Integer constitution)
{
this.constitution = constitution;
}
public Integer getWisdom()
{
return wisdom;
}
public void setWisdom(Integer wisdom)
{
this.wisdom = wisdom;
}
public Integer getPractises()
{
return practises;
}
public void setPractises(Integer practises)
{
this.practises = practises;
}
public Integer getTraining()
{
return training;
}
public void setTraining(Integer training)
{
this.training = training;
}
public Integer getBandage()
{
return bandage;
}
public void setBandage(Integer bandage)
{
this.bandage = bandage;
}
public Integer getAlignment()
{
return alignment;
}
public void setAlignment(Integer alignment)
{
this.alignment = alignment;
}
public Integer getManastats()
{
return manastats;
}
public void setManastats(Integer manastats)
{
this.manastats = manastats;
}
public Integer getMovementstats()
{
return movementstats;
}
public void setMovementstats(Integer movementstats)
{
this.movementstats = movementstats;
}
public Integer getMaxmana()
{
return maxmana;
}
public void setMaxmana(Integer maxmana)
{
this.maxmana = maxmana;
}
public Integer getMaxmove()
{
return maxmove;
}
public void setMaxmove(Integer maxmove)
{
this.maxmove = maxmove;
}
public Integer getMaxvital()
{
return maxvital;
}
public void setMaxvital(Integer maxvital)
{
this.maxvital = maxvital;
}
public Integer getJumpmana()
{
return jumpmana;
}
public void setJumpmana(Integer jumpmana)
{
this.jumpmana = jumpmana;
}
public Integer getJumpmove()
{
return jumpmove;
}
public void setJumpmove(Integer jumpmove)
{
this.jumpmove = jumpmove;
}
public Integer getJumpvital()
{
return jumpvital;
}
public void setJumpvital(Integer jumpvital)
{
this.jumpvital = jumpvital;
}
public Date getCreation()
{
return creation;
}
public void setCreation(Date creation)
{
this.creation = creation;
}
public String getNotes()
{
return notes;
}
public void setNotes(String notes)
{
this.notes = notes;
}
/**
* returns the state of the character, for example "He seems to be on
* fire.". Primarily used for roleplaying.
*
* @return String containing the description of the current condition of the
* character.
*/
public String getState()
{
return state;
}
/**
* sets the state/condition of the character.
*
* @param state String containing the description of the current condition
* of the character.
*/
public void setState(String state)
{
this.state = state;
}
@Override
public Admin getOwner()
{
return owner;
}
@Override
public void setOwner(Admin owner)
{
this.owner = owner;
}
private void addDescriptionPiece(StringBuilder builder, String part)
{
if (part != null && !"none".equalsIgnoreCase(part))
{
builder.append(", ").append(part);
}
}
/**
* Returns the description of the character. All characteristics, if
* possible, are taken into account. Does not provide any info on the name
* or title. It contains a strictly visual cue.
*
* @return String containing the description
*/
public String getDescription()
{
StringBuilder builder = new StringBuilder();
if (getAge() != null)
{
builder.append(getAge());
}
addDescriptionPiece(builder, getHeight());
addDescriptionPiece(builder, getWidth());
addDescriptionPiece(builder, getComplexion());
addDescriptionPiece(builder, getEyes());
addDescriptionPiece(builder, getFace());
addDescriptionPiece(builder, getHair());
addDescriptionPiece(builder, getBeard());
addDescriptionPiece(builder, getArm());
addDescriptionPiece(builder, getLeg());
addDescriptionPiece(builder, getFace());
builder.append(" ").append(getSex()).append(" ").append(getRace());
return builder.toString().trim();
}
/**
* Indicates if this is a common user. This means it indicates that it is
* basically someone behind a keyboard.
*
* @return true if it is a common user (or a god/administrator), false
* otherwise.
*/
public boolean isUser()
{
if (getGod() == null)
{
return true;
}
return (getGod() == God.DEFAULT_USER || getGod() == God.GOD);
}
@Override
public int hashCode()
{
int hash = 0;
hash += (name != null ? name.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object)
{
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Person))
{
return false;
}
Person other = (Person) object;
if ((this.name == null && other.name != null) || (this.name != null && !this.name.equals(other.name)))
{
return false;
}
return true;
}
@Override
public String toString()
{
return "mmud.database.entities.game.Person[ name=" + name + " ]";
}
/**
* Clears the log, i.e. deletes the file and recreates it.
*
* @see #createLog()
*/
public void clearLog() throws MudException
{
createLog();
}
/**
* writes a message to the log file of the character that contains all
* communication and messages. The sentence will start with a capital.
*
* <p>
* <b>Important!</b> : Use this method only for Environmental communication
* or personal communication , as it does not check the Ignore Flag. Use the
* writeMessage(Person aSource, String aMessage) for specific communication
* between users.</p> TODO : move the logging to a protected hashtable in a
* singleton bean containing StringBuffers.
*
* @param aMessage the message to be written to the logfile.
* @see #writeMessage(Person aSource, Person aTarget, String aMessage)
* @see #writeMessage(Person aSource, String aMessage)
*/
public void writeMessage(String aMessage) throws MudException
{
if (aMessage == null)
{
return;
}
try
{
aMessage = Utils.security(aMessage);
} catch (PolicyException | ScanException ex)
{
throw new MudException(ex);
}
int i = 0;
int _container = 0;
int foundit = -1;
while ((i < aMessage.length()) && (foundit == -1))
{
if (_container == 0)
{
if (aMessage.charAt(i) == '<')
{
_container = 1;
} else if (aMessage.charAt(i) != ' ')
{
foundit = i;
}
} else if (_container == 1)
{
if (aMessage.charAt(i) == '>')
{
_container = 0;
}
}
i++;
}
if (foundit != -1)
{
aMessage = aMessage.substring(0, foundit)
+ Character.toUpperCase(aMessage.charAt(foundit))
+ aMessage.substring(foundit + 1);
}
try (FileWriter myFileWriter = new FileWriter(getLogfile(), true))
{
myFileWriter.write(aMessage, 0, aMessage.length());
} catch (IOException e)
{
throw new MudException("error writing message", e);
}
}
/**
* writes a message to the log file of the character that contains all
* communication and messages. The message will be <I>interpreted</I> by
* replacing the following values by the following other values: <TABLE>
* <TR> <TD><B>REPLACE</B></TD> <TD><B>WITH (if target)</B></TD> <TD><B>WITH
* (if not target)</B></TD> </TR> <TR> <TD>%TNAME</TD> <TD>you</TD>
* <TD>name</TD> </TR> <TR> <TD>%TNAMESELF</TD> <TD>yourself</TD>
* <TD>name</TD> </TR> <TR> <TD>%THISHER</TD> <TD>your</TD> <TD>his/her</TD>
* </TR> <TR> <TD>%THIMHER</TD> <TD>you</TD> <TD>him/her</TD> </TR> <TR>
* <TD>%THESHE</TD> <TD>you</TD> <TD>he/she</TD> </TR> <TR> <TD>%TISARE</TD>
* <TD>are</TD> <TD>is</TD> </TR> <TR> <TD>%THASHAVE</TD> <TD>have</TD>
* <TD>has</TD> </TR> <TR> <TD>%TYOUPOSS</TD> <TD>your</TD> <TD>name +
* s</TD> </TR> <TR> <TD></TD> <TD></TD> <TD></TD> </TR> </TABLE>
*
* @param aMessage the message to be written to the logfile.
* @param aSource the source of the message, the thing originating the
* message.
* @param aTarget the target of the message, could be null if there is not
* target for this specific message.
* @see #writeMessage(String aMessage)
* @see #writeMessage(Person aSource, String aMessage)
*/
public void writeMessage(Person aSource, Person aTarget, String aMessage) throws MudException
{
if (this.isIgnoring(aSource))
{
return;
}
String message = aMessage;
if (aTarget == this)
{
message = message.replaceAll("%TNAMESELF", "yourself");
message = message.replaceAll("%TNAME", "you");
message = message.replaceAll("%THISHER", "your");
message = message.replaceAll("%THIMHER", "you");
message = message.replaceAll("%THESHE", "you");
message = message.replaceAll("%TISARE", "are");
message = message.replaceAll("%THASHAVE", "have");
message = message.replaceAll("%TYOUPOSS", "your");
} else
{
message = message.replaceAll("%TNAMESELF", aTarget.getName());
message = message.replaceAll("%TNAME", aTarget.getName());
message = message.replaceAll("%THISHER", (aTarget.getSex().posession()));
message = message.replaceAll("%THIMHER", (aTarget.getSex().indirect()));
message = message.replaceAll("%THESHE", (aTarget.getSex().direct()));
message = message.replaceAll("%TISARE", "is");
message = message.replaceAll("%THASHAVE", "has");
message = message.replaceAll("%TYOUPOSS", aTarget.getName() + "s");
}
writeMessage(aSource, message);
}
/**
* writes a message to the log file of the character that contains all
* communication and messages. The message will be <I>interpreted</I> by
* replacing the following values by the following other values: <TABLE>
* <TR> <TD><B>REPLACE</B></TD> <TD><B>WITH (if source)</B></TD> <TD><B>WITH
* (if not source)</B></TD> </TR> <TR> <TD>%SNAME</TD> <TD>you</TD>
* <TD>name</TD> </TR> <TR> <TD>%SNAMESELF</TD> <TD>yourself</TD>
* <TD>name</TD> </TR> <TR> <TD>%SHISHER</TD> <TD>your</TD> <TD>his/her</TD>
* </TR> <TR> <TD>%SHIMHER</TD> <TD>you</TD> <TD>him/her</TD> </TR> <TR>
* <TD>%SHESHE</TD> <TD>you</TD> <TD>he/she</TD> </TR> <TR> <TD>%SISARE</TD>
* <TD>are</TD> <TD>is</TD> </TR> <TR> <TD>%SHASHAVE</TD> <TD>have</TD>
* <TD>has</TD> </TR> <TR> <TD>%SYOUPOSS</TD> <TD>your</TD> <TD>name +
* s</TD> </TR> <TR> <TD>%VERB1</TD> <TD></TD> <TD>es</TD> </TR> <TR>
* <TD>%VERB2</TD> <TD></TD> <TD>s</TD> </TR> <TR> <TD></TD> <TD></TD>
* <TD></TD> </TR> </TABLE>
*
* @param aMessage the message to be written to the logfile.
* @param aSource the source of the message, the thing originating the
* message.
* @see #writeMessage(Person aSource, Person aTarget, String aMessage)
* @see #writeMessage(String aMessage)
*/
public void writeMessage(Person aSource, String aMessage) throws MudException
{
if (this.isIgnoring(aSource))
{
return;
}
String message = aMessage;
if (aSource == this)
{
message = message.replaceAll("%SNAMESELF", "yourself");
message = message.replaceAll("%SNAME", "you");
message = message.replaceAll("%SHISHER", "your");
message = message.replaceAll("%SHIMHER", "you");
message = message.replaceAll("%SHESHE", "you");
message = message.replaceAll("%SISARE", "are");
message = message.replaceAll("%SHASHAVE", "have");
message = message.replaceAll("%SYOUPOSS", "your");
message = message.replaceAll("%VERB1", "");
message = message.replaceAll("%VERB2", "");
} else
{
message = message.replaceAll("%SNAMESELF", aSource.getName());
message = message.replaceAll("%SNAME", aSource.getName());
message = message.replaceAll("%SHISHER", (aSource.getSex().posession()));
message = message.replaceAll("%SHIMHER", (aSource.getSex().indirect()));
message = message.replaceAll("%SHESHE", (aSource.getSex().direct()));
message = message.replaceAll("%SISARE", "is");
message = message.replaceAll("%SHASHAVE", "has");
message = message.replaceAll("%SYOUPOSS", aSource.getName() + "s");
message = message.replaceAll("%VERB1", "es");
message = message.replaceAll("say%VERB2", "says");
message = message.replaceAll("y%VERB2", "ies");
message = message.replaceAll("%VERB2", "s");
}
writeMessage(message);
}
/**
* creates a new log file and deletes the old one.
*
* @throws MudException which indicates probably that the log file could not
* be created. Possibly due to either permissions or the directory does not
* exist.
*/
protected void createLog() throws MudException
{
if (getLogfile().exists())
{
getLogfile().delete();
}
try
{
getLogfile().createNewFile();
} catch (IOException e)
{
throw new MudException("Error creating logfile for " + getName()
+ " in " + Constants.getMudfilepath(), e);
}
}
private File getLogfile()
{
if (theLogfile == null)
{
theLogfile = new File(Constants.getMudfilepath(), getName() + ".log");
}
return theLogfile;
}
private void readLog() throws MudException
{
File file = getLogfile();
try (BufferedReader reader = new BufferedReader(
new FileReader(file)))
{
theLog = new StringBuffer(1000);
char[] buf = new char[1024];
int numRead;
while ((numRead = reader.read(buf)) != -1)
{
theLog.append(buf, 0, numRead);
}
} catch (FileNotFoundException ex)
{
try
{
throw new MudException("Logfile of " + name + " (" + file.getCanonicalPath() + ") not found", ex);
} catch (IOException ex1)
{
throw new MudException("Logfile of " + name, ex);
// surrender peacefully with your hands up!
}
} catch (IOException ex)
{
try
{
throw new MudException("Error reading logfile of " + name + " (" + file.getCanonicalPath() + ")", ex);
} catch (IOException ex1)
{
throw new MudException("Error reading logfile of " + name, ex);
// surrender peacefully with your hands up!
}
}
}
/**
* Returns the log starting from the offset, or an empty string if the
* offset is past the length of the log.Can also contain the empty string,
* if the log happens to be empty.
*
* @param offset the offset from whence to read the log. Offset starts with
* 0 and is inclusive.
* @return a String, part of the Log.
* @throws MudException in case of accidents with reading the log, or a
* negative offset.
*/
public String getLog(Integer offset) throws MudException
{
if (offset == null)
{
offset = 0;
}
if (theLog == null)
{
readLog();
}
if (offset >= theLog.length())
{
return EMPTY_LOG;
}
if (offset < 0)
{
throw new MudException("Attempting to get log with negative offset.");
}
return theLog.substring(offset);
}
/**
* Display statistics .
*
* @return String containing all the statistics in html format.
*/
public String getStatistics() throws MudException
{
// TODO : get wearables
// String stuff = ItemsDb.getWearablesFromChar(this);
// stuff.replaceAll("%SHISHER", "your");
StringBuilder stuff = new StringBuilder();
String whimpy = (getWimpy() == null ? "You are not whimpy at all.<BR>"
: "You will flee when you are " + getWimpy().getDescription() + ".<BR>");
String state = getState() == null ? "" : "Your condition is \"" + getState() + "\"<br/>";
stuff.append("A ").append(getLongDescription()).append(".<BR>You seem to be ").append(Health.getHealth(getVitals()).getDescription()).append(".<BR>You are ").append(Movement.getMovement(getMovementstats()).getDescription()).append(".<BR>").append(Sobriety.getSobriety(getDrinkstats()).getDescription()).append("<br />").append(Appetite.getAppetite(getEatstats()).getDescription()).append("<br />" + "You are ").append(Alignment.getAlignment(alignment).getDescription()).append(".<BR>" + "You are level ").append(getLevel()).append(" and ").append(1000 - getExperience()).append(" experience points away from levelling.<BR>").append(whimpy);
stuff.append(state);
// Skill
return stuff.toString();
}
private StringBuilder addLongDescription(StringBuilder builder)
{
builder.append(getAge().equals("none") ? "" : getAge() + ", ");
builder.append(getHeight().equals("none") ? "" : getHeight() + ", ");
builder.append(getWidth().equals("none") ? "" : getWidth() + ", ");
builder.append(getComplexion().equals("none") ? "" : getComplexion() + ", ");
builder.append(getEyes().equals("none") ? "" : getEyes() + ", ");
builder.append(getFace().equals("none") ? "" : getFace() + ", ");
builder.append(getHair().equals("none") ? "" : getHair() + ", ");
builder.append(getBeard().equals("none") ? "" : getBeard() + ", ");
builder.append(getArm().equals("none") ? "" : getArm() + ", ");
builder.append(getLeg().equals("none") ? "" : getLeg() + ", ");
builder.append(getSex()).append(" ").append(getRace()).append(" who calls ").append(getSex().indirect());
builder.append("self ").append(getName());
if (getTitle() != null && !getTitle().trim().equals(""))
{
builder.append(" (").append(getTitle()).append(")");
}
builder.append(".");
return builder;
}
/**
* returns the description of the character. All characteristics, if
* possible, are taken into account.
*
* @return String containing the description
*/
public String getLongDescription()
{
return addLongDescription(new StringBuilder()).toString();
}
@Override
public boolean removeAttribute(String name)
{
Charattribute attr = getCharattribute(name);
if (attr == null)
{
return false;
}
return attributes.remove(attr);
}
private Charattribute getCharattribute(String name)
{
if (attributes == null)
{
itsLog.finer("getCharattribute name=" + name + " collection is null");
return null;
}
for (Charattribute attr : attributes)
{
itsLog.finer("getCharattribute name=" + name + " attr=" + attr);
if (attr.getName().equals(name))
{
return attr;
}
}
itsLog.log(Level.FINER, "getCharattribute name={0} not found", name);
return null;
}
@Override
public Attribute getAttribute(String name)
{
return getCharattribute(name);
}
@Override
public void setAttribute(String name, String value)
{
Charattribute attr = getCharattribute(name);
if (attr == null)
{
attr = new Charattribute(name, getName());
attr.setPerson(this);
}
attr.setValue(value);
attr.setValueType(Attributes.VALUETYPE_STRING);
attributes.add(attr);
}
@Override
public boolean verifyAttribute(String name, String value)
{
Charattribute attr = getCharattribute(name);
if (attr == null)
{
itsLog.log(Level.FINER, "verifyAttribute (name={0}, value={1}) not found on user {2}.", new Object[]
{
name, value, getName()
});
return false;
}
if (attr.getValue().equals(value))
{
itsLog.log(Level.FINER, "verifyAttribute (name={0}, value={1}) matches on user {2}!", new Object[]
{
name, value, getName()
});
return true;
}
itsLog.log(Level.FINER, "verifyAttribute (name={0}, value={1}) with (name={2}, value={3}) no match on user {4}.", new Object[]
{
name, value, attr.getName(), attr.getValue(), getName()
});
return false;
}
@Override
public Set<Item> getItems()
{
return items;
}
/**
* Returns the amount of money that you are carrying.
*
* @return String description of the amount of money.
* @see Constants#getDescriptionOfMoney
*/
public String getDescriptionOfMoney()
{
return Constants.getDescriptionOfMoney(getCopper());
}
@Override
public String getMainTitle() throws MudException
{
return getName();
}
@Override
public String getImage() throws MudException
{
return null;
}
private String getWearables()
{
StringBuilder builder = new StringBuilder();
if (getWieldleft() != null)
{
builder.append("%SHESHE %SISARE wielding ").append(getWieldleft().getDescription())
.append(" in %SHISHER left hand.<br/>\r\n");
}
if (getWieldright() != null)
{
builder.append("%SHESHE %SISARE wielding ").append(getWieldright().getDescription())
.append(" in %SHISHER right hand.<br/>\r\n");
}
if (getWieldboth() != null)
{
builder.append("%SHESHE %SISARE wielding ").append(getWieldboth().getDescription())
.append(" in both hands.<br/>\r\n");
}
if (getWearhead() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearhead().getDescription())
.append(" on %SHISHER head.<br/>\r\n");
}
if (getWearneck() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearneck().getDescription())
.append(" on %SHISHER neck.<br/>\r\n");
}
if (getWeartorso() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWeartorso().getDescription())
.append(" on %SHISHER torso.<br/>\r\n");
}
if (getWeararms() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWeararms().getDescription())
.append(" on %SHISHER arms.<br/>\r\n");
}
if (getWearleftwrist() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearleftwrist().getDescription())
.append(" on %SHISHER left wrist.<br/>\r\n");
}
if (getWearrightwrist() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearrightwrist().getDescription())
.append(" on %SHISHER right wrist.<br/>\r\n");
}
if (getWearleftfinger() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearleftfinger().getDescription())
.append(" on %SHISHER left finger.<br/>\r\n");
}
if (getWearrightfinger() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearrightfinger().getDescription())
.append(" on %SHISHER right finger.<br/>\r\n");
}
if (getWearfeet() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearfeet().getDescription())
.append(" on %SHISHER feet.<br/>\r\n");
}
if (getWearhands() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearhands().getDescription())
.append(" on %SHISHER hands.<br/>\r\n");
}
if (getWearfloatingnearby() != null)
{
builder.append(getWearfloatingnearby().getDescription())
.append(" is floating nearby.<br/>\r\n");
}
if (getWearwaist() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearwaist().getDescription())
.append(" around %SHISHER waist.<br/>\r\n");
}
if (getWearlegs() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearlegs().getDescription())
.append(" on %SHISHER legs.<br/>\r\n");
}
if (getWeareyes() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWeareyes().getDescription())
.append(" %SHISHER.<br/>\r\n");
}
if (getWearears() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearears().getDescription())
.append(" in %SHISHER ears.<br/>\r\n");
}
if (getWearaboutbody() != null)
{
builder.append("%SHESHE %SISARE wearing ").append(getWearaboutbody().getDescription())
.append(" about %SHISHER body.<br/>\r\n");
}
return builder.toString();
}
@Override
public String getBody() throws MudException
{
StringBuilder builder = new StringBuilder(
getLongDescription() + "<br/>\r\n"
+ getWearables());
if (getState() != null)
{
builder.append(getState()).append("<br/>\r\n");
}
String stuff2 = builder.toString();
stuff2 = stuff2.replaceAll("%SHESHE", getSex().Direct());
stuff2 = stuff2.replaceAll("%SHISHER", getSex()
.posession());
stuff2 = stuff2.replaceAll("%SISARE", "is");
return stuff2;
}
/**
* Returns items in the inventory of this character, based on description
* provided by the user.
*
* @param parsed the parsed description of the item as given by the user,
* for example {"light-green", "leather", "pants"}.
* @return list of found items, empty if not found.
*/
@Override
public List<Item> findItems(List<String> parsed)
{
List<Item> result = new ArrayList<>();
for (Item item : getItems())
{
if (item.isDescribedBy(parsed))
{
result.add(item);
}
}
return result;
}
private Item getWieldleft()
{
return wieldleft;
}
private void setWieldleft(Item item) throws ItemException
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wieldleft = item;
}
private Item getWieldright()
{
return wieldright;
}
private void setWieldright(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wieldright = item;
}
private Item getWieldboth()
{
return wieldboth;
}
private void setWieldboth(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wieldboth = item;
}
private Item getWearhead()
{
return wearhead;
}
private void setWearhead(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearhead = item;
}
private Item getWearneck()
{
return wearneck;
}
private void setWearneck(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearneck = item;
}
private Item getWeartorso()
{
return weartorso;
}
private void setWeartorso(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.weartorso = item;
}
private Item getWeararms()
{
return weararms;
}
private void setWeararms(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.weararms = item;
}
private Item getWearleftwrist()
{
return wearleftwrist;
}
private void setWearleftwrist(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearleftwrist = item;
}
private Item getWearrightwrist()
{
return wearrightwrist;
}
private void setWearrightwrist(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearrightwrist = item;
}
private Item getWearleftfinger()
{
return wearleftfinger;
}
private void setWearleftfinger(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearleftfinger = item;
}
private Item getWearrightfinger()
{
return wearrightfinger;
}
private void setWearrightfinger(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearrightfinger = item;
}
private Item getWearfeet()
{
return wearfeet;
}
private void setWearfeet(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearfeet = item;
}
private Item getWearhands()
{
return wearhands;
}
private void setWearhands(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearhands = item;
}
private Item getWearfloatingnearby()
{
return wearfloatingnearby;
}
private void setWearfloatingnearby(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearfloatingnearby = item;
}
private Item getWearwaist()
{
return wearwaist;
}
private void setWearwaist(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearwaist = item;
}
private Item getWearlegs()
{
return wearlegs;
}
private void setWearlegs(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearlegs = item;
}
private Item getWeareyes()
{
return weareyes;
}
private void setWeareyes(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.weareyes = item;
}
private Item getWearears()
{
return wearears;
}
private void setWearears(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearears = item;
}
private Item getWearaboutbody()
{
return wearaboutbody;
}
private void setWearaboutbody(Item item)
{
if (item != null && !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
this.wearaboutbody = item;
}
@Override
public boolean destroyItem(Item item)
{
if (item == null)
{
throw new ItemException("That is not an item.");
}
if (!items.contains(item))
{
throw new ItemException("You do not have that item.");
}
if (isWearing(item))
{
throw new ItemException("That item is still being worn, and cannot be destroyed.");
}
if (item.containsItems())
{
throw new ItemException("That item contains items. Empty it first.");
}
return items.remove(item);
// note: as the collection is an orphan, the delete
// on the set will take place automatically.
}
/**
* Returns the item being worn at that position.
*
* @param position the position to check.
* @return the item worn at that position, may be null if nothing is being
* worn there.
*/
public Item wears(Wearing position)
{
if (position == null)
{
throw new RuntimeException("You cannot wear an item on null");
}
switch (position)
{
case ABOUT_BODY:
return getWearaboutbody();
case FLOATING_NEARBY:
return getWearfloatingnearby();
case ON_ARMS:
return getWeararms();
case ON_EARS:
return getWearears();
case ON_EYES:
return getWeareyes();
case ON_FEET:
return getWearfeet();
case ON_HANDS:
return getWearhands();
case ON_HEAD:
return getWearhead();
case ON_LEFT_FINGER:
return getWearleftfinger();
case ON_LEFT_WRIST:
return getWearleftwrist();
case ON_LEGS:
return getWearlegs();
case ON_NECK:
return getWearneck();
case ON_RIGHT_FINGER:
return getWearrightfinger();
case ON_RIGHT_WRIST:
return getWearrightwrist();
case ON_TORSO:
return getWeartorso();
case ON_WAIST:
return getWearwaist();
}
throw new RuntimeException("You cannot wear an item on " + position);
}
/**
* Indicates if an item is being worn,
*
* @param item the item to check, if null provided it will never be worn,
* obviously.
* @return true if the item is being worn, false otherwise.
*/
public boolean isWearing(Item item)
{
if (item == null)
{
return false;
}
return item == getWearaboutbody()
|| item == getWearfloatingnearby()
|| item == getWeararms()
|| item == getWearears()
|| item == getWeareyes()
|| item == getWearfeet()
|| item == getWearhands()
|| item == getWearhead()
|| item == getWearleftfinger()
|| item == getWearleftwrist()
|| item == getWearlegs()
|| item == getWearneck()
|| item == getWearrightfinger()
|| item == getWearrightwrist()
|| item == getWeartorso()
|| item == getWearwaist();
}
/**
* Makes you wear an item at a specific position
*
* @param item the item to be worn. In case this is null, it means an item
* that used to be worn at this position will be removed.
* @param position the position on which the item is to be worn
*
*/
public void wear(Item item, Wearing position)
{
if (position == null)
{
throw new ItemException("You cannot wear an item on nothing.");
}
if (item != null && !item.isWearable(position))
{
throw new ItemException("You cannot wear that item there.");
}
switch (position)
{
case ABOUT_BODY:
setWearaboutbody(item);
break;
case FLOATING_NEARBY:
setWearfloatingnearby(item);
break;
case ON_ARMS:
setWeararms(item);
break;
case ON_EARS:
setWearears(item);
break;
case ON_EYES:
setWeareyes(item);
break;
case ON_FEET:
setWearfeet(item);
break;
case ON_HANDS:
setWearhands(item);
break;
case ON_HEAD:
setWearhead(item);
break;
case ON_LEFT_FINGER:
setWearleftfinger(item);
break;
case ON_LEFT_WRIST:
setWearleftwrist(item);
break;
case ON_LEGS:
setWearlegs(item);
break;
case ON_NECK:
setWearneck(item);
break;
case ON_RIGHT_FINGER:
setWearrightfinger(item);
break;
case ON_RIGHT_WRIST:
setWearrightwrist(item);
break;
case ON_TORSO:
setWeartorso(item);
break;
case ON_WAIST:
setWearwaist(item);
break;
default:
throw new ItemException("You cannot wear " + (item == null ? "that" : item.getDescription()) + " on " + position + ".");
}
}
/**
* Returns the item being wielded at that position.
*
* @param position the position to check.
* @return the item wielded at that position, may be null if nothing is
* being wielded there.
*/
public Item wields(Wielding position)
{
if (position == null)
{
throw new RuntimeException("You cannot wield an item on null");
}
switch (position)
{
case WIELD_BOTH:
return getWieldboth();
case WIELD_RIGHT:
return getWieldright();
case WIELD_LEFT:
return getWieldleft();
}
throw new RuntimeException("You cannot wield an item on " + position);
}
/**
* Indicates if an item is being wielded,
*
* @param item the item to check, if null provided it will never be wielded,
* obviously.
* @return true if the item is being wielded, false otherwise.
*/
public boolean isWielding(Item item)
{
if (item == null)
{
return false;
}
return item == getWieldboth()
|| item == getWieldleft()
|| item == getWieldright();
}
/**
* Makes you wield an item at a specific position
*
* @param item the item to be wielded. In case this is null, it means an
* item that used to be wielded at this position will be removed.
* @param position the position on which the item is to be wielded,
* lefthand, righthand or with both hands.
*
*/
public void wield(Item item, Wielding position)
{
if (position == null)
{
throw new ItemException("You cannot wield an item on null");
}
if (item != null && !item.isWieldable(position))
{
throw new ItemException("You cannot wield that item there.");
}
switch (position)
{
case WIELD_BOTH:
if (getWieldleft() != null || getWieldright() != null)
{
throw new ItemException("You cannot wield something in both hands, when you are already wielding something in either right or left hand.<br/>\r\n");
}
setWieldboth(item);
break;
case WIELD_LEFT:
if (getWieldboth() != null)
{
throw new ItemException("You cannot wield something in your left hand, when you are already wielding something in both hands.<br/>\r\n");
}
setWieldleft(item);
break;
case WIELD_RIGHT:
if (getWieldboth() != null)
{
throw new ItemException("You cannot wield something in your right hand, when you are already wielding something in both hands.<br/>\r\n");
}
setWieldright(item);
break;
default:
throw new ItemException("You cannot wield " + (item == null ? "that" : item.getDescription()) + " on " + position);
}
}
/**
* Determines if the item is being used or not. If it is used, it is not
* allowed to be dropped, get, drunk, eaten, etc.
*
* @param item the item to check
* @return true if the item is available for use.
*/
public boolean unused(Item item)
{
return !isWearing(item) && !isWielding(item);
}
public void drop(Item item)
{
if (item == null || !items.contains(item))
{
throw new ItemException("You do not have that item.");
}
if (!unused(item))
{
throw new ItemException("You are using this item.");
}
if (!getRoom().drop(item))
{
throw new ItemException("Unable to add item to the room.");
}
if (!items.remove(item))
{
throw new ItemException("Unable to remove item from inventory.");
}
item.drop(this, getRoom());
}
/**
* Picked up an item from a room.
*
* @param item
*/
public void get(Item item)
{
getRoom().get(item);
if (!items.add(item))
{
throw new ItemException("Unable to add item to your inventory.");
}
item.get(this, getRoom());
}
/**
* Transfers money from one person (this one) to another.
*
* @param newamount the amount of copper (base currency to move)
* @param target the target that is to receive said money
* @throws MoneyException if the money amount is illegal, or the person
* simply does not have that much money.
*/
public void transferMoney(Integer newamount, Person target) throws MoneyException
{
if (target == null)
{
throw new MoneyException("You want to transfer money to whom?");
}
if (newamount == null || newamount <= 0)
{
throw new MoneyException("I beg your pardon?");
}
if (getMoney() < newamount)
{
throw new MoneyException("You do not have that much money.");
}
setCopper(getCopper() - newamount);
target.setCopper(target.getCopper() + newamount);
}
protected boolean isIgnoring(Person aSource)
{
return false;
}
/**
* Indicates whether or not this person can receive items or money from
* other players.
*
* @return
*/
abstract public boolean canReceive();
public void give(Item item, Person toperson)
{
if (!items.remove(item))
{
throw new ItemException("Unable to remove item from inventory.");
}
toperson.receive(item);
item.give(toperson);
}
protected void receive(Item item)
{
items.add(item);
}
/**
* Adds an {@link Item} to the inventory of this person.
* It is assumed that this item has not yet been assigned
* to something (a person, a room or a container (bag)).
*
* @param item the new item. May not be null.
* @return the new item, null if unable to add.
*/
@Override
public Item addItem(Item item)
{
if (item.getBelongsTo() != null || item.getRoom() != null || item.getContainer() != null)
{
throw new MudException("Item already assigned.");
}
if (!items.add(item))
{
return null;
}
item.give(this);
return item;
}
/**
* A user is always visible, will return always true.
*
* @return true
*/
public boolean getVisible()
{
return true;
}
/**
* Empty implementation. A user is always visible.
*
* @param visible
*/
public void setVisible(boolean visible)
{
// purposefully empty,
}
}