Custom deferred register with parallel entry initialization

This commit is contained in:
DBotThePony 2024-01-05 21:35:14 +07:00
parent 2dcfa99f9c
commit e55764c10d
Signed by: DBot
GPG Key ID: DCC23B5715498507
19 changed files with 253 additions and 119 deletions

View File

@ -8,22 +8,22 @@ import ru.dbotthepony.mc.otm.android.DummyAndroidFeature
import ru.dbotthepony.mc.otm.android.feature.*
object AndroidFeatures {
private val registry = DeferredRegister.create(MRegistry.ANDROID_FEATURES_KEY, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(MRegistry.ANDROID_FEATURES_KEY)
val AIR_BAGS: AndroidFeatureType<DummyAndroidFeature> by registry.register(MNames.AIR_BAGS) { AndroidFeatureType(::DummyAndroidFeature) }
val STEP_ASSIST: AndroidFeatureType<StepAssistFeature> by registry.register(MNames.STEP_ASSIST) { AndroidFeatureType(::StepAssistFeature) }
val SWIM_BOOSTERS: AndroidFeatureType<SwimBoostersFeature> by registry.register(MNames.SWIM_BOOSTERS) { AndroidFeatureType(::SwimBoostersFeature) }
val LIMB_OVERCLOCKING: AndroidFeatureType<LimbOverclockingFeature> by registry.register(MNames.LIMB_OVERCLOCKING) { AndroidFeatureType(::LimbOverclockingFeature) }
val ATTACK_BOOST: AndroidFeatureType<AttackBoostFeature> by registry.register(MNames.ATTACK_BOOST) { AndroidFeatureType(::AttackBoostFeature) }
val NANOBOTS_REGENERATION: AndroidFeatureType<NanobotsRegenerationFeature> by registry.register(MNames.NANOBOTS_REGENERATION) { AndroidFeatureType(::NanobotsRegenerationFeature) }
val NANOBOTS_ARMOR: AndroidFeatureType<NanobotsArmorFeature> by registry.register(MNames.NANOBOTS_ARMOR) { AndroidFeatureType(::NanobotsArmorFeature) }
val EXTENDED_REACH: AndroidFeatureType<ExtendedReachFeature> by registry.register(MNames.EXTENDED_REACH) { AndroidFeatureType(::ExtendedReachFeature) }
val NIGHT_VISION: AndroidFeatureType<NightVisionFeature> by registry.register(MNames.NIGHT_VISION) { AndroidFeatureType(::NightVisionFeature) }
val SHOCKWAVE: AndroidFeatureType<ShockwaveFeature> by registry.register(MNames.SHOCKWAVE) { AndroidFeatureType(::ShockwaveFeature) }
val ITEM_MAGNET: AndroidFeatureType<ItemMagnetFeature> by registry.register(MNames.ITEM_MAGNET) { AndroidFeatureType(::ItemMagnetFeature) }
val FALL_DAMPENERS: AndroidFeatureType<FallDampenersFeature> by registry.register(MNames.FALL_DAMPENERS) { AndroidFeatureType(::FallDampenersFeature) }
val JUMP_BOOST: AndroidFeatureType<JumpBoostFeature> by registry.register(MNames.JUMP_BOOST) { AndroidFeatureType(::JumpBoostFeature) }
val ENDER_TELEPORTER: AndroidFeatureType<EnderTeleporterFeature> by registry.register(MNames.ENDER_TELEPORTER) { AndroidFeatureType(::EnderTeleporterFeature) }
val AIR_BAGS by registry.register(MNames.AIR_BAGS) { AndroidFeatureType(::DummyAndroidFeature) }
val STEP_ASSIST by registry.register(MNames.STEP_ASSIST) { AndroidFeatureType(::StepAssistFeature) }
val SWIM_BOOSTERS by registry.register(MNames.SWIM_BOOSTERS) { AndroidFeatureType(::SwimBoostersFeature) }
val LIMB_OVERCLOCKING by registry.register(MNames.LIMB_OVERCLOCKING) { AndroidFeatureType(::LimbOverclockingFeature) }
val ATTACK_BOOST by registry.register(MNames.ATTACK_BOOST) { AndroidFeatureType(::AttackBoostFeature) }
val NANOBOTS_REGENERATION by registry.register(MNames.NANOBOTS_REGENERATION) { AndroidFeatureType(::NanobotsRegenerationFeature) }
val NANOBOTS_ARMOR by registry.register(MNames.NANOBOTS_ARMOR) { AndroidFeatureType(::NanobotsArmorFeature) }
val EXTENDED_REACH by registry.register(MNames.EXTENDED_REACH) { AndroidFeatureType(::ExtendedReachFeature) }
val NIGHT_VISION by registry.register(MNames.NIGHT_VISION) { AndroidFeatureType(::NightVisionFeature) }
val SHOCKWAVE by registry.register(MNames.SHOCKWAVE) { AndroidFeatureType(::ShockwaveFeature) }
val ITEM_MAGNET by registry.register(MNames.ITEM_MAGNET) { AndroidFeatureType(::ItemMagnetFeature) }
val FALL_DAMPENERS by registry.register(MNames.FALL_DAMPENERS) { AndroidFeatureType(::FallDampenersFeature) }
val JUMP_BOOST by registry.register(MNames.JUMP_BOOST) { AndroidFeatureType(::JumpBoostFeature) }
val ENDER_TELEPORTER by registry.register(MNames.ENDER_TELEPORTER) { AndroidFeatureType(::EnderTeleporterFeature) }
internal fun register(bus: IEventBus) {
registry.register(bus)

View File

@ -1,25 +0,0 @@
package ru.dbotthepony.mc.otm.registry
import net.minecraft.world.item.DyeColor
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import java.util.function.Supplier
import kotlin.reflect.KProperty
operator fun <T : Any> RegistryObject<T>.getValue(thisRef: Any, property: KProperty<*>): T {
return get()
}
internal fun <T, R : T> DeferredRegister<T>.colored(prefix: String, factory: (color: DyeColor) -> R): Map<DyeColor, R> {
return SupplierMap(MRegistry.DYE_ORDER.map { it to register(prefix + "_" + it.name.lowercase()) { factory.invoke(it) } })
}
internal fun <T, R : T> DeferredRegister<T>.coloredWithBase(prefix: String, factory: (color: DyeColor?) -> R): Map<DyeColor?, R> {
val values = ArrayList<Pair<DyeColor?, Supplier<R>>>()
values.add(null to register(prefix) { factory.invoke(null) })
MRegistry.DYE_ORDER.forEach { values.add(it to register(prefix + "_" + it.name.lowercase()) { factory.invoke(it) }) }
return SupplierMap(values)
}

View File

@ -38,13 +38,13 @@ import java.util.function.Supplier
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // Type<*> is unused in BlockEntityType.Builder
object MBlockEntities {
private val registry = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(ForgeRegistries.BLOCK_ENTITY_TYPES)
private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, vararg blocks: Supplier<Block>): RegistryObject<BlockEntityType<T>> {
private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, vararg blocks: Supplier<Block>): MDeferredRegister<*>.Entry<BlockEntityType<T>> {
return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.map { it.get() }.toTypedArray()).build(null) }
}
private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, blocks: Map<*, Block>): RegistryObject<BlockEntityType<T>> {
private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, blocks: Map<*, Block>): MDeferredRegister<*>.Entry<BlockEntityType<T>> {
return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.values.toTypedArray()).build(null) }
}

View File

@ -80,7 +80,7 @@ import ru.dbotthepony.mc.otm.shapes.BlockShapes
import java.util.function.Supplier
object MBlocks {
private val registry = DeferredRegister.create(ForgeRegistries.BLOCKS, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(ForgeRegistries.BLOCKS)
internal fun register(bus: IEventBus) {
registry.register(bus)
@ -222,7 +222,7 @@ object MBlocks {
val TRITANIUM_TRAPDOOR = registry.coloredWithBase(MNames.TRITANIUM_TRAPDOOR, ::TritaniumTrapdoorBlock)
val TRITANIUM_STRIPED_BLOCK: Block by registry.register(MNames.TRITANIUM_STRIPED_BLOCK) { Block(
val TRITANIUM_STRIPED_BLOCK: Block by registry.register(MNames.TRITANIUM_STRIPED_BLOCK, true) { Block(
BlockBehaviour.Properties.of()
.mapColor(MapColor.COLOR_LIGHT_BLUE)
.sound(SoundType.BASALT)

View File

@ -273,7 +273,7 @@ private fun addDecorativeTabItems(consumer: CreativeModeTab.Output) {
}
object MCreativeTabs {
private val registry = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(Registries.CREATIVE_MODE_TAB)
val MAIN: CreativeModeTab by registry.register("main") {
CreativeModeTab.builder()

View File

@ -0,0 +1,157 @@
package ru.dbotthepony.mc.otm.registry
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap
import net.minecraft.Util
import net.minecraft.core.Registry
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.IForgeRegistry
import net.minecraftforge.registries.RegisterEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.SystemTime
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import java.util.LinkedList
import java.util.concurrent.FutureTask
import java.util.concurrent.locks.LockSupport
import java.util.function.Supplier
import kotlin.reflect.KProperty
/**
* DeferredRegister which allows parallel initialization
*/
class MDeferredRegister<R : Any>(val registry: ResourceKey<Registry<R>>, val modId: String = OverdriveThatMatters.MOD_ID) {
constructor(registry: IForgeRegistry<R>, modId: String = OverdriveThatMatters.MOD_ID) : this(registry.registryKey, modId)
private val entries = Object2ObjectLinkedOpenHashMap<String, Entry<R>>()
private var allowRegistration = true
private var eventRegistered = false
private val stages = ArrayList<RegistrationStage>()
private inner class RegistrationStage(val serial: Boolean) {
private val entries = ArrayList<Entry<R>>()
fun add(entry: Entry<R>) {
entries.add(entry)
}
fun run(): List<Entry<R>> {
if (serial) {
LOGGER.debug("Serial registration of {} entries from {} for {}...", entries.size, modId, registry.location())
val t = SystemTime()
entries.forEach { it.initialize() }
LOGGER.debug("Serial registration of {} entries from {} for {} took {} ms", entries.size, modId, registry.location(), t.millis)
} else {
LOGGER.debug("Parallel registration of {} entries from {} for {}...", entries.size, modId, registry.location())
val t = SystemTime()
val futures = LinkedList<FutureTask<R>>()
entries.forEach { futures.add(FutureTask(it::initialize)) }
futures.forEach { Util.backgroundExecutor().submit(it) }
while (futures.isNotEmpty()) {
futures.removeIf { it.run(); it.isDone } // help executor threads to minimize thread stalling
// especially true when executor threads are busy with work created by other mods
// so we keep worst-case scenario where every registry entry is initialized and registered serially as it was before
LockSupport.parkNanos(1_000_000L)
}
// memory barrier to avoid specifying _value as @Volatile
LockSupport.parkNanos(1_000_000L)
LOGGER.debug("Parallel registration of {} entries from {} for {} took {} ms", entries.size, modId, registry.location(), t.millis)
}
return entries
}
}
inner class Entry<out T : R>(val name: String, private val factory: Supplier<T>, serial: Boolean) : Supplier<@UnsafeVariance T>, Lazy<T> {
constructor(name: String, factory: Supplier<T>) : this(name, factory, false)
init {
check(allowRegistration) { "Unable to register new entries after RegisterEvent has been fired" }
require(entries.put(name, this) == null) { "Duplicate entry $name for registry $registry" }
if (stages.isEmpty() || stages.last().serial != serial) {
val stage = RegistrationStage(serial)
stage.add(this)
stages.add(stage)
} else {
stages.last().add(this)
}
}
val key = ResourceLocation(modId, name)
private var _value: T? = null
override val value: T get() {
return _value ?: throw IllegalStateException("Trying to access $name of $registry before it is initialized")
}
override fun isInitialized(): Boolean {
return _value != null
}
override fun get(): T {
return value
}
operator fun getValue(receiver: Any?, property: KProperty<*>): T {
return value
}
fun initialize(): T {
check(_value == null) { "Already initialized $name of $registry!" }
val getValue = try {
factory.get()
} catch (err: Throwable) {
throw RuntimeException("Unable to initialize registry entry $name of $registry", err)
}
_value = getValue
return value
}
}
fun <T : R> colored(prefix: String, factory: (color: DyeColor) -> T): Map<DyeColor, T> {
return SupplierMap(MRegistry.DYE_ORDER.map { it to Entry(prefix + "_" + it.name.lowercase()) { factory.invoke(it) } })
}
fun <T : R> coloredWithBase(prefix: String, factory: (color: DyeColor?) -> T): Map<DyeColor?, T> {
val values = ArrayList<Pair<DyeColor?, Supplier<T>>>()
values.add(null to Entry(prefix) { factory.invoke(null) })
MRegistry.DYE_ORDER.forEach { values.add(it to Entry(prefix + "_" + it.name.lowercase()) { factory.invoke(it) }) }
return SupplierMap(values)
}
fun <T : R> register(name: String, factory: Supplier<T>) = Entry(name, factory)
fun <T : R> register(name: String, factory: Supplier<T>, serial: Boolean) = Entry(name, factory, serial)
fun <T : R> register(name: String, serial: Boolean, factory: Supplier<T>) = Entry(name, factory, serial)
private fun onRegisterEvent(event: RegisterEvent) {
if (event.registryKey == registry) {
allowRegistration = false
for (stage in stages) {
stage.run().forEach {
event.register(registry, it.key, it)
}
}
}
}
fun register(bus: IEventBus) {
check(!eventRegistered) { "Already registered!" }
eventRegistered = true
bus.addListener(this::onRegisterEvent)
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}

View File

@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate
import ru.dbotthepony.mc.otm.entity.PlasmaProjectile
object MEntityTypes {
private val registry: DeferredRegister<EntityType<*>> = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(ForgeRegistries.ENTITY_TYPES)
val PLASMA: EntityType<*> by registry.register(MNames.PLASMA) {
EntityType.Builder.of<PlasmaProjectile>({ _, level -> PlasmaProjectile(level) }, MobCategory.MISC).sized(0.4f, 0.4f).build(MNames.PLASMA)

View File

@ -15,8 +15,8 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
import java.util.function.Consumer
object MFluids {
private val types: DeferredRegister<FluidType> = DeferredRegister.create(ForgeRegistries.FLUID_TYPES, OverdriveThatMatters.MOD_ID)
private val fluids: DeferredRegister<Fluid> = DeferredRegister.create(ForgeRegistries.FLUIDS, OverdriveThatMatters.MOD_ID)
private val types = MDeferredRegister(ForgeRegistries.Keys.FLUID_TYPES)
private val fluids = MDeferredRegister(ForgeRegistries.FLUIDS)
internal fun register(bus: IEventBus) {
types.register(bus)

View File

@ -10,7 +10,7 @@ import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem
object MItemFunctionTypes {
private val registry = DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(Registries.LOOT_FUNCTION_TYPE, OverdriveThatMatters.MOD_ID)
val COPY_TILE_NBT: LootItemFunctionType by registry.register("copy_tile_nbt") { LootItemFunctionType(CopyTileNbtFunction.CODEC) }
val PROCEDURAL_BATTERY: LootItemFunctionType by registry.register(MNames.PROCEDURAL_BATTERY) { LootItemFunctionType(ProceduralBatteryItem.Randomizer.CODEC) }

View File

@ -48,7 +48,7 @@ import java.util.function.Supplier
object MItems {
private val DEFAULT_PROPERTIES = Properties()
private val registry: DeferredRegister<Item> = DeferredRegister.create(ForgeRegistries.ITEMS, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(ForgeRegistries.ITEMS)
private fun register(name: String, blocks: Map<DyeColor?, Block>, properties: Properties = DEFAULT_PROPERTIES): Map<DyeColor?, BlockItem> {
return registry.coloredWithBase(name) { color -> BlockItem(blocks[color]!!, properties) }

View File

@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
object MLootItemConditions {
private val registry = DeferredRegister.create(Registries.LOOT_CONDITION_TYPE, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(Registries.LOOT_CONDITION_TYPE, OverdriveThatMatters.MOD_ID)
val HAS_EXOPACK: LootItemConditionType by registry.register("has_exopack") { LootItemConditionType(SingletonCodec(HasExoPackCondition)) }
val CHANCE_WITH_PLAYTIME: LootItemConditionType by registry.register("chance_with_playtime") { LootItemConditionType(ChanceWithPlaytimeCondition.CODEC) }

View File

@ -75,43 +75,43 @@ import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
object MMenus {
private val registry = DeferredRegister.create(ForgeRegistries.MENU_TYPES, OverdriveThatMatters.MOD_ID)
private val registry = MDeferredRegister(ForgeRegistries.MENU_TYPES)
val ANDROID_STATION: MenuType<AndroidStationMenu> by registry.register(MNames.ANDROID_STATION) { MenuType(::AndroidStationMenu, FeatureFlags.VANILLA_SET) }
val ANDROID_CHARGER: MenuType<AndroidChargerMenu> by registry.register(MNames.ANDROID_CHARGER) { MenuType({ a, b -> AndroidChargerMenu(a, b, null as AndroidChargerBlockEntity?) }, FeatureFlags.VANILLA_SET) }
val BATTERY_BANK: MenuType<BatteryBankMenu> by registry.register(MNames.BATTERY_BANK) { MenuType(::BatteryBankMenu, FeatureFlags.VANILLA_SET) }
val MATTER_DECOMPOSER: MenuType<MatterDecomposerMenu> by registry.register(MNames.MATTER_DECOMPOSER) { MenuType(::MatterDecomposerMenu, FeatureFlags.VANILLA_SET) }
val MATTER_CAPACITOR_BANK: MenuType<MatterCapacitorBankMenu> by registry.register(MNames.MATTER_CAPACITOR_BANK) { MenuType(::MatterCapacitorBankMenu, FeatureFlags.VANILLA_SET) }
val PATTERN_STORAGE: MenuType<PatternStorageMenu> by registry.register(MNames.PATTERN_STORAGE) { MenuType(::PatternStorageMenu, FeatureFlags.VANILLA_SET) }
val MATTER_SCANNER: MenuType<MatterScannerMenu> by registry.register(MNames.MATTER_SCANNER) { MenuType(::MatterScannerMenu, FeatureFlags.VANILLA_SET) }
val MATTER_PANEL: MenuType<MatterPanelMenu> by registry.register(MNames.MATTER_PANEL) { MenuType(::MatterPanelMenu, FeatureFlags.VANILLA_SET) }
val MATTER_REPLICATOR: MenuType<MatterReplicatorMenu> by registry.register(MNames.MATTER_REPLICATOR) { MenuType(::MatterReplicatorMenu, FeatureFlags.VANILLA_SET) }
val MATTER_BOTTLER: MenuType<MatterBottlerMenu> by registry.register(MNames.MATTER_BOTTLER) { MenuType(::MatterBottlerMenu, FeatureFlags.VANILLA_SET) }
val DRIVE_VIEWER: MenuType<DriveViewerMenu> by registry.register(MNames.DRIVE_VIEWER) { MenuType(::DriveViewerMenu, FeatureFlags.VANILLA_SET) }
val CARGO_CRATE: MenuType<CargoCrateMenu> by registry.register(MNames.CARGO_CRATE) { MenuType(::CargoCrateMenu, FeatureFlags.VANILLA_SET) }
val MINECART_CARGO_CRATE: MenuType<MinecartCargoCrateMenu> by registry.register(MNames.MINECART_CARGO_CRATE) { MenuType(::MinecartCargoCrateMenu, FeatureFlags.VANILLA_SET) }
val DRIVE_RACK: MenuType<DriveRackMenu> by registry.register(MNames.DRIVE_RACK) { MenuType(::DriveRackMenu, FeatureFlags.VANILLA_SET) }
val ITEM_MONITOR: MenuType<ItemMonitorMenu> by registry.register(MNames.ITEM_MONITOR) { MenuType(::ItemMonitorMenu, FeatureFlags.VANILLA_SET) }
val ENERGY_COUNTER: MenuType<EnergyCounterMenu> by registry.register(MNames.ENERGY_COUNTER) { MenuType(::EnergyCounterMenu, FeatureFlags.VANILLA_SET) }
val CHEMICAL_GENERATOR: MenuType<ChemicalGeneratorMenu> by registry.register(MNames.CHEMICAL_GENERATOR) { MenuType(::ChemicalGeneratorMenu, FeatureFlags.VANILLA_SET) }
val PLATE_PRESS: MenuType<PlatePressMenu> by registry.register(MNames.PLATE_PRESS) { MenuType(::PlatePressMenu, FeatureFlags.VANILLA_SET) }
val POWERED_FURNACE: MenuType<PoweredFurnaceMenu> by registry.register(MNames.POWERED_FURNACE) { MenuType(PoweredFurnaceMenu::furnace, FeatureFlags.VANILLA_SET) }
val POWERED_BLAST_FURNACE: MenuType<PoweredFurnaceMenu> by registry.register(MNames.POWERED_BLAST_FURNACE) { MenuType(PoweredFurnaceMenu::blasting, FeatureFlags.VANILLA_SET) }
val POWERED_SMOKER: MenuType<PoweredFurnaceMenu> by registry.register(MNames.POWERED_SMOKER) { MenuType(PoweredFurnaceMenu::smoking, FeatureFlags.VANILLA_SET) }
val TWIN_PLATE_PRESS: MenuType<TwinPlatePressMenu> by registry.register(MNames.TWIN_PLATE_PRESS) { MenuType(::TwinPlatePressMenu, FeatureFlags.VANILLA_SET) }
val MATTER_RECYCLER: MenuType<MatterRecyclerMenu> by registry.register(MNames.MATTER_RECYCLER) { MenuType(::MatterRecyclerMenu, FeatureFlags.VANILLA_SET) }
val ENERGY_SERVO: MenuType<EnergyServoMenu> by registry.register(MNames.ENERGY_SERVO) { MenuType(::EnergyServoMenu, FeatureFlags.VANILLA_SET) }
val HOLO_SIGN: MenuType<HoloSignMenu> by registry.register(MNames.HOLO_SIGN) { MenuType(::HoloSignMenu, FeatureFlags.VANILLA_SET) }
val COBBLESTONE_GENERATOR: MenuType<CobblerMenu> by registry.register(MNames.COBBLESTONE_GENERATOR) { MenuType(::CobblerMenu, FeatureFlags.VANILLA_SET) }
val ESSENCE_STORAGE: MenuType<EssenceStorageMenu> by registry.register(MNames.ESSENCE_STORAGE) { MenuType(::EssenceStorageMenu, FeatureFlags.VANILLA_SET) }
val ITEM_REPAIER: MenuType<MatterReconstructorMenu> by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) }
val FLUID_TANK: MenuType<FluidTankMenu> by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) }
val PAINTER: MenuType<PainterMenu> by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) }
val MATTER_ENTANGLER: MenuType<MatterEntanglerMenu> by registry.register(MNames.MATTER_ENTANGLER) { MenuType(::MatterEntanglerMenu, FeatureFlags.VANILLA_SET) }
val ANDROID_STATION by registry.register(MNames.ANDROID_STATION) { MenuType(::AndroidStationMenu, FeatureFlags.VANILLA_SET) }
val ANDROID_CHARGER by registry.register(MNames.ANDROID_CHARGER) { MenuType({ a, b -> AndroidChargerMenu(a, b, null as AndroidChargerBlockEntity?) }, FeatureFlags.VANILLA_SET) }
val BATTERY_BANK by registry.register(MNames.BATTERY_BANK) { MenuType(::BatteryBankMenu, FeatureFlags.VANILLA_SET) }
val MATTER_DECOMPOSER by registry.register(MNames.MATTER_DECOMPOSER) { MenuType(::MatterDecomposerMenu, FeatureFlags.VANILLA_SET) }
val MATTER_CAPACITOR_BANK by registry.register(MNames.MATTER_CAPACITOR_BANK) { MenuType(::MatterCapacitorBankMenu, FeatureFlags.VANILLA_SET) }
val PATTERN_STORAGE by registry.register(MNames.PATTERN_STORAGE) { MenuType(::PatternStorageMenu, FeatureFlags.VANILLA_SET) }
val MATTER_SCANNER by registry.register(MNames.MATTER_SCANNER) { MenuType(::MatterScannerMenu, FeatureFlags.VANILLA_SET) }
val MATTER_PANEL by registry.register(MNames.MATTER_PANEL) { MenuType(::MatterPanelMenu, FeatureFlags.VANILLA_SET) }
val MATTER_REPLICATOR by registry.register(MNames.MATTER_REPLICATOR) { MenuType(::MatterReplicatorMenu, FeatureFlags.VANILLA_SET) }
val MATTER_BOTTLER by registry.register(MNames.MATTER_BOTTLER) { MenuType(::MatterBottlerMenu, FeatureFlags.VANILLA_SET) }
val DRIVE_VIEWER by registry.register(MNames.DRIVE_VIEWER) { MenuType(::DriveViewerMenu, FeatureFlags.VANILLA_SET) }
val CARGO_CRATE by registry.register(MNames.CARGO_CRATE) { MenuType(::CargoCrateMenu, FeatureFlags.VANILLA_SET) }
val MINECART_CARGO_CRATE by registry.register(MNames.MINECART_CARGO_CRATE) { MenuType(::MinecartCargoCrateMenu, FeatureFlags.VANILLA_SET) }
val DRIVE_RACK by registry.register(MNames.DRIVE_RACK) { MenuType(::DriveRackMenu, FeatureFlags.VANILLA_SET) }
val ITEM_MONITOR by registry.register(MNames.ITEM_MONITOR) { MenuType(::ItemMonitorMenu, FeatureFlags.VANILLA_SET) }
val ENERGY_COUNTER by registry.register(MNames.ENERGY_COUNTER) { MenuType(::EnergyCounterMenu, FeatureFlags.VANILLA_SET) }
val CHEMICAL_GENERATOR by registry.register(MNames.CHEMICAL_GENERATOR) { MenuType(::ChemicalGeneratorMenu, FeatureFlags.VANILLA_SET) }
val PLATE_PRESS by registry.register(MNames.PLATE_PRESS) { MenuType(::PlatePressMenu, FeatureFlags.VANILLA_SET) }
val POWERED_FURNACE by registry.register(MNames.POWERED_FURNACE) { MenuType(PoweredFurnaceMenu::furnace, FeatureFlags.VANILLA_SET) }
val POWERED_BLAST_FURNACE by registry.register(MNames.POWERED_BLAST_FURNACE) { MenuType(PoweredFurnaceMenu::blasting, FeatureFlags.VANILLA_SET) }
val POWERED_SMOKER by registry.register(MNames.POWERED_SMOKER) { MenuType(PoweredFurnaceMenu::smoking, FeatureFlags.VANILLA_SET) }
val TWIN_PLATE_PRESS by registry.register(MNames.TWIN_PLATE_PRESS) { MenuType(::TwinPlatePressMenu, FeatureFlags.VANILLA_SET) }
val MATTER_RECYCLER by registry.register(MNames.MATTER_RECYCLER) { MenuType(::MatterRecyclerMenu, FeatureFlags.VANILLA_SET) }
val ENERGY_SERVO by registry.register(MNames.ENERGY_SERVO) { MenuType(::EnergyServoMenu, FeatureFlags.VANILLA_SET) }
val HOLO_SIGN by registry.register(MNames.HOLO_SIGN) { MenuType(::HoloSignMenu, FeatureFlags.VANILLA_SET) }
val COBBLESTONE_GENERATOR by registry.register(MNames.COBBLESTONE_GENERATOR) { MenuType(::CobblerMenu, FeatureFlags.VANILLA_SET) }
val ESSENCE_STORAGE by registry.register(MNames.ESSENCE_STORAGE) { MenuType(::EssenceStorageMenu, FeatureFlags.VANILLA_SET) }
val ITEM_REPAIER by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) }
val FLUID_TANK by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) }
val PAINTER by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) }
val MATTER_ENTANGLER by registry.register(MNames.MATTER_ENTANGLER) { MenuType(::MatterEntanglerMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_BUS: MenuType<StorageBusMenu> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_IMPORTER_EXPORTER: MenuType<StorageImporterExporterMenu> by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_POWER_SUPPLIER: MenuType<StoragePowerSupplierMenu> by registry.register(MNames.STORAGE_POWER_SUPPLIER) { MenuType(::StoragePowerSupplierMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_BUS by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_IMPORTER_EXPORTER by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_POWER_SUPPLIER by registry.register(MNames.STORAGE_POWER_SUPPLIER) { MenuType(::StoragePowerSupplierMenu, FeatureFlags.VANILLA_SET) }
internal fun register(bus: IEventBus) {
registry.register(bus)

View File

@ -20,15 +20,15 @@ object MRecipes {
}
}
private val types = DeferredRegister.create(ForgeRegistries.RECIPE_TYPES, OverdriveThatMatters.MOD_ID)
private val serializers = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, OverdriveThatMatters.MOD_ID)
private val types = MDeferredRegister(ForgeRegistries.RECIPE_TYPES, OverdriveThatMatters.MOD_ID)
private val serializers = MDeferredRegister(ForgeRegistries.RECIPE_SERIALIZERS, OverdriveThatMatters.MOD_ID)
internal fun register(bus: IEventBus) {
types.register(bus)
serializers.register(bus)
}
private fun <T : Recipe<*>> register(name: String): RegistryObject<Type<T>> {
private fun <T : Recipe<*>> register(name: String): MDeferredRegister<*>.Entry<Type<T>> {
return types.register(name) { Type(name) }
}

View File

@ -114,11 +114,11 @@ object MRegistry : IBlockItemRegistryAcceptor {
private val decorativeBlocks = ArrayList<IBlockItemRegistryAcceptor>()
override fun registerItems(registry: DeferredRegister<Item>) {
override fun registerItems(registry: MDeferredRegister<Item>) {
decorativeBlocks.forEach { it.registerItems(registry) }
}
override fun registerBlocks(registry: DeferredRegister<Block>) {
override fun registerBlocks(registry: MDeferredRegister<Block>) {
decorativeBlocks.forEach { it.registerBlocks(registry) }
}

View File

@ -11,19 +11,19 @@ import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters
object MSoundEvents {
private val registry: DeferredRegister<SoundEvent> = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, OverdriveThatMatters.MOD_ID)
private val registry: MDeferredRegister<SoundEvent> = MDeferredRegister(ForgeRegistries.SOUND_EVENTS, OverdriveThatMatters.MOD_ID)
// TODO: 1.19.3
private fun make(name: String) = registry.register(name) { SoundEvent.createVariableRangeEvent(ResourceLocation(OverdriveThatMatters.MOD_ID, name)) }
private fun make(name: String): MDeferredRegister<SoundEvent>.Entry<SoundEvent> = registry.register(name) { SoundEvent.createVariableRangeEvent(ResourceLocation(OverdriveThatMatters.MOD_ID, name)) }
val RIFLE_SHOT: SoundEvent by make("item.rifle_shot")
val PLASMA_WEAPON_OVERHEAT: SoundEvent by make("item.plasma_weapon_overheat")
val PLAYER_BECOME_ANDROID: SoundEvent by make("player_become_android")
val CARGO_CRATE_OPEN: SoundEvent by make("cargo_crate_open")
val RIFLE_SHOT by make("item.rifle_shot")
val PLASMA_WEAPON_OVERHEAT by make("item.plasma_weapon_overheat")
val PLAYER_BECOME_ANDROID by make("player_become_android")
val CARGO_CRATE_OPEN by make("cargo_crate_open")
val ANDROID_JUMP_BOOST: SoundEvent by make("android.jump_boost")
val ANDROID_SHOCKWAVE: SoundEvent by make("android.shockwave")
val ANDROID_PROJ_PARRY: SoundEvent by make("android.projectile_parry")
val ANDROID_JUMP_BOOST by make("android.jump_boost")
val ANDROID_SHOCKWAVE by make("android.shockwave")
val ANDROID_PROJ_PARRY by make("android.projectile_parry")
internal fun register(bus: IEventBus) {
registry.register(bus)

View File

@ -8,8 +8,10 @@ import net.minecraft.world.level.block.state.BlockBehaviour
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.EnumMap
import java.util.function.Supplier
/**
* Colored only
@ -25,8 +27,8 @@ open class ColoredDecorativeBlock(
var registeredBlocks = false
private set
protected val itemMap = EnumMap<DyeColor, RegistryObject<Item>>(DyeColor::class.java)
protected val blockMap = EnumMap<DyeColor, RegistryObject<Block>>(DyeColor::class.java)
protected val itemMap = EnumMap<DyeColor, Supplier<Item>>(DyeColor::class.java)
protected val blockMap = EnumMap<DyeColor, Supplier<Block>>(DyeColor::class.java)
fun forEachItem(consumer: (String, DyeColor, Item) -> Unit) {
MRegistry.DYE_ORDER.forEach {
@ -60,7 +62,7 @@ open class ColoredDecorativeBlock(
SupplierMap(MRegistry.DYE_ORDER.map { it to itemMap[it]!! })
}
override fun registerBlocks(registry: DeferredRegister<Block>) {
override fun registerBlocks(registry: MDeferredRegister<Block>) {
check(blockMap.isEmpty()) { "( ͡° ͜ʖ ͡°) No. \\(• ε •)/ ( ͠° ل͜ ͡°) ( ͠° ͟ ͟ʖ ͡°) (ง ͠° ͟ل͜ ͡°)ง ( ͡°︺͡°) ('ω')" }
MRegistry.DYE_ORDER.forEach {
@ -72,7 +74,7 @@ open class ColoredDecorativeBlock(
private val properties = Item.Properties().stacksTo(64)
override fun registerItems(registry: DeferredRegister<Item>) {
override fun registerItems(registry: MDeferredRegister<Item>) {
check(itemMap.isEmpty()) { "( ͡° ͜ʖ ͡°) No. \\(• ε •)/ ( ͠° ل͜ ͡°) ( ͠° ͟ ͟ʖ ͡°) (ง ͠° ͟ل͜ ͡°)ง ( ͡°︺͡°) ('ω')" }
check(registeredBlocks) { "wtffffff???????????" }

View File

@ -11,17 +11,16 @@ import net.minecraft.world.level.block.state.BlockBehaviour
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.getShapeForEachState
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.shapes.BlockShape
import ru.dbotthepony.mc.otm.shapes.BlockShapes
import java.util.function.Supplier
import java.util.stream.Stream
/**
@ -31,8 +30,8 @@ class DecorativeBlock(
baseName: String,
private val provider: (DyeColor?) -> Block,
) : ColoredDecorativeBlock(baseName, provider) {
private var _block: RegistryObject<Block> by WriteOnce()
private var _item: RegistryObject<Item> by WriteOnce()
private var _block: Supplier<Block> by WriteOnce()
private var _item: Supplier<Item> by WriteOnce()
val block: Block get() = _block.get()
val item: Item get() = _item.get()
@ -47,12 +46,12 @@ class DecorativeBlock(
SupplierMap(Streams.concat(MRegistry.DYE_ORDER.stream().map { it to itemMap[it]!! }, Stream.of(null to _item)))
}
override fun registerBlocks(registry: DeferredRegister<Block>) {
override fun registerBlocks(registry: MDeferredRegister<Block>) {
_block = registry.register(baseName) { provider.invoke(null) }
super.registerBlocks(registry)
}
override fun registerItems(registry: DeferredRegister<Item>) {
override fun registerItems(registry: MDeferredRegister<Item>) {
_item = registry.register(baseName) { BlockItem(_block.get(), Item.Properties().stacksTo(64)) }
super.registerItems(registry)
}

View File

@ -2,9 +2,9 @@ package ru.dbotthepony.mc.otm.registry.objects
import net.minecraft.world.item.Item
import net.minecraft.world.level.block.Block
import net.minecraftforge.registries.DeferredRegister
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
interface IBlockItemRegistryAcceptor {
fun registerItems(registry: DeferredRegister<Item>)
fun registerBlocks(registry: DeferredRegister<Block>)
fun registerItems(registry: MDeferredRegister<Item>)
fun registerBlocks(registry: MDeferredRegister<Block>)
}

View File

@ -10,6 +10,7 @@ import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.core.collect.SupplierList
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import java.util.EnumMap
import java.util.function.Supplier
@ -21,8 +22,8 @@ class StripedColoredDecorativeBlock(
BlockItem(block, Item.Properties().stacksTo(64))
}
) : IBlockItemRegistryAcceptor {
private val mapBlocks = EnumMap<DyeColor, EnumMap<DyeColor, RegistryObject<Block>>>(DyeColor::class.java)
private val mapItems = EnumMap<DyeColor, EnumMap<DyeColor, RegistryObject<Item>>>(DyeColor::class.java)
private val mapBlocks = EnumMap<DyeColor, EnumMap<DyeColor, Supplier<Block>>>(DyeColor::class.java)
private val mapItems = EnumMap<DyeColor, EnumMap<DyeColor, Supplier<Item>>>(DyeColor::class.java)
fun getBlockNullable(base: DyeColor, stripe: DyeColor): Block? {
check(registeredBlocks) { "Didn't register items yet" }
@ -82,7 +83,7 @@ class StripedColoredDecorativeBlock(
SupplierList(mapBlocks.flatMap { it.value.values })
}
override fun registerItems(registry: DeferredRegister<Item>) {
override fun registerItems(registry: MDeferredRegister<Item>) {
for (base in DyeColor.entries) {
for (stripe in DyeColor.entries) {
if (base == stripe) {
@ -97,7 +98,7 @@ class StripedColoredDecorativeBlock(
registeredItems = true
}
override fun registerBlocks(registry: DeferredRegister<Block>) {
override fun registerBlocks(registry: MDeferredRegister<Block>) {
for (base in DyeColor.entries) {
for (stripe in DyeColor.entries) {
if (base == stripe) {