de.rpgframework.genericrpg.items.CarriedItem Maven / Gradle / Ivy
package de.rpgframework.genericrpg.items;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import org.prelle.simplepersist.AttribConvert;
import org.prelle.simplepersist.Attribute;
import org.prelle.simplepersist.Element;
import org.prelle.simplepersist.ElementList;
import org.prelle.simplepersist.Root;
import de.rpgframework.genericrpg.chargen.OperationResult;
import de.rpgframework.genericrpg.data.ComplexDataItemValue;
import de.rpgframework.genericrpg.data.Decision;
import de.rpgframework.genericrpg.data.IReferenceResolver;
import de.rpgframework.genericrpg.data.Lifeform;
import de.rpgframework.genericrpg.modification.Modification;
import de.rpgframework.genericrpg.modification.Modification.Origin;
import de.rpgframework.genericrpg.modification.ValueModification;
import de.rpgframework.genericrpg.persist.IntegerArrayConverter;
import de.rpgframework.genericrpg.requirements.Requirement;
/**
* @author prelle
*
*/
@Root(name="item")
public class CarriedItem extends ComplexDataItemValue implements IReferenceResolver {
final static Logger logger = System.getLogger(CarriedItem.class.getPackageName());
@Attribute(name="variant", required = false)
private String variantRef;
/** How is the item associated with the character */
@Attribute(required = false)
private CarryMode mode = CarryMode.CARRIED;
@Element
private String description;
@Attribute(required = false)
private int count;
@Attribute
private Hook slot;
// ToDo: Ausrüstungssets
@ElementList(type = String.class, entry = "set")
private List equipmentSets;
@Element
private String notes;
@Element
private byte[] image;
@Element
private Boolean primary;
@Element(name="mode")
protected String activeMode;
@Attribute(name="changes")
@AttribConvert(value=IntegerArrayConverter.class)
protected int[] modificationSlotChanges;
private transient PieceOfGearVariant variant;
private transient List allowedHooks;
/** Calculated item attributes */
private transient Map> attributes;
protected transient List requirements;
/** User added accessories */
@ElementList(entry="item",type=CarriedItem.class)
private List> accessories;
@ElementList(entry="enhancement",type=ItemEnhancementValue.class)
private List enhancements;
protected transient Lifeform user;
protected transient boolean isInitialized=false;
protected transient Map> slots;
protected transient List autoEnhancements;
protected transient List> alternates;
/** Item needs recalculation */
protected transient boolean dirty = true;
protected transient CarriedItem parent;
private transient OperationResult> lastRecalculateResult;
//-------------------------------------------------------------------
public CarriedItem() {
attributes = new HashMap>();
requirements = new ArrayList<>();
decisions = new ArrayList<>();
accessories = new ArrayList<>();
enhancements = new ArrayList<>();
autoEnhancements= new ArrayList();
alternates = new ArrayList<>();
allowedHooks = new ArrayList<>();
isInitialized = true;
slots = new HashMap<>();
this.uuid = UUID.randomUUID();
}
//-------------------------------------------------------------------
public CarriedItem(CarriedItem toCopy) {
super(toCopy.getResolved());
attributes = deepCopy(toCopy.attributes);
requirements = new ArrayList<>();
decisions = new ArrayList<>(toCopy.decisions);
accessories = new ArrayList<>();
enhancements = new ArrayList<>();
autoEnhancements= new ArrayList();
alternates = new ArrayList<>();
allowedHooks = new ArrayList<>();
isInitialized = true;
slots = new HashMap<>();
this.uuid = UUID.randomUUID();
}
//-------------------------------------------------------------------
public static Map> deepCopy(Map> old) {
HashMap> copy = new HashMap<>();
for (Map.Entry> entry : old.entrySet()) {
copy.put(entry.getKey(), (ItemAttributeValue) entry.getValue().clone());
}
return copy;
}
//-------------------------------------------------------------------
/**
* Use the item in NORMAL usage
*/
public CarriedItem(T item, PieceOfGearVariant> variant, CarryMode mode) {
super(item);
this.mode = mode;
if (variant!=null) {
this.variant = variant;
this.variantRef = variant.getId();
}
uuid = UUID.randomUUID();
attributes = new HashMap>();
requirements = new ArrayList<>();
decisions = new ArrayList<>();
accessories = new ArrayList<>();
setResolved(item, variant);
enhancements = new ArrayList<>();
autoEnhancements= new ArrayList();
alternates = new ArrayList<>();
allowedHooks = new ArrayList<>();
isInitialized = true;
slots = new HashMap<>();
}
//-------------------------------------------------------------------
public String toString() {
return "CarriedItem("+getKey()+")";
}
//-------------------------------------------------------------------
public String getNameWithoutRating(Locale loc) {
// User defined name gets precedence
if (customName!=null) return customName;
// Lookup real items name
if (resolved==null)
return ref;
//String decString = decisions.isEmpty()?"":getDecisionString(loc);
String baseName = resolved.getName(loc);//+" "+decString;
if (variant!=null) {
// If the variant is optional, add the variants name in brackets
if (!resolved.requiresVariant()) {
return baseName+" ("+variant.getName(loc)+")";
}
// Otherwise use full name
return variant.getName(loc);
}
return baseName;
}
//-------------------------------------------------------------------
@Override
public String getNameWithoutRating() {
return getNameWithoutRating(Locale.getDefault());
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.data.ComplexDataItemValue#getNameWithRating(java.util.Locale)
*/
@Override
public String getNameWithRating(Locale loc) {
String baseName = getNameWithoutRating(loc);
if (getDecision(UUID.fromString("c2d17c87-1cfe-4355-9877-a20fe09c170d"))!=null) {
return baseName + " "+ getDecision(UUID.fromString("c2d17c87-1cfe-4355-9877-a20fe09c170d")).getValueAsInt();
}
if (value==0) return baseName;
return baseName+" "+value;
}
//-------------------------------------------------------------------
public String getNameWithCount(Locale loc) {
if (count>1)
return getNameWithRating(loc)+" ("+count+"x)";
return getNameWithRating(loc);
}
//-------------------------------------------------------------------
public String getTemplateID() {
return getKey();
}
//-------------------------------------------------------------------
public void setResolved(T template, PieceOfGearVariant variant) {
this.resolved = template;
this.variant = variant;
if (variant!=null) {
this.variantRef = variant.getId();
}
if (isInitialized) {
refresh();
}
}
//-------------------------------------------------------------------
private void refresh() {
logger.log(Level.TRACE, "START: refresh() "+uuid+" "+ref);
try {
attributes.clear();
requirements.clear();
allowedHooks.clear();
GearTool.recalculate("", this.getResolved().getReferenceType(), user, this);
} finally {
logger.log(Level.TRACE, "STOP : refresh() "+uuid+" "+ref);
}
}
//-------------------------------------------------------------------
public Collection> getAttributes() {
return attributes.values();
}
//-------------------------------------------------------------------
public Collection getAttributeKeys() {
return attributes.keySet();
}
//-------------------------------------------------------------------
public ItemAttributeNumericalValue getAsValue(A attrib) {
if (attributes.get(attrib)==null)
return null;
if (attributes.get(attrib) instanceof ItemAttributeNumericalValue)
return (ItemAttributeNumericalValue) attributes.get(attrib);
throw new ClassCastException("getAsValue() is the wrong method for "+attributes.get(attrib).getClass().getSimpleName()+"="+attributes.get(attrib));
}
//-------------------------------------------------------------------
public boolean isFloat(A attrib) {
if (attributes.get(attrib)==null)
return false;
return (attributes.get(attrib) instanceof ItemAttributeFloatValue);
}
//-------------------------------------------------------------------
public ItemAttributeFloatValue getAsFloat(A attrib) {
if (attributes.get(attrib)==null)
return null;
if (attributes.get(attrib) instanceof ItemAttributeFloatValue)
return (ItemAttributeFloatValue) attributes.get(attrib);
throw new ClassCastException("getAsFloat() is the wrong method for "+attributes.get(attrib).getClass().getSimpleName()+"="+attributes.get(attrib));
}
//-------------------------------------------------------------------
public ItemAttributeObjectValue getAsObject(A attrib) {
return (ItemAttributeObjectValue) attributes.get(attrib);
}
//-------------------------------------------------------------------
public void setDecisions(List val) {
this.decisions = val;
// refresh();
}
//-------------------------------------------------------------------
/**
* @return the uuid
*/
public UUID getUuid() {
return uuid;
}
//-------------------------------------------------------------------
public void setAttribute(IItemAttribute attrib, ItemAttributeValue val) {
//if (logger.isLoggable(Level.DEBUG)) logger.log(Level.DEBUG, "SetAttribute("+attrib+", "+val);
attributes.put(attrib, val);
if (attrib.name().equals("PRICE") && val instanceof ItemAttributeObjectValue)
throw new IllegalArgumentException("Should not be an object");
// if (attrib.name().equals("DAMAGE") && !val.getClass().getSimpleName().equals("Damage"))
// throw new IllegalArgumentException("Should be a Damage object");
}
//-------------------------------------------------------------------
public ItemAttributeValue> getAttributeRaw(IItemAttribute key) {
return attributes.get(key);
}
//-------------------------------------------------------------------
public String dump() {
StringBuffer buf = new StringBuffer(uuid+"");
for (ItemAttributeValue attr : attributes.values()) {
buf.append("\n "+attr.getModifyable()+" : "+attr+" = "+attr.getClass());
}
buf.append("\nSlots\n");
for (AAvailableSlot, ?> slot : this.slots.values()) {
buf.append(String.format(" %20s \t%s\n", slot.getHook(), slot));
}
return buf.toString();
}
//-------------------------------------------------------------------
/**
* @return the variantRef
*/
public String getVariantID() {
return variantRef;
}
//-------------------------------------------------------------------
/**
* @return the variant
*/
public PieceOfGearVariant getVariant() {
return variant;
}
//-------------------------------------------------------------------
/**
* @param variant the variant to set
*/
public void setVariant(PieceOfGearVariant variant) {
this.variant = variant;
}
//-------------------------------------------------------------------
public void addRequirement(Requirement req) {
requirements.add(req);
}
//-------------------------------------------------------------------
public List getRequirements() {
return new ArrayList(requirements);
}
//-------------------------------------------------------------------
/**
* @return the count
*/
public int getCount() {
if (count==0) return 1;
return count;
}
//-------------------------------------------------------------------
/**
* @param count the count to set
*/
public void setCount(int count) {
this.count = count;
}
//-------------------------------------------------------------------
/**
* @return the user
*/
public Lifeform getUser() {
return user;
}
//-------------------------------------------------------------------
/**
* @param user the user to set
*/
public void setUser(Lifeform user) {
this.user = user;
}
//-------------------------------------------------------------------
public void addAccessory(CarriedItem val, Hook slot) {
if (getSlot(slot)==null)
throw new NullPointerException("No slot "+slot+" in item "+getKey());
if (val.getUuid()!=null) {
for (CarriedItem already : accessories) {
if (val.getUuid().equals(already.getUuid()))
throw new RuntimeException("Already added");
}
}
logger.log(Level.INFO, "Add accessory ''{0}'' to slot {1}", val.getKey(), slot);
val.setUsedSlot(slot);
val.parent = this;
accessories.add(val);
getSlot(slot).addEmbeddedItem(val);
}
//-------------------------------------------------------------------
public boolean removeAccessory(CarriedItem val, Hook slot) {
boolean notFound = true;
if (val.getUuid()!=null) {
for (CarriedItem already : accessories) {
if (val.getUuid().equals(already.getUuid()) || val==already)
notFound = false;
}
}
if (notFound) {
for (CarriedItem already : accessories) {
if (val==already)
notFound = false;
}
}
if (notFound) {
logger.log(Level.ERROR, "{0}: No item Removed {1} with UUID {3} in {2}", getKey(), val, slot, val.getUuid());
return false;
}
val.setUsedSlot(null);
val.parent = null;
accessories.remove(val);
slots.get(slot).removeEmbeddedItem(val);
logger.log(Level.DEBUG, "{0}: Removed {1} from {2}", getKey(), val, slot);
return true;
}
//-------------------------------------------------------------------
public List> getAccessories() {
return accessories;
}
//-------------------------------------------------------------------
public List> getAccessory(String id, String variant) {
List> ret = new ArrayList<>();
for (CarriedItem tmp : getEffectiveAccessories()) {
if (!tmp.getKey().equals(id))
continue;
if (variant!=null && !variant.equals(tmp.getVariantID()))
continue;
ret.add(tmp);
}
// for (AAvailableSlot,T> slot : getSlots()) {
// for (CarriedItem tmp : slot.getAllEmbeddedItems()) {
// if (!tmp.getKey().equals(id))
// continue;
// if (variant!=null && !variant.equals(tmp.getVariantID()))
// continue;
// ret.add(tmp);
// }
// }
return ret;
}
//-------------------------------------------------------------------
public Collection> getEffectiveAccessories() {
List> ret = new ArrayList>();
for (CarriedItem tmp : accessories) {
ret.add(tmp);
ret.addAll(tmp.getEffectiveAccessories());
}
return ret;
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.data.ComplexDataItemValue#reset()
*/
@Override
public void reset() {
super.reset();
clearModificationsFromCharacter();
clearOutgoingModifications();
autoEnhancements.clear();
slots.clear();
// Remove auto-added accessories
for (CarriedItem tmp : new ArrayList(accessories)) {
if ("DEFAULT".equals(tmp.getInjectedBy())) {
accessories.remove(tmp);
}
}
// Remove all modifications from item attributes
for (ItemAttributeValue attr : attributes.values()) {
attr.clearIncomingModifications();
}
clearIncomingModifications();
// Remove dynamic flags
autoFlags.clear();
}
//-------------------------------------------------------------------
public > A getSlot(Hook slot) {
return (A) slots.get(slot);
}
//-------------------------------------------------------------------
public Collection> getSlots() {
return slots.values();
}
//-------------------------------------------------------------------
public void addSlot(AAvailableSlot slot) {
// logger.log(Level.ERROR, "#######ADD SLOT "+slot);
// try {
// throw new Exception("Trace");
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// System.exit(1);
if (slots.containsKey(slot.getHook()))
throw new IllegalStateException("Hook "+slot+" already exists");
slots.put(slot.getHook(), slot);
}
//-------------------------------------------------------------------
public void removeSlot(Hook hook) {
slots.remove(hook);
}
//-------------------------------------------------------------------
/**
* @return the slot
*/
public Hook getUsedSlot() {
return slot;
}
//-------------------------------------------------------------------
/**
* @param slot the slot to set
*/
public void setUsedSlot(Hook slot) {
this.slot = slot;
}
//-------------------------------------------------------------------
/**
* @return the mode
*/
public CarryMode getCarryMode() {
return mode;
}
//-------------------------------------------------------------------
/**
* @param mode the mode to set
*/
public void setCarryMode(CarryMode mode) {
this.mode = mode;
}
//-------------------------------------------------------------------
/**
* @return the notes
*/
public String getNotes() {
return notes;
}
//-------------------------------------------------------------------
/**
* @param notes the notes to set
*/
public void setNotes(String notes) {
this.notes = notes;
}
//-------------------------------------------------------------------
public byte[] getImage() {
return image;
}
//-------------------------------------------------------------------
public void setImage(byte[] image) {
this.image = image;
}
//-------------------------------------------------------------------
public boolean hasAttribute(IItemAttribute key) {
return attributes.containsKey(key);
}
//-------------------------------------------------------------------
/**
* @return the dirty
*/
public boolean isDirty() {
return dirty;
}
//-------------------------------------------------------------------
/**
* @param dirty the dirty to set
*/
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
//-------------------------------------------------------------------
public CarriedItem getEmbeddedItem(String id) {
for (CarriedItem tmp : getEffectiveAccessories()) {
if (tmp.getKey().equals(id))
return tmp;
}
return null;
}
//-------------------------------------------------------------------
public List getOperationModes(boolean recursive) {
List options = new ArrayList<>();
@SuppressWarnings("unchecked")
List modes = getResolved().getOperationModes();
if (!modes.isEmpty()) {
OperationModeOption option = new OperationModeOption(this, modes) ;
options.add( option);
}
// Recurse accessories
if (recursive) {
for (CarriedItem> acc : getAccessories()) {
options.addAll(acc.getOperationModes(true));
}
}
return new ArrayList(options);
}
//-------------------------------------------------------------------
public List getActiveOperationModes(boolean recursive) {
List ret = new ArrayList<>();
if (mode!=null) {
List modes = getResolved().getOperationModes();
for (OperationMode tmp : modes) {
if (tmp.id.equals(activeMode)) {
ret.add(tmp);
}
}
}
// Recurse accessories
if (recursive) {
for (CarriedItem> acc : getAccessories()) {
ret.addAll(acc.getActiveOperationModes(true));
}
}
return ret;
}
//-------------------------------------------------------------------
public void setMode(OperationMode mode, boolean active) {
if (!active) {
if (mode.getId().equals(activeMode)) {
activeMode = null;
dirty = true;
}
return;
}
List modes = getResolved().getOperationModes();
for (OperationMode tmp : modes) {
if (tmp==mode) {
activeMode = mode.id;
dirty = true;
break;
}
}
}
//-------------------------------------------------------------------
public void addAutoEnhancement(ItemEnhancementValue value) {
autoEnhancements.add(value);
}
//-------------------------------------------------------------------
public List> getEnhancements() {
List> ret = new ArrayList<>();
autoEnhancements.forEach(e -> ret.add(e));
enhancements.forEach(e -> ret.add(e));
return ret;
}
//-------------------------------------------------------------------
@SuppressWarnings("unchecked")
public ItemEnhancementValue getEnhancement(E data) {
for (ItemEnhancementValue val : enhancements) {
if (val.getResolved()==data)
return val;
}
return null;
}
//-------------------------------------------------------------------
public boolean hasEnhancement(AItemEnhancement value) {
return getEnhancements().stream().anyMatch(e -> e.getResolved().equals(value));
}
//-------------------------------------------------------------------
public void addEnhancement(ItemEnhancementValue value) {
enhancements.add(value);
dirty = true;
}
//-------------------------------------------------------------------
public void removeEnhancement(ItemEnhancementValue value) {
enhancements.remove(value);
dirty = true;
}
//-------------------------------------------------------------------
public int getModificationSlotsUsed() {
int capacityUsed = 0;
for (ItemEnhancementValue extends AItemEnhancement> tmp : getEnhancements()) {
if (!tmp.isAutoAdded())
capacityUsed+= tmp.getResolved().getSize();
}
return capacityUsed;
}
//-------------------------------------------------------------------
public List> getAlternates() {
return alternates;
}
//-------------------------------------------------------------------
public void addAlternates(CarriedItem> alt) {
this.alternates.add(alt);
}
//-------------------------------------------------------------------
public void clearAlternates() {
this.alternates.clear();
}
//-------------------------------------------------------------------
/**
* @see de.rpgframework.genericrpg.data.IReferenceResolver#resolveItem(java.lang.String)
*/
@Override
public T resolveItem(String key) {
return ((IReferenceResolver)resolved).resolveItem(key);
}
//-------------------------------------------------------------------
public CarriedItem getParent() {
return parent;
}
public void setParent(CarriedItem parent) { this.parent = parent; }
//-------------------------------------------------------------------
/**
* @return the modificationSlotChanges
*/
public int[] getModificationSlotChanges() {
return modificationSlotChanges;
}
//-------------------------------------------------------------------
/**
* @param modificationSlotChanges the modificationSlotChanges to set
*/
public void setModificationSlotChanges(int[] modificationSlotChanges) {
this.modificationSlotChanges = modificationSlotChanges;
}
//-------------------------------------------------------------------
public void setLastRecalculateResult(OperationResult> unprocessed) {
this.lastRecalculateResult = unprocessed;
}
//-------------------------------------------------------------------
public OperationResult> getLastRecalculateResult() {
return this.lastRecalculateResult;
}
//-------------------------------------------------------------------
public void clearModificationsFromCharacter() {
for (ItemAttributeValue> val : attributes.values()) {
val.removeIncomingModifications(Origin.OUTSIDE);
}
}
// //-------------------------------------------------------------------
// /**
// * @see de.rpgframework.genericrpg.modification.Modifyable#setIncomingModifications(java.util.List)
// */
// @Override
// public void removeIncomingModification(Modification mod) {
// super.removeIncomingModification(mod);
// dirty = true;
// }
//-------------------------------------------------------------------
public void addModificationFromCharacter(ValueModification mod) {
mod.setOrigin(Origin.OUTSIDE);
ItemAttributeValue> val = getAttributeRaw( (IItemAttribute)mod.getResolvedKey());
if (val==null) {
logger.log(Level.ERROR, "Trying to add modification to unknown attribute {0} in {1}",mod.getResolvedKey(), this.getKey());
}
val.addIncomingModification(mod);
}
//-------------------------------------------------------------------
public List getAllowedHooks() {
return allowedHooks;
}
//-------------------------------------------------------------------
public void setAllowedHooks(Collection value) {
allowedHooks.clear();
allowedHooks.addAll(value);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy