diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/ModBlocks.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/ModBlocks.java index c94fd77e..24939e9e 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/ModBlocks.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/ModBlocks.java @@ -16,6 +16,7 @@ import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockEnderLotus; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockEtherealGlass; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockFloating; +import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockFluxCrystal; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockInverted; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockLapisAetherius; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockMagicWood; @@ -24,6 +25,7 @@ import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockPortalEndOfTime; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockPortalUnderWorld; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockPureLove; +import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockQED; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockRadicallyReducedChest; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockRainMuffler; import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockRedstoneClock; @@ -132,9 +134,12 @@ public enum ModBlocks { SPIKE_DIAMOND(BlockConfig.spikes.enableDiamondSpike, new BlockSpike(BlockSpike.SpikeType.DIAMOND, "diamond_spike"), BlockSpike.ItemSpike.class, "diamond_spike"), UNDERWORLD_PORTAL(BlockConfig.enableUnderWorldPortal && UnderWorldConfig.enableUnderWorld, new BlockPortalUnderWorld(), "underworld_portal"), END_OF_TIME_PORTAL(BlockConfig.enableEndOfTimePortal && EndOfTimeConfig.enableEndOfTime, new BlockPortalEndOfTime(), BlockPortalEndOfTime.ItemBlockPortalEndOfTime.class, "temporal_gate"), + QED(BlockConfig.enableQED, new BlockQED(), "qed"), + FLUX_CRYSTAL(BlockConfig.enableQED, new BlockFluxCrystal(), "flux_crystal"), DECORATIVE_GLASS(BlockConfig.enableDecorativeGlass, new BlockDecorativeGlass(), BlockDecorativeGlass.ItemBlockDecorativeGlass.class, "decorative_glass"), PACIFISTS_BENCH(BlockConfig.enablePacifistsBench, new BlockPacifistsBench(), "pacifists_bench"), - SMART_PUMP(BlockConfig.enableSmartPump, new BlockSmartPump(), "smart_pump") + SMART_PUMP(BlockConfig.enableSmartPump, new BlockSmartPump(), "smart_pump"), + ; // leave trailing semicolon // spotless:on diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/UtilitiesInExcess.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/UtilitiesInExcess.java index 764354f9..59035a7b 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/UtilitiesInExcess.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/UtilitiesInExcess.java @@ -22,6 +22,7 @@ import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityPacifistsBench; import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityPortalUnderWorld; import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityPureLove; +import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityQED; import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityRadicallyReducedChest; import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityRainMuffler; import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityRedstoneClock; @@ -123,6 +124,7 @@ public void init(FMLInitializationEvent event) { GameRegistry.registerTileEntity(TileEntityConveyor.class, "TileEntityConveyorUIE"); GameRegistry.registerTileEntity(TileEntityPortalUnderWorld.class, "TileEntityPortalUnderWorldUIE"); GameRegistry.registerTileEntity(TileEntitySmartPump.class, "TileEntitySmartPumpUIE"); + GameRegistry.registerTileEntity(TileEntityQED.class, "TileEntityQEDUIE"); GameRegistry.registerTileEntity( TileEntityLowTemperatureFurnaceGenerator.class, "TileEntityLowTemperatureFurnaceGeneratorUIE"); diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockFluxCrystal.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockFluxCrystal.java new file mode 100644 index 00000000..8a349efb --- /dev/null +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockFluxCrystal.java @@ -0,0 +1,13 @@ +package com.fouristhenumber.utilitiesinexcess.common.blocks; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; + +public class BlockFluxCrystal extends Block { + + public BlockFluxCrystal() { + super(Material.iron); + setBlockName("flux_crystal"); + setBlockTextureName("utilitiesinexcess:flux_crystal"); + } +} diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockQED.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockQED.java new file mode 100644 index 00000000..122b1993 --- /dev/null +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/blocks/BlockQED.java @@ -0,0 +1,34 @@ +package com.fouristhenumber.utilitiesinexcess.common.blocks; + +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import com.cleanroommc.modularui.factory.GuiFactories; +import com.fouristhenumber.utilitiesinexcess.common.tileentities.TileEntityQED; + +public class BlockQED extends BlockContainer { + + public BlockQED() { + super(Material.iron); + setBlockName("qed"); + setBlockTextureName("utilitiesinexcess:qed"); + } + + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + return new TileEntityQED(); + } + + @Override + public boolean onBlockActivated(World worldIn, int x, int y, int z, EntityPlayer player, int side, float subX, + float subY, float subZ) { + if (!worldIn.isRemote) { + GuiFactories.tileEntity() + .open(player, x, y, z); + } + return true; + } +} diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/tileentities/TileEntityQED.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/tileentities/TileEntityQED.java new file mode 100644 index 00000000..e0a5b2f7 --- /dev/null +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/tileentities/TileEntityQED.java @@ -0,0 +1,286 @@ +package com.fouristhenumber.utilitiesinexcess.common.tileentities; + +import static com.cleanroommc.modularui.drawable.GuiTextures.PROGRESS_ARROW; +import static com.fouristhenumber.utilitiesinexcess.utils.UIEUtils.scanForBlock; + +import java.util.Set; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryCraftResult; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.StatCollector; +import net.minecraftforge.common.util.Constants; + +import com.cleanroommc.modularui.api.IGuiHolder; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.utils.item.IItemHandler; +import com.cleanroommc.modularui.utils.item.InvWrapper; +import com.cleanroommc.modularui.value.sync.DoubleSyncValue; +import com.cleanroommc.modularui.value.sync.GenericSyncValue; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ItemDisplayWidget; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.slot.ItemSlot; +import com.cleanroommc.modularui.widgets.slot.ModularSlot; +import com.fouristhenumber.utilitiesinexcess.ModBlocks; +import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; +import com.fouristhenumber.utilitiesinexcess.api.QEDRegistry; +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; + +public class TileEntityQED extends TileEntity implements IInventory, IGuiHolder { + + private final InventoryCrafting craftMatrix = new InventoryCrafting(new ContainerDummy(), 3, 3); + private final InventoryCraftResult craftResult = new InventoryCraftResult(); + + private static final ItemStack fakeItem = new ItemStack(new Item()); + private ItemStack preview = fakeItem; + + private int craftingProgress = 0; + private boolean crafting = false; + private int crystals = 0; + + @Override + public void updateEntity() { + if (crafting) { + craftingProgress += crystals; + } + if (craftingProgress >= 500) { + ItemStack newStack = QEDRegistry.instance() + .findRecipe(craftMatrix, true); + if (newStack != null) { + ItemStack outputStack = craftResult.getStackInSlot(0); + + if (outputStack == null) craftResult.setInventorySlotContents(0, newStack); + else if (canInsertToOutput(newStack)) outputStack.stackSize += newStack.stackSize; + else UtilitiesInExcess.LOG + .error("Failed to complete QED recipe because output stack did not match craft result."); + } + craftingProgress = 0; + crafting = false; + updateCraftingResult(); + } + super.updateEntity(); + } + + private void scan() { + Set positions = scanForBlock(worldObj, xCoord, yCoord, zCoord, 9, ModBlocks.FLUX_CRYSTAL.get()); + crystals = positions.size(); + } + + private void updateCraftingResult() { + ItemStack stack = QEDRegistry.instance() + .findRecipe(craftMatrix, false); + + if (stack != null) scan(); + crafting = stack != null && canInsertToOutput(stack); + preview = stack != null ? stack : fakeItem; + } + + public boolean canInsertToOutput(ItemStack toInsert) { + ItemStack outputStack = craftResult.getStackInSlot(0); + if (outputStack == null) return true; + + if (!outputStack.isItemEqual(toInsert) || !ItemStack.areItemStackTagsEqual(outputStack, toInsert)) { + return false; + } + + return (outputStack.stackSize + toInsert.stackSize) <= outputStack.getMaxStackSize(); + } + + @Override + public ModularPanel buildUI(PosGuiData data, PanelSyncManager syncManager, UISettings settings) { + + ModularPanel panel = new ModularPanel("panel"); + panel.bindPlayerInventory(); + + syncManager.syncValue("preview", GenericSyncValue.forItem(() -> preview, null)); + IntSyncValue craftingSyncer = new IntSyncValue(() -> craftingProgress); + IntSyncValue connected = new IntSyncValue(() -> crystals); + syncManager.syncValue("craftingProgress", craftingSyncer); + syncManager.syncValue("connected", connected); + + // Add title + panel.child( + new ParentWidget<>().coverChildren() + .topRelAnchor(0, 1) + .child( + IKey.str(StatCollector.translateToLocal(getInventoryName())) + .asWidget() + .marginLeft(5) + .marginRight(5) + .marginTop(5) + .marginBottom(-15))); + + panel.child( + IKey.dynamic(connected::getStringValue) + .asWidget() + .marginTop(70) + .marginLeft(10)); + + IItemHandler itemHandler = new InvWrapper(this); + + // Input slots + panel.child( + SlotGroupWidget.builder() + .matrix("III", "III", "III") + .key( + 'I', + index -> new ItemSlot().slot( + new ModularSlot(itemHandler, index).changeListener((w, x, y, z) -> updateCraftingResult()))) + .build() + .marginTop(20) + .marginLeft(37)); + + // Progress bar + panel.child( + new ProgressWidget().texture(PROGRESS_ARROW, 20) + .value(new DoubleSyncValue(() -> (double) craftingSyncer.getIntValue() / 500)) + .marginTop(38) + .marginLeft(97)); + + // Preview slot + panel.child( + new ItemDisplayWidget().syncHandler("preview") + .marginTop(15) + .marginLeft(97)); + + // Output slot + panel + .child( + new ItemSlot() + .slot( + new ModularSlot(itemHandler, 9).changeListener((w, x, y, z) -> updateCraftingResult()) + .accessibility(false, true)) + .marginTop(38) + .marginLeft(121)); + + return panel; + } + + @Override + public int getSizeInventory() { + return 10; + } + + @Override + public String getInventoryName() { + return "tile.qed.name"; + } + + @Override + public ItemStack getStackInSlot(int index) { + return index < 9 ? craftMatrix.getStackInSlot(index) : craftResult.getStackInSlot(0); + } + + @Override + public ItemStack decrStackSize(int index, int count) { + ItemStack stack; + if (index < 9) { + stack = craftMatrix.decrStackSize(index, count); + } else { + stack = craftResult.decrStackSize(0, count); + } + markDirty(); + return stack; + } + + @Override + public ItemStack getStackInSlotOnClosing(int index) { + return index < 9 ? craftMatrix.getStackInSlotOnClosing(index) : craftResult.getStackInSlotOnClosing(0); + } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) { + if (index < 9) { + craftMatrix.setInventorySlotContents(index, stack); + } else { + craftResult.setInventorySlotContents(0, stack); + } + markDirty(); + } + + @Override + public boolean hasCustomInventoryName() { + return false; + } + + @Override + public int getInventoryStackLimit() { + return 64; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) { + return this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) == this && player + .getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D, (double) this.zCoord + 0.5D) + <= 64.0D; + } + + @Override + public void openInventory() {} + + @Override + public void closeInventory() {} + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) { + return true; + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + super.readFromNBT(tag); + NBTTagList nbttaglist = tag.getTagList("Items", Constants.NBT.TAG_COMPOUND); + for (int index = 0; index < nbttaglist.tagCount(); index++) { + NBTTagCompound nbttagcompound1 = nbttaglist.getCompoundTagAt(index); + int slot = nbttagcompound1.getByte("Slot") & 255; + if (slot < getSizeInventory()) { + setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(nbttagcompound1)); + } + } + craftingProgress = tag.getInteger("craftingProgress"); + crafting = tag.getBoolean("crafting"); + crystals = tag.getInteger("crystals"); + } + + @Override + public void writeToNBT(NBTTagCompound tag) { + super.writeToNBT(tag); + NBTTagList nbttaglist = new NBTTagList(); + for (int index = 0; index < getSizeInventory(); index++) { + ItemStack curStack = getStackInSlot(index); + if (curStack != null) { + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + nbttagcompound1.setByte("Slot", (byte) index); + curStack.writeToNBT(nbttagcompound1); + nbttaglist.appendTag(nbttagcompound1); + } + } + tag.setTag("Items", nbttaglist); + tag.setInteger("craftingProgres", craftingProgress); + tag.setBoolean("crafting", crafting); + tag.setInteger("crystals", crystals); + } + + public static class ContainerDummy extends Container { + + public ContainerDummy() {} + + public boolean canInteractWith(EntityPlayer var1) { + return false; + } + } +} diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/config/blocks/BlockConfig.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/config/blocks/BlockConfig.java index 6e17bd80..f214b573 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/config/blocks/BlockConfig.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/config/blocks/BlockConfig.java @@ -91,6 +91,9 @@ public static void registerConfig() throws ConfigException { @Config.DefaultBoolean(true) public static boolean enableEndOfTimePortal; + @Config.DefaultBoolean(true) + public static boolean enableQED; + @Config.DefaultBoolean(true) public static boolean enableSmartPump; diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/UIEUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/UIEUtils.java index afe46bdf..e3f652a1 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/UIEUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/UIEUtils.java @@ -1,12 +1,17 @@ package com.fouristhenumber.utilitiesinexcess.utils; import java.text.DecimalFormat; +import java.util.HashSet; import java.util.Random; +import java.util.Set; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.world.World; import com.fouristhenumber.utilitiesinexcess.compat.Mods; +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; import baubles.common.container.InventoryBaubles; import baubles.common.lib.PlayerHandler; @@ -46,4 +51,32 @@ public static boolean hasBauble(EntityPlayer player, Class clazz) { return false; } + + public static Set scanForBlock(World world, int x, int y, int z, int radius, Block findBlock) { + return scanForBlock(world, x, y, z, radius, findBlock, 0); + } + + public static Set scanForBlock(World world, int x, int y, int z, int radius, Block findBlock, int meta) { + Set positions = new HashSet<>(); + for (int dx = -radius; dx <= radius; dx++) { + for (int dy = -radius; dy <= radius; dy++) { + int rem = radius - (Math.abs(dx) + Math.abs(dy)); + if (rem < 0) continue; + + for (int dz = -rem; dz <= rem; dz++) { + if (Math.abs(dx) + Math.abs(dy) + Math.abs(dz) > radius) continue; + + int nx = x + dx; + int ny = y + dy; + int nz = z + dz; + + if (!world.blockExists(nx, ny, nz)) continue; + + if (world.getBlock(nx, ny, nz) == findBlock && world.getBlockMetadata(nx, ny, nz) == meta) + positions.add(new BlockPos(nx, ny, nz)); + } + } + } + return positions; + } } diff --git a/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang b/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang index d2c60bb9..b1ccee53 100644 --- a/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang +++ b/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang @@ -293,6 +293,9 @@ nei.infopage.uie.golden_bag.1=A fancy bag which can carry a double chest's worth item.xray_glasses.name=X-Ray Glasses nei.infopage.uie.xray_glasses.1=These stylish spectacles will highlight like blocks adjacent to the one you are looking at through walls. Spot entire ore veins with ease! +tile.qed.name=QED +tile.flux_crystal.name=Flux Crystal + utilitiesinexcess.config.block.ender_lotus=Ender Lotus item.ender_lotus_seed.name=Ender-Lotus Seed diff --git a/src/main/resources/assets/utilitiesinexcess/textures/blocks/flux_crystal.png b/src/main/resources/assets/utilitiesinexcess/textures/blocks/flux_crystal.png new file mode 100644 index 00000000..53ff07d5 Binary files /dev/null and b/src/main/resources/assets/utilitiesinexcess/textures/blocks/flux_crystal.png differ diff --git a/src/main/resources/assets/utilitiesinexcess/textures/blocks/qed.png b/src/main/resources/assets/utilitiesinexcess/textures/blocks/qed.png new file mode 100644 index 00000000..d5e4ec1b Binary files /dev/null and b/src/main/resources/assets/utilitiesinexcess/textures/blocks/qed.png differ