From 22a1498d64fb6e29a2ecc7c2aea1befd3fa547c0 Mon Sep 17 00:00:00 2001 From: Collin Smith Date: Thu, 28 Mar 2019 20:10:21 -0700 Subject: [PATCH] Changed item type lookup to use custom Bits implementation Changed item type lookup to use custom Bits implementation Item type lookup should now be O(1) -- I'll look into further optimizations --- core/src/com/riiablo/entity/Player.java | 18 +-- core/src/com/riiablo/item/Item.java | 44 ++--- core/src/com/riiablo/item/Type.java | 152 ++++++++++++++++++ .../src/com/riiablo/panel/InventoryPanel.java | 4 +- 4 files changed, 186 insertions(+), 32 deletions(-) create mode 100644 core/src/com/riiablo/item/Type.java diff --git a/core/src/com/riiablo/entity/Player.java b/core/src/com/riiablo/entity/Player.java index 7ca300cb..3f5eb598 100644 --- a/core/src/com/riiablo/entity/Player.java +++ b/core/src/com/riiablo/entity/Player.java @@ -259,18 +259,18 @@ public class Player extends Entity { Item RH = null, LH = null, SH = null; Item rArm = getSlot(Slot.RARM); if (rArm != null) { - if (rArm.type.is("weap")) { + if (rArm.type.is(com.riiablo.item.Type.WEAP)) { RH = rArm; - } else if (rArm.type.is("shld")) { + } else if (rArm.type.is(com.riiablo.item.Type.SHLD)) { SH = rArm; } } Item lArm = getSlot(Slot.LARM); if (lArm != null) { - if (lArm.type.is("weap")) { + if (lArm.type.is(com.riiablo.item.Type.WEAP)) { LH = lArm; - } else if (lArm.type.is("shld")) { + } else if (lArm.type.is(com.riiablo.item.Type.SHLD)) { SH = lArm; } } @@ -292,9 +292,9 @@ public class Player extends Entity { setWeapon(WEAPON_1JS); // Left Jab Right Swing } else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1ht")) { setWeapon(WEAPON_1JT); // Left Jab Right Thrust - } else if (LH.type.is("miss") || RH.type.is("miss")) { - setWeapon((byte) Riiablo.files.WeaponClass.index(LH.type.is("miss") ? LHEntry.wclass : RHEntry.wclass)); - } else if (LH.type.is("h2h") || RH.type.is("h2h")) { + } else if (LH.type.is(com.riiablo.item.Type.MISS) || RH.type.is(com.riiablo.item.Type.MISS)) { + setWeapon((byte) Riiablo.files.WeaponClass.index(LH.type.is(com.riiablo.item.Type.MISS) ? LHEntry.wclass : RHEntry.wclass)); + } else if (LH.type.is(com.riiablo.item.Type.H2H) || RH.type.is(com.riiablo.item.Type.H2H)) { setWeapon(WEAPON_HT2); // Two Hand-to-Hand } else { setWeapon(WEAPON_HTH); @@ -304,12 +304,12 @@ public class Player extends Entity { } else if (LH != null || RH != null) { RH = ObjectUtils.firstNonNull(RH, LH); LH = null; - if (RH.type.is("bow")) { + if (RH.type.is(com.riiablo.item.Type.BOW)) { LH = RH; RH = null; Weapons.Entry LHEntry = LH.getBase(); setWeapon((byte) Riiablo.files.WeaponClass.index(LHEntry.wclass)); - } else if (RH.type.is("weap")) { // make sure weap and not e.g. misl, might not be required + } else if (RH.type.is(com.riiablo.item.Type.WEAP)) { // make sure weap and not e.g. misl, might not be required Weapons.Entry RHEntry = RH.getBase(); setWeapon((byte) Riiablo.files.WeaponClass.index(RHEntry.wclass)); } else { diff --git a/core/src/com/riiablo/item/Item.java b/core/src/com/riiablo/item/Item.java index 53ab9305..fe8bf9ec 100644 --- a/core/src/com/riiablo/item/Item.java +++ b/core/src/com/riiablo/item/Item.java @@ -138,7 +138,8 @@ public class Item extends Actor implements Disposable { public PropertyList stats[]; public ItemEntry base; - public ItemTypes.Entry type; + public ItemTypes.Entry typeEntry; + public Type type; private String name; private AssetDescriptor invFileDescriptor; @@ -180,7 +181,8 @@ public class Item extends Actor implements Disposable { socketed = new Array<>(6); base = findBase(typeCode); - type = Riiablo.files.ItemTypes.get(base.type); + typeEntry = Riiablo.files.ItemTypes.get(base.type); + type = Type.get(typeEntry); props = new PropertyList(); props.put(Stat.item_levelreq, base.levelreq); @@ -216,7 +218,7 @@ public class Item extends Actor implements Disposable { qualityData = null; runewordData = 0; inscription = null; - if (type.is("gem") || type.is("rune")) { + if (type.is(Type.GEM) || type.is(Type.RUNE)) { Gems.Entry gem = Riiablo.files.Gems.get(base.code); stats = new PropertyList[NUM_GEM_PROPS]; stats[WEAPON_PROPS] = new PropertyList().add(gem.weaponModCode, gem.weaponModParam, gem.weaponModMin, gem.weaponModMax); @@ -275,22 +277,22 @@ public class Item extends Actor implements Disposable { bitStream.skip(1); // TODO: Unknown, this usually is 0, but is 1 on a Tome of Identify. (It's still 0 on a Tome of Townportal.) - if (type.is("armo")) { + if (type.is(Type.ARMO)) { props.read(Stat.armorclass, bitStream); } - if (type.is("armo") || type.is("weap")) { + if (type.is(Type.ARMO) || type.is(Type.WEAP)) { int maxdurability = props.read(Stat.maxdurability, bitStream); if (maxdurability > 0) { props.read(Stat.durability, bitStream); } } - if ((flags & SOCKETED) == SOCKETED && (type.is("armo") || type.is("weap"))) { + if ((flags & SOCKETED) == SOCKETED && (type.is(Type.ARMO) || type.is(Type.WEAP))) { props.read(Stat.item_numsockets, bitStream); } - if (type.is("book")) { + if (type.is(Type.BOOK)) { bitStream.skip(5); // TODO: Tomes have an extra 5 bits inserted at this point. I have no idea what purpose they serve. It looks like the value is 0 on all of my tomes. } @@ -304,7 +306,7 @@ public class Item extends Actor implements Disposable { listsFlags |= (lists << SET_PROPS); } - if (type.is("book")) { + if (type.is(Type.BOOK)) { listsFlags = 0; } @@ -562,7 +564,7 @@ public class Item extends Actor implements Disposable { return "invtrch"; } } - return type.InvGfx[pictureId]; + return typeEntry.InvGfx[pictureId]; } switch (quality) { case SET: @@ -818,7 +820,7 @@ public class Item extends Actor implements Disposable { break; } - if (Item.this.type.is("rune")) + if (Item.this.type.is(Type.RUNE)) name.setColor(Riiablo.colors.orange); add(name).center().space(SPACING).row(); @@ -837,7 +839,7 @@ public class Item extends Actor implements Disposable { String runequote = Riiablo.string.lookup("RuneQuote"); StringBuilder runewordBuilder = null; for (Item socket : socketed) { - if (socket.type.is("rune")) { + if (socket.type.is(Type.RUNE)) { if (runewordBuilder == null) runewordBuilder = new StringBuilder(runequote); runewordBuilder.append(Riiablo.string.lookup(socket.base.namestr + "L")); // TODO: Is there a r##L reference somewhere? } @@ -848,15 +850,15 @@ public class Item extends Actor implements Disposable { } } - if (Item.this.type.is("book")) { + if (Item.this.type.is(Type.BOOK)) { add(new Label(Riiablo.string.lookup("InsertScrolls"), font, Riiablo.colors.white)).center().space(SPACING).row(); - } else if (Item.this.type.is("char")) { + } else if (Item.this.type.is(Type.CHAR)) { add(new Label(Riiablo.string.lookup("ItemExpcharmdesc"), font, Riiablo.colors.white)).center().space(SPACING).row(); - } else if (Item.this.type.is("sock")) { + } else if (Item.this.type.is(Type.SOCK)) { add(new Label(Riiablo.string.lookup("ExInsertSocketsX"), font, Riiablo.colors.white)).center().space(SPACING).row(); } - if (Item.this.type.is("gem") || Item.this.type.is("rune")) { + if (Item.this.type.is(Type.GEM) || Item.this.type.is(Type.RUNE)) { assert stats.length == NUM_GEM_PROPS; add().height(font.getLineHeight()).space(SPACING).row(); add(new Label(Riiablo.string.lookup("GemXp3") + " " + stats[WEAPON_PROPS].copy().reduce().get().format(), font, Riiablo.colors.white)).center().space(SPACING).row(); @@ -893,11 +895,11 @@ public class Item extends Actor implements Disposable { Stat.Instance prop; if ((prop = props.get(Stat.armorclass)) != null) add(new Label(Riiablo.string.lookup("ItemStats1h") + " " + prop.value, font, Riiablo.colors.white)).center().space(SPACING).row(); - if (Item.this.type.is("weap")) { + if (Item.this.type.is(Type.WEAP)) { if ((prop = props.get(Stat.maxdamage)) != null) // TODO: Conditional 2 handed if barbarian, etc add(new Label(Riiablo.string.lookup("ItemStats1l") + " " + props.get(Stat.mindamage).value + " to " + prop.value, font, Riiablo.colors.white)).center().space(SPACING).row(); } - if (Item.this.type.is("shld")) { + if (Item.this.type.is(Type.SHLD)) { if ((prop = props.get(Stat.toblock)) != null) add(new Label(Riiablo.string.lookup("ItemStats1r") + prop.value + "%", font, Riiablo.colors.white)).center().space(SPACING).row(); // TODO: if paladin, show smite damage -- ItemStats1o %d to %d @@ -906,8 +908,8 @@ public class Item extends Actor implements Disposable { } if (!Item.this.base.nodurability && (prop = props.get(Stat.durability)) != null) add(new Label(Riiablo.string.lookup("ItemStats1d") + " " + prop.value + " " + Riiablo.string.lookup("ItemStats1j") + " " + props.get(Stat.maxdurability).value, font, Riiablo.colors.white)).center().space(SPACING).row(); - if (Item.this.type.is("clas")) { - add(new Label(Riiablo.string.lookup(CharacterClass.get(Item.this.type.Class).entry().StrClassOnly), font, Riiablo.colors.white)).center().space(SPACING).row(); + if (Item.this.type.is(Type.CLAS)) { + add(new Label(Riiablo.string.lookup(CharacterClass.get(Item.this.typeEntry.Class).entry().StrClassOnly), font, Riiablo.colors.white)).center().space(SPACING).row(); } if ((prop = props.get(Stat.reqdex)) != null && prop.value > 0) add(new Label(Riiablo.string.lookup("ItemStats1f") + " " + prop.value, font, Riiablo.colors.white)).center().space(SPACING).row(); @@ -917,7 +919,7 @@ public class Item extends Actor implements Disposable { add(new Label(Riiablo.string.lookup("ItemStats1p") + " " + prop.value, font, Riiablo.colors.white)).center().space(SPACING).row(); if ((prop = props.get(Stat.quantity)) != null) add(new Label(Riiablo.string.lookup("ItemStats1i") + " " + prop.value, font, Riiablo.colors.white)).center().space(SPACING).row(); - if (Item.this.type.is("weap")) { + if (Item.this.type.is(Type.WEAP)) { add(new Label(Riiablo.string.lookup(WEAPON_DESC.get(Item.this.base.type)) + " - " + 0, font, Riiablo.colors.white)).center().space(SPACING).row(); } //} @@ -929,7 +931,7 @@ public class Item extends Actor implements Disposable { if (magicProps != null) { PropertyList magicPropsAggregate = magicProps.copy(); for (Item socket : socketed) { - if (socket.type.is("gem") | socket.type.is("rune")) { + if (socket.type.is(Type.GEM) || socket.type.is(Type.RUNE)) { magicPropsAggregate.addAll(socket.stats[base.gemapplytype]); } else { magicPropsAggregate.addAll(socket.stats[MAGIC_PROPS]); diff --git a/core/src/com/riiablo/item/Type.java b/core/src/com/riiablo/item/Type.java new file mode 100644 index 00000000..ed9fd0e3 --- /dev/null +++ b/core/src/com/riiablo/item/Type.java @@ -0,0 +1,152 @@ +package com.riiablo.item; + +import com.badlogic.gdx.utils.Bits; +import com.riiablo.Riiablo; +import com.riiablo.codec.excel.ItemTypes; + +public class Type extends Bits { + private static final Type[] TYPES; + static { + TYPES = new Type[128]; + for (int i = 0, size = Riiablo.files.ItemTypes.size(); i < size; i++) { + if (TYPES[i] == null) TYPES[i] = new Type(Riiablo.files.ItemTypes.get(i)); + } + } + + public static Type get(ItemTypes.Entry type) { + return get(type.Code); + } + + public static Type get(String type) { + return TYPES[Riiablo.files.ItemTypes.index(type)]; + } + + Type(String type) { + super(128); + setAll(type); + } + + Type(ItemTypes.Entry type) { + this(type.Code); + } + + private void setAll(String type) { + int id = Riiablo.files.ItemTypes.index(type); + if (TYPES[id] != null) { + or(TYPES[id]); + return; + } else { + TYPES[id] = this; + set(id); + } + + ItemTypes.Entry entry = Riiablo.files.ItemTypes.get(id); + for (String equiv : entry.Equiv) { + if (equiv.isEmpty()) break; + setAll(equiv); + } + } + + public boolean is(int index) { + return get(index); + } + + public static final int SHIE = Riiablo.files.ItemTypes.index("shie"); + public static final int TORS = Riiablo.files.ItemTypes.index("tors"); + public static final int GOLD = Riiablo.files.ItemTypes.index("gold"); + public static final int BOWQ = Riiablo.files.ItemTypes.index("bowq"); + public static final int XBOQ = Riiablo.files.ItemTypes.index("xboq"); + public static final int PLAY = Riiablo.files.ItemTypes.index("play"); + public static final int HERB = Riiablo.files.ItemTypes.index("herb"); + public static final int POTI = Riiablo.files.ItemTypes.index("poti"); + public static final int RING = Riiablo.files.ItemTypes.index("ring"); + public static final int ELIX = Riiablo.files.ItemTypes.index("elix"); + public static final int AMUL = Riiablo.files.ItemTypes.index("amul"); + public static final int CHAR = Riiablo.files.ItemTypes.index("char"); + public static final int BOOT = Riiablo.files.ItemTypes.index("boot"); + public static final int GLOV = Riiablo.files.ItemTypes.index("glov"); + public static final int BOOK = Riiablo.files.ItemTypes.index("book"); + public static final int BELT = Riiablo.files.ItemTypes.index("belt"); + public static final int GEM = Riiablo.files.ItemTypes.index("gem"); + public static final int TORC = Riiablo.files.ItemTypes.index("torc"); + public static final int SCRO = Riiablo.files.ItemTypes.index("scro"); + public static final int SCEP = Riiablo.files.ItemTypes.index("scep"); + public static final int WAND = Riiablo.files.ItemTypes.index("wand"); + public static final int STAF = Riiablo.files.ItemTypes.index("staf"); + public static final int BOW = Riiablo.files.ItemTypes.index("bow"); + public static final int AXE = Riiablo.files.ItemTypes.index("axe"); + public static final int CLUB = Riiablo.files.ItemTypes.index("club"); + public static final int SWOR = Riiablo.files.ItemTypes.index("swor"); + public static final int HAMM = Riiablo.files.ItemTypes.index("hamm"); + public static final int KNIF = Riiablo.files.ItemTypes.index("knif"); + public static final int SPEA = Riiablo.files.ItemTypes.index("spea"); + public static final int POLE = Riiablo.files.ItemTypes.index("pole"); + public static final int XBOW = Riiablo.files.ItemTypes.index("xbow"); + public static final int MACE = Riiablo.files.ItemTypes.index("mace"); + public static final int HELM = Riiablo.files.ItemTypes.index("helm"); + public static final int TPOT = Riiablo.files.ItemTypes.index("tpot"); + public static final int QUES = Riiablo.files.ItemTypes.index("ques"); + public static final int BODY = Riiablo.files.ItemTypes.index("body"); + public static final int KEY = Riiablo.files.ItemTypes.index("key"); + public static final int TKNI = Riiablo.files.ItemTypes.index("tkni"); + public static final int TAXE = Riiablo.files.ItemTypes.index("taxe"); + public static final int JAVE = Riiablo.files.ItemTypes.index("jave"); + public static final int WEAP = Riiablo.files.ItemTypes.index("weap"); + public static final int MELE = Riiablo.files.ItemTypes.index("mele"); + public static final int MISS = Riiablo.files.ItemTypes.index("miss"); + public static final int THRO = Riiablo.files.ItemTypes.index("thro"); + public static final int COMB = Riiablo.files.ItemTypes.index("comb"); + public static final int ARMO = Riiablo.files.ItemTypes.index("armo"); + public static final int SHLD = Riiablo.files.ItemTypes.index("shld"); + public static final int MISC = Riiablo.files.ItemTypes.index("misc"); + public static final int SOCK = Riiablo.files.ItemTypes.index("sock"); + public static final int SECO = Riiablo.files.ItemTypes.index("seco"); + public static final int ROD = Riiablo.files.ItemTypes.index("rod"); + public static final int MISL = Riiablo.files.ItemTypes.index("misl"); + public static final int BLUN = Riiablo.files.ItemTypes.index("blun"); + public static final int JEWL = Riiablo.files.ItemTypes.index("jewl"); + public static final int CLAS = Riiablo.files.ItemTypes.index("clas"); + public static final int AMAZ = Riiablo.files.ItemTypes.index("amaz"); + public static final int BARB = Riiablo.files.ItemTypes.index("barb"); + public static final int NECR = Riiablo.files.ItemTypes.index("necr"); + public static final int PALA = Riiablo.files.ItemTypes.index("pala"); + public static final int SORC = Riiablo.files.ItemTypes.index("sorc"); + public static final int ASSN = Riiablo.files.ItemTypes.index("assn"); + public static final int DRUI = Riiablo.files.ItemTypes.index("drui"); + public static final int H2H = Riiablo.files.ItemTypes.index("h2h"); + public static final int ORB = Riiablo.files.ItemTypes.index("orb"); + public static final int HEAD = Riiablo.files.ItemTypes.index("head"); + public static final int ASHD = Riiablo.files.ItemTypes.index("ashd"); + public static final int PHLM = Riiablo.files.ItemTypes.index("phlm"); + public static final int PELT = Riiablo.files.ItemTypes.index("pelt"); + public static final int CLOA = Riiablo.files.ItemTypes.index("cloa"); + public static final int RUNE = Riiablo.files.ItemTypes.index("rune"); + public static final int CIRC = Riiablo.files.ItemTypes.index("circ"); + public static final int HPOT = Riiablo.files.ItemTypes.index("hpot"); + public static final int MPOT = Riiablo.files.ItemTypes.index("mpot"); + public static final int RPOT = Riiablo.files.ItemTypes.index("rpot"); + public static final int SPOT = Riiablo.files.ItemTypes.index("spot"); + public static final int APOT = Riiablo.files.ItemTypes.index("apot"); + public static final int WPOT = Riiablo.files.ItemTypes.index("wpot"); + public static final int SCHA = Riiablo.files.ItemTypes.index("scha"); + public static final int MCHA = Riiablo.files.ItemTypes.index("mcha"); + public static final int LCHA = Riiablo.files.ItemTypes.index("lcha"); + public static final int ABOW = Riiablo.files.ItemTypes.index("abow"); + public static final int ASPE = Riiablo.files.ItemTypes.index("aspe"); + public static final int AJAV = Riiablo.files.ItemTypes.index("ajav"); + public static final int H2H2 = Riiablo.files.ItemTypes.index("h2h2"); + public static final int MBOQ = Riiablo.files.ItemTypes.index("mboq"); + public static final int MXBQ = Riiablo.files.ItemTypes.index("mxbq"); + public static final int GEM0 = Riiablo.files.ItemTypes.index("gem0"); + public static final int GEM1 = Riiablo.files.ItemTypes.index("gem1"); + public static final int GEM2 = Riiablo.files.ItemTypes.index("gem2"); + public static final int GEM3 = Riiablo.files.ItemTypes.index("gem3"); + public static final int GEM4 = Riiablo.files.ItemTypes.index("gem4"); + public static final int GEMA = Riiablo.files.ItemTypes.index("gema"); + public static final int GEMD = Riiablo.files.ItemTypes.index("gemd"); + public static final int GEME = Riiablo.files.ItemTypes.index("geme"); + public static final int GEMR = Riiablo.files.ItemTypes.index("gemr"); + public static final int GEMS = Riiablo.files.ItemTypes.index("gems"); + public static final int GEMT = Riiablo.files.ItemTypes.index("gemt"); + public static final int GEMZ = Riiablo.files.ItemTypes.index("gemz"); +} diff --git a/core/src/com/riiablo/panel/InventoryPanel.java b/core/src/com/riiablo/panel/InventoryPanel.java index 4fc7d9f0..dbcad6a6 100644 --- a/core/src/com/riiablo/panel/InventoryPanel.java +++ b/core/src/com/riiablo/panel/InventoryPanel.java @@ -314,7 +314,7 @@ public class InventoryPanel extends WidgetGroup implements Disposable { public void clicked(InputEvent event, float x, float y) { Item cursor = Riiablo.cursor.getItem(); if (cursor != null) { - if (!ArrayUtils.contains(cursor.type.BodyLoc, bodyPart)) { + if (!ArrayUtils.contains(cursor.typeEntry.BodyLoc, bodyPart)) { Riiablo.audio.play(gameScreen.player.stats.getCharClass().name().toLowerCase() + "_impossible_1", false); return; } @@ -357,7 +357,7 @@ public class InventoryPanel extends WidgetGroup implements Disposable { boolean blocked = false; Item cursorItem = Riiablo.cursor.getItem(); if (cursorItem != null) { - blocked = !ArrayUtils.contains(cursorItem.type.BodyLoc, bodyPart); + blocked = !ArrayUtils.contains(cursorItem.typeEntry.BodyLoc, bodyPart); } // TODO: red if does not meet item requirements