package ocelot.desktop.inventory import ocelot.desktop.graphics.IconSource import ocelot.desktop.inventory.item._ import ocelot.desktop.util.Logging import ocelot.desktop.util.ReflectionUtils.linearizationOrder import totoro.ocelot.brain.loot.Loot import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.{ExtendedTier, Tier} import scala.collection.mutable import scala.collection.mutable.ArrayBuffer object Items extends Logging { private val _groups = ArrayBuffer.empty[ItemGroup] private val _recoverers = mutable.Map.empty[Class[_], ItemRecoverer[_, _]] // this is just to force load the class during initialization def init(): Unit = {} /** * Registers a recoverer for [[ItemRecoverer.sourceClass]]. */ def registerRecoverer(recoverer: ItemRecoverer[_, _]): Unit = { if (!_recoverers.contains(recoverer.sourceClass)) { _recoverers(recoverer.sourceClass) = recoverer logger.info(s"Registered a recoverer for ${recoverer.sourceClass.getName}") } } private def registerItemFactoryRecoverers(factory: ItemFactory): Unit = { for (recoverer <- factory.recoverers) { registerRecoverer(recoverer) } } def registerSingleton(factory: ItemFactory): Unit = { _groups += SingletonItemGroup(factory.name, factory) registerItemFactoryRecoverers(factory) } def registerTiered(name: String, tiers: IterableOnce[Tier])(factory: Tier => ItemFactory): Unit = { val group = TieredItemGroup(name, tiers.iterator.map(tier => (tier, factory(tier))).toSeq) _groups += group for ((_, factory) <- group.factories) { registerItemFactoryRecoverers(factory) } } def registerExtendedTiered(name: String, tiers: IterableOnce[ExtendedTier])( factory: ExtendedTier => ItemFactory ): Unit = { val group = ExtendedTieredItemGroup(name, tiers.iterator.map(tier => (tier, factory(tier))).toSeq) _groups += group for ((_, factory) <- group.factories) { registerItemFactoryRecoverers(factory) } } def registerArbitrary(name: String, icon: IconSource, factories: IterableOnce[(String, ItemFactory)]): Unit = { val group = ArbitraryItemGroup(name, icon, factories.iterator.toSeq) _groups += group for ((_, factory) <- group.factories) { registerItemFactoryRecoverers(factory) } } def groups: Iterable[ItemGroup] = _groups /** * Attempts to recover an [[Item]] from `source`. * * Checks superclasses and traits while looking for a recoverer. */ def recover[A](source: A): Option[Item] = { linearizationOrder(source.getClass.asInstanceOf[Class[_]]) .flatMap(_recoverers.get) .map(_.asInstanceOf[ItemRecoverer[_ >: A, _ <: Item]].recover(source)) .nextOption() } sealed trait ItemGroup { def name: String } case class SingletonItemGroup(name: String, factory: ItemFactory) extends ItemGroup case class TieredItemGroup(name: String, factories: Seq[(Tier, ItemFactory)]) extends ItemGroup case class ExtendedTieredItemGroup(name: String, factories: Seq[(ExtendedTier, ItemFactory)]) extends ItemGroup case class ArbitraryItemGroup(name: String, icon: IconSource, factories: Seq[(String, ItemFactory)]) extends ItemGroup ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// registerTiered("CPU", Tier.One to Tier.Three)(new CpuItem.Factory(_)) registerTiered("APU", Tier.Two to Tier.Creative)(tier => new ApuItem.Factory(tier.saturatingSub(1))) registerExtendedTiered("Memory", ExtendedTier.One to ExtendedTier.ThreeHalf)(new MemoryItem.Factory(_)) registerTiered("HDD", Tier.One to Tier.Three)(new HddItem.Factory(managed = true, _)) registerArbitrary( "Floppy", FloppyItem.Factory.Empty.icon, Loot.Floppies.iterator .map(new FloppyItem.Factory.Loot(_)) .map(factory => (factory.name, factory)) ++ Some(("Empty", FloppyItem.Factory.Empty)) ) registerArbitrary( "EEPROM", EepromItem.Factory.Empty.icon, Loot.Eeproms.iterator .map(new EepromItem.Factory.Loot(_)) .map(factory => (factory.name, factory)) ++ Some(("Empty", EepromItem.Factory.Empty)) ) registerTiered("Graphics Card", Tier.One to Tier.Three)(new GraphicsCardItem.Factory(_)) registerSingleton(NetworkCardItem.Factory) registerTiered("Wireless Net. Card", Tier.One to Tier.Two) { case Tier.One => WirelessNetworkCardItem.Tier1.Factory case Tier.Two => WirelessNetworkCardItem.Tier2.Factory } registerSingleton(LinkedCardItem.Factory) registerSingleton(InternetCardItem.Factory) registerTiered("Redstone Card", Tier.One to Tier.Two) { case Tier.One => RedstoneCardItem.Tier1.Factory case Tier.Two => RedstoneCardItem.Tier2.Factory } registerTiered("Data Card", Tier.One to Tier.Three) { case Tier.One => DataCardItem.Tier1.Factory case Tier.Two => DataCardItem.Tier2.Factory case Tier.Three => DataCardItem.Tier3.Factory } registerSingleton(SoundCardItem.Factory) registerSingleton(SelfDestructingCardItem.Factory) registerTiered("Server", Tier.One to Tier.Creative)(new ServerItem.Factory(_)) registerTiered("Component bus", Tier.One to Tier.Creative)(new ComponentBusItem.Factory(_)) registerSingleton(DiskDriveMountableItem.Factory) }