diff --git a/build.gradle.kts b/build.gradle.kts index 70ea476a2..4d93835b5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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") } diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CopperChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CopperChestBlockEntityMixin.java new file mode 100644 index 000000000..49af2c026 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CopperChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CrystalChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CrystalChestBlockEntityMixin.java new file mode 100644 index 000000000..fca710c70 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/CrystalChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DiamondChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DiamondChestBlockEntityMixin.java new file mode 100644 index 000000000..5c9f4dea4 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DiamondChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DirtChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DirtChestBlockEntityMixin.java new file mode 100644 index 000000000..e828a851a --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/DirtChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/GoldChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/GoldChestBlockEntityMixin.java new file mode 100644 index 000000000..f985dbebe --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/GoldChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/IronChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/IronChestBlockEntityMixin.java new file mode 100644 index 000000000..c95ab1dc8 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/IronChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/ObsidianChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/ObsidianChestBlockEntityMixin.java new file mode 100644 index 000000000..1e2a45aa6 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/ObsidianChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCopperChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCopperChestBlockEntityMixin.java new file mode 100644 index 000000000..5f3313725 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCopperChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCrystalChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCrystalChestBlockEntityMixin.java new file mode 100644 index 000000000..149d6c5a9 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedCrystalChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDiamondChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDiamondChestBlockEntityMixin.java new file mode 100644 index 000000000..0c454f5a7 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDiamondChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDirtChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDirtChestBlockEntityMixin.java new file mode 100644 index 000000000..5b8c8600b --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedDirtChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedGoldChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedGoldChestBlockEntityMixin.java new file mode 100644 index 000000000..0b52e7787 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedGoldChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedIronChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedIronChestBlockEntityMixin.java new file mode 100644 index 000000000..56a5458a7 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedIronChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedObsidianChestBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedObsidianChestBlockEntityMixin.java new file mode 100644 index 000000000..49efee1f8 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironchest/TrappedObsidianChestBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CopperShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CopperShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..c99bc8496 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CopperShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CrystalShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CrystalShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..c2a05b4c3 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/CrystalShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/DiamondShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/DiamondShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..6ed982d9a --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/DiamondShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/GoldShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/GoldShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..4adb75011 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/GoldShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/IronShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/IronShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..bdd856532 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/IronShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/ObsidianShulkerBoxBlockEntityMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/ObsidianShulkerBoxBlockEntityMixin.java new file mode 100644 index 000000000..6a9990a37 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/ironshulkerbox/ObsidianShulkerBoxBlockEntityMixin.java @@ -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)); + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt index 1f66d1b96..c9fdcaad9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/OverdriveThatMatters.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/cos/CosmeticArmorCompat.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/cos/CosmeticArmorCompat.kt index 0cb56a423..1106b0819 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/cos/CosmeticArmorCompat.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/cos/CosmeticArmorCompat.kt @@ -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") } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/curios/CuriosCompat.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/curios/CuriosCompat.kt index d236113c1..ee2652365 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/curios/CuriosCompat.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/curios/CuriosCompat.kt @@ -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) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/IronChestMenuTypes.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/IronChestMenuTypes.kt new file mode 100644 index 000000000..ca612deee --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/IronChestMenuTypes.kt @@ -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) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/MatteryIronChestMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/MatteryIronChestMenu.kt new file mode 100644 index 000000000..bd19c9d13 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironchest/MatteryIronChestMenu.kt @@ -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) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/IronShulkersMenuTypes.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/IronShulkersMenuTypes.kt new file mode 100644 index 000000000..cebcc5a3f --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/IronShulkersMenuTypes.kt @@ -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().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) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/MatteryIronShulkerBoxMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/MatteryIronShulkerBoxMenu.kt new file mode 100644 index 000000000..2f0d6e13e --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/ironshulkerbox/MatteryIronShulkerBoxMenu.kt @@ -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) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/itemborders/ItemBordersCompat.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/itemborders/ItemBordersCompat.kt index 7464294ae..02619a2e6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/itemborders/ItemBordersCompat.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/itemborders/ItemBordersCompat.kt @@ -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") } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryStreamCodec.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryStreamCodec.kt index a217ec302..c685fb861 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryStreamCodec.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryStreamCodec.kt @@ -189,6 +189,35 @@ interface MatteryStreamCodec : StreamCodec<@UnsafeVariance S, val values: List = listOf(*this.clazz.enumConstants!!) val valuesMap = values.associateBy { it.name } + private val nullable = object : MatteryStreamCodec { + override fun decode(stream: S): V? { + val value = stream.readVarInt() + + if (value == 0) { + return null + } else { + val id = value ushr 1 + return values.getOrNull(id) ?: throw NoSuchElementException("No such enum with index $id") + } + } + + override fun encode(stream: S, value: V?) { + if (value == null) { + stream.writeVarInt(0) + } else { + stream.writeVarInt(1 or (value.ordinal shl 1)) + } + } + + override fun copy(value: V?): V? { + return value + } + + override fun compare(a: V?, b: V?): Boolean { + return a === b + } + } + override fun decode(stream: S): V { val id = stream.readVarInt() return values.getOrNull(id) ?: throw NoSuchElementException("No such enum with index $id") @@ -206,6 +235,10 @@ interface MatteryStreamCodec : StreamCodec<@UnsafeVariance S, return a === b } + fun nullable(): MatteryStreamCodec { + return nullable + } + companion object { /** * FIXME: enums with abstract methods which get compiled to subclasses, whose DO NOT expose "parent's" enum constants array diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/StreamCodecs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/StreamCodecs.kt index 62ce5522a..0402e7a67 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/StreamCodecs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/StreamCodecs.kt @@ -39,6 +39,8 @@ object StreamCodecs { val BLOCK_TYPE = MatteryStreamCodec.Of(FriendlyByteBuf::writeBlockType, FriendlyByteBuf::readBlockType) val RELATIVE_SIDE = MatteryStreamCodec.Enum(RelativeSide::class.java) val DIRECTION = MatteryStreamCodec.Enum(Direction::class.java) + val RELATIVE_SIDE_NULLABLE = RELATIVE_SIDE.nullable() + val DIRECTION_NULLABLE = DIRECTION.nullable() val RGBA: MatteryStreamCodec = StreamCodec.of( { s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue); s.writeFloat(v.alpha) }, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt index 1d2ac6625..f7664893a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/syncher/DynamicSynchableGroup.kt @@ -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( * first-time networking of [T] to remote */ private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {}, -) : ISynchable, MutableSet { +) : ISynchable, ReferenceSet { private inner class RemoteState(val listener: Runnable) : IRemoteState { private inner class RemoteSlot(val slot: Slot, fromConstructor: Boolean) : Runnable, Closeable { val remoteState = synchable(slot.value).createRemoteState(this) @@ -188,11 +199,12 @@ class DynamicSynchableGroup( } } - private data class Slot(val value: T, val id: Int) + private class Slot(val value: T, val id: Int) + private var defaultReturnValue: T? = null private val remoteStates = ArrayList() - private val value2slot = LinkedHashMap>() - private val id2slot = Int2ObjectOpenHashMap>() + private val value2slot = Reference2ObjectLinkedOpenHashMap>() + private val id2slot = Int2ReferenceLinkedOpenHashMap>() private val idAllocator = IDAllocator() override val hasRemotes: Boolean @@ -210,7 +222,7 @@ class DynamicSynchableGroup( 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( 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( return value2slot.isEmpty() } - override fun iterator(): MutableIterator { - return object : MutableIterator { + override fun iterator(): ObjectIterator { + return object : ObjectIterator { private val parent = value2slot.values.iterator() private var last: KOptional> = KOptional() @@ -323,11 +335,15 @@ class DynamicSynchableGroup( } } - override fun remove(element: T): Boolean { - val slot = value2slot.remove(element) ?: return false - checkNotNull(id2slot.remove(slot.id)) + private fun removeBySlot(slot: Slot) { + 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( 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 by lazy { + object : Int2ReferenceMap { + 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) { + from.forEach { (k, v) -> + put(k, v) + } + } + + override fun containsValue(value: T): Boolean { + return value2slot.containsKey(value) + } + + private val entrySet: ObjectSet> by lazy(LazyThreadSafetyMode.PUBLICATION) { + object : ObjectSet> { + inner class Entry(private val ikey: Int) : Int2ReferenceMap.Entry { + 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?).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): Boolean { + return put(element.intKey, element.value) != null + } + + override fun addAll(elements: Collection>): Boolean { + var any = false + elements.forEach { any = add(it) || any } + return any + } + + override fun clear() { + this@DynamicSynchableGroup.clear() + } + + override fun iterator(): ObjectIterator> { + return object : ObjectIterator> { + private val parent = id2slot.int2ReferenceEntrySet().iterator() + private var last: Slot? = 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 { + val value = parent.next() + last = value.value + return Entry(value.intKey) + } + } + } + + override fun remove(element: Int2ReferenceMap.Entry): 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>): Boolean { + var any = false + elements.forEach { any = remove(it) || any } + return any + } + + override fun retainAll(elements: Collection>): 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): Boolean { + return id2slot.get(element.intKey)?.value === element.value + } + + override fun containsAll(elements: Collection>): Boolean { + return elements.all { contains(it) } + } + + override fun isEmpty(): Boolean { + return id2slot.isEmpty() + } + } + } + + override fun int2ReferenceEntrySet(): ObjectSet> { + 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): 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): 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): 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): 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 + get() = this@DynamicSynchableGroup + } + } + companion object { private const val END = 0 private const val ADD_ENTRY = 1 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt index 64b3969a9..16ae2e52b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt @@ -328,7 +328,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 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/util/IDAllocator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/util/IDAllocator.kt index 9fa5b05ff..cc197fb62 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/util/IDAllocator.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/util/IDAllocator.kt @@ -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() } } diff --git a/src/main/resources/META-INF/coremods.json b/src/main/resources/META-INF/coremods.json index 677dde2cf..715af5a6c 100644 --- a/src/main/resources/META-INF/coremods.json +++ b/src/main/resources/META-INF/coremods.json @@ -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" } \ No newline at end of file diff --git a/src/main/resources/coremods/iron_chest_menus.js b/src/main/resources/coremods/iron_chest_menus.js new file mode 100644 index 000000000..192b72f69 --- /dev/null +++ b/src/main/resources/coremods/iron_chest_menus.js @@ -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 +} diff --git a/src/main/resources/overdrive_that_matters.ironchest.mixins.json b/src/main/resources/overdrive_that_matters.ironchest.mixins.json new file mode 100644 index 000000000..20cb09454 --- /dev/null +++ b/src/main/resources/overdrive_that_matters.ironchest.mixins.json @@ -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" + ] +} diff --git a/src/main/resources/overdrive_that_matters.ironshulkerbox.mixins.json b/src/main/resources/overdrive_that_matters.ironshulkerbox.mixins.json new file mode 100644 index 000000000..12d348dc5 --- /dev/null +++ b/src/main/resources/overdrive_that_matters.ironshulkerbox.mixins.json @@ -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" + ] +}