From 62b4a8c31297e61120b302a235be15a39538ce2f Mon Sep 17 00:00:00 2001 From: stfwi Date: Sat, 4 May 2019 13:11:35 +0200 Subject: [PATCH] Added experimental electrical pass-through furnace. Release version commit v1.0.4-mc1.12.2. --- 1.12/gradle.properties | 2 +- 1.12/meta/update.json | 7 +- 1.12/readme.md | 18 +- .../engineersdecor/ModEngineersDecor.java | 3 + .../blocks/BlockDecorFurnace.java | 135 ++-- .../blocks/BlockDecorFurnaceElectrical.java | 683 ++++++++++++++++++ .../wile/engineersdecor/blocks/ModBlocks.java | 29 +- .../wile/engineersdecor/detail/ModConfig.java | 20 + .../blockstates/small_electrical_furnace.json | 12 + .../assets/engineersdecor/lang/en_us.lang | 6 + .../assets/engineersdecor/lang/ru_ru.lang | 6 + .../small_electrical_furnace_model.json | 106 +++ .../engineersdecor/recipes/_constants.json | 11 + .../small_electrical_furnace_recipe.json | 32 + .../furnace/small_electrical_furnace_back.png | Bin 0 -> 533 bytes .../small_electrical_furnace_bottom.png | Bin 0 -> 472 bytes .../small_electrical_furnace_front.png | Bin 0 -> 531 bytes .../small_electrical_furnace_gloom_off.png | Bin 0 -> 184 bytes .../small_electrical_furnace_gloom_on.png | Bin 0 -> 693 bytes ...all_electrical_furnace_gloom_on.png.mcmeta | 1 + .../furnace/small_electrical_furnace_left.png | Bin 0 -> 522 bytes .../small_electrical_furnace_right.png | Bin 0 -> 517 bytes .../furnace/small_electrical_furnace_top.png | Bin 0 -> 484 bytes .../gui/small_electrical_furnace_gui.png | Bin 0 -> 22957 bytes meta/update.json | 7 +- 25 files changed, 994 insertions(+), 84 deletions(-) create mode 100644 1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java create mode 100644 1.12/src/main/resources/assets/engineersdecor/blockstates/small_electrical_furnace.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/models/block/furnace/small_electrical_furnace_model.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/recipes/small_electrical_furnace_recipe.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_back.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_bottom.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_front.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_off.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png.mcmeta create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_left.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_right.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_top.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/gui/small_electrical_furnace_gui.png diff --git a/1.12/gradle.properties b/1.12/gradle.properties index 5b3f7e2..4b6c77f 100644 --- a/1.12/gradle.properties +++ b/1.12/gradle.properties @@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx8G version_minecraft=1.12.2 version_forge=14.23.5.2768 version_jei=4.10.0.198 -version_engineersdecor=1.0.4-b9 +version_engineersdecor=1.0.4 diff --git a/1.12/meta/update.json b/1.12/meta/update.json index 921c35d..15eb6a0 100644 --- a/1.12/meta/update.json +++ b/1.12/meta/update.json @@ -1,7 +1,8 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.12.2": { - "1.0.4-b9": "[F] Inserting fluids with pressurized tag only into IE piping.\n[F] Valve redstone connector rendering does not check for \"can connect redstone\" but only for \"can provide power\".\n[M] Valves are adpted to be detected as pipe by IE.", + "1.0.4": "[R] Release based on v1.0.3-b9. Release-to-release changes: * Crafting table: Quick crafting history re-fab, JEI integration. * Rendering improvements and issue fixes (stairs, ambient occlusion, optifine, etc). * Walls with texture variations. * Thin/thick steel poles with support feet/heads. * Horizontal steel double-T support beams added. * Fluid pipe valves added: Check valve, redstone controlled valve, analog redstone controlled valve. Support pressuzized transfer. * Tooltip documentation (CTRL-SHIFT) for stairs added. * Internal code cleanups. * Recipes tuned.\n[E] Added pass-through electrical furnace (experimental, see config).", + "1.0.4-b9": "[F] Inserting fluids with pressurized tag only into IE piping.\n[F] Valve redstone connector rendering does not check for \"can connect redstone\" but only for \"can provide power\".\n[M] Valves are adapted to be detected as pipe by IE.", "1.0.4-b8": "[F] Fixed stairs rendering without smooth light (thanks rastot9).\n[E] Added passive fluid accumulator (experimental feature, see config).", "1.0.4-b7": "[F] Fixed recipe loading issue if IE is not installed.\n[M] Valves support IE pressurized fluid transfer.", "1.0.4-b6": "[A] Added redstone controlled fluid valve.\n[A] Added redstone controlled analog fluid valve.\n[M] Check valve recipe adapted (thanks majijn).", @@ -32,7 +33,7 @@ "1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table." }, "promos": { - "1.12.2-recommended": "1.0.3", - "1.12.2-latest": "1.0.4-b9" + "1.12.2-recommended": "1.0.4", + "1.12.2-latest": "1.0.4" } } \ No newline at end of file diff --git a/1.12/readme.md b/1.12/readme.md index e525b34..6549ddd 100644 --- a/1.12/readme.md +++ b/1.12/readme.md @@ -10,10 +10,26 @@ Mod sources for Minecraft version 1.12.2. ---- ## Revision history + ------------------------------------------------------------------- + - v1.0.4 [R] Release based on v1.0.3-b9. Release-to-release changes: + * Crafting table: Quick crafting history re-fab, JEI integration. + * Rendering improvements and issue fixes (stairs, ambient occlusion, + optifine, etc). + * Walls with texture variations. + * Thin/thick steel poles with support feet/heads. + * Horizontal steel double-T support beams added. + * Fluid pipe valves added: Check valve, redstone controlled valve, + analog redstone controlled valve. Support pressuzized transfer. + * Tooltip documentation (CTRL-SHIFT) for stairs added. + * Internal code cleanups. + * Recipes tuned. + ------------------------------------------------------------------- + [E] Added pass-through electrical furnace (experimental, see config). + - v1.0.4-b9 [F] Inserting fluids with pressurized tag only into IE piping. [F] Valve redstone connector rendering does not check for "can connect redstone" but only for "can provide power". - [M] Valves are adpted to be detected as pipe by IE. + [M] Valves are adapted to be detected as pipe by IE. - v1.0.4-b8 [F] Fixed stairs rendering without smooth light (thanks rastot9). [E] Added passive fluid accumulator (experimental feature, see config). diff --git a/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java b/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java index b96866d..aad5da8 100644 --- a/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java +++ b/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java @@ -153,6 +153,7 @@ public class ModEngineersDecor { public static final int GUIID_CRAFTING_TABLE = 213101; public static final int GUIID_SMALL_LAB_FURNACE = 213102; + public static final int GUIID_ELECTRICAL_LAB_FURNACE = 213103; @Override public Object getServerGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z) @@ -162,6 +163,7 @@ public class ModEngineersDecor switch(guiid) { case GUIID_CRAFTING_TABLE: return BlockDecorCraftingTable.getServerGuiElement(player, world, pos, te); case GUIID_SMALL_LAB_FURNACE: return BlockDecorFurnace.getServerGuiElement(player, world, pos, te); + case GUIID_ELECTRICAL_LAB_FURNACE: return BlockDecorFurnaceElectrical.getServerGuiElement(player, world, pos, te); } return null; } @@ -175,6 +177,7 @@ public class ModEngineersDecor switch(guiid) { case GUIID_CRAFTING_TABLE: return BlockDecorCraftingTable.getClientGuiElement(player, world, pos, te); case GUIID_SMALL_LAB_FURNACE: return BlockDecorFurnace.getClientGuiElement(player, world, pos, te); + case GUIID_ELECTRICAL_LAB_FURNACE: return BlockDecorFurnaceElectrical.getClientGuiElement(player, world, pos, te); } return null; } diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java index 189861f..c5317ca 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java @@ -471,7 +471,7 @@ public class BlockDecorFurnace extends BlockDecorDirected private int proc_time_needed_; private int boost_energy_; // small, not saved in nbt. private boolean heater_inserted_ = false; - private NonNullList stacks_; + protected NonNullList stacks_; public static void on_config(int speed_percent, int fuel_efficiency_percent, int boost_energy_per_tick) { @@ -485,7 +485,7 @@ public class BlockDecorFurnace extends BlockDecorDirected public BTileEntity() { reset(); } - public void reset() + protected void reset() { stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); proc_time_elapsed_ = 0; @@ -507,7 +507,7 @@ public class BlockDecorFurnace extends BlockDecorDirected fuel_burntime_ = getItemBurnTime(stacks_.get(SMELTING_FUEL_SLOT_NO)); } - private void writenbt(NBTTagCompound compound) + protected void writenbt(NBTTagCompound compound) { compound.setInteger("BurnTime", MathHelper.clamp(burntime_left_,0 , MAX_BURNTIME)); compound.setInteger("CookTime", MathHelper.clamp(proc_time_elapsed_, 0, MAX_BURNTIME)); @@ -652,68 +652,6 @@ public class BlockDecorFurnace extends BlockDecorDirected public void clear() { stacks_.clear(); } - @Override - public void update() - { - if(--tick_timer_ > 0) return; - tick_timer_ = TICK_INTERVAL; - final boolean was_burning = isBurning(); - if(was_burning) burntime_left_ -= TICK_INTERVAL; - if(burntime_left_ < 0) burntime_left_ = 0; - if(world.isRemote) return; - boolean dirty = false; - if(--fifo_timer_ <= 0) { - fifo_timer_ = FIFO_INTERVAL/TICK_INTERVAL; - // note, intentionally not using bitwise OR piping. - if(transferItems(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, 1)) dirty = true; - if(transferItems(SMELTING_OUTPUT_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, 1)) dirty = true; - if(transferItems(FIFO_FUEL_0_SLOT_NO, SMELTING_FUEL_SLOT_NO, 1)) dirty = true; - if(transferItems(FIFO_FUEL_1_SLOT_NO, FIFO_FUEL_0_SLOT_NO, 1)) dirty = true; - if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 1)) dirty = true; - if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 1)) dirty = true; - heater_inserted_ = (ExtItems.IE_EXTERNAL_HEATER==null) // without IE always allow electrical boost - || (stacks_.get(AUX_0_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER) - || (stacks_.get(AUX_1_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER); - } - ItemStack fuel = stacks_.get(SMELTING_FUEL_SLOT_NO); - if(isBurning() || (!fuel.isEmpty()) && (!(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty())) { - if(!isBurning() && canSmelt()) { - burntime_left_ = (int)MathHelper.clamp((proc_fuel_efficiency_ * getItemBurnTime(fuel)), 0, MAX_BURNTIME); - fuel_burntime_ = (burntime_left_ * proc_speed_interval_) / VANILLA_FURNACE_SPEED_INTERVAL; - if(isBurning()) { - dirty = true; - if(!fuel.isEmpty()) { - Item fuel_item = fuel.getItem(); - fuel.shrink(1); - if(fuel.isEmpty()) stacks_.set(SMELTING_FUEL_SLOT_NO, fuel_item.getContainerItem(fuel)); - } - } - } - if(isBurning() && canSmelt()) { - proc_time_elapsed_ += TICK_INTERVAL; - if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL; } - if(proc_time_elapsed_ >= proc_time_needed_) { - proc_time_elapsed_ = 0; - proc_time_needed_ = getCookTime(stacks_.get(SMELTING_INPUT_SLOT_NO)); - smeltItem(); - dirty = true; - } - } else { - proc_time_elapsed_ = 0; - } - } else if(!isBurning() && (proc_time_elapsed_ > 0)) { - proc_time_elapsed_ = MathHelper.clamp(proc_time_elapsed_-2, 0, proc_time_needed_); - } - if(was_burning != isBurning()) { - dirty = true; - final IBlockState state = world.getBlockState(pos); - if(state.getBlock() instanceof BlockDecorFurnace) { - world.setBlockState(pos, state.withProperty(LIT, isBurning())); - } - } - if(dirty) markDirty(); - } - public boolean isBurning() { return burntime_left_ > 0; } @@ -754,7 +692,7 @@ public class BlockDecorFurnace extends BlockDecorDirected return changed; } - private boolean canSmelt() + protected boolean canSmelt() { if(stacks_.get(SMELTING_INPUT_SLOT_NO).isEmpty()) return false; final ItemStack recipe_result_items = BRecipes.instance().getSmeltingResult(stacks_.get(SMELTING_INPUT_SLOT_NO)); @@ -772,7 +710,6 @@ public class BlockDecorFurnace extends BlockDecorDirected final ItemStack smelting_input_stack = stacks_.get(SMELTING_INPUT_SLOT_NO); final ItemStack recipe_result_items = BRecipes.instance().getSmeltingResult(smelting_input_stack); final ItemStack smelting_output_stack = stacks_.get(SMELTING_OUTPUT_SLOT_NO); - final ItemStack fuel_stack = stacks_.get(SMELTING_FUEL_SLOT_NO); if(smelting_output_stack.isEmpty()) { stacks_.set(SMELTING_OUTPUT_SLOT_NO, recipe_result_items.copy()); } else if(smelting_output_stack.getItem() == recipe_result_items.getItem()) { @@ -853,6 +790,70 @@ public class BlockDecorFurnace extends BlockDecorDirected return super.getCapability(capability, facing); } } + + // ITickable ------------------------------------------------------------------------------------ + + @Override + public void update() + { + if(--tick_timer_ > 0) return; + tick_timer_ = TICK_INTERVAL; + final boolean was_burning = isBurning(); + if(was_burning) burntime_left_ -= TICK_INTERVAL; + if(burntime_left_ < 0) burntime_left_ = 0; + if(world.isRemote) return; + boolean dirty = false; + if(--fifo_timer_ <= 0) { + fifo_timer_ = FIFO_INTERVAL/TICK_INTERVAL; + // note, intentionally not using bitwise OR piping. + if(transferItems(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, 1)) dirty = true; + if(transferItems(SMELTING_OUTPUT_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, 1)) dirty = true; + if(transferItems(FIFO_FUEL_0_SLOT_NO, SMELTING_FUEL_SLOT_NO, 1)) dirty = true; + if(transferItems(FIFO_FUEL_1_SLOT_NO, FIFO_FUEL_0_SLOT_NO, 1)) dirty = true; + if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 1)) dirty = true; + if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 1)) dirty = true; + heater_inserted_ = (ExtItems.IE_EXTERNAL_HEATER==null) // without IE always allow electrical boost + || (stacks_.get(AUX_0_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER) + || (stacks_.get(AUX_1_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER); + } + ItemStack fuel = stacks_.get(SMELTING_FUEL_SLOT_NO); + if(isBurning() || (!fuel.isEmpty()) && (!(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty())) { + if(!isBurning() && canSmelt()) { + burntime_left_ = (int)MathHelper.clamp((proc_fuel_efficiency_ * getItemBurnTime(fuel)), 0, MAX_BURNTIME); + fuel_burntime_ = (burntime_left_ * proc_speed_interval_) / VANILLA_FURNACE_SPEED_INTERVAL; + if(isBurning()) { + dirty = true; + if(!fuel.isEmpty()) { + Item fuel_item = fuel.getItem(); + fuel.shrink(1); + if(fuel.isEmpty()) stacks_.set(SMELTING_FUEL_SLOT_NO, fuel_item.getContainerItem(fuel)); + } + } + } + if(isBurning() && canSmelt()) { + proc_time_elapsed_ += TICK_INTERVAL; + if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL; } + if(proc_time_elapsed_ >= proc_time_needed_) { + proc_time_elapsed_ = 0; + proc_time_needed_ = getCookTime(stacks_.get(SMELTING_INPUT_SLOT_NO)); + smeltItem(); + dirty = true; + } + } else { + proc_time_elapsed_ = 0; + } + } else if(!isBurning() && (proc_time_elapsed_ > 0)) { + proc_time_elapsed_ = MathHelper.clamp(proc_time_elapsed_-2, 0, proc_time_needed_); + } + if(was_burning != isBurning()) { + dirty = true; + final IBlockState state = world.getBlockState(pos); + if(state.getBlock() instanceof BlockDecorFurnace) { + world.setBlockState(pos, state.withProperty(LIT, isBurning())); + } + } + if(dirty) markDirty(); + } } //-------------------------------------------------------------------------------------------------------------------- diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java new file mode 100644 index 0000000..92c9694 --- /dev/null +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java @@ -0,0 +1,683 @@ +/* + * @file BlockDecorFurnaceElectrical.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * ED electrical furnace. + */ +package wile.engineersdecor.blocks; + + +import wile.engineersdecor.ModEngineersDecor; + +import net.minecraft.stats.StatList; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.world.World; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.init.Items; +import net.minecraft.item.*; +import net.minecraft.inventory.*; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.*; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.energy.CapabilityEnergy; +import net.minecraftforge.energy.IEnergyStorage; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Random; + +public class BlockDecorFurnaceElectrical extends BlockDecorFurnace +{ + public BlockDecorFurnaceElectrical(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB) + { + super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); + } + + @Nullable + public TileEntity createTileEntity(World world, IBlockState state) + { return new BlockDecorFurnaceElectrical.BTileEntity(); } + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) + { + if(world.isRemote) return true; + player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_ELECTRICAL_LAB_FURNACE, world, pos.getX(), pos.getY(), pos.getZ()); + player.addStat(StatList.FURNACE_INTERACTION); + return true; + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd) + {} + + //-------------------------------------------------------------------------------------------------------------------- + // ModEngineersDecor.GuiHandler connectors + //-------------------------------------------------------------------------------------------------------------------- + + public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te) + { return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; } + + public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te) + { return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; } + + //-------------------------------------------------------------------------------------------------------------------- + // GUI + //-------------------------------------------------------------------------------------------------------------------- + + @SideOnly(Side.CLIENT) + private static class BGui extends GuiContainer + { + private final BTileEntity te; + + public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te) + { super(new BContainer(playerInventory, world, pos, te)); this.te = te; } + + @Override + public void initGui() + { super.initGui(); } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) + { + drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + renderHoveredToolTip(mouseX, mouseY); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) + { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/small_electrical_furnace_gui.png")); + final int x0=(width-xSize)/2, y0=(height-ySize)/2, w=xSize, h=ySize; + drawTexturedModalRect(x0, y0, 0, 0, w, h); + if(BTileEntity.isBurning(te)) { + if(BlockDecorFurnace.BTileEntity.isBurning(te)) { + final int hi = 13; + final int k = heat_px(hi); + drawTexturedModalRect(x0+61, y0+53+hi-k, 177, hi-k, 13, k); + } + } + drawTexturedModalRect(x0+79, y0+30, 176, 15, 1+progress_px(17), 15); + int we = energy_px(32, 8); + if(we>0) drawTexturedModalRect(x0+88, y0+53, 185, 30, we, 13); + } + + private int progress_px(int pixels) + { final int tc=te.getField(2), T=te.getField(3); return ((T>0) && (tc>0)) ? (tc * pixels / T) : (0); } + + private int heat_px(int pixels) + { + int k = ((te.getField(0) * (pixels+1)) / (BlockDecorFurnaceElectrical.BTileEntity.HEAT_CAPACITY)); + return (k < pixels) ? k : pixels; + } + + private int energy_px(int maxwidth, int quantization) + { + int k = ((maxwidth * te.getField(1) * 9) / 8) / (te.getMaxEnergyStored()+1); + k = (k >= maxwidth-2) ? maxwidth : k; + if(quantization > 0) k = ((k+(quantization/2))/quantization) * quantization; + return k; + } + + } + + //-------------------------------------------------------------------------------------------------------------------- + // container + //-------------------------------------------------------------------------------------------------------------------- + + public static class BContainer extends Container + { + private static final int PLAYER_INV_START_SLOTNO = 7; + private final World world; + private final BlockPos pos; + private final EntityPlayer player; + private final BTileEntity te; + private int burntime_left_, energy_stored_, proc_time_elapsed_, proc_time_needed_, speed_; + + public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te) + { + this.player = playerInventory.player; + this.world = world; + this.pos = pos; + this.te = te; + addSlotToContainer(new Slot(te, 0, 59, 28)); // smelting input + addSlotToContainer(new Slot(te, 1, 16, 52)); // aux + addSlotToContainer(new BSlotResult(playerInventory.player, te, 2, 101, 28)); // smelting result + addSlotToContainer(new BSlotInpFifo(te, 3, 34, 28)); // input fifo 0 + addSlotToContainer(new BSlotInpFifo(te, 4, 16, 28)); // input fifo 1 + addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 5, 126, 28)); // out fifo 0 + addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 6, 144, 28)); // out fifo 1 + for(int x=0; x<9; ++x) { + addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8 + } + for(int y=0; y<3; ++y) { + for(int x=0; x<9; ++x) { + addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35 + } + } + } + + @Override + public void addListener(IContainerListener listener) + { super.addListener(listener); listener.sendAllWindowProperties(this, te); } + + @Override + public void detectAndSendChanges() + { + super.detectAndSendChanges(); + for(int i=0; i= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) { + // Player inventory + if(!BRecipes.instance().getSmeltingResult(slot_stack).isEmpty()) { + if( + (!mergeItemStack(slot_stack, 0, 1, false)) && // smelting input + (!mergeItemStack(slot_stack, 3, 4, false)) && // fifo0 + (!mergeItemStack(slot_stack, 4, 5, false)) // fifo1 + ) return ItemStack.EMPTY; + } else if((index >= PLAYER_INV_START_SLOTNO) && (index < PLAYER_INV_START_SLOTNO+27)) { + // player inventory --> player hotbar + if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO+27, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY; + } else if((index >= PLAYER_INV_START_SLOTNO+27) && (index < PLAYER_INV_START_SLOTNO+36) && (!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+27, false))) { + // player hotbar --> player inventory + return ItemStack.EMPTY; + } + } else { + // invalid slot + return ItemStack.EMPTY; + } + if(slot_stack.isEmpty()) { + slot.putStack(ItemStack.EMPTY); + } else { + slot.onSlotChanged(); + } + if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY; + slot.onTake(player, slot_stack); + return transferred; + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class BTileEntity extends BlockDecorFurnace.BTileEntity implements ITickable, ISidedInventory, IEnergyStorage, IItemHandler + { + public static final int TICK_INTERVAL = 4; + public static final int FIFO_INTERVAL = 20; + public static final int HEAT_CAPACITY = 200; + public static final int HEAT_INCREMENT = 20; + public static final int MAX_ENERGY_TRANSFER = 256; + public static final int MAX_ENERGY_BUFFER = 32000; + public static final int MAX_SPEED_SETTING = 2; + public static final int NUM_OF_SLOTS = 7; + public static final int SMELTING_INPUT_SLOT_NO = 0; + public static final int SMELTING_AUX_SLOT_NO = 1; + public static final int SMELTING_OUTPUT_SLOT_NO = 2; + public static final int FIFO_INPUT_0_SLOT_NO = 3; + public static final int FIFO_INPUT_1_SLOT_NO = 4; + public static final int FIFO_OUTPUT_0_SLOT_NO = 5; + public static final int FIFO_OUTPUT_1_SLOT_NO = 6; + public static final int DEFAULT_SPEED_PERCENT = 200; + public static final int DEFAULT_ENERGY_CONSUMPTION = 16 ; + public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT/100; + + private static int energy_consumption_ = DEFAULT_SCALED_ENERGY_CONSUMPTION; + private static int transfer_energy_consumption_ = DEFAULT_SCALED_ENERGY_CONSUMPTION/8; + private static int proc_speed_percent_ = DEFAULT_SPEED_PERCENT; + private int burntime_left_; + private int proc_time_elapsed_; + private int proc_time_needed_; + private int energy_stored_; + private int speed_; + private int tick_timer_; + private int fifo_timer_; + + public static void on_config(int speed_percent, int standard_energy_per_tick) + { + proc_speed_percent_ = MathHelper.clamp(speed_percent, 10, 500); + energy_consumption_ = MathHelper.clamp(standard_energy_per_tick, 10, 256) * HEAT_INCREMENT * proc_speed_percent_ / 100; + transfer_energy_consumption_ = MathHelper.clamp(energy_consumption_/8, 8, HEAT_INCREMENT); + ModEngineersDecor.logger.info("Config electrical furnace speed:" + proc_speed_percent_ + ", power consumption:" + energy_consumption_); + } + + public BTileEntity() + { super(); reset(); } + + public void reset() + { + stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + burntime_left_ = 0; + proc_time_elapsed_ = 0; + proc_time_needed_ = 0; + fifo_timer_ = 0; + tick_timer_ = 0; + energy_stored_= 0; + speed_ = 0; + } + + public void readnbt(NBTTagCompound compound) + { + reset(); + ItemStackHelper.loadAllItems(compound, this.stacks_); + while(this.stacks_.size() < NUM_OF_SLOTS) this.stacks_.add(ItemStack.EMPTY); + burntime_left_ = compound.getInteger("BurnTime"); + proc_time_elapsed_ = compound.getInteger("CookTime"); + proc_time_needed_ = compound.getInteger("CookTimeTotal"); + energy_stored_ = compound.getInteger("Energy"); + speed_ = compound.getInteger("SpeedSetting"); + } + + protected void writenbt(NBTTagCompound compound) + { + compound.setInteger("BurnTime", MathHelper.clamp(burntime_left_,0 , HEAT_CAPACITY)); + compound.setInteger("CookTime", MathHelper.clamp(proc_time_elapsed_, 0, MAX_BURNTIME)); + compound.setInteger("CookTimeTotal", MathHelper.clamp(proc_time_needed_, 0, MAX_BURNTIME)); + compound.setInteger("Energy", MathHelper.clamp(energy_stored_,0 , MAX_ENERGY_BUFFER)); + compound.setInteger("SpeedSetting", MathHelper.clamp(speed_, -1, MAX_SPEED_SETTING)); + ItemStackHelper.saveAllItems(compound, stacks_); + } + + // TileEntity ------------------------------------------------------------------------------ + // IWorldNamable --------------------------------------------------------------------------- + // IInventory ------------------------------------------------------------------------------ + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) + { + switch(index) { + case SMELTING_INPUT_SLOT_NO: + case FIFO_INPUT_0_SLOT_NO: + case FIFO_INPUT_1_SLOT_NO: + return true; + default: + return false; + } + } + + @Override + public int getField(int id) + { + switch (id) { + case 0: return burntime_left_; + case 1: return energy_stored_; + case 2: return proc_time_elapsed_; + case 3: return proc_time_needed_; + case 4: return speed_; + default: return 0; + } + } + + @Override + public void setField(int id, int value) + { + switch(id) { + case 0: burntime_left_ = value; break; + case 1: energy_stored_ = value; break; + case 2: proc_time_elapsed_ = value; break; + case 3: proc_time_needed_ = value; break; + case 4: speed_ = value; break; + } + } + + @Override + public int getFieldCount() + { return 7; } + + public boolean isBurning() + { return burntime_left_ > 0; } + + private boolean transferItems(final int index_from, final int index_to, int count) + { + ItemStack from = stacks_.get(index_from); + if(from.isEmpty()) return false; + ItemStack to = stacks_.get(index_to); + if(from.getCount() < count) count = from.getCount(); + if(count <= 0) return false; + boolean changed = true; + if(to.isEmpty()) { + stacks_.set(index_to, from.splitStack(count)); + } else if(to.getCount() >= to.getMaxStackSize()) { + changed = false; + } else if((!from.isItemEqual(to)) || (!ItemStack.areItemStackTagsEqual(from, to))) { + changed = false; + } else { + if((to.getCount()+count) >= to.getMaxStackSize()) { + from.shrink(to.getMaxStackSize()-to.getCount()); + to.setCount(to.getMaxStackSize()); + } else { + from.shrink(count); + to.grow(count); + } + } + if(from.isEmpty() && from!=ItemStack.EMPTY) { + stacks_.set(index_from, ItemStack.EMPTY); + changed = true; + } + return changed; + } + + // ISidedInventory ---------------------------------------------------------------------------- + + private static final int[] SIDED_INV_SLOTS = new int[] { + SMELTING_INPUT_SLOT_NO, SMELTING_AUX_SLOT_NO, SMELTING_OUTPUT_SLOT_NO, + FIFO_INPUT_0_SLOT_NO, FIFO_INPUT_1_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO + }; + + @Override + public int[] getSlotsForFace(EnumFacing side) + { return SIDED_INV_SLOTS; } + + @Override + public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction) + { return isItemValidForSlot(index, itemStackIn); } + + @Override + public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) + { return ((index!=SMELTING_INPUT_SLOT_NO) && (index!=FIFO_INPUT_0_SLOT_NO) && (index!=FIFO_INPUT_1_SLOT_NO)) || (stack.getItem()==Items.BUCKET); } + + // IEnergyStorage ---------------------------------------------------------------------------- + + public boolean canExtract() + { return false; } + + public boolean canReceive() + { return true; } + + public int getMaxEnergyStored() + { return MAX_ENERGY_BUFFER; } + + public int getEnergyStored() + { return energy_stored_; } + + public int extractEnergy(int maxExtract, boolean simulate) + { return 0; } + + public int receiveEnergy(int maxReceive, boolean simulate) + { + if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0; + int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_)); + if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER; + if(!simulate) {energy_stored_ += n; markDirty(); } + return n; + } + + // IItemHandler -------------------------------------------------------------------------------- + + @Override + public int getSlots() + { return SIDED_INV_SLOTS.length; } + + @Override + @Nonnull + public ItemStack getStackInSlot(int index) + { return ((index < 0) || (index >= SIDED_INV_SLOTS.length)) ? ItemStack.EMPTY : stacks_.get(SIDED_INV_SLOTS[index]); } + + @Override + public int getSlotLimit(int index) + { return getInventoryStackLimit(); } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) + { return true; } + + @Override + @Nonnull + public ItemStack insertItem(int index, @Nonnull ItemStack stack, boolean simulate) + { + if(stack.isEmpty()) return ItemStack.EMPTY; + if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY; + int slotno = SIDED_INV_SLOTS[index]; + ItemStack slotstack = getStackInSlot(slotno); + if(!slotstack.isEmpty()) + { + if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(index))) return stack; + if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; + if(!canInsertItem(slotno, stack, EnumFacing.UP) || (!isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)) - slotstack.getCount(); + if(stack.getCount() <= n) { + if(!simulate) { + ItemStack copy = stack.copy(); + copy.grow(slotstack.getCount()); + setInventorySlotContents(slotno, copy); + } + return ItemStack.EMPTY; + } else { + stack = stack.copy(); + if(!simulate) { + ItemStack copy = stack.splitStack(n); + copy.grow(slotstack.getCount()); + setInventorySlotContents(slotno, copy); + return stack; + } else { + stack.shrink(n); + return stack; + } + } + } else { + if(!canInsertItem(slotno, stack, EnumFacing.UP) || (!isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)); + if(n < stack.getCount()) { + stack = stack.copy(); + if(!simulate) { + setInventorySlotContents(slotno, stack.splitStack(n)); + return stack; + } else { + stack.shrink(n); + return stack; + } + } else { + if(!simulate) setInventorySlotContents(slotno, stack); + return ItemStack.EMPTY; + } + } + } + + @Override + @Nonnull + public ItemStack extractItem(int index, int amount, boolean simulate) + { + if(amount == 0) return ItemStack.EMPTY; + if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY; + int slotno = SIDED_INV_SLOTS[index]; + ItemStack stackInSlot = getStackInSlot(slotno); + if(stackInSlot.isEmpty()) return ItemStack.EMPTY; + if(!canExtractItem(slotno, stackInSlot, EnumFacing.DOWN)) return ItemStack.EMPTY; + if(simulate) { + if(stackInSlot.getCount() < amount) return stackInSlot.copy(); + ItemStack ostack = stackInSlot.copy(); + ostack.setCount(amount); + return ostack; + } else { + ItemStack ostack = decrStackSize(slotno, Math.min(stackInSlot.getCount(), amount)); + markDirty(); + return ostack; + } + } + + // Capability export ---------------------------------------------------------------------------- + + @Override + public boolean hasCapability(Capability cap, EnumFacing facing) + { return ((cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || (cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); } + + @Override + @SuppressWarnings("unchecked") + @Nullable + public T getCapability(Capability capability, @Nullable EnumFacing facing) + { + if((capability == CapabilityEnergy.ENERGY) || (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) { + return ((T)this); + } else { + return super.getCapability(capability, facing); + } + } + + // ITickable ------------------------------------------------------------------------------------ + + private boolean adjacent_inventory_shift(boolean inp, boolean out) + { + boolean dirty = false; + if(energy_stored_ < transfer_energy_consumption_) return false; + final IBlockState state = world.getBlockState(pos); + if(!(state.getBlock() instanceof BlockDecorFurnaceElectrical)) return false; + final EnumFacing out_facing = state.getValue(FACING); + final EnumFacing inp_facing = state.getValue(FACING).getOpposite(); + if(out && (!stacks_.get(FIFO_OUTPUT_1_SLOT_NO).isEmpty())) { + TileEntity te = world.getTileEntity(pos.offset(out_facing)); + if((te!=null) && (te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, inp_facing))) { + IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, inp_facing); + ItemStack remaining = ItemHandlerHelper.insertItemStacked(hnd, stacks_.get(FIFO_OUTPUT_1_SLOT_NO).copy(), false); + stacks_.set(FIFO_OUTPUT_1_SLOT_NO, remaining); + energy_stored_ -= transfer_energy_consumption_; + dirty = true; + } + } + if(inp && (stacks_.get(FIFO_INPUT_1_SLOT_NO).isEmpty())) { + TileEntity te = world.getTileEntity(pos.offset(inp_facing)); + if((te!=null) && (te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, out_facing))) { + IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, out_facing); + for(int i=0; i< hnd.getSlots(); ++i) { + ItemStack adj_stack = hnd.getStackInSlot(i); + if(!adj_stack.isEmpty()) { + ItemStack my_stack = adj_stack.copy(); + if(my_stack.getCount() > getInventoryStackLimit()) my_stack.setCount(getInventoryStackLimit()); + adj_stack.shrink(my_stack.getCount()); + stacks_.set(FIFO_INPUT_1_SLOT_NO, my_stack); + energy_stored_ -= transfer_energy_consumption_; + dirty = true; + break; + } + } + } + } + return dirty; + } + + // returns TE dirty + private boolean heat_up() + { + if(energy_stored_ < (energy_consumption_)) return false; + if(burntime_left_ >= (HEAT_CAPACITY-HEAT_INCREMENT)) return false; + energy_stored_ -= energy_consumption_; + burntime_left_ += HEAT_INCREMENT; + this.markDirty(); + return true; + } + + @Override + public void update() + { + if(--tick_timer_ > 0) return; + tick_timer_ = TICK_INTERVAL; + final boolean was_burning = isBurning(); + if(was_burning) burntime_left_ -= TICK_INTERVAL; + if(burntime_left_ < 0) burntime_left_ = 0; + if(world.isRemote) return; + boolean dirty = false; + boolean shift_in = false; + boolean shift_out = false; + if(--fifo_timer_ <= 0) { + fifo_timer_ = FIFO_INTERVAL/TICK_INTERVAL; + if(transferItems(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, 64)) { dirty = true; } else { shift_out = true; } + if(transferItems(SMELTING_OUTPUT_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, 64)) dirty = true; + if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 64)) dirty = true; + if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 64)) { dirty = true; } else { shift_in = true; } + } + if((!(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty()) && (energy_stored_ >= energy_consumption_)) { + final boolean can_smelt = canSmelt(); + if((!can_smelt) && (BRecipes.instance().getSmeltingResult(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty())) { + // bypass + if(transferItems(SMELTING_INPUT_SLOT_NO, SMELTING_OUTPUT_SLOT_NO, 1)) dirty = true; + } else { + // smelt + if(!isBurning() && can_smelt) { + if(heat_up()) dirty = true; + } + if(isBurning() && can_smelt) { + if(heat_up()) dirty = true; + proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_percent_/100); + if(proc_time_elapsed_ >= proc_time_needed_) { + proc_time_elapsed_ = 0; + proc_time_needed_ = getCookTime(stacks_.get(SMELTING_INPUT_SLOT_NO)); + smeltItem(); + dirty = true; + shift_out = true; + } + } else { + proc_time_elapsed_ = 0; + } + } + } else if(proc_time_elapsed_ > 0) { + proc_time_elapsed_ -= ((stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty() ? 20 : 1); + if(proc_time_elapsed_ < 0) { proc_time_elapsed_ = 0; shift_out = true; } + } + if(was_burning != isBurning()) { + dirty = true; + final IBlockState state = world.getBlockState(pos); + if(state.getBlock() instanceof BlockDecorFurnace) { + world.setBlockState(pos, state.withProperty(LIT, isBurning())); + } + } + if(adjacent_inventory_shift(shift_in, shift_out)) dirty = true; + if(dirty) markDirty(); + } + } +} diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/ModBlocks.java b/1.12/src/main/java/wile/engineersdecor/blocks/ModBlocks.java index e74d366..ee7d7d8 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/ModBlocks.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/ModBlocks.java @@ -163,21 +163,28 @@ public class ModBlocks public static final BlockDecorFurnace SMALL_LAB_FURNACE = new BlockDecorFurnace( "small_lab_furnace", BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT, - Material.IRON, 1.0f, 15f, SoundType.METAL, - ModAuxiliaries.getPixeledAABB(1,0,1, 15,15,16.0) + Material.IRON, 0.35f, 15f, SoundType.METAL, + ModAuxiliaries.getPixeledAABB(1,0,1, 15,15,16) + ); + + public static final BlockDecorFurnaceElectrical SMALL_ELECTRICAL_FURNACE = new BlockDecorFurnaceElectrical( + "small_electrical_furnace", + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT, + Material.IRON, 0.35f, 15f, SoundType.METAL, + ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16) ); public static final BlockDecorDirected SIGN_MODLOGO = new BlockDecorDirected( "sign_decor", BlockDecor.CFG_CUTOUT|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<*J+Bj?OGj;JcbFmOB`xAzz$0D&`geSOW<)fHXWQEMfHK;QQqk4HoVGsE3cRa8V+ zkGqpn!ptx;9`>J^KYT(&7Pj!4ueG*-hzP2RnQcs}O0AWjKfZJK?JKGZK;QR-5H`Zr z8oDBi2z}qvT0=xArSNY2!h1h#005VlmxK^#tu3SgW=7X_%=3)9^ZfiwN{M-%w+tR1 z9|5Sf(skWtA*kw!?35A>P*qY&lv)uHQqFj-q@1BajFE912_k~1ayT6Rn8s>n_4~SR zZa%&pqi}zJ$23jM^L%c)#285_F$@D{FTuMzUL9zZQqDFvK!EAho4W&`i_Ast-f6F*8(k^SV|_ z33sQpM$UPe!Zb~|JHs%Xu&g_<1*W=5FQqJ>44{<4e!s`vPd2TTvNf97$r6=PaCd$I XkZ0(Nzn|h_00000NkvXXu0mjf6!_|v literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_bottom.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..d806f99ce5122b32c69900e40429a1079770cfbd GIT binary patch literal 472 zcmV;}0Vn>6P)6|+(FLN z_rFmmi20d?WT%1IwHG!ZQ&iO}O5fk#otgag831Dp9*+kgx(fgwgYG6XaWl-Fj36SB z;PrYD5g5R}?^HML4nVK&CSekipwHD=cfa3f&8a{VnZa=!m^4qzB&+_D-QBb4*+6SU zbz^3LrkyIfimIAc+>wm#hEIbjaoaX*Eke^>m>IIUL1t7H5||ko`GI(<0C0C2hzPoy z{p*X2SQZm=$9;S(NPOg&VP;g;lnKOfT#O`xZYIs4A*@NjJ=<-N^g} zu^W@Y%D;L-i->8bi}(9Y#Btf;R|;dsa&B&fK!%yaIR|FTqOZD{6Trw!s-_XGmz!Tc zBZ7TRB{Yqw%4^)L7nCD{%v{7_+cw4+jBVq*D<@#O@lzGRaU5)8fP{~Mnc+Ua!=2mh zhNLx6lg-(5NaFc?a@%)IVvKRYY*-2Cn$Yg1x_LdHABdUB^XKPJ*ZCj%hWO0rx`;0T O0000XP)!HELlwKV%ZP5ZgR!)D3zxrSG-~PVr&h}y4hI9sIb&ul zmrG`|8RzpEGh?&aFpeWHFE1@Vjw5D*joQcCoFPo4XD62AW$QB}P6 z^nFiCsl@?e2mw_krPP9T!RH?z8HNE>Y1qRsaJ${waU;+WMTF<)=Y}XEJUu-TLSP(6 zN-2#b=gjSPBdRK^)rzj`P*p+*6f;zW5CUcfK)+m4R4Hb3u_MOF>+9=85W9}!@yL7K z7q=Q!?f3iX2;O^2DS+dAJ~gyQ>bj1U66^K48As8D_3 z|IF;(eZk@Wkb7076l;i+A^*`t3rqyHGb_Per#@6ErDcir`T!P-1v%$-oo@wxQ%Z?a z3Nc3J^Et7Uf{0K`VZC1em8EuHHK`4zs;wKF!EU!Bgg}h3J?&~x=S8Gd|9ZUw@Edo6 V3C7p;wm<*?002ovPDHLkV1mP`;Uxe7 literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_off.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_off.png new file mode 100644 index 0000000000000000000000000000000000000000..481f72d5478496abde8a9fc19405437c8f46f7d7 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP%z8W z#WBR<^xF#?MVkY7oG+@^nmw3oD)enWrx?R+%@;u}O>;t4gcSDc+Qt_bDn3ifd%#x5 z#54csE*+OQA`YUHPWY%?j!J&>*LuTS>8YNwOspIYEU*4Fr3r_69B<#&!I6{vTjs^( d$NQD{F=p_{zuxql$r@-YgQu&X%Q~loCIIb@K0yEg literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png new file mode 100644 index 0000000000000000000000000000000000000000..02da0360fe33acdd23c7f887409f9b706e6c3f4c GIT binary patch literal 693 zcmV;m0!safP)h649aa%+62aP!(pEtsjg}G%ksyf1T<#-oF8j_{>_#MlyWk-f@0RZ_&rUJ>Fuz$j zySU{1#ijh^l>iAa5+5Aw*oLVdo1-q0wlo5d>|mAh$!X`2q7r$R?i2Q z7jwqvPjK}3N#sZy@_l0Vm6gZu>iOW&+a@9%j5pv8?mw$aK1hHB_~$-AK)|h-ghM0X zKx?vH{W)JdKSQH6L1-#@Ho&r79B1`atgZlH^>rU)fSG|AZicEN8fy5UJ)im@0TN&| zKKO>}!Bp;8jOBa~K!ny*l@G*OzIYl5O=7mou(yp59h%DOi=8??5LTYO2NbgirIAFn zuvDcFX68~KBtQa;!Uw%>=>u1ABbp(A9{8X#FCg5!vV?n+ILyiSGQC^`akN_j`LBEHJfCE@D zvAYpMz^OAIxN-OPGG>vy|A}E|gZ-UNoXCUcyEW&75DFi}94{-7a(_^nSkiou00}TE zAM|!mQNWA55c6O1g4X-LaO?U7@@&9x`y<)bCh>b89Sb~MAFG=eifmvp2XovVQBZCC bhk4-#zUdTDfe9UT00000NkvXXu0mjf1t2%c literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png.mcmeta b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png.mcmeta new file mode 100644 index 0000000..e745021 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_gloom_on.png.mcmeta @@ -0,0 +1 @@ +{ "animation":{ "frames": [0,1,2,3,4,5,6,7], "frametime":8, "interpolate":true }} \ No newline at end of file diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_left.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/furnace/small_electrical_furnace_left.png new file mode 100644 index 0000000000000000000000000000000000000000..40012d5e95074321d79db1abe41d9c960b6c7490 GIT binary patch literal 522 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 W3(FSP0H!UoS()2ksyFj~^#1_OyMS5% literal 0 HcmV?d00001 diff --git a/meta/update.json b/meta/update.json index a6d98b8..b0a040d 100644 --- a/meta/update.json +++ b/meta/update.json @@ -1,7 +1,8 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.12.2": { - "1.0.4-b9": "[F] Inserting fluids with pressurized tag only into IE piping.\n[F] Valve redstone connector rendering does not check for \"can connect redstone\" but only for \"can provide power\".\n[M] Valves are adpted to be detected as pipe by IE.", + "1.0.4": "[R] Release based on v1.0.3-b9. Release-to-release changes: * Crafting table: Quick crafting history re-fab, JEI integration. * Rendering improvements and issue fixes (stairs, ambient occlusion, optifine, etc). * Walls with texture variations. * Thin/thick steel poles with support feet/heads. * Horizontal steel double-T support beams added. * Fluid pipe valves added: Check valve, redstone controlled valve, analog redstone controlled valve. Support pressuzized transfer. * Tooltip documentation (CTRL-SHIFT) for stairs added. * Internal code cleanups. * Recipes tuned.\n[E] Added pass-through electrical furnace (experimental, see config).", + "1.0.4-b9": "[F] Inserting fluids with pressurized tag only into IE piping.\n[F] Valve redstone connector rendering does not check for \"can connect redstone\" but only for \"can provide power\".\n[M] Valves are adapted to be detected as pipe by IE.", "1.0.4-b8": "[F] Fixed stairs rendering without smooth light (thanks rastot9).\n[E] Added passive fluid accumulator (experimental feature, see config).", "1.0.4-b7": "[F] Fixed recipe loading issue if IE is not installed.\n[M] Valves support IE pressurized fluid transfer.", "1.0.4-b6": "[A] Added redstone controlled fluid valve.\n[A] Added redstone controlled analog fluid valve.\n[M] Check valve recipe adapted (thanks majijn).", @@ -41,8 +42,8 @@ "1.0.0-a1": "[A] Initial port to 1.13.2 with Forge beta." }, "promos": { - "1.12.2-recommended": "1.0.3", - "1.12.2-latest": "1.0.4-b9", + "1.12.2-recommended": "1.0.4", + "1.12.2-latest": "1.0.4", "1.13.2-recommended": "", "1.13.2-latest": "1.0.4-b3" }