147 lines
5.2 KiB
Scala

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)
}