First iteration of attributes revision

This commit is contained in:
Collin Smith
2020-09-01 23:47:16 -07:00
parent b1ddb912fe
commit fc01a7dea9
11 changed files with 1692 additions and 0 deletions

View File

@ -0,0 +1,43 @@
package com.riiablo.attributes;
public class AggregateAttributes extends Attributes {
final StatList base = StatList.obtain(1);
final StatList agg = StatList.obtain(1);
final StatList rem = StatList.obtain(1);
@Override
public StatList base() {
return base;
}
@Override
public StatList aggregate() {
return agg;
}
@Override
public StatList remaining() {
return rem;
}
@Override
public void resetToBase() {
assert base.numLists() == 1;
agg.setAll(base);
//mod.clear();
rem.clear();
super.clear();
}
/**
* {@inheritDoc}, {@link #base()}, {@link #aggregate()}, and {@link #remaining()}
*/
@Override
public void clear() {
base.clear();
agg.clear();
//mod.clear();
rem.clear();
super.clear();
}
}

View File

@ -0,0 +1,136 @@
package com.riiablo.attributes;
import android.support.annotation.CallSuper;
import java.util.Iterator;
import org.apache.commons.collections4.IteratorUtils;
public abstract class Attributes implements Iterable<StatGetter> {
/**
* an arithmetic association of StatList
*
* item property lists will be frozen after creation
* base stats should be mutable for players, monsters
*
* descriptions
*/
public static AggregateAttributes fixedAttributes() {
return new AggregateAttributes();
}
public static GemAttributes gemAttributes() {
return new GemAttributes();
}
public static StatListWrapper wrappedAttributes(StatList stats) {
return new StatListWrapper(stats);
}
private StatList stats;
Attributes() {
this.stats = StatList.obtain();
}
Attributes(StatList stats) {
this.stats = stats;
}
/**
* Returns the number of properties contained within {@link #aggregate()}.
*/
public int size() {
return aggregate().size();
}
/**
* Returns the whether or not {@link #aggregate()} contains any properties.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns the property list containing intrinsic traits of the attributes.
*
* @see #aggregate()
* @see #remaining()
* @see #list()
*/
public StatList base() {
return list();
}
/**
* Returns the property list containing properties from {@link #list() list}
* that were applied onto {@link #base() base}.
*
* @see #base()
* @see #remaining()
* @see #list()
*/
public StatList aggregate() {
return list();
}
/**
* Returns the property list containing properties from {@link #list() list}
* that were applied onto {@link #base() base}, but could not be
* {@link #aggregate() aggregated}.
*
* @see #base()
* @see #aggregate()
* @see #list()
*/
public StatList remaining() {
return list();
}
/**
* Returns the property list associated with this attributes. These
* properties will be applied onto {@link #base() base} and the result will
* be {@link #aggregate() aggregated}, with any unused properties being
* {@link #remaining() remaining}.
*
* @see #base()
* @see #aggregate()
* @see #remaining()
*/
public StatList list() {
return stats;
}
/**
* Returns the <i>nth</i> list within {@link #list()}.
*/
public StatListGetter list(int list) {
final StatList stats = list();
assert stats.contains(list) : "list(" + list + ") does not exist: numLists(" + stats.numLists() + ")";
return stats.get(list);
}
/**
* Clears {@link #remaining()} and sets {@link #aggregate()} equal to
* {@link #base()}.
*/
public void resetToBase() {}
/**
* Clears {@link #list()}
*/
@CallSuper
public void clear() {
stats.clear();
}
/**
* Returns an iterator over the {@link #aggregate() aggregate} properties.
*/
@Override
public Iterator<StatGetter> iterator() {
final StatList agg = aggregate();
final int numLists = agg.numLists();
if (numLists < 1) return IteratorUtils.emptyIterator();
return agg.statIterator(0);
}
}

View File

@ -0,0 +1,19 @@
package com.riiablo.attributes;
public class Fixed {
public static int floatToIntBits(float value, int precision) {
return (int) (value * (1 << precision));
}
public static float intBitsToFloat(int value, int precision) {
final int pow2 = (1 << precision);
final int mask = pow2 - 1;
return ((value >>> precision) + ((value & mask) / (float) pow2));
}
public static int intBitsToFloatFloor(int value, int precision) {
return value >>> precision;
}
private Fixed() {}
}

View File

@ -0,0 +1,16 @@
package com.riiablo.attributes;
import com.riiablo.item.Item;
public class GemAttributes extends Attributes {
private static final int NUM_GEMPROPS = Item.NUM_GEMPROPS; // TODO: move this somewhere else
GemAttributes() {
super(StatList.obtain(NUM_GEMPROPS));
}
@Override
public void resetToBase() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,388 @@
package com.riiablo.attributes;
@SuppressWarnings("unused")
public class Stat {
public static final short strength = 0;
public static final short energy = 1;
public static final short dexterity = 2;
public static final short vitality = 3;
public static final short statpts = 4;
public static final short newskills = 5;
public static final short hitpoints = 6;
public static final short maxhp = 7;
public static final short mana = 8;
public static final short maxmana = 9;
public static final short stamina = 10;
public static final short maxstamina = 11;
public static final short level = 12;
public static final short experience = 13;
public static final short gold = 14;
public static final short goldbank = 15;
public static final short item_armor_percent = 16;
public static final short item_maxdamage_percent = 17;
public static final short item_mindamage_percent = 18;
public static final short tohit = 19;
public static final short toblock = 20;
public static final short mindamage = 21;
public static final short maxdamage = 22;
public static final short secondary_mindamage = 23;
public static final short secondary_maxdamage = 24;
public static final short damagepercent = 25;
public static final short manarecovery = 26;
public static final short manarecoverybonus = 27;
public static final short staminarecoverybonus = 28;
public static final short lastexp = 29;
public static final short nextexp = 30;
public static final short armorclass = 31;
public static final short armorclass_vs_missile = 32;
public static final short armorclass_vs_hth = 33;
public static final short normal_damage_reduction = 34;
public static final short magic_damage_reduction = 35;
public static final short damageresist = 36;
public static final short magicresist = 37;
public static final short maxmagicresist = 38;
public static final short fireresist = 39;
public static final short maxfireresist = 40;
public static final short lightresist = 41;
public static final short maxlightresist = 42;
public static final short coldresist = 43;
public static final short maxcoldresist = 44;
public static final short poisonresist = 45;
public static final short maxpoisonresist = 46;
public static final short damageaura = 47;
public static final short firemindam = 48;
public static final short firemaxdam = 49;
public static final short lightmindam = 50;
public static final short lightmaxdam = 51;
public static final short magicmindam = 52;
public static final short magicmaxdam = 53;
public static final short coldmindam = 54;
public static final short coldmaxdam = 55;
public static final short coldlength = 56;
public static final short poisonmindam = 57;
public static final short poisonmaxdam = 58;
public static final short poisonlength = 59;
public static final short lifedrainmindam = 60;
public static final short lifedrainmaxdam = 61;
public static final short manadrainmindam = 62;
public static final short manadrainmaxdam = 63;
public static final short stamdrainmindam = 64;
public static final short stamdrainmaxdam = 65;
public static final short stunlength = 66;
public static final short velocitypercent = 67;
public static final short attackrate = 68;
public static final short other_animrate = 69;
public static final short quantity = 70;
public static final short value = 71;
public static final short durability = 72;
public static final short maxdurability = 73;
public static final short hpregen = 74;
public static final short item_maxdurability_percent = 75;
public static final short item_maxhp_percent = 76;
public static final short item_maxmana_percent = 77;
public static final short item_attackertakesdamage = 78;
public static final short item_goldbonus = 79;
public static final short item_magicbonus = 80;
public static final short item_knockback = 81;
public static final short item_timeduration = 82;
public static final short item_addclassskills = 83;
public static final short unsentparam1 = 84;
public static final short item_addexperience = 85;
public static final short item_healafterkill = 86;
public static final short item_reducedprices = 87;
public static final short item_doubleherbduration = 88;
public static final short item_lightradius = 89;
public static final short item_lightcolor = 90;
public static final short item_req_percent = 91;
public static final short item_levelreq = 92;
public static final short item_fasterattackrate = 93;
public static final short item_levelreqpct = 94;
public static final short lastblockframe = 95;
public static final short item_fastermovevelocity = 96;
public static final short item_nonclassskill = 97;
public static final short state = 98;
public static final short item_fastergethitrate = 99;
public static final short monster_playercount = 100;
public static final short skill_poison_override_length = 101;
public static final short item_fasterblockrate = 102;
public static final short skill_bypass_undead = 103;
public static final short skill_bypass_demons = 104;
public static final short item_fastercastrate = 105;
public static final short skill_bypass_beasts = 106;
public static final short item_singleskill = 107;
public static final short item_restinpeace = 108;
public static final short curse_resistance = 109;
public static final short item_poisonlengthresist = 110;
public static final short item_normaldamage = 111;
public static final short item_howl = 112;
public static final short item_stupidity = 113;
public static final short item_damagetomana = 114;
public static final short item_ignoretargetac = 115;
public static final short item_fractionaltargetac = 116;
public static final short item_preventheal = 117;
public static final short item_halffreezeduration = 118;
public static final short item_tohit_percent = 119;
public static final short item_damagetargetac = 120;
public static final short item_demondamage_percent = 121;
public static final short item_undeaddamage_percent = 122;
public static final short item_demon_tohit = 123;
public static final short item_undead_tohit = 124;
public static final short item_throwable = 125;
public static final short item_elemskill = 126;
public static final short item_allskills = 127;
public static final short item_attackertakeslightdamage = 128;
public static final short ironmaiden_level = 129;
public static final short lifetap_level = 130;
public static final short thorns_percent = 131;
public static final short bonearmor = 132;
public static final short bonearmormax = 133;
public static final short item_freeze = 134;
public static final short item_openwounds = 135;
public static final short item_crushingblow = 136;
public static final short item_kickdamage = 137;
public static final short item_manaafterkill = 138;
public static final short item_healafterdemonkill = 139;
public static final short item_extrablood = 140;
public static final short item_deadlystrike = 141;
public static final short item_absorbfire_percent = 142;
public static final short item_absorbfire = 143;
public static final short item_absorblight_percent = 144;
public static final short item_absorblight = 145;
public static final short item_absorbmagic_percent = 146;
public static final short item_absorbmagic = 147;
public static final short item_absorbcold_percent = 148;
public static final short item_absorbcold = 149;
public static final short item_slow = 150;
public static final short item_aura = 151;
public static final short item_indesctructible = 152;
public static final short item_cannotbefrozen = 153;
public static final short item_staminadrainpct = 154;
public static final short item_reanimate = 155;
public static final short item_pierce = 156;
public static final short item_magicarrow = 157;
public static final short item_explosivearrow = 158;
public static final short item_throw_mindamage = 159;
public static final short item_throw_maxdamage = 160;
public static final short skill_handofathena = 161;
public static final short skill_staminapercent = 162;
public static final short skill_passive_staminapercent = 163;
public static final short skill_concentration = 164;
public static final short skill_enchant = 165;
public static final short skill_pierce = 166;
public static final short skill_conviction = 167;
public static final short skill_chillingarmor = 168;
public static final short skill_frenzy = 169;
public static final short skill_decrepify = 170;
public static final short skill_armor_percent = 171;
public static final short alignment = 172;
public static final short target0 = 173;
public static final short target1 = 174;
public static final short goldlost = 175;
public static final short conversion_level = 176;
public static final short conversion_maxhp = 177;
public static final short unit_dooverlay = 178;
public static final short attack_vs_montype = 179;
public static final short damage_vs_montype = 180;
public static final short fade = 181;
public static final short armor_override_percent = 182;
public static final short unused183 = 183;
public static final short unused184 = 184;
public static final short unused185 = 185;
public static final short unused186 = 186;
public static final short unused187 = 187;
public static final short item_addskill_tab = 188;
public static final short unused189 = 189;
public static final short unused190 = 190;
public static final short unused191 = 191;
public static final short unused192 = 192;
public static final short unused193 = 193;
public static final short item_numsockets = 194;
public static final short item_skillonattack = 195;
public static final short item_skillonkill = 196;
public static final short item_skillondeath = 197;
public static final short item_skillonhit = 198;
public static final short item_skillonlevelup = 199;
public static final short unused200 = 200;
public static final short item_skillongethit = 201;
public static final short unused202 = 202;
public static final short unused203 = 203;
public static final short item_charged_skill = 204;
public static final short unused204 = 205;
public static final short unused205 = 206;
public static final short unused206 = 207;
public static final short unused207 = 208;
public static final short unused208 = 209;
public static final short unused209 = 210;
public static final short unused210 = 211;
public static final short unused211 = 212;
public static final short unused212 = 213;
public static final short item_armor_perlevel = 214;
public static final short item_armorpercent_perlevel = 215;
public static final short item_hp_perlevel = 216;
public static final short item_mana_perlevel = 217;
public static final short item_maxdamage_perlevel = 218;
public static final short item_maxdamage_percent_perlevel = 219;
public static final short item_strength_perlevel = 220;
public static final short item_dexterity_perlevel = 221;
public static final short item_energy_perlevel = 222;
public static final short item_vitality_perlevel = 223;
public static final short item_tohit_perlevel = 224;
public static final short item_tohitpercent_perlevel = 225;
public static final short item_cold_damagemax_perlevel = 226;
public static final short item_fire_damagemax_perlevel = 227;
public static final short item_ltng_damagemax_perlevel = 228;
public static final short item_pois_damagemax_perlevel = 229;
public static final short item_resist_cold_perlevel = 230;
public static final short item_resist_fire_perlevel = 231;
public static final short item_resist_ltng_perlevel = 232;
public static final short item_resist_pois_perlevel = 233;
public static final short item_absorb_cold_perlevel = 234;
public static final short item_absorb_fire_perlevel = 235;
public static final short item_absorb_ltng_perlevel = 236;
public static final short item_absorb_pois_perlevel = 237;
public static final short item_thorns_perlevel = 238;
public static final short item_find_gold_perlevel = 239;
public static final short item_find_magic_perlevel = 240;
public static final short item_regenstamina_perlevel = 241;
public static final short item_stamina_perlevel = 242;
public static final short item_damage_demon_perlevel = 243;
public static final short item_damage_undead_perlevel = 244;
public static final short item_tohit_demon_perlevel = 245;
public static final short item_tohit_undead_perlevel = 246;
public static final short item_crushingblow_perlevel = 247;
public static final short item_openwounds_perlevel = 248;
public static final short item_kick_damage_perlevel = 249;
public static final short item_deadlystrike_perlevel = 250;
public static final short item_find_gems_perlevel = 251;
public static final short item_replenish_durability = 252;
public static final short item_replenish_quantity = 253;
public static final short item_extra_stack = 254;
public static final short item_find_item = 255;
public static final short item_slash_damage = 256;
public static final short item_slash_damage_percent = 257;
public static final short item_crush_damage = 258;
public static final short item_crush_damage_percent = 259;
public static final short item_thrust_damage = 260;
public static final short item_thrust_damage_percent = 261;
public static final short item_absorb_slash = 262;
public static final short item_absorb_crush = 263;
public static final short item_absorb_thrust = 264;
public static final short item_absorb_slash_percent = 265;
public static final short item_absorb_crush_percent = 266;
public static final short item_absorb_thrust_percent = 267;
public static final short item_armor_bytime = 268;
public static final short item_armorpercent_bytime = 269;
public static final short item_hp_bytime = 270;
public static final short item_mana_bytime = 271;
public static final short item_maxdamage_bytime = 272;
public static final short item_maxdamage_percent_bytime = 273;
public static final short item_strength_bytime = 274;
public static final short item_dexterity_bytime = 275;
public static final short item_energy_bytime = 276;
public static final short item_vitality_bytime = 277;
public static final short item_tohit_bytime = 278;
public static final short item_tohitpercent_bytime = 279;
public static final short item_cold_damagemax_bytime = 280;
public static final short item_fire_damagemax_bytime = 281;
public static final short item_ltng_damagemax_bytime = 282;
public static final short item_pois_damagemax_bytime = 283;
public static final short item_resist_cold_bytime = 284;
public static final short item_resist_fire_bytime = 285;
public static final short item_resist_ltng_bytime = 286;
public static final short item_resist_pois_bytime = 287;
public static final short item_absorb_cold_bytime = 288;
public static final short item_absorb_fire_bytime = 289;
public static final short item_absorb_ltng_bytime = 290;
public static final short item_absorb_pois_bytime = 291;
public static final short item_find_gold_bytime = 292;
public static final short item_find_magic_bytime = 293;
public static final short item_regenstamina_bytime = 294;
public static final short item_stamina_bytime = 295;
public static final short item_damage_demon_bytime = 296;
public static final short item_damage_undead_bytime = 297;
public static final short item_tohit_demon_bytime = 298;
public static final short item_tohit_undead_bytime = 299;
public static final short item_crushingblow_bytime = 300;
public static final short item_openwounds_bytime = 301;
public static final short item_kick_damage_bytime = 302;
public static final short item_deadlystrike_bytime = 303;
public static final short item_find_gems_bytime = 304;
public static final short item_pierce_cold = 305;
public static final short item_pierce_fire = 306;
public static final short item_pierce_ltng = 307;
public static final short item_pierce_pois = 308;
public static final short item_damage_vs_monster = 309;
public static final short item_damage_percent_vs_monster = 310;
public static final short item_tohit_vs_monster = 311;
public static final short item_tohit_percent_vs_monster = 312;
public static final short item_ac_vs_monster = 313;
public static final short item_ac_percent_vs_monster = 314;
public static final short firelength = 315;
public static final short burningmin = 316;
public static final short burningmax = 317;
public static final short progressive_damage = 318;
public static final short progressive_steal = 319;
public static final short progressive_other = 320;
public static final short progressive_fire = 321;
public static final short progressive_cold = 322;
public static final short progressive_lightning = 323;
public static final short item_extra_charges = 324;
public static final short progressive_tohit = 325;
public static final short poison_count = 326;
public static final short damage_framerate = 327;
public static final short pierce_idx = 328;
public static final short passive_fire_mastery = 329;
public static final short passive_ltng_mastery = 330;
public static final short passive_cold_mastery = 331;
public static final short passive_pois_mastery = 332;
public static final short passive_fire_pierce = 333;
public static final short passive_ltng_pierce = 334;
public static final short passive_cold_pierce = 335;
public static final short passive_pois_pierce = 336;
public static final short passive_critical_strike = 337;
public static final short passive_dodge = 338;
public static final short passive_avoid = 339;
public static final short passive_evade = 340;
public static final short passive_warmth = 341;
public static final short passive_mastery_melee_th = 342;
public static final short passive_mastery_melee_dmg = 343;
public static final short passive_mastery_melee_crit = 344;
public static final short passive_mastery_throw_th = 345;
public static final short passive_mastery_throw_dmg = 346;
public static final short passive_mastery_throw_crit = 347;
public static final short passive_weaponblock = 348;
public static final short passive_summon_resist = 349;
public static final short modifierlist_skill = 350;
public static final short modifierlist_level = 351;
public static final short last_sent_hp_pct = 352;
public static final short source_unit_type = 353;
public static final short source_unit_id = 354;
public static final short shortparam1 = 355;
public static final short questitemdifficulty = 356;
public static final short passive_mag_mastery = 357;
public static final short passive_mag_pierce = 358;
static final int BITS = 9;
static final short NONE = (1 << BITS) - 1; // 0x1FF
private static final byte[] ENCODED_COUNT = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, // 32
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 256
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 288
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 320
1, 1, 1, 1, 1, 1, 1, // 352
};
static byte getNumEncoded(short stat) {
return ENCODED_COUNT[stat];
}
private Stat() {}
}

View File

@ -0,0 +1,109 @@
package com.riiablo.attributes;
public final class StatGetter {
StatList stats;
int index;
StatGetter() {}
StatGetter(StatList stats) {
this.stats = stats;
}
StatGetter set(StatList stats, int index) {
this.stats = stats;
this.index = index;
return this;
}
StatGetter update(int index) {
assert stats != null;
this.index = index;
return this;
}
/** @see StatList#param(int) */
int param(short stat) {
return stats.param(index);
}
/** @see StatList#value(int) */
int value(short stat) {
return stats.value(index);
}
/** @see StatList#id(int) */
public short id() {
return stats.id(index);
}
/** @see StatList#asInt(int) */
public int asInt() {
return stats.asInt(index);
}
/** @see StatList#asLong(int) */
public long asLong() {
return stats.asLong(index);
}
/** @see StatList#asFixed(int) */
public float asFixed() {
return stats.asFixed(index);
}
/** @see StatList#asString(int) */
public String asString() {
return stats.asString(index);
}
/** @see StatList#indexDebugString(int) */
public String debugString() {
return stats.indexDebugString(index);
}
@Override
public String toString() {
return asString();
}
/** @see StatList#value1(int) */
public int value1() {
return stats.value1(index);
}
/** @see StatList#value2(int) */
public int value2() {
return stats.value2(index);
}
/** @see StatList#value3(int) */
public int value3() {
return stats.value3(index);
}
/** @see StatList#param1(int) */
public int param1() {
return stats.param1(index);
}
/** @see StatList#param2(int) */
public int param2() {
return stats.param2(index);
}
/** @see StatList#add(int, int) */
public void add(int value) {
stats.add(index, value);
}
/** @see StatList#add(int, long) */
public void add(long value) {
stats.add(index, value);
}
/** @see StatList#add(int, float) */
public void add(float value) {
stats.add(index, value);
}
}

View File

@ -0,0 +1,665 @@
package com.riiablo.attributes;
import io.netty.buffer.ByteBufUtil;
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.math.NumberUtils;
import com.riiablo.Riiablo;
import com.riiablo.codec.excel.ItemStatCost;
import com.riiablo.logger.LogManager;
import com.riiablo.logger.Logger;
public final class StatList {
private static final Logger log = LogManager.getLogger(StatList.class);
public static StatList obtain() {
return new StatList();
}
public static StatList obtain(int maxLists) {
return new StatList(maxLists);
}
private static final StatList EMPTY_LIST = new StatList().freeze();
public static StatList emptyList() {
return EMPTY_LIST;
}
private static final int MAX_LISTS = 8;
private static final int MAX_STATS = 32;
/** @see #encodeFlags */
private static final int ENCODING_MASK = (1 << 3) - 1;
private static final int FLAG_PARAMS = 1 << 3;
private static final int FLAG_FIXED = 1 << 4;
private static final int FLAG_LONG = 1 << 5;
private static final long UINT_MAX_VALUE = (1L << Integer.SIZE) - 1;
private final byte[] offsets;
private final short[] ids;
private final int[] params;
private final int[] values;
private final byte[] flags;
private int maxLists;
private int size;
private int tail;
private int numLists;
private boolean immutable;
private IndexIterator INDEX_ITERATOR;
private StatIterator STAT_ITERATOR;
StatList() {
this(MAX_LISTS);
}
StatList(int maxLists) {
log.traceEntry("StatList(maxLists: {})", maxLists);
assert maxLists > 0 : "maxLists(" + maxLists + ") <= " + 0;
this.maxLists = maxLists;
offsets = new byte[maxLists << 1];
ids = new short[MAX_STATS];
params = new int[MAX_STATS];
values = new int[MAX_STATS];
flags = new byte[MAX_STATS];
}
public StatList freeze() {
immutable = true;
return this;
}
public void clear() {
assertMutable();
size = 0;
tail = 0;
numLists = 0;
}
public int size() {
return size;
}
public int size(int list) {
return endingOffset(list) - startingOffset(list);
}
public boolean isEmpty(int list) {
return size(list) == 0;
}
public int numLists() {
return numLists;
}
public void clearList(int list) {
assertMutable();
size -= size(list);
final int offset = list << 1;
final byte[] offsets = this.offsets;
offsets[offset + 1] = offsets[offset];
}
public int newList(int capacity) {
assertMutable();
if (numLists >= maxLists) { // should never exceed maxLists
throw new AssertionError("numLists(" + numLists + ") >= maxLists(" + maxLists + ")");
}
if (tail + capacity >= MAX_STATS) {
throw new IllegalArgumentException("capacity(" + capacity + ") would exceed MAX_STATS(" + MAX_STATS + ")");
}
final int list = numLists;
final int offset = list << 1;
final byte[] offsets = this.offsets;
offsets[offset] = offsets[offset + 1] = (byte) tail;
numLists++;
ensureCapacity(list, capacity);
return list;
}
public StatListBuilder buildList() {
return buildList(0);
}
public StatListBuilder buildList(int capacity) {
assertMutable();
return new StatListBuilder(this, newList(capacity));
}
public void ensureCapacity(int list, int capacity) {
assertMutable();
final int startOffset = startingOffset(list);
final int endOffset = endingOffset(list);
final int nextStartOffset = (list + 1) < numLists ? startingOffset(list + 1) : MAX_STATS;
if (nextStartOffset - startOffset > capacity) {
if (tail == endOffset) tail += capacity;
return;
}
final int additionalCapacity = capacity - (nextStartOffset - endOffset);
if (tail + additionalCapacity >= MAX_STATS) {
throw new IllegalArgumentException("capacity(" + capacity + ") would exceed MAX_STATS(" + MAX_STATS + ")");
}
final int dstOffset = nextStartOffset + additionalCapacity;
final int length = tail - nextStartOffset;
System.arraycopy(ids, nextStartOffset, ids, dstOffset, length);
System.arraycopy(params, nextStartOffset, params, dstOffset, length);
System.arraycopy(values, nextStartOffset, values, dstOffset, length);
System.arraycopy(flags, nextStartOffset, flags, dstOffset, length);
tail += additionalCapacity;
final byte[] offsets = this.offsets;
final int listsSize = numLists << 1;
for (int i = ((list + 1) << 1); i < listsSize; i++) offsets[i] += additionalCapacity;
assert isSorted(offsets, 0, listsSize) : "offsets(" + ByteBufUtil.hexDump(offsets, 0, listsSize) + ") contains property lists that are out of order";
}
public StatList copy(int list, StatList src, int srcList) {
assertMutable();
final int length = src.size(srcList);
ensureCapacity(list, length);
final int srcListStart = src.startingOffset(srcList);
final int dstListStart = this.startingOffset(list);
System.arraycopy(src.ids, srcListStart, this.ids, dstListStart, length);
System.arraycopy(src.params, srcListStart, this.params, dstListStart, length);
System.arraycopy(src.values, srcListStart, this.values, dstListStart, length);
System.arraycopy(src.flags, srcListStart, this.flags, dstListStart, length);
size += length;
final byte[] offsets = this.offsets;
offsets[(list << 1) + 1] += length;
assert isSorted(offsets, 0, numLists << 1) : "offsets(" + ByteBufUtil.hexDump(offsets, 0, numLists << 1) + ") contains property lists that are out of order";
return this;
}
public StatList set(int list, StatList src, int srcList) {
assertMutable();
clearList(list);
copy(list, src, srcList);
return this;
}
public StatList setAll(StatList src) {
assertMutable();
clear();
final int length = src.tail;
System.arraycopy(src.offsets, 0, this.offsets, 0, src.numLists() << 1);
System.arraycopy(src.ids, 0, this.ids, 0, length);
System.arraycopy(src.params, 0, this.params, 0, length);
System.arraycopy(src.values, 0, this.values, 0, length);
System.arraycopy(src.flags, 0, this.flags, 0, length);
size = src.size;
tail = src.tail;
numLists = src.numLists;
return this;
}
public StatListGetter get(int list) {
return new StatListGetter(this, list);
}
public int add(int index, int value) {
assertMutable();
log.traceEntry("add(index: {}, value: {})", index, value);
final short stat = ids[index];
assert !hasParams(stat) : "stat(" + stat + ") requires params";
assert encoding(stat) <= 2 : "#add() unsupported for encoding(" + encoding(stat) + ")";
if (log.debugEnabled()) log.debug(
"add(stat: {} ({}), this: {}, src: {})",
stat, entry(stat), asString(index), _asString(index, value));
return values[index] += value;
}
public int add(int index, long value) {
return add(index, _asInt(value));
}
public int add(int index, float value) {
return add(index, _asInt(value));
}
public int add(int list, short stat, StatList src, int srcList) {
assertMutable();
log.traceEntry("add(list: {}, stat: {}, src: {}, srcList: {})", list, stat, src, srcList);
assert !hasParams(stat) : "stat(" + stat + ") requires params";
assert encoding(stat) <= 2 : "#add() unsupported for encoding(" + encoding(stat) + ")";
final int index = indexOf(list, stat, 0);
final int otherIndex = src.indexOf(srcList, stat, 0);
if (log.debugEnabled()) log.debug(
"add(stat: {} ({}), this: {}, src: {})",
stat, entry(stat), index >= 0 ? asString(index) : "null", src.asString(otherIndex));
if (index >= 0) {
values[index] += src.values[otherIndex];
return index;
} else {
/** TODO: possibility to speed this up with {@link #insertAt} */
final int putIndex = put(list, stat, src.values[otherIndex]);
assert putIndex == ~index : "index(" + putIndex + ") != expected index(" + ~index + ")";
return putIndex;
}
// max
}
public void addAll(int list, StatList src, int srcList) {
assertMutable();
final int srcStartOffset = src.startingOffset(srcList);
final int srcEndOffset = src.endingOffset(srcList);
for (int i = srcStartOffset, s = srcEndOffset; i < s; i++) {
final short stat = src.id(i);
add(list, stat, src, srcList);
}
}
/**
* @deprecated undefined behavior -- stat operations should be reversible,
* i.e., subtracting a stat to it's default should remove it.
* Validate that a value of 0 indicates default for all stats.
* Maybe some stats allow 0 value and nonzero param?
*/
@Deprecated
public boolean sub(int list, short stat, StatList src, int srcList) {
if (true) throw new UnsupportedOperationException();
assertMutable();
log.traceEntry("sub(list: {}, stat: {}, src: {}, srcList: {})", list, stat, src, srcList);
assert !hasParams(stat) : "stat(" + stat + ") requires params";
assert encoding(stat) <= 2 : "#sub() unsupported for encoding(" + encoding(stat) + ")";
final int index = indexOf(list, stat, 0);
final int otherIndex = src.indexOf(srcList, stat, 0);
if (log.debugEnabled()) log.debug(
"sub(stat: {} ({}), this: {}, src: {})",
stat, entry(stat), index >= 0 ? asString(index) : "null", src.asString(otherIndex));
assert index >= 0 : "property list does not contain stat(" + stat + ")";
if (index < 0) return false; // indefined behavior
values[index] -= src.values[otherIndex];
// TODO: if values[index] <= 0, remove it? is <= 0 appropriate
return true;
// min
}
/** @deprecated see {@link #sub} */
@Deprecated
public void subAll(int list, StatList src, int srcList) {
assertMutable();
final int srcStartOffset = src.startingOffset(srcList);
final int srcEndOffset = src.endingOffset(srcList);
for (int i = srcStartOffset, s = srcEndOffset; i < s; i++) {
final short stat = src.id(i);
sub(list, stat, src, srcList);
}
}
public int put(int list, short stat, int param, int value) {
assertMutable();
final ItemStatCost.Entry entry = entry(stat);
final int encoding = entry.Encode;
if (log.traceEnabled()) log.tracefEntry(
"put(stat: %d (%s), param: %d (0x%3$x), value: %d (0x%4$x))", stat, entry, param, value);
if (log.warnEnabled() && (encoding < 0 || encoding > 4)) log.warn(
"stat: {} ({}) has unsupported encoding({})", stat, entry, encoding);
final int index = indexOf(list, stat, param);
if (index >= 0) {
set(index, stat, param, value, entry);
if (log.debugEnabled()) log.debug(indexDebugString(index));
return index;
} else {
insertAt(list, ~index, stat, param, value, entry);
if (log.debugEnabled()) log.debug(indexDebugString(~index));
return ~index;
}
}
public int put(int list, short stat, int value) {
assert !hasParams(stat) : "stat(" + stat + ") requires params";
return put(list, stat, 0, value);
}
public int put(int list, short stat, long value) {
assert !hasParams(stat) : "stat(" + stat + ") requires params";
assert value <= UINT_MAX_VALUE : "value(" + value + ") > " + UINT_MAX_VALUE;
return put(list, stat, 0, _asInt(value));
}
public int put(int list, short stat, float value) {
assert !hasParams(stat) : "stat(" + stat + ") requires params";
assert entry(stat).ValShift == 8 : "entry.ValShift(" + entry(stat).ValShift + ") != " + 8;
return put(list, stat, 0, _asInt(value));
}
public boolean contains(int list) {
return list >= 0 && list < numLists;
}
public boolean contains(int list, short stat) {
return Arrays.binarySearch(ids, startingOffset(list), endingOffset(list), stat) >= 0;
}
public int indexOf(int list, short stat, int param) {
final int listStart = startingOffset(list);
final int listEnd = endingOffset(list);
final int index = Arrays.binarySearch(ids, listStart, listEnd, stat);
if (index >= 0) {
final int startIndex = firstIndexOf(stat, index, listStart);
final int endIndex = lastIndexOf(stat, index, listEnd);
return Arrays.binarySearch(params, startIndex, endIndex, param);
} else {
return index;
}
}
public int indexOf(int list, short stat) {
assert !hasParams(stat) : "stat(" + stat + ") requires params";
return indexOf(list, stat, 0);
}
private int firstIndexOf(final short stat, final int startIndex, final int listStart) {
int i = startIndex - 1;
final short[] ids = this.ids;
while (i >= listStart && ids[i] == stat) i--;
return i + 1;
}
private int lastIndexOf(final short stat, final int startIndex, final int listEnd) {
int i = startIndex + 1;
final short[] ids = this.ids;
for (final int s = listEnd; i < s && ids[i] == stat; i++);
return i;
}
int asInt(int index) {
return values[index];
}
private static int _asInt(long value) {
return (int) value;
}
private static long _asLong(int value) {
return value & UINT_MAX_VALUE;
}
long asLong(int index) {
assert entry(ids[index]).Send_Bits >= Integer.SIZE : "entry.Send_Bits(" + entry(ids[index]).Send_Bits + ") < " + Integer.SIZE;
return _asLong(values[index]);
}
private static int _asInt(float value) {
return Fixed.floatToIntBits(value, 8);
}
private static float _asFixed(int value) {
return Fixed.intBitsToFloat(value, 8);
}
float asFixed(int index) {
assert entry(ids[index]).ValShift == 8 : "entry.ValShift(" + entry(ids[index]).ValShift + ") != " + 8;
return _asFixed(values[index]);
}
private String _asString(int index, int value) {
final byte flags = this.flags[index];
return (flags & FLAG_FIXED) == 0
? (flags & FLAG_LONG) == 0
? String.valueOf(value)
: String.valueOf(_asLong(value))
: String.valueOf(_asFixed(value));
}
String asString(int index) {
final byte flags = this.flags[index];
return (flags & FLAG_FIXED) == 0
? (flags & FLAG_LONG) == 0
? String.valueOf(asInt(index))
: String.valueOf(asLong(index))
: String.valueOf(asFixed(index));
}
public short id(int index) {
return ids[index];
}
public int encoding(int index) {
return flags[index] & ENCODING_MASK;
}
byte flags(int index) {
return flags[index];
}
int value(int index) {
return values[index];
}
int param(int index) {
return params[index];
}
public int value1(int index) {
switch (encoding(index)) {
default: // fall-through
case 0: return values[index];
case 1: return values[index];
case 2: return values[index];
case 3: return values[index] & 0xFF;
case 4: return values[index] & 0x3;
}
}
public int value2(int index) {
switch (encoding(index)) {
default: // fall-through
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return (values[index] >>> 8) & 0xFF;
case 4: return (values[index] >>> 2) & 0x3FF;
}
}
public int value3(int index) {
switch (encoding(index)) {
default: // fall-through
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return 0;
case 4: return (values[index] >>> 12) & 0x3FF;
}
}
public int param1(int index) {
switch (encoding(index)) {
default: // fall-through
case 0: return params[index];
case 1: return params[index];
case 2: return params[index] & 0x3F;
case 3: return params[index] & 0x3F;
case 4: return params[index];
}
}
public int param2(int index) {
switch (encoding(index)) {
default: // fall-through
case 0: return 0;
case 1: return 0;
case 2: return (params[index] >>> 6) & 0x3FF;
case 3: return (params[index] >>> 6) & 0x3FF;
case 4: return 0;
}
}
private int startingOffset(int list) {
return offsets[(list << 1)] & 0xFF;
}
private int endingOffset(int list) {
return offsets[(list << 1) + 1] & 0xFF;
}
private static boolean isSorted(final byte[] array, final int startIndex, final int endIndex) {
if (endIndex - startIndex < 2) return true;
byte previous = array[startIndex];
for (int i = startIndex + 1; i < endIndex; i++) {
final byte current = array[i];
if (NumberUtils.compare(previous, current) > 0) {
return false;
}
previous = current;
}
return true;
}
private static byte encodeFlags(ItemStatCost.Entry entry) {
byte flags = (byte) (entry.Encode & ENCODING_MASK);
if (entry.Save_Param_Bits > 0) flags |= FLAG_PARAMS;
if (entry.Send_Bits >= Integer.SIZE) flags |= FLAG_LONG;
if (entry.ValShift > 0) flags |= FLAG_FIXED;
return flags;
}
private void set(int index, short stat, int param, int value, ItemStatCost.Entry entry) {
if (log.traceEnabled()) log.tracefEntry(
"set(index: %d, stat: %d (%s), param: %d (0x%4$x), value: %d (0x%5$x))", index, stat, entry, param, value);
ids[index] = stat;
params[index] = param;
values[index] = value;
flags[index] = encodeFlags(entry);
}
private void insertAt(int list, int index, short stat, int param, int value, ItemStatCost.Entry entry) {
if (log.traceEnabled()) log.tracefEntry(
"insertAt(index: %d, stat: %d (%s), param: %d (0x%4$x), value: %d (0x%5$x))", index, stat, entry, param, value);
if (size >= MAX_STATS) {
log.warn("stat(" + stat + ") cannot be inserted, property list is full!");
return;
}
ensureCapacity(list, 1);
set(index, stat, param, value, entry);
size++;
final byte[] offsets = this.offsets;
offsets[(list << 1) + 1]++;
final int listsSize = numLists << 1;
for (int i = ((list + 1) << 1); i < listsSize; i++) offsets[i]++;
assert isSorted(offsets, 0, listsSize) : "offsets(" + Arrays.toString(offsets) + ") contains property lists that are out of order";
}
private void assertMutable() {
if (immutable) throw new UnsupportedOperationException("Stat list has been frozen");
}
public String indexDebugString(int index) {
final byte flags = this.flags[index];
switch (flags & ENCODING_MASK) {
default: // fall-through
case 0: return entry(ids[index]) + "(" + ids[index] + ")=" + ((flags & FLAG_PARAMS) == 0 ? asString(index) : (asString(index) + ":" + params[index]));
case 1: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + value1(index);
case 2: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + param2(index) + ":" + value1(index);
case 3: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + param2(index) + ":" + value1(index) + ":" + value2(index);
case 4: return entry(ids[index]) + "(" + ids[index] + ")=" + value1(index) + ":" + value2(index) + ":" + value3(index);
}
}
public String listDebugString(int list) {
final int startIndex = startingOffset(list);
final int endIndex = endingOffset(list);
return new ToStringBuilder(this)
.append("immutable", immutable)
.append("offsets", '{' + StringUtils.join(offsets, ',', (list << 1), (list << 1) + 2) + '}')
.append("ids", '{' + StringUtils.join(ids, ',', startIndex, endIndex) + '}')
.append("values", '{' + StringUtils.join(values, ',', startIndex, endIndex) + '}')
.append("params", '{' + StringUtils.join(params, ',', startIndex, endIndex) + '}')
.append("flags", '{' + StringUtils.join(flags, ',', startIndex, endIndex) + '}')
.build();
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("immutable", immutable)
.append("offsets", '{' + StringUtils.join(offsets, ',', 0, numLists << 1) + '}')
.append("ids", '{' + StringUtils.join(ids, ',', 0, tail) + '}')
.append("values", '{' + StringUtils.join(values, ',', 0, tail) + '}')
.append("params", '{' + StringUtils.join(params, ',', 0, tail) + '}')
.append("flags", '{' + StringUtils.join(flags, ',', 0, tail) + '}')
.build();
}
private static ItemStatCost.Entry entry(short stat) {
return Riiablo.files.ItemStatCost.get(stat);
}
private static boolean hasParams(short stat) {
return false; // TODO: determine if stat requires params
}
public IndexIterator indexIterator(int list) {
return INDEX_ITERATOR == null
? INDEX_ITERATOR = new IndexIterator().reset(list)
: INDEX_ITERATOR.reset(list);
}
public final class IndexIterator {
int index;
int endIndex;
IndexIterator reset(int list) {
index = startingOffset(list);
endIndex = endingOffset(list);
return this;
}
public boolean hasNext() {
return index < endIndex;
}
public int next() {
return index++;
}
}
public StatIterator statIterator(int list) {
return STAT_ITERATOR == null
? STAT_ITERATOR = new StatIterator().reset(list)
: STAT_ITERATOR.reset(list);
}
public final class StatIterator implements Iterator<StatGetter> {
final StatGetter stat = new StatGetter(StatList.this);
int index;
int endIndex;
StatIterator reset(int list) {
index = startingOffset(list);
endIndex = endingOffset(list);
return this;
}
@Override
public boolean hasNext() {
return index < endIndex;
}
@Override
public StatGetter next() {
return stat.update(index++);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}

View File

@ -0,0 +1,47 @@
package com.riiablo.attributes;
public final class StatListBuilder {
final StatList stats;
final int list;
StatListBuilder(StatList stats, int list) {
this.stats = stats;
this.list = list;
}
/**
* Returns the list index.
*/
public int build() {
return list;
}
/** @see StatList#get(int) */
public StatListGetter get() {
return stats.get(list);
}
/** @see StatList#put(int, short, int, int) */
public StatListBuilder put(short stat, int param, int value) {
stats.put(list, stat, param, value);
return this;
}
/** @see StatList#put(int, short, int) */
public StatListBuilder put(short stat, int value) {
stats.put(list, stat, value);
return this;
}
/** @see StatList#put(int, short, long) */
public StatListBuilder put(short stat, long value) {
stats.put(list, stat, value);
return this;
}
/** @see StatList#put(int, short, float) */
public StatListBuilder put(short stat, float value) {
stats.put(list, stat, value);
return this;
}
}

View File

@ -0,0 +1,91 @@
package com.riiablo.attributes;
public final class StatListGetter {
final StatList stats;
final int list;
final StatGetter tuple = new StatGetter();
StatListGetter(StatList stats, int list) {
this.stats = stats;
this.list = list;
}
int param(short stat) {
return stats.param(indexOf(stat));
}
int value(short stat) {
return stats.value(indexOf(stat));
}
int indexOf(short stat) {
return stats.indexOf(list, stat);
}
public boolean contains(short stat) {
return stats.contains(list, stat);
}
public StatGetter get(short stat) {
final int index = indexOf(stat);
if (index < 0) return null;
return tuple.set(stats, index);
}
public void addAll(StatListGetter src) {
stats.addAll(list, src.stats, src.list);
}
public StatList.IndexIterator indexIterator() {
return stats.indexIterator(list);
}
public StatList.StatIterator statIterator() {
return stats.statIterator(list);
}
public String debugString() {
return stats.listDebugString(list);
}
@Override
public String toString() {
return debugString();
}
// public int asInt(short stat) {
// return stats.asInt(indexOf(stat));
// }
// public long asLong(short stat) {
// return stats.asLong(indexOf(stat));
// }
// public float asFixed(short stat) {
// return stats.asFixed(indexOf(stat));
// }
// public String asString(short stat) {
// return stats.asString(indexOf(stat));
// }
// public int value1(short stat) {
// return stats.value1(indexOf(stat));
// }
// public int value2(short stat) {
// return stats.value2(indexOf(stat));
// }
// public int value3(short stat) {
// return stats.value3(indexOf(stat));
// }
// public int param1(short stat) {
// return stats.param1(indexOf(stat));
// }
// public int param2(short stat) {
// return stats.param2(indexOf(stat));
// }
}

View File

@ -0,0 +1,18 @@
package com.riiablo.attributes;
public class StatListWrapper extends Attributes {
StatListWrapper(StatList stats) {
super(stats);
}
@Override
public StatListGetter list(int list) {
assert list == 0 : "list(" + list + ") != " + 0;
return super.list(list);
}
@Override
public void resetToBase() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,160 @@
package com.riiablo.attributes;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.headless.HeadlessApplication;
import com.riiablo.Files;
import com.riiablo.Riiablo;
import com.riiablo.codec.StringTBLs;
import com.riiablo.logger.Level;
import com.riiablo.logger.LogManager;
import com.riiablo.mpq.MPQFileHandleResolver;
public class StatListTest {
@BeforeClass
public static void setup() {
Gdx.app = new HeadlessApplication(new ApplicationAdapter() {});
Riiablo.home = Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II");
Riiablo.mpqs = new MPQFileHandleResolver();
Riiablo.string = new StringTBLs(Riiablo.mpqs);
Riiablo.files = new Files();
}
@AfterClass
public static void teardown() {
Gdx.app.exit();
}
@BeforeClass
public static void before() {
LogManager.setLevel("com.riiablo.attributes", Level.TRACE);
}
private static StatList newInstance() {
return new StatList();
}
@Test
public void strength() {
StatList stats = newInstance();
final int list = stats.newList(0);
final int index = stats.put(0, Stat.strength, 15);
Assert.assertTrue(stats.contains(list, Stat.strength));
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(15, stats.value(index));
}
@Test
public void strength_builder() {
StatList stats = newInstance();
final int list = stats.buildList(0)
.put(Stat.strength, 15)
.build();
final int index = stats.indexOf(list, Stat.strength);
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(15, stats.value(index));
System.out.println(stats);
}
@Test
public void hitpoints() {
StatList stats = newInstance();
final int list = stats.buildList(0)
.put(Stat.hitpoints, 1 << 8)
.build();
final int index = stats.indexOf(list, Stat.hitpoints);
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(1 << 8, stats.value(index));
Assert.assertEquals(1.0f, stats.asFixed(index), 0f);
System.out.println(stats);
}
@Test
public void hitpoints_float() {
StatList stats = newInstance();
final int list = stats.buildList(0)
.put(Stat.hitpoints, 1.0f)
.build();
final int index = stats.indexOf(list, Stat.hitpoints);
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(1 << 8, stats.value(index));
Assert.assertEquals(1.0f, stats.asFixed(index), 0f);
System.out.println(stats);
}
@Test
public void experience() {
StatList stats = newInstance();
final int list = stats.buildList(0)
.put(Stat.experience, 0xFFFFFFFF)
.build();
final int index = stats.indexOf(list, Stat.experience);
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(0xFFFFFFFF, stats.value(index));
Assert.assertEquals(0xFFFFFFFFL, stats.asLong(index));
System.out.println(stats);
}
@Test
public void experience_long() {
StatList stats = newInstance();
final int list = stats.buildList(0)
.put(Stat.experience, 0xFFFFFFFFL)
.build();
final int index = stats.indexOf(list, Stat.experience);
Assert.assertEquals(0, stats.param(index));
Assert.assertEquals(0xFFFFFFFF, stats.value(index));
Assert.assertEquals(0xFFFFFFFFL, stats.asLong(index));
System.out.println(stats);
}
@Test
public void strength_add() {
StatList stats = newInstance();
final int statsList = stats.buildList(0)
.put(Stat.strength, 15)
.build();
final int statsIndex = stats.indexOf(statsList, Stat.strength);
assert stats.asInt(statsIndex) == 15;
StatList add = newInstance();
final int addList = add.buildList(0)
.put(Stat.strength, 5)
.build();
final int addIndex = stats.indexOf(addList, Stat.strength);
assert add.asInt(addIndex) == 5;
stats.add(statsList, Stat.strength, add, addList);
Assert.assertEquals(0, stats.param(statsIndex));
Assert.assertEquals(20, stats.value(statsIndex));
Assert.assertEquals(0, add.param(addIndex));
Assert.assertEquals(5, add.value(addIndex));
System.out.println(stats);
System.out.println(add);
}
@Test
public void strength_add_internal() {
StatList stats = newInstance();
final int statsList = stats.buildList(0)
.put(Stat.strength, 15)
.build();
final int statsIndex = stats.indexOf(statsList, Stat.strength);
assert stats.asInt(statsIndex) == 15;
final int addList = stats.buildList(0)
.put(Stat.strength, 5)
.build();
final int addIndex = stats.indexOf(addList, Stat.strength);
assert stats.asInt(addIndex) == 5;
stats.add(statsList, Stat.strength, stats, addList);
Assert.assertEquals(0, stats.param(statsIndex));
Assert.assertEquals(20, stats.value(statsIndex));
Assert.assertEquals(0, stats.param(addIndex));
Assert.assertEquals(5, stats.value(addIndex));
System.out.println(stats);
}
}