package games.strategy.engine.data;
import com.google.common.base.Preconditions;
import games.strategy.engine.data.annotations.GameProperty;
import games.strategy.net.GUID;
import games.strategy.triplea.attachments.UnitAttachment;
public class Unit extends GameDataComponent {
private static final long serialVersionUID = -7906193079642776282L;
private PlayerID m_owner;
private final GUID m_uid;
private int m_hits = 0;
private final UnitType m_type;
/**
* Creates new Unit. Should use a call to UnitType.create(). Owner can be null
*/
public Unit(final UnitType type, final PlayerID owner, final GameData data) {
super(data);
m_type = Preconditions.checkNotNull(type);
m_uid = new GUID();
setOwner(owner);
}
public GUID getID() {
return m_uid;
}
public UnitType getType() {
return m_type;
}
public UnitType getUnitType() {
return m_type;
}
public PlayerID getOwner() {
return m_owner;
}
public UnitAttachment getUnitAttachment() {
return (UnitAttachment) m_type.getAttachment("unitAttachment");
}
/**
* @deprecated DO NOT USE THIS METHOD if at all possible. It is very slow.
* This can return null if the unit is not in any territories.
* A unit just created, or held by a player after purchasing may not be in a territory.
* A unit can be in exactly 2 territories, if the unit is in the process of moving from one territory to
* another. This
* method will just
* return the first territory found.
* A unit should never be in more than 2 territories.
*/
@Deprecated
protected Territory getTerritoryUnitIsIn() {
for (final Territory t : this.getData().getMap().getTerritories()) {
if (t.getUnits().getUnits().contains(this)) {
return t;
}
}
return null;
}
public int getHits() {
return m_hits;
}
/**
* Remember to always use a ChangeFactory change over an IDelegate Bridge for any changes to game data, or any change
* that should go over
* the network.
*/
@GameProperty(xmlProperty = false, gameProperty = true, adds = false)
public void setHits(final int hits) {
m_hits = hits;
}
/**
* can be null.
*/
@GameProperty(xmlProperty = false, gameProperty = true, adds = false)
public void setOwner(PlayerID player) {
if (player == null) {
player = PlayerID.NULL_PLAYERID;
}
m_owner = player;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof Unit)) {
return false;
}
final Unit other = (Unit) o;
return this.m_uid.equals(other.m_uid);
}
public boolean isEquivalent(final Unit unit) {
if (m_type == null || m_owner == null) {
return false;
}
return m_type.equals(unit.getType()) && m_owner.equals(unit.getOwner()) && m_hits == unit.getHits();
}
@Override
public int hashCode() {
if (m_type == null || m_owner == null || m_uid == null || this.getData() == null) {
final String text =
"Unit.toString() -> Possible java de-serialization error: "
+ (m_type == null ? "Unit of UNKNOWN TYPE" : m_type.getName()) + " owned by " + (m_owner == null
? "UNKNOWN OWNER" : m_owner.getName())
+ " in territory: " + ((this.getData() != null && this.getData().getMap() != null)
? getTerritoryUnitIsIn() : "UNKNOWN TERRITORY")
+ " with id: " + getID();
UnitDeserializationErrorLazyMessage.printError(text);
return 0;
}
return m_uid.hashCode();
}
@Override
public String toString() {
// TODO: none of these should happen,... except that they did a couple times.
if (m_type == null || m_owner == null || m_uid == null || this.getData() == null) {
final String text =
"Unit.toString() -> Possible java de-serialization error: "
+ (m_type == null ? "Unit of UNKNOWN TYPE" : m_type.getName()) + " owned by " + (m_owner == null
? "UNKNOWN OWNER" : m_owner.getName())
+ " in territory: " + ((this.getData() != null && this.getData().getMap() != null)
? getTerritoryUnitIsIn() : "UNKNOWN TERRITORY")
+ " with id: " + getID();
UnitDeserializationErrorLazyMessage.printError(text);
return text;
}
return m_type.getName() + " owned by " + m_owner.getName();
}
public String toStringNoOwner() {
return m_type.getName();
}
/**
* Until this error gets fixed, lets not scare the crap out of our users, as the problem doesn't seem to be causing
* any serious issues.
* TODO: fix the root cause of this deserialization issue (probably a circular dependency somewhere)
*/
public static class UnitDeserializationErrorLazyMessage {
private static transient boolean s_shownError = false;
private static void printError(final String errorMessage) {
if (s_shownError == false) {
s_shownError = true;
System.err.println(errorMessage);
}
}
}
}