Compare commits

...

11 Commits

37 changed files with 1116 additions and 30 deletions

View File

@ -209,6 +209,9 @@ dependencies {
// runtimeOnly("curse.maven:integrated-tunnels-251389:4344632")
implementation("mekanism:Mekanism:${mc_version}-${mekanism_version}")
implementation("curse.maven:iron-chests-228756:5491156")
implementation("curse.maven:iron-shulker-boxes-314911:5491246")
}
}
@ -268,6 +271,8 @@ minecraft {
mixin {
config("$mod_id.mixins.json")
config("$mod_id.ironchest.mixins.json")
config("$mod_id.ironshulkerbox.mixins.json")
// config("$mod_id.ad_astra.mixins.json")
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.CopperChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(CopperChestBlockEntity.class)
public abstract class CopperChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.copper(containerId, inventory, ((CopperChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.CrystalChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(CrystalChestBlockEntity.class)
public abstract class CrystalChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.crystal(containerId, inventory, ((CrystalChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.DiamondChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(DiamondChestBlockEntity.class)
public abstract class DiamondChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.diamond(containerId, inventory, ((DiamondChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.DirtChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(DirtChestBlockEntity.class)
public abstract class DirtChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.dirt(containerId, inventory, ((DirtChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.GoldChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(GoldChestBlockEntity.class)
public abstract class GoldChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.gold(containerId, inventory, ((GoldChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.IronChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(IronChestBlockEntity.class)
public abstract class IronChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.iron(containerId, inventory, ((IronChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.regular.entity.ObsidianChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(ObsidianChestBlockEntity.class)
public abstract class ObsidianChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.obsidian(containerId, inventory, ((ObsidianChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedCopperChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedCopperChestBlockEntity.class)
public abstract class TrappedCopperChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.copper(containerId, inventory, ((TrappedCopperChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedCrystalChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedCrystalChestBlockEntity.class)
public abstract class TrappedCrystalChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.crystal(containerId, inventory, ((TrappedCrystalChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedDiamondChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedDiamondChestBlockEntity.class)
public abstract class TrappedDiamondChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.diamond(containerId, inventory, ((TrappedDiamondChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedDirtChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedDirtChestBlockEntity.class)
public abstract class TrappedDirtChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.dirt(containerId, inventory, ((TrappedDirtChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedGoldChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedGoldChestBlockEntity.class)
public abstract class TrappedGoldChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.gold(containerId, inventory, ((TrappedGoldChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedIronChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedIronChestBlockEntity.class)
public abstract class TrappedIronChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.iron(containerId, inventory, ((TrappedIronChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironchest;
import com.progwml6.ironchest.common.block.trapped.entity.TrappedObsidianChestBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironchest.MatteryIronChestMenu;
@Mixin(TrappedObsidianChestBlockEntity.class)
public abstract class TrappedObsidianChestBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronChestMenu.obsidian(containerId, inventory, ((TrappedObsidianChestBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.CopperShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(CopperShulkerBoxBlockEntity.class)
public abstract class CopperShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.copper(containerId, inventory, ((CopperShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.CrystalShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(CrystalShulkerBoxBlockEntity.class)
public abstract class CrystalShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.crystal(containerId, inventory, ((CrystalShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.DiamondShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(DiamondShulkerBoxBlockEntity.class)
public abstract class DiamondShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.diamond(containerId, inventory, ((DiamondShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.GoldShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(GoldShulkerBoxBlockEntity.class)
public abstract class GoldShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.gold(containerId, inventory, ((GoldShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.IronShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(IronShulkerBoxBlockEntity.class)
public abstract class IronShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.iron(containerId, inventory, ((IronShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin.ironshulkerbox;
import com.progwml6.ironshulkerbox.common.block.entity.ObsidianShulkerBoxBlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu;
@Mixin(ObsidianShulkerBoxBlockEntity.class)
public abstract class ObsidianShulkerBoxBlockEntityMixin {
@Overwrite(remap = false)
public AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return MatteryIronShulkerBoxMenu.obsidian(containerId, inventory, ((ObsidianShulkerBoxBlockEntity)(Object) this));
}
}

View File

@ -44,6 +44,10 @@ import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer
import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer
import ru.dbotthepony.mc.otm.compat.curios.isCuriosLoaded
import ru.dbotthepony.mc.otm.compat.curios.onCuriosSlotModifiersUpdated
import ru.dbotthepony.mc.otm.compat.ironchest.IronChestMenuTypes
import ru.dbotthepony.mc.otm.compat.ironchest.isIronChestLoaded
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.IronShulkersMenuTypes
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.isIronShulkersLoaded
import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu
import ru.dbotthepony.mc.otm.compat.vanilla.VanillaMenuTypes
import ru.dbotthepony.mc.otm.config.PlayerConfig
@ -134,6 +138,14 @@ object OverdriveThatMatters {
StorageStack.register(MOD_BUS)
VanillaMenuTypes.register(MOD_BUS)
if (isIronChestLoaded) {
IronChestMenuTypes.register(MOD_BUS)
}
if (isIronShulkersLoaded) {
IronShulkersMenuTypes.register(MOD_BUS)
}
MCreativeTabs.initialize(MOD_BUS)
MOD_BUS.addListener(::registerNetworkPackets)

View File

@ -31,7 +31,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
import java.util.Collections.emptyIterator
import java.util.stream.Stream
val isCosmeticArmorLoaded by lazy {
internal val isCosmeticArmorLoaded by lazy {
ModList.get().isLoaded("cosmeticarmorreworked")
}

View File

@ -35,7 +35,7 @@ import java.util.Collections.emptyIterator
import java.util.stream.Stream
import kotlin.collections.ArrayList
val isCuriosLoaded by lazy {
internal val isCuriosLoaded by lazy {
ModList.get().isLoaded(CuriosApi.MODID)
}

View File

@ -0,0 +1,66 @@
package ru.dbotthepony.mc.otm.compat.ironchest
import com.progwml6.ironchest.IronChests
import com.progwml6.ironchest.common.block.IronChestsTypes
import net.minecraft.core.BlockPos
import net.minecraft.core.registries.Registries
import net.minecraft.world.Container
import net.minecraft.world.flag.FeatureFlags
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.bus.api.IEventBus
import net.neoforged.fml.ModList
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.IQuickStackContainer
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.compat.vanilla.VanillaChestScreen
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
internal val isIronChestLoaded by lazy {
ModList.get().isLoaded(IronChests.MODID)
}
object IronChestMenuTypes {
private val registrar = MDeferredRegister(Registries.MENU, OverdriveThatMatters.MOD_ID)
val IRON by registrar.register("ironchest_iron") { MenuType(MatteryIronChestMenu::iron, FeatureFlags.VANILLA_SET) }
val GOLD by registrar.register("ironchest_gold") { MenuType(MatteryIronChestMenu::gold, FeatureFlags.VANILLA_SET) }
val DIAMOND by registrar.register("ironchest_diamond") { MenuType(MatteryIronChestMenu::diamond, FeatureFlags.VANILLA_SET) }
val COPPER by registrar.register("ironchest_copper") { MenuType(MatteryIronChestMenu::copper, FeatureFlags.VANILLA_SET) }
val CRYSTAL by registrar.register("ironchest_crystal") { MenuType(MatteryIronChestMenu::crystal, FeatureFlags.VANILLA_SET) }
val OBSIDIAN by registrar.register("ironchest_obsidian") { MenuType(MatteryIronChestMenu::obsidian, FeatureFlags.VANILLA_SET) }
val DIRT by registrar.register("ironchest_dirt") { MenuType(MatteryIronChestMenu::dirt, FeatureFlags.VANILLA_SET) }
private fun provider(level: Level, pos: BlockPos, state: BlockState, blockEntity: BlockEntity?, context: Void?): IQuickStackContainer? {
val container = blockEntity as? Container ?: return null
return IQuickStackContainer.Simple(makeSlots(container, ::MatteryMenuSlot))
}
fun registerCapabilities(event: RegisterCapabilitiesEvent) {
IronChestsTypes.entries.map { IronChestsTypes.get(it) }.forEach {
event.registerBlock(MatteryCapability.QUICK_STACK_CONTAINER, ::provider, *it.toTypedArray())
}
}
internal fun register(bus: IEventBus) {
registrar.register(bus)
bus.addListener(this::registerScreens)
bus.addListener(this::registerCapabilities)
}
private fun registerScreens(event: RegisterMenuScreensEvent) {
event.register(IRON, ::VanillaChestScreen)
event.register(GOLD, ::VanillaChestScreen)
event.register(DIAMOND, ::VanillaChestScreen)
event.register(COPPER, ::VanillaChestScreen)
event.register(CRYSTAL, ::VanillaChestScreen)
event.register(OBSIDIAN, ::VanillaChestScreen)
event.register(DIRT, ::VanillaChestScreen)
}
}

View File

@ -0,0 +1,82 @@
package ru.dbotthepony.mc.otm.compat.ironchest
import com.progwml6.ironchest.common.block.IronChestsTypes
import net.minecraft.world.Container
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import ru.dbotthepony.mc.otm.compat.vanilla.AbstractVanillaChestMenu
import ru.dbotthepony.mc.otm.container.EnhancedContainer
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
import ru.dbotthepony.mc.otm.menu.QuickMoveInput
import ru.dbotthepony.mc.otm.menu.makeSlots
class MatteryIronChestMenu(
type: MenuType<*>, containerId: Int,
inventory: Inventory, chestType: IronChestsTypes,
container: Container = EnhancedContainer.Simple(chestType.size),
) : AbstractVanillaChestMenu(type, containerId, inventory, container) {
override val columns = chestType.rowLength
override val rows = chestType.size / chestType.rowLength
override val containerSlots = if (chestType == IronChestsTypes.DIRT) makeSlots(container, ::MDirtChestSlot) else makeSlots(container, ::MatteryMenuSlot)
init {
container.startOpen(player)
addStorageSlot(containerSlots)
addInventorySlots()
}
override val quickMoveToStorage = QuickMoveInput.create(this, playerCombinedInventorySlots, containerSlots)
override val quickMoveFromStorage = QuickMoveInput.create(this, containerSlots, playerInventorySlots, false)
class MDirtChestSlot(container: Container, slot: Int) : MatteryMenuSlot(container, slot) {
override fun mayPlace(stack: ItemStack): Boolean = stack.isEmpty || stack.`is`(Items.DIRT)
}
companion object {
@JvmStatic
@JvmOverloads
fun iron(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.IRON.size), chestType: IronChestsTypes = IronChestsTypes.IRON): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.IRON, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun gold(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.GOLD.size), chestType: IronChestsTypes = IronChestsTypes.GOLD): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.GOLD, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun diamond(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.DIAMOND.size), chestType: IronChestsTypes = IronChestsTypes.DIAMOND): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.DIAMOND, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun copper(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.COPPER.size), chestType: IronChestsTypes = IronChestsTypes.COPPER): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.COPPER, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun crystal(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.CRYSTAL.size), chestType: IronChestsTypes = IronChestsTypes.CRYSTAL): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.CRYSTAL, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun obsidian(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.OBSIDIAN.size), chestType: IronChestsTypes = IronChestsTypes.OBSIDIAN): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.OBSIDIAN, containerId, inventory, chestType, container)
}
@JvmStatic
@JvmOverloads
fun dirt(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronChestsTypes.DIRT.size), chestType: IronChestsTypes = IronChestsTypes.DIRT): MatteryIronChestMenu {
return MatteryIronChestMenu(IronChestMenuTypes.DIRT, containerId, inventory, chestType, container)
}
}
}

View File

@ -0,0 +1,68 @@
package ru.dbotthepony.mc.otm.compat.ironshulkerbox
import com.progwml6.ironshulkerbox.IronShulkerBoxes
import com.progwml6.ironshulkerbox.common.block.IronShulkerBoxesTypes
import net.minecraft.core.BlockPos
import net.minecraft.core.registries.Registries
import net.minecraft.world.Container
import net.minecraft.world.flag.FeatureFlags
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.DyeColor
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.bus.api.IEventBus
import net.neoforged.fml.ModList
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.IQuickStackContainer
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.compat.ironshulkerbox.MatteryIronShulkerBoxMenu.Slot
import ru.dbotthepony.mc.otm.compat.vanilla.VanillaChestScreen
import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import kotlin.collections.toTypedArray
internal val isIronShulkersLoaded by lazy {
ModList.get().isLoaded(IronShulkerBoxes.MODID)
}
object IronShulkersMenuTypes {
private val registrar = MDeferredRegister(Registries.MENU, OverdriveThatMatters.MOD_ID)
val IRON by registrar.register("ironshulkerbox_iron") { MenuType(MatteryIronShulkerBoxMenu::iron, FeatureFlags.VANILLA_SET) }
val GOLD by registrar.register("ironshulkerbox_gold") { MenuType(MatteryIronShulkerBoxMenu::gold, FeatureFlags.VANILLA_SET) }
val DIAMOND by registrar.register("ironshulkerbox_diamond") { MenuType(MatteryIronShulkerBoxMenu::diamond, FeatureFlags.VANILLA_SET) }
val COPPER by registrar.register("ironshulkerbox_copper") { MenuType(MatteryIronShulkerBoxMenu::copper, FeatureFlags.VANILLA_SET) }
val CRYSTAL by registrar.register("ironshulkerbox_crystal") { MenuType(MatteryIronShulkerBoxMenu::crystal, FeatureFlags.VANILLA_SET) }
val OBSIDIAN by registrar.register("ironshulkerbox_obsidian") { MenuType(MatteryIronShulkerBoxMenu::obsidian, FeatureFlags.VANILLA_SET) }
private fun provider(level: Level, pos: BlockPos, state: BlockState, blockEntity: BlockEntity?, context: Void?): IQuickStackContainer? {
val container = blockEntity as? Container ?: return null
return IQuickStackContainer.Simple(makeSlots(container, ::Slot))
}
fun registerCapabilities(event: RegisterCapabilitiesEvent) {
val colors = DyeColor.entries.toMutableList<DyeColor?>().also { it.add(0, null) }
IronShulkerBoxesTypes.entries.forEach { type ->
event.registerBlock(MatteryCapability.QUICK_STACK_CONTAINER, ::provider, *colors.map { IronShulkerBoxesTypes.get(type, it) }.toTypedArray())
}
}
internal fun register(bus: IEventBus) {
registrar.register(bus)
bus.addListener(this::registerScreens)
bus.addListener(this::registerCapabilities)
}
private fun registerScreens(event: RegisterMenuScreensEvent) {
event.register(IRON, ::VanillaChestScreen)
event.register(GOLD, ::VanillaChestScreen)
event.register(DIAMOND, ::VanillaChestScreen)
event.register(COPPER, ::VanillaChestScreen)
event.register(CRYSTAL, ::VanillaChestScreen)
event.register(OBSIDIAN, ::VanillaChestScreen)
}
}

View File

@ -0,0 +1,77 @@
package ru.dbotthepony.mc.otm.compat.ironshulkerbox
import com.progwml6.ironshulkerbox.common.block.IronShulkerBoxesTypes
import net.minecraft.world.Container
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.compat.vanilla.AbstractVanillaChestMenu
import ru.dbotthepony.mc.otm.container.EnhancedContainer
import ru.dbotthepony.mc.otm.menu.MatteryMenuSlot
import ru.dbotthepony.mc.otm.menu.QuickMoveInput
import ru.dbotthepony.mc.otm.menu.makeSlots
class MatteryIronShulkerBoxMenu(
type: MenuType<*>, containerId: Int,
inventory: Inventory, boxType: IronShulkerBoxesTypes,
container: Container = EnhancedContainer.Simple(boxType.size)
) : AbstractVanillaChestMenu(type, containerId, inventory, container) {
override val rows: Int = boxType.size / boxType.rowLength
override val columns: Int = boxType.rowLength
override val containerSlots = makeSlots(container, ::Slot)
init {
container.startOpen(player)
addStorageSlot(containerSlots)
addInventorySlots()
}
override val quickMoveToStorage = QuickMoveInput.create(this, playerCombinedInventorySlots, containerSlots)
override val quickMoveFromStorage = QuickMoveInput.create(this, containerSlots, playerInventorySlots, false)
class Slot(container: Container, slot: Int) : MatteryMenuSlot(container, slot) {
override fun mayPlace(stack: ItemStack): Boolean {
return super.mayPlace(stack) && stack.item.canFitInsideContainerItems()
}
}
companion object {
@JvmStatic
@JvmOverloads
fun iron(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.IRON.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.IRON): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.IRON, containerId, inventory, boxType, container)
}
@JvmStatic
@JvmOverloads
fun gold(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.GOLD.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.GOLD): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.GOLD, containerId, inventory, boxType, container)
}
@JvmStatic
@JvmOverloads
fun diamond(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.DIAMOND.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.DIAMOND): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.DIAMOND, containerId, inventory, boxType, container)
}
@JvmStatic
@JvmOverloads
fun copper(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.COPPER.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.COPPER): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.COPPER, containerId, inventory, boxType, container)
}
@JvmStatic
@JvmOverloads
fun crystal(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.CRYSTAL.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.CRYSTAL): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.CRYSTAL, containerId, inventory, boxType, container)
}
@JvmStatic
@JvmOverloads
fun obsidian(containerId: Int, inventory: Inventory, container: Container = SimpleContainer(IronShulkerBoxesTypes.OBSIDIAN.size), boxType: IronShulkerBoxesTypes = IronShulkerBoxesTypes.OBSIDIAN): MatteryIronShulkerBoxMenu {
return MatteryIronShulkerBoxMenu(IronShulkersMenuTypes.OBSIDIAN, containerId, inventory, boxType, container)
}
}
}

View File

@ -5,7 +5,7 @@ import net.minecraft.world.inventory.Slot
import net.neoforged.fml.ModList
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
val isItemBordersLoaded by lazy {
internal val isItemBordersLoaded by lazy {
ModList.get().isLoaded("itemborders")
}

View File

@ -39,6 +39,8 @@ object StreamCodecs {
val BLOCK_TYPE = MatteryStreamCodec.Of(FriendlyByteBuf::writeBlockType, FriendlyByteBuf::readBlockType)
val RELATIVE_SIDE = MatteryStreamCodec.Enum<FriendlyByteBuf, RelativeSide>(RelativeSide::class.java)
val DIRECTION = MatteryStreamCodec.Enum<FriendlyByteBuf, Direction>(Direction::class.java)
val RELATIVE_SIDE_NULLABLE = RELATIVE_SIDE.nullable()
val DIRECTION_NULLABLE = DIRECTION.nullable()
val RGBA: MatteryStreamCodec<ByteBuf, RGBAColor> = StreamCodec.of<ByteBuf, RGBAColor>(
{ s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue); s.writeFloat(v.alpha) },

View File

@ -1,8 +1,19 @@
package ru.dbotthepony.mc.otm.network.syncher
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.ints.Int2ReferenceLinkedOpenHashMap
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap
import it.unimi.dsi.fastutil.ints.IntArraySet
import it.unimi.dsi.fastutil.ints.IntCollection
import it.unimi.dsi.fastutil.ints.IntIterator
import it.unimi.dsi.fastutil.ints.IntSet
import it.unimi.dsi.fastutil.objects.ObjectIterator
import it.unimi.dsi.fastutil.objects.ObjectSet
import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap
import it.unimi.dsi.fastutil.objects.ReferenceCollection
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
import it.unimi.dsi.fastutil.objects.ReferenceSet
import net.minecraft.network.RegistryFriendlyByteBuf
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.mc.otm.util.IDAllocator
@ -39,7 +50,7 @@ class DynamicSynchableGroup<T : Any>(
* first-time networking of [T] to remote
*/
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {},
) : ISynchable, MutableSet<T> {
) : ISynchable, ReferenceSet<T> {
private inner class RemoteState(val listener: Runnable) : IRemoteState {
private inner class RemoteSlot(val slot: Slot<T>, fromConstructor: Boolean) : Runnable, Closeable {
val remoteState = synchable(slot.value).createRemoteState(this)
@ -188,11 +199,12 @@ class DynamicSynchableGroup<T : Any>(
}
}
private data class Slot<T : Any>(val value: T, val id: Int)
private class Slot<T : Any>(val value: T, val id: Int)
private var defaultReturnValue: T? = null
private val remoteStates = ArrayList<RemoteState>()
private val value2slot = LinkedHashMap<T, Slot<T>>()
private val id2slot = Int2ObjectOpenHashMap<Slot<T>>()
private val value2slot = Reference2ObjectLinkedOpenHashMap<T, Slot<T>>()
private val id2slot = Int2ReferenceLinkedOpenHashMap<Slot<T>>()
private val idAllocator = IDAllocator()
override val hasRemotes: Boolean
@ -210,7 +222,7 @@ class DynamicSynchableGroup<T : Any>(
REMOVE_ENTRY -> {
val id = stream.readVarInt()
val slot = checkNotNull(id2slot.remove(id)) { "No such slot with ID: $id" }
check(value2slot.remove(slot.value) == value2slot)
check(value2slot.remove(slot.value) == slot)
remoteStates.forEach { it.remove(slot) }
}
@ -223,7 +235,7 @@ class DynamicSynchableGroup<T : Any>(
if (id2slot.containsKey(id)) {
val slot = id2slot.remove(id)!!
check(value2slot.remove(slot.value) == value2slot)
check(value2slot.remove(slot.value) == slot)
remoteStates.forEach { it.remove(slot) }
}
@ -298,8 +310,8 @@ class DynamicSynchableGroup<T : Any>(
return value2slot.isEmpty()
}
override fun iterator(): MutableIterator<T> {
return object : MutableIterator<T> {
override fun iterator(): ObjectIterator<T> {
return object : ObjectIterator<T> {
private val parent = value2slot.values.iterator()
private var last: KOptional<Slot<T>> = KOptional()
@ -323,11 +335,15 @@ class DynamicSynchableGroup<T : Any>(
}
}
override fun remove(element: T): Boolean {
val slot = value2slot.remove(element) ?: return false
checkNotNull(id2slot.remove(slot.id))
private fun removeBySlot(slot: Slot<T>) {
value2slot.remove(slot.value)
id2slot.remove(slot.id)
remoteStates.forEach { it.remove(slot) }
idAllocator.release(slot.id)
}
override fun remove(element: T): Boolean {
removeBySlot(value2slot.remove(element) ?: return false)
return true
}
@ -351,6 +367,341 @@ class DynamicSynchableGroup<T : Any>(
return any
}
/**
* Representation of this synchable group as an [Int2ReferenceMap]. Changes made to [DynamicSynchableGroup] are reflected in this map
* and vice versa. Entries can be put at arbitrary keys, but negative keys should be avoided, since they are not efficiently
* networked, and hence will create a lot of network traffic if synchables with negative keys get frequently updated.
*/
val asMap: Int2ReferenceMap<T> by lazy {
object : Int2ReferenceMap<T> {
override fun isEmpty(): Boolean {
return this@DynamicSynchableGroup.isEmpty()
}
override fun remove(key: Int): T? {
val slot = id2slot.remove(key) ?: return null
removeBySlot(slot)
return slot.value
}
override fun getOrDefault(key: Int, defaultValue: T): T {
return super.getOrDefault(key, defaultValue)
}
override val size: Int
get() = this@DynamicSynchableGroup.size
override fun put(key: Int, value: T): T? {
val slot = Slot(value, key)
val oldSlot = id2slot.put(key, slot)
if (oldSlot?.value === value)
return value
if (oldSlot != null) {
remoteStates.forEach { it.remove(oldSlot) }
value2slot.remove(oldSlot.value)
} else {
idAllocator.allocate(key)
}
value2slot[value] = slot
remoteStates.forEach { it.add(slot) }
return oldSlot?.value
}
override fun get(key: Int): T? {
return id2slot.get(key)?.value ?: defaultReturnValue
}
override fun containsKey(key: Int): Boolean {
return id2slot.containsKey(key)
}
override fun defaultReturnValue(rv: T?) {
defaultReturnValue = rv
}
override fun defaultReturnValue(): T? {
return defaultReturnValue
}
override fun putAll(from: Map<out Int, T>) {
from.forEach { (k, v) ->
put(k, v)
}
}
override fun containsValue(value: T): Boolean {
return value2slot.containsKey(value)
}
private val entrySet: ObjectSet<Int2ReferenceMap.Entry<T>> by lazy(LazyThreadSafetyMode.PUBLICATION) {
object : ObjectSet<Int2ReferenceMap.Entry<T>> {
inner class Entry(private val ikey: Int) : Int2ReferenceMap.Entry<T> {
override val value: T
get() = id2slot[ikey]?.value ?: throw NoSuchElementException()
override fun setValue(newValue: T): T? {
return put(ikey, newValue)
}
override fun getIntKey(): Int {
return ikey
}
override fun equals(other: Any?): Boolean {
return this === other || other is Int2ReferenceMap.Entry<*> && other.intKey == ikey && other.value === id2slot[ikey]?.value
}
override fun hashCode(): Int {
return ikey * 31 + (id2slot[ikey] as Slot<T>?).hashCode()
}
override fun toString(): String {
return "Map.Entry[$ikey, ${id2slot[ikey]?.value}]"
}
}
override val size: Int
get() = id2slot.size
override fun add(element: Int2ReferenceMap.Entry<T>): Boolean {
return put(element.intKey, element.value) != null
}
override fun addAll(elements: Collection<Int2ReferenceMap.Entry<T>>): Boolean {
var any = false
elements.forEach { any = add(it) || any }
return any
}
override fun clear() {
this@DynamicSynchableGroup.clear()
}
override fun iterator(): ObjectIterator<Int2ReferenceMap.Entry<T>> {
return object : ObjectIterator<Int2ReferenceMap.Entry<T>> {
private val parent = id2slot.int2ReferenceEntrySet().iterator()
private var last: Slot<T>? = null
override fun hasNext(): Boolean {
return parent.hasNext()
}
override fun remove() {
if (last == null)
throw NoSuchElementException()
parent.remove()
removeBySlot(last!!)
last = null
}
override fun next(): Int2ReferenceMap.Entry<T> {
val value = parent.next()
last = value.value
return Entry(value.intKey)
}
}
}
override fun remove(element: Int2ReferenceMap.Entry<T>): Boolean {
val slot = id2slot.get(element.intKey)
if (slot?.value === element.value) {
this@DynamicSynchableGroup.removeBySlot(slot)
return true
}
return false
}
override fun removeAll(elements: Collection<Int2ReferenceMap.Entry<T>>): Boolean {
var any = false
elements.forEach { any = remove(it) || any }
return any
}
override fun retainAll(elements: Collection<Int2ReferenceMap.Entry<T>>): Boolean {
if (elements.isEmpty()) {
val isNotEmpty = id2slot.isNotEmpty()
this@DynamicSynchableGroup.clear()
return isNotEmpty
}
var any = false
val itr = id2slot.int2ReferenceEntrySet().iterator()
for (entry in itr) {
if (elements.none { it.intKey == entry.intKey && it.value === entry.value.value }) {
any = true
itr.remove()
removeBySlot(entry.value)
}
}
return any
}
override fun contains(element: Int2ReferenceMap.Entry<T>): Boolean {
return id2slot.get(element.intKey)?.value === element.value
}
override fun containsAll(elements: Collection<Int2ReferenceMap.Entry<T>>): Boolean {
return elements.all { contains(it) }
}
override fun isEmpty(): Boolean {
return id2slot.isEmpty()
}
}
}
override fun int2ReferenceEntrySet(): ObjectSet<Int2ReferenceMap.Entry<T>> {
return entrySet
}
override val keys: IntSet by lazy(LazyThreadSafetyMode.PUBLICATION) {
object : IntSet {
override fun add(key: Int): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(c: IntCollection): Boolean {
throw UnsupportedOperationException()
}
override fun addAll(elements: Collection<Int>): Boolean {
throw UnsupportedOperationException()
}
override fun clear() {
this@DynamicSynchableGroup.clear()
}
override fun iterator(): IntIterator {
return object : IntIterator {
private val parent = id2slot.keys.iterator()
private var last = -1
private var hasLast = false
override fun hasNext(): Boolean {
return parent.hasNext()
}
override fun remove() {
if (!hasLast)
throw NoSuchElementException()
hasLast = false
val slot = id2slot.get(last)
parent.remove()
removeBySlot(slot)
}
override fun nextInt(): Int {
last = parent.nextInt()
hasLast = true
return last
}
}
}
override fun remove(k: Int): Boolean {
removeBySlot(id2slot.get(k) ?: return false)
return true
}
override fun removeAll(c: IntCollection): Boolean {
val itr = c.iterator()
var any = false
while (itr.hasNext()) {
any = remove(itr.nextInt()) || any
}
return any
}
override fun removeAll(elements: Collection<Int>): Boolean {
val itr = elements.iterator()
var any = false
while (itr.hasNext()) {
any = remove(itr.next()) || any
}
return any
}
override fun retainAll(c: IntCollection): Boolean {
val itr = id2slot.values.iterator()
var any = false
for (slot in itr) {
if (!c.contains(slot.id)) {
itr.remove()
check(value2slot.remove(slot.value) == slot)
remoteStates.forEach { it.remove(slot) }
any = true
}
}
return any
}
override fun retainAll(elements: Collection<Int>): Boolean {
val itr = id2slot.values.iterator()
var any = false
for (slot in itr) {
if (!elements.contains(slot.id)) {
itr.remove()
check(value2slot.remove(slot.value) == slot)
remoteStates.forEach { it.remove(slot) }
any = true
}
}
return any
}
override fun contains(key: Int): Boolean {
return id2slot.containsKey(key)
}
override fun containsAll(c: IntCollection): Boolean {
return id2slot.keys.containsAll(c)
}
override fun containsAll(elements: Collection<Int>): Boolean {
return id2slot.keys.containsAll(elements)
}
override fun isEmpty(): Boolean {
return id2slot.isEmpty()
}
override fun toArray(a: IntArray?): IntArray {
return id2slot.keys.toArray(a)
}
override fun toIntArray(): IntArray {
return id2slot.keys.toIntArray()
}
override val size: Int
get() = id2slot.size
}
}
override val values: ReferenceCollection<T>
get() = this@DynamicSynchableGroup
}
}
companion object {
private const val END = 0
private const val ADD_ENTRY = 1

View File

@ -326,7 +326,7 @@ object MRegistry : IBlockItemRegistryAcceptor {
}
}
for (item in MItems.ALL_BATTERIES) {
for (item in MItems.ALL_BATTERIES.toMutableList().also { it.add(MItems.PROCEDURAL_BATTERY) }) {
ItemProperties.register(item, ResourceLocation(OverdriveThatMatters.MOD_ID, "capacitor_gauge")) { stack, _, _, _ ->
val energy = stack.matteryEnergy ?: return@register 1f

View File

@ -1,37 +1,58 @@
package ru.dbotthepony.mc.otm.util
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import it.unimi.dsi.fastutil.ints.IntRBTreeSet
class IDAllocator {
private var highestID = 0
private val gaps = IntAVLTreeSet()
private var nextID = -1
private val gaps = IntRBTreeSet()
private val sparseAllocations = IntRBTreeSet()
private fun increaseHighestID(): Int {
while (sparseAllocations.remove(++nextID)) {}
return nextID
}
fun allocate(): Int {
if (gaps.isEmpty()) {
return highestID++
return increaseHighestID()
} else {
return gaps.removeFirst()
}
}
fun allocate(id: Int): Boolean {
if (id < 0) {
return true // not handling negative IDs
} else if (id > nextID) {
sparseAllocations.add(id)
return true
} else if (id == nextID) {
increaseHighestID()
return true
} else {
return gaps.remove(id)
}
}
fun release(id: Int) {
if (id >= 0) {
throw IllegalArgumentException("Invalid ID: $id")
} else if (id >= highestID) {
throw IllegalArgumentException("Not tracking ID: $id (highest known ID is ${highestID - 1})")
if (id < 0) {
return // not handling negative IDs
} else if (sparseAllocations.remove(id)) {
return // was allocated above highest ID
} else if (id > nextID) {
throw IllegalArgumentException("Not tracking ID: $id (highest known ID is ${nextID})")
} else if (id in gaps) {
throw IllegalArgumentException("ID is already free: $id")
}
if (id + 1 == highestID) {
highestID--
} else if (id == nextID) {
nextID--
} else {
gaps.add(id)
check(gaps.add(id))
}
}
fun reset() {
highestID = 0
nextID = -1
gaps.clear()
sparseAllocations.clear()
}
}

View File

@ -1,5 +1,6 @@
{
"code_injector": "coremods/code_injector.js",
"chest_menus": "coremods/chest_menus.js",
"limb_brush_overclock": "coremods/limb_brush_overclock.js"
"limb_brush_overclock": "coremods/limb_brush_overclock.js",
"iron_chest_menus": "coremods/iron_chest_menus.js"
}

View File

@ -0,0 +1,45 @@
var Opcodes = Java.type('org.objectweb.asm.Opcodes')
var MethodNode = Java.type('org.objectweb.asm.tree.MethodNode')
var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode')
var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode')
var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode')
var TypeInsnNode = Java.type('org.objectweb.asm.tree.TypeInsnNode')
var isOwnPatches = [
'com.progwml6.ironchest.common.block.regular.entity.AbstractIronChestBlockEntity$1',
]
function initializeCoreMod() {
var result = {}
for (i in isOwnPatches) {
var clazz = isOwnPatches[i]
result[clazz] = {
'target': {
'type': 'METHOD',
'class': clazz,
'methodName': 'isOwnContainer',
'methodDesc': '(Lnet/minecraft/world/entity/player/Player;)Z'
},
'transformer': function(node) {
for (var i = 0; i < node.instructions.size(); i++) {
var instr = node.instructions.get(i)
if ((instr.getOpcode() == Opcodes.INSTANCEOF || instr.getOpcode() == Opcodes.CHECKCAST) && instr.desc == 'com/progwml6/ironchest/common/inventory/IronChestMenu') {
instr.desc = 'ru/dbotthepony/mc/otm/compat/ironchest/MatteryIronChestMenu'
} else if (instr.getOpcode() == Opcodes.INVOKEVIRTUAL && instr.owner == 'com/progwml6/ironchest/common/inventory/IronChestMenu' && instr.name == 'getContainer') {
instr.owner = 'ru/dbotthepony/mc/otm/compat/ironchest/MatteryIronChestMenu'
instr.name = 'getContainer'
}
}
return node
}
}
}
return result
}

View File

@ -0,0 +1,22 @@
{
"required": false,
"package": "ru.dbotthepony.mc.otm.mixin.ironchest",
"compatibilityLevel": "JAVA_21",
"minVersion": "0.8",
"mixins": [
"IronChestBlockEntityMixin",
"GoldChestBlockEntityMixin",
"DiamondChestBlockEntityMixin",
"CopperChestBlockEntityMixin",
"CrystalChestBlockEntityMixin",
"ObsidianChestBlockEntityMixin",
"DirtChestBlockEntityMixin",
"TrappedIronChestBlockEntityMixin",
"TrappedGoldChestBlockEntityMixin",
"TrappedDiamondChestBlockEntityMixin",
"TrappedCopperChestBlockEntityMixin",
"TrappedCrystalChestBlockEntityMixin",
"TrappedObsidianChestBlockEntityMixin",
"TrappedDirtChestBlockEntityMixin"
]
}

View File

@ -0,0 +1,14 @@
{
"required": false,
"package": "ru.dbotthepony.mc.otm.mixin.ironshulkerbox",
"compatibilityLevel": "JAVA_21",
"minVersion": "0.8",
"mixins": [
"IronShulkerBoxBlockEntityMixin",
"GoldShulkerBoxBlockEntityMixin",
"DiamondShulkerBoxBlockEntityMixin",
"CopperShulkerBoxBlockEntityMixin",
"CrystalShulkerBoxBlockEntityMixin",
"ObsidianShulkerBoxBlockEntityMixin"
]
}