package net.sourceforge.pain.data; import net.sourceforge.pain.db.*; import net.sourceforge.pain.*; import net.sourceforge.pain.logic.*; /* Affect with information of its start and end time time tracking routines are provided by codebase */ public class TimedAffectData extends AffectData { private static int AFFECT_START_TIME = LAST_BASE_FIELD_INDEX + 1; private static int AFFECT_END_TIME = LAST_BASE_FIELD_INDEX + 2; private static int GREATER_END_TIME = LAST_BASE_FIELD_INDEX + 3; private static int LOWER_END_TIME = LAST_BASE_FIELD_INDEX + 4; private static int STARTED = LAST_BASE_FIELD_INDEX + 5; protected static int TA_LAST_BASE_FIELD_INDEX = STARTED; /** * Class that will handle affect start and stop events */ private static int NFIELDS = TA_LAST_BASE_FIELD_INDEX + 1; /** * used on startup by db */ public TimedAffectData() { } public TimedAffectData(final PainDB db, Role role, Class affectImplClass, int affectTypeId, int duration) throws Exception { super(db, role, affectImplClass, affectTypeId); if (!TimedAffect.class.isAssignableFrom(affectImplClass)) { throw new IllegalArgumentException("Illegal affect impl class!"); } final int time = Core.getTime().getTime(); setInt(AFFECT_START_TIME, time); if (duration < 0) { setInt(AFFECT_END_TIME, -1); } else { setInt(AFFECT_END_TIME, time + duration); } addToOffQueue(); } protected DbClassSchema provideSchema() { byte types[] = new byte[NFIELDS]; String names[] = new String[NFIELDS]; fillSuperSchema(types, names); return new DbClassSchema(types, names); } protected void fillSuperSchema(byte[] types, String[] names) { super.fillSuperSchema(types, names); types[AFFECT_START_TIME] = DbType.INT; names[AFFECT_START_TIME] = "start_time"; types[AFFECT_END_TIME] = DbType.INT; names[AFFECT_END_TIME] = "end_time"; types[GREATER_END_TIME] = DbType.REFERENCE; names[GREATER_END_TIME] = "greater_end_affect"; types[LOWER_END_TIME] = DbType.REFERENCE; names[LOWER_END_TIME] = "lower_end_affect"; types[STARTED] = DbType.BOOLEAN; names[STARTED] = "started"; } private void addToOffQueue() { int off = getAffectOffTime(); //handling off time (-1 == never off -> do not add such affect to timer queue) if (off == -1) { return; } TimedAffectsQueue tq = getAffectsQueue(); TimedAffectData aff = tq.getLastOff(); while (aff != null && aff.getAffectOffTime() > off) { aff = aff.getPrevOff(); } if (aff != null) { TimedAffectData nextOff = aff.getNextOff(); _setNextOff(nextOff); _setPrevOff(aff); if (nextOff != null) { nextOff._setPrevOff(this); } else { // lastOff tq.setLastOff(this); } aff._setNextOff(this); } else { // firstOff final TimedAffectData firstOff = tq.getFirstOff(); _setNextOff(firstOff); _setPrevOff(null); tq.setFirstOff(this); if (firstOff == null) { tq.setLastOff(this); } else { firstOff._setPrevOff(this); } } } private TimedAffectsQueue getAffectsQueue() { return Core.getWorld().getAffectsQueue(); } private void _setPrevOff(TimedAffectData prevOff) { setReference(LOWER_END_TIME, prevOff); } private void _setNextOff(TimedAffectData nextOff) { setReference(GREATER_END_TIME, nextOff); } public final int getAffectOnTime() { return getInt(AFFECT_START_TIME); } public final int getAffectOffTime() { return getInt(AFFECT_END_TIME); } public final TimedAffectData getNextOff() { return (TimedAffectData) getReference(GREATER_END_TIME); } public final TimedAffectData getPrevOff() { return (TimedAffectData) getReference(LOWER_END_TIME); } public final void setAffectOffTime(int offTime) { int oldOff = getAffectOffTime(); if (oldOff == offTime) { return; } if (oldOff != -1) { removeFromOffQueue(); } setInt(AFFECT_END_TIME, offTime >= 0 ? offTime : -1); if (offTime >= 0) { addToOffQueue(); } } private void removeFromOffQueue() { TimedAffectData nextOff = getNextOff(); TimedAffectData prevOff = getPrevOff(); TimedAffectsQueue tq = Core.getWorld().getAffectsQueue(); if (nextOff == null) { tq.setLastOff(prevOff); } else { nextOff._setPrevOff(prevOff); } if (prevOff == null) { tq.setFirstOff(nextOff); } else { prevOff._setNextOff(nextOff); } } public void delete() { if (getAffectOffTime() != -1) { removeFromOffQueue(); } super.delete(); } }