From 41b48208a00840e3bd5f6b54a4fed9254feff793 Mon Sep 17 00:00:00 2001 From: stfwi Date: Sat, 21 Mar 2020 18:00:37 +0100 Subject: [PATCH] 1.12: Backported E-Furnace/Labeled Crate from 1.14/1.15. --- 1.12/gradle.properties | 2 +- 1.12/meta/update.json | 4 +- 1.12/readme.md | 5 +- .../java/wile/engineersdecor/ModContent.java | 14 + .../engineersdecor/ModEngineersDecor.java | 3 + .../blocks/BlockDecorFurnaceElectrical.java | 96 ++- .../blocks/BlockDecorLabeledCrate.java | 593 +++++++++++++++++ .../wile/engineersdecor/detail/ModTesrs.java | 49 +- .../blockstates/labeled_crate.json | 11 + .../assets/engineersdecor/lang/en_us.lang | 2 + .../assets/engineersdecor/lang/ru_ru.lang | 2 + .../assets/engineersdecor/lang/zh_cn.lang | 2 + .../block/misc/labeled_crate_model.json | 77 +++ .../labeled_crate_recipe_standalone.json | 33 + .../dependent/labeled_crate_recipe.json | 33 + .../misc/labeled_crate_front_texture.png | Bin 0 -> 662 bytes .../misc/labeled_crate_side_texture.png | Bin 0 -> 672 bytes .../textures/gui/labeled_crate_gui.png | Bin 0 -> 16765 bytes .../gui/small_electrical_furnace_gui.png | Bin 22957 -> 25902 bytes 1.14/gradle.properties | 2 +- 1.14/readme.md | 3 + .../java/wile/engineersdecor/ModContent.java | 19 + .../blocks/BlockDecorFurnaceElectrical.java | 2 +- .../blocks/BlockDecorHopper.java | 4 +- .../blocks/BlockDecorLabeledCrate.java | 596 +++++++++++++++++ .../wile/engineersdecor/detail/ModTesrs.java | 48 +- 1.14/src/main/resources/META-INF/mods.toml | 2 +- .../blockstates/labeled_crate.json | 8 + .../assets/engineersdecor/lang/en_us.json | 2 + .../assets/engineersdecor/lang/ru_ru.json | 2 + .../assets/engineersdecor/lang/zh_cn.json | 2 + .../block/misc/labeled_crate_model.json | 77 +++ .../models/item/labeled_crate.json | 1 + .../misc/labeled_crate_front_texture.png | Bin 0 -> 662 bytes .../block/misc/labeled_crate_side_texture.png | Bin 0 -> 672 bytes .../textures/gui/labeled_crate_gui.png | Bin 0 -> 16765 bytes .../dependent/labeled_crate_recipe.json | 58 ++ 1.15/gradle.properties | 4 +- 1.15/readme.md | 2 + .../java/wile/engineersdecor/ModContent.java | 22 + .../blocks/BlockDecorFurnaceElectrical.java | 2 +- .../blocks/BlockDecorHopper.java | 4 +- .../blocks/BlockDecorLabeledCrate.java | 597 ++++++++++++++++++ .../engineersdecor/detail/ModRenderers.java | 53 +- .../blockstates/labeled_crate.json | 8 + .../assets/engineersdecor/lang/en_us.json | 2 + .../assets/engineersdecor/lang/ru_ru.json | 2 + .../assets/engineersdecor/lang/zh_cn.json | 2 + .../block/misc/labeled_crate_model.json | 77 +++ .../models/item/labeled_crate.json | 1 + .../misc/labeled_crate_front_texture.png | Bin 0 -> 662 bytes .../block/misc/labeled_crate_side_texture.png | Bin 0 -> 672 bytes .../textures/gui/labeled_crate_gui.png | Bin 0 -> 16765 bytes .../dependent/labeled_crate_recipe.json | 58 ++ meta/update.json | 4 +- 55 files changed, 2556 insertions(+), 34 deletions(-) create mode 100644 1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java create mode 100644 1.12/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/recipes/alternative/labeled_crate_recipe_standalone.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/recipes/dependent/labeled_crate_recipe.json create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_front_texture.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_side_texture.png create mode 100644 1.12/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png create mode 100644 1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java create mode 100644 1.14/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png create mode 100644 1.14/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json create mode 100644 1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java create mode 100644 1.15/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json create mode 100644 1.15/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json create mode 100644 1.15/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json create mode 100644 1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png create mode 100644 1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png create mode 100644 1.15/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png create mode 100644 1.15/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json diff --git a/1.12/gradle.properties b/1.12/gradle.properties index 67808a7..78c91d5 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.20-b1 +version_engineersdecor=1.0.20-b2 diff --git a/1.12/meta/update.json b/1.12/meta/update.json index b4597d6..3e0264d 100644 --- a/1.12/meta/update.json +++ b/1.12/meta/update.json @@ -1,6 +1,8 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.12.2": { + "1.0.20-b2": "[A] Backported Electrical Furnace GUI speed selection switch.\n[A] Backported Labeled Crate (storage crate with built-in item frame).", + "1.0.20-b1": "[/] Version skipped for 1.12.2.", "1.0.19": "[R] Release based on v1.0.19-b4. Release-to-release changes: * Transfer fixes for Tree Cutter / Block Breaker, and Factory hopper. * Cleanups, feature backports * Visual fixes and improvements\n[A] Backport of status display for Tree Cutter, Block Breaker and Solar Panel.", "1.0.19-b4": "[A] Creative tab opt-out visibility handling added (issue #90, thx pimalel233).", "1.0.19-b3": "[A] Factory Hopper: Added bottom item handler (CR#227).", @@ -82,6 +84,6 @@ }, "promos": { "1.12.2-recommended": "1.0.19", - "1.12.2-latest": "1.0.19" + "1.12.2-latest": "1.0.20-b2" } } \ No newline at end of file diff --git a/1.12/readme.md b/1.12/readme.md index 768a266..4271db6 100644 --- a/1.12/readme.md +++ b/1.12/readme.md @@ -10,7 +10,10 @@ Mod sources for Minecraft version 1.12.2. ---- ## Version history - ~ v1.0.20-b1 [F] + - v1.0.20-b2 [A] Backported Electrical Furnace GUI speed selection switch. + [A] Backported Labeled Crate (storage crate with built-in item frame). + + - v1.0.20-b1 [/] Version skipped for 1.12.2. ------------------------------------------------------------------- - v1.0.19 [R] Release based on v1.0.19-b4. Release-to-release changes: diff --git a/1.12/src/main/java/wile/engineersdecor/ModContent.java b/1.12/src/main/java/wile/engineersdecor/ModContent.java index 3e03d86..95e2e3b 100644 --- a/1.12/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.12/src/main/java/wile/engineersdecor/ModContent.java @@ -210,6 +210,13 @@ public class ModContent ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16) ); + public static final BlockDecorLabeledCrate.DecorLabeledCrateBlock LABELED_CRATE = new BlockDecorLabeledCrate.DecorLabeledCrateBlock( + "labeled_crate", + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT, + Material.WOOD, 0.5f, 128f, SoundType.METAL, + ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16) + ); + //-------------------------------------------------------------------------------------------------------------------- public static final BlockDecorStraightPole TREATED_WOOD_POLE = new BlockDecorStraightPole( @@ -478,6 +485,9 @@ public class ModContent private static final TileEntityRegistrationData TREATED_WOOD_CRAFTING_TABLE_TEI = new TileEntityRegistrationData( BlockDecorCraftingTable.BTileEntity.class, "te_crafting_table" ); + private static final TileEntityRegistrationData LABELED_CRATE_TEI = new TileEntityRegistrationData( + BlockDecorLabeledCrate.LabeledCrateTileEntity.class, "te_labeled_crate" + ); private static final TileEntityRegistrationData SMALL_LAB_FURNACE_TEI = new TileEntityRegistrationData( BlockDecorFurnace.BTileEntity.class, "te_small_lab_furnace" ); @@ -530,6 +540,7 @@ public class ModContent private static final Object content[] = { TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE_TEI, + LABELED_CRATE, LABELED_CRATE_TEI, SMALL_LAB_FURNACE, SMALL_LAB_FURNACE_TEI, SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE_TEI, FACTORY_HOPPER,FACTORY_HOPPER_TEI, @@ -704,6 +715,9 @@ public class ModContent if(!ModConfig.isOptedOut(TREATED_WOOD_CRAFTING_TABLE)) { ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.BTileEntity.class, new ModTesrs.TesrDecorCraftingTable()); } + if(!ModConfig.isOptedOut(LABELED_CRATE)) { + ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorLabeledCrate.LabeledCrateTileEntity.class, new ModTesrs.TesrDecorLabeledCrate()); + } if(!ModConfig.isOptedOut(TEST_BLOCK)) { ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorTest.BTileEntity.class, new ModTesrs.TesrDecorTest()); } diff --git a/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java b/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java index 810bb70..88d6199 100644 --- a/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java +++ b/1.12/src/main/java/wile/engineersdecor/ModEngineersDecor.java @@ -161,6 +161,7 @@ public class ModEngineersDecor public static final int GUIID_FACTORY_DROPPER = 213105; public static final int GUIID_FACTORY_HOPPER = 213106; public static final int GUIID_FACTORY_PLACER = 213107; + public static final int GUIID_LABELED_CRATE = 213108; @Override public Object getServerGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z) @@ -175,6 +176,7 @@ public class ModEngineersDecor case GUIID_FACTORY_DROPPER: return BlockDecorDropper.getServerGuiElement(player, world, pos, te); case GUIID_FACTORY_HOPPER: return BlockDecorHopper.getServerGuiElement(player, world, pos, te); case GUIID_FACTORY_PLACER: return BlockDecorPlacer.getServerGuiElement(player, world, pos, te); + case GUIID_LABELED_CRATE: return BlockDecorLabeledCrate.getServerGuiElement(player, world, pos, te); } return null; } @@ -193,6 +195,7 @@ public class ModEngineersDecor case GUIID_FACTORY_DROPPER: return BlockDecorDropper.getClientGuiElement(player, world, pos, te); case GUIID_FACTORY_HOPPER: return BlockDecorHopper.getClientGuiElement(player, world, pos, te); case GUIID_FACTORY_PLACER: return BlockDecorPlacer.getClientGuiElement(player, world, pos, te); + case GUIID_LABELED_CRATE: return BlockDecorLabeledCrate.getClientGuiElement(player, world, pos, te); } return null; } diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java index a10f9a3..47fa6f4 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java @@ -38,9 +38,11 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import wile.engineersdecor.detail.Networking; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.IOException; import java.util.Random; public class BlockDecorFurnaceElectrical extends BlockDecorFurnace @@ -134,6 +136,13 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace 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); + switch(te.getField(4)) { + case 0: drawTexturedModalRect(x0+144, y0+57, 180, 57, 6, 9); break; + case 1: drawTexturedModalRect(x0+142, y0+58, 190, 58, 9, 6); break; + case 2: drawTexturedModalRect(x0+144, y0+56, 200, 57, 6, 9); break; + case 3: drawTexturedModalRect(x0+143, y0+58, 210, 58, 9, 6); break; + default: break; + } } private int progress_px(int pixels) @@ -153,10 +162,33 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace return k; } + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException + { + BContainer container = (BContainer)inventorySlots; + int mx = (int)(mouseX - getGuiLeft() + .5), my = (int)(mouseY - getGuiTop() + .5); + int speed = -1; + if((!isPointInRegion(136, 48, 28, 28, mouseX, mouseY))) { + super.mouseClicked(mouseX, mouseY, mouseButton); + } else if(isPointInRegion(144, 64, 6, 10, mouseX, mouseY)) { + speed = 0; + } else if(isPointInRegion(134, 58, 10, 6, mouseX, mouseY)) { + speed = 1; + } else if(isPointInRegion(144, 48, 6, 10, mouseX, mouseY)) { + speed = 2; + } else if(isPointInRegion(150, 58, 10, 6, mouseX, mouseY)) { + speed = 3; + } + if(speed >= 0) { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("speed", speed); + Networking.PacketTileNotify.sendToServer(te, nbt); + } + } } //-------------------------------------------------------------------------------------------------------------------- - // container + // Container //-------------------------------------------------------------------------------------------------------------------- public static class BContainer extends Container @@ -274,7 +306,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class BTileEntity extends BlockDecorFurnace.BTileEntity implements ITickable, ISidedInventory, IEnergyStorage + public static class BTileEntity extends BlockDecorFurnace.BTileEntity implements ITickable, ISidedInventory, IEnergyStorage, Networking.IPacketReceiver { public static final int TICK_INTERVAL = 4; public static final int FIFO_INTERVAL = 20; @@ -295,16 +327,12 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace 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; + // Config ---------------------------------------------------------------------------------- + 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_; + private static double speed_setting_factor_[] = {0.0, 1.0, 1.5, 2.0}; public static void on_config(int speed_percent, int standard_energy_per_tick) { @@ -314,6 +342,17 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace ModEngineersDecor.logger.info("Config electrical furnace speed:" + proc_speed_percent_ + ", power consumption:" + energy_consumption_); } + // BTileEntity ------------------------------------------------------------------------------ + + 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_; + private boolean enabled_ = false; + public BTileEntity() { super(); reset(); } @@ -326,7 +365,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace fifo_timer_ = 0; tick_timer_ = 0; energy_stored_= 0; - speed_ = 0; + speed_ = 1; } public void readnbt(NBTTagCompound compound) @@ -339,6 +378,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace proc_time_needed_ = compound.getInteger("CookTimeTotal"); energy_stored_ = compound.getInteger("Energy"); speed_ = compound.getInteger("SpeedSetting"); + speed_ = (speed_ < 0) ? (1) : ((speed_>3) ? 3 : speed_); } protected void writenbt(NBTTagCompound compound) @@ -602,6 +642,19 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace return super.getCapability(capability, facing); } + // IPacketReceiver ------------------------------------------------------------------------------- + + @Override + public void onServerPacketReceived(NBTTagCompound nbt) + {} + + @Override + public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt) + { + if(nbt.hasKey("speed")) speed_ = MathHelper.clamp(nbt.getInteger("speed"), 0, 3); + markDirty(); + } + // ITickable ------------------------------------------------------------------------------------ private boolean adjacent_inventory_shift(boolean inp, boolean out) @@ -646,14 +699,24 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace // returns TE dirty private boolean heat_up() { - if(energy_stored_ < (energy_consumption_)) return false; + if(energy_stored_ < (energy_consumption())) return false; if(burntime_left_ >= (HEAT_CAPACITY-HEAT_INCREMENT)) return false; - energy_stored_ -= energy_consumption_; + energy_stored_ -= energy_consumption(); burntime_left_ += HEAT_INCREMENT; this.markDirty(); return true; } + int energy_consumption() + { + switch(speed_) { + case 1: return energy_consumption_; + case 2: return energy_consumption_ * 2; + case 3: return energy_consumption_ * 4; + default: return 0; + } + } + private void sync_blockstate() { final IBlockState state = world.getBlockState(pos); @@ -682,9 +745,14 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace 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(energy_stored_ < energy_consumption()) { + enabled_ = false; + } else if(energy_stored_ >= (MAX_ENERGY_BUFFER/2)) { + enabled_ = true; + } final ItemStack last_inp_stack = current_smelting_input_stack_; current_smelting_input_stack_ = stacks_.get(SMELTING_INPUT_SLOT_NO); - if((!current_smelting_input_stack_.isEmpty()) && (energy_stored_ >= energy_consumption_)) { + if((!current_smelting_input_stack_.isEmpty()) && (enabled_) && (speed_>0) && (speed_<4)) { if(!current_smelting_input_stack_.isItemEqual(current_smelting_input_stack_)) { proc_time_elapsed_ = 0; proc_time_needed_ = getCookTime(current_smelting_input_stack_); @@ -700,7 +768,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace } if(isBurning() && can_smelt) { if(heat_up()) dirty = true; - proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_percent_/100); + proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_percent_ * speed_setting_factor_[speed_] / 100); if(proc_time_elapsed_ >= proc_time_needed_) { proc_time_elapsed_ = 0; proc_time_needed_ = getCookTime(current_smelting_input_stack_); diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java new file mode 100644 index 0000000..9a2f912 --- /dev/null +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java @@ -0,0 +1,593 @@ +/* + * @file BlockDecorLabeledCrate.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Storage crate with a content hint. + */ +package wile.engineersdecor.blocks; + +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.*; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import wile.engineersdecor.ModEngineersDecor; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + + +public class BlockDecorLabeledCrate +{ + public static void on_config(int stack_limit) + { + } + + //-------------------------------------------------------------------------------------------------------------------- + // Block + //-------------------------------------------------------------------------------------------------------------------- + + public static class DecorLabeledCrateBlock extends BlockDecorDirectedHorizontal + { + public DecorLabeledCrateBlock(@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); } + + @Override + public boolean hasTileEntity(IBlockState state) + { return true; } + + @Override + @Nullable + public TileEntity createTileEntity(World world, IBlockState state) + { return new LabeledCrateTileEntity(); } + + @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_LABELED_CRATE, world, pos.getX(), pos.getY(), pos.getZ()); + return true; + } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) + { + if(world.isRemote) return; + if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("inventory"))) return; + NBTTagCompound inventory_nbt = stack.getTagCompound().getCompoundTag("inventory"); + if(inventory_nbt.isEmpty()) return; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return; + ((LabeledCrateTileEntity)te).readnbt(inventory_nbt); + ((LabeledCrateTileEntity)te).markDirty(); + } + + private ItemStack itemize_with_inventory(World world, BlockPos pos) + { + TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return ItemStack.EMPTY; + ItemStack stack = new ItemStack(this, 1); + NBTTagCompound inventory_nbt = new NBTTagCompound(); + ItemStackHelper.saveAllItems(inventory_nbt, ((LabeledCrateTileEntity)te).stacks_, false); + if(!inventory_nbt.isEmpty()) { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setTag("inventory", inventory_nbt); + stack.setTagCompound(nbt); + } + return stack; + } + + @Override + public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) + { + if(world.isRemote) return true; + final ItemStack stack = itemize_with_inventory(world, pos); + if(stack != ItemStack.EMPTY) { + world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack)); + world.setBlockToAir(pos); + world.removeTileEntity(pos); + return false; + } else { + return super.removedByPlayer(state, world, pos, player, willHarvest); + } + } + + @Override + public void onBlockExploded(World world, BlockPos pos, Explosion explosion) + { + if(world.isRemote) return; + TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return; + for(ItemStack stack: ((LabeledCrateTileEntity)te).stacks_) { + if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack)); + } + ((LabeledCrateTileEntity)te).reset(); + super.onBlockExploded(world, pos, explosion); + } + + @Override + @SuppressWarnings("deprecation") + public boolean hasComparatorInputOverride(IBlockState state) + { return true; } + + @Override + @SuppressWarnings("deprecation") + public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos) + { return Container.calcRedstone(world.getTileEntity(pos)); } + + } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class LabeledCrateTileEntity extends TileEntity implements ISidedInventory + { + public static final int NUM_OF_FIELDS = 1; + public static final int NUM_OF_SLOTS = 55; + public static final int ITEMFRAME_SLOTNO = 54; + + // LabeledCrateTileEntity -------------------------------------------------------------------------- + + protected NonNullList stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + + public LabeledCrateTileEntity() + { reset(); } + + protected void reset() + { stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); } + + public void readnbt(NBTTagCompound compound) + { + NonNullList stacks = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(compound, stacks); + while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY); + stacks_ = stacks; + } + + protected void writenbt(NBTTagCompound compound) + { ItemStackHelper.saveAllItems(compound, stacks_); } + + public ItemStack getItemFrameStack() + { return (stacks_.size() > ITEMFRAME_SLOTNO)?(stacks_.get(ITEMFRAME_SLOTNO)):(ItemStack.EMPTY); } + + // TileEntity ------------------------------------------------------------------------------ + + @Override + public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns) + { return (os.getBlock()!=ns.getBlock())||(!(ns.getBlock() instanceof DecorLabeledCrateBlock));} + + @Override + public void readFromNBT(NBTTagCompound compound) + { super.readFromNBT(compound); readnbt(compound); } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound) + { super.writeToNBT(compound); writenbt(compound); return compound; } + + @Override + public NBTTagCompound getUpdateTag() + { NBTTagCompound nbt = super.getUpdateTag(); writenbt(nbt); return nbt; } + + @Override + @Nullable + public SPacketUpdateTileEntity getUpdatePacket() + { return new SPacketUpdateTileEntity(pos, 1, getUpdateTag()); } + + @Override + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) // on client + { super.readFromNBT(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } + + @Override + public void handleUpdateTag(NBTTagCompound tag) // on client + { readFromNBT(tag); } + + // INameable --------------------------------------------------------------------------- + + @Override + public String getName() + { final Block block = getBlockType(); return (block!=null)?(block.getTranslationKey()+".name"):(""); } + + @Override + public boolean hasCustomName() + { return false; } + + @Override + public ITextComponent getDisplayName() + { return new TextComponentTranslation(getName(), new Object[0]); } + + // IInventory ------------------------------------------------------------------------------ + + @Override + public int getSizeInventory() + { return stacks_.size(); } + + @Override + public boolean isEmpty() + { for(ItemStack stack : stacks_) { if(!stack.isEmpty()) return false; } return true; } + + @Override + public ItemStack getStackInSlot(int index) + { return ((index >= 0)&&(index < getSizeInventory()))?stacks_.get(index):ItemStack.EMPTY; } + + @Override + public ItemStack decrStackSize(int index, int count) + { return ItemStackHelper.getAndSplit(stacks_, index, count); } + + @Override + public ItemStack removeStackFromSlot(int index) + { return ItemStackHelper.getAndRemove(stacks_, index); } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) + { + if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); + stacks_.set(index, stack); + markDirty(); + if(!getWorld().isRemote) { + // This should result in sending TE data (getUpdateTag etc) to the client for the TER. + IBlockState state = world.getBlockState(getPos()); + getWorld().notifyBlockUpdate(getPos(), state, state, 2|16|32); + } + } + + @Override + public int getInventoryStackLimit() + { return 64; } + + @Override + public void markDirty() + { super.markDirty(); } + + @Override + public boolean isUsableByPlayer(EntityPlayer player) + { return getPos().distanceSq(player.getPosition()) < 36; } + + @Override + public void openInventory(EntityPlayer player) + {} + + @Override + public void closeInventory(EntityPlayer player) + { markDirty(); } + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) + { return (index!=ITEMFRAME_SLOTNO); } + + @Override + public void clear() + { stacks_.clear(); } + + // Fields ----------------------------------------------------------------------------------------------- + + @Override + public int getField(int id) + { return 0; } + + @Override + public void setField(int id, int value) + {} + + @Override + public int getFieldCount() + { return 0; } + + // ISidedInventory ---------------------------------------------------------------------------- + + private static final int[] SIDED_INV_SLOTS; + static { + SIDED_INV_SLOTS = new int[LabeledCrateTileEntity.NUM_OF_SLOTS-1]; + for(int i = 0; i < SIDED_INV_SLOTS.length; ++i) SIDED_INV_SLOTS[i] = i; + } + + @Override + public int[] getSlotsForFace(EnumFacing side) + { return SIDED_INV_SLOTS; } + + @Override + public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction) + { return true; } + + @Override + public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) + { return true; } + + // IItemHandler -------------------------------------------------------------------------------- + + protected static class BItemHandler implements IItemHandler + { + private LabeledCrateTileEntity te; + + BItemHandler(LabeledCrateTileEntity te) + { + this.te = te; + } + + @Override + public int getSlots() + { + return ITEMFRAME_SLOTNO; + } // iframe slot is the last + + @Override + public int getSlotLimit(int index) + { + return te.getInventoryStackLimit(); + } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) + { + return true; + } + + @Override + @Nonnull + public ItemStack insertItem(int slotno, @Nonnull ItemStack stack, boolean simulate) + { + if(stack.isEmpty()) return ItemStack.EMPTY; + if((slotno < 0)||((slotno >= NUM_OF_SLOTS))||((slotno==ITEMFRAME_SLOTNO))) return ItemStack.EMPTY; + ItemStack slotstack = getStackInSlot(slotno); + if(!slotstack.isEmpty()) { + if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(slotno))) return stack; + if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; + if(!te.canInsertItem(slotno, stack, EnumFacing.UP)||(!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno))-slotstack.getCount(); + if(stack.getCount() <= n) { + if(!simulate) { + ItemStack copy = stack.copy(); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + } + return ItemStack.EMPTY; + } + else { + stack = stack.copy(); + if(!simulate) { + ItemStack copy = stack.splitStack(n); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + return stack; + } + else { + stack.shrink(n); + return stack; + } + } + } + else { + if(!te.canInsertItem(slotno, stack, EnumFacing.UP)||(!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)); + if(n < stack.getCount()) { + stack = stack.copy(); + if(!simulate) { + te.setInventorySlotContents(slotno, stack.splitStack(n)); + return stack; + } + else { + stack.shrink(n); + return stack; + } + } + else { + if(!simulate) te.setInventorySlotContents(slotno, stack); + return ItemStack.EMPTY; + } + } + } + + @Override + @Nonnull + public ItemStack extractItem(int index, int amount, boolean simulate) + { + if((index < 0)||((index >= NUM_OF_SLOTS))||((index==ITEMFRAME_SLOTNO))) return ItemStack.EMPTY; + if(!simulate) return ItemStackHelper.getAndSplit(te.stacks_, index, amount); + ItemStack stack = te.stacks_.get(index).copy(); + if(stack.getCount() > amount) stack.setCount(amount); + return stack; + } + + @Override + @Nonnull + public ItemStack getStackInSlot(int index) + { + return te.getStackInSlot(index); + } + } + + // Capability export ---------------------------------------------------------------------------- + + private final IItemHandler item_handler_ = new BItemHandler(this); + + @Override + public boolean hasCapability(Capability cap, EnumFacing facing) + { + return (cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)||super.hasCapability(cap, facing); + } + + @Override + @SuppressWarnings("unchecked") + @Nullable + public T getCapability(Capability capability, @Nullable EnumFacing facing) + { + if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T)item_handler_; + return super.getCapability(capability, facing); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // GUI + //-------------------------------------------------------------------------------------------------------------------- + + @SideOnly(Side.CLIENT) + private static class BGui extends GuiContainer + { + private final LabeledCrateTileEntity te; + + public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, LabeledCrateTileEntity te) + { + super(new BContainer(playerInventory, world, pos, te)); + this.te = te; + xSize = 213; + ySize = 206; + } + + @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/labeled_crate_gui.png")); + final int x0=guiLeft, y0=guiTop, w=xSize, h=ySize; + drawTexturedModalRect(x0, y0, 0, 0, w, h); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Container + //-------------------------------------------------------------------------------------------------------------------- + + public static class BContainer extends Container + { + //------------------------------------------------------------------------------------------------------------------ + private static final int PLAYER_INV_START_SLOTNO = LabeledCrateTileEntity.NUM_OF_SLOTS; + private final World world; + private final BlockPos pos; + private final EntityPlayer player; + private final LabeledCrateTileEntity te; + //------------------------------------------------------------------------------------------------------------------ + + public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, LabeledCrateTileEntity te) + { + this.player = playerInventory.player; + this.world = world; + this.pos = pos; + this.te = te; + int i=-1; + // storage slots (stacks 0 to 53) + for(int y=0; y<6; ++y) { + for(int x=0; x<9; ++x) { + int xpos = 28+x*18, ypos = 10+y*18; + addSlotToContainer(new Slot(te, ++i, xpos, ypos)); + } + } + // picture frame slot (54) + addSlotToContainer(new Slot(te, ++i, 191, 100) { + @Override public int getSlotStackLimit(){return 1;} + }); + // player slots + for(int x=0; x<9; ++x) { + addSlotToContainer(new Slot(playerInventory, x, 28+x*18, 183)); // 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, 28+x*18, 125+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(); } + + @Override + @SideOnly(Side.CLIENT) + public void updateProgressBar(int id, int data) + { te.setField(id, data); } + + @Override + public boolean canInteractWith(EntityPlayer player) + { return (world.getBlockState(pos).getBlock() instanceof DecorLabeledCrateBlock) && (player.getDistanceSq(pos) <= 64); } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slot) + { return (slot.getSlotStackLimit() > 1); } + + @Override + public void onContainerClosed(EntityPlayer player) + { super.onContainerClosed(player); } + + @Override + public ItemStack transferStackInSlot(EntityPlayer player, int index) + { + Slot slot = getSlot(index); + if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY; + ItemStack slot_stack = slot.getStack(); + ItemStack transferred = slot_stack.copy(); + if((index>=0) && (index= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) { + // Player slot + if(!mergeItemStack(slot_stack, 0, PLAYER_INV_START_SLOTNO-1, false)) 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; + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // ModEngineersDecor.GuiHandler connectors + //-------------------------------------------------------------------------------------------------------------------- + + public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te) + { return (te instanceof LabeledCrateTileEntity) ? (new BContainer(player.inventory, world, pos, (LabeledCrateTileEntity)te)) : null; } + + public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te) + { return (te instanceof LabeledCrateTileEntity) ? (new BGui(player.inventory, world, pos, (LabeledCrateTileEntity)te)) : null; } + +} diff --git a/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java b/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java index 3b44cd4..439355a 100644 --- a/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java +++ b/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java @@ -27,6 +27,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.math.MathHelper; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import wile.engineersdecor.blocks.BlockDecorLabeledCrate; +import wile.engineersdecor.blocks.BlockDecorLabeledCrate.DecorLabeledCrateBlock; import wile.engineersdecor.blocks.BlockDecorTest; public class ModTesrs @@ -82,13 +84,58 @@ public class ModTesrs } } catch(Throwable e) { if(--tesr_error_counter<=0) { - ModEngineersDecor.logger.error("TESR was disabled because broken, exception was: " + e.getMessage()); + ModEngineersDecor.logger.error("Crafting Table TESR was disabled because broken, exception was: " + e.getMessage()); ModEngineersDecor.logger.error(e.getStackTrace()); } } } } + //-------------------------------------------------------------------------------------------------------------------- + // Labeled Crate + //-------------------------------------------------------------------------------------------------------------------- + + @SideOnly(Side.CLIENT) + public static class TesrDecorLabeledCrate extends TileEntitySpecialRenderer + { + private static int tesr_error_counter = 4; + private static double scaler = 0.35; + double tr[][]= { // [hdirection=S-W-N-E][param] + { +8.0/32, -8.0/32, +15.5/32, 180.0 }, // N + { -15.5/32, -8.0/32, +8.0/32, 90.0 }, // E + { -8.0/32, -8.0/32, -15.5/32, 0.0 }, // S param=tx,ty,tz,ry + { +15.5/32, -8.0/32, -8.0/32, 270.0 }, // W + }; + + @Override + public void render(final BlockDecorLabeledCrate.LabeledCrateTileEntity te, final double x, final double y, final double z, final float partialTicks, final int destroyStage, final float alpha) + { + if(tesr_error_counter<=0) return; + try { + final ItemStack stack = te.getItemFrameStack(); + if(stack.isEmpty()) return; + final int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).getValue(DecorLabeledCrateBlock.FACING).getHorizontalIndex(), 0, 3); + double ox = tr[di][0], oy = tr[di][1], oz = tr[di][2], ry = tr[di][3]; + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + RenderHelper.enableStandardItemLighting(); + GlStateManager.translate(x+0.5+ox, y+0.5+oy, z+0.5+oz); + GlStateManager.rotate((float)ry, 0, 1, 0); + GlStateManager.scale(scaler, scaler, scaler); + Minecraft.getMinecraft().getRenderItem().renderItem(stack, TransformType.FIXED); + RenderHelper.disableStandardItemLighting(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + } catch(Throwable e) { + if(--tesr_error_counter<=0) { + ModEngineersDecor.logger.error("Labeled Crate TESR was disabled (because broken), exception was: " + e.getMessage()); + } + } + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Test Block //-------------------------------------------------------------------------------------------------------------------- @SideOnly(Side.CLIENT) diff --git a/1.12/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json b/1.12/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json new file mode 100644 index 0000000..e8da6fc --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json @@ -0,0 +1,11 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "engineersdecor:misc/labeled_crate_model" + }, + "variants": { + "normal": [{}], + "inventory": [{}], + "facing": { "north": {"y":0}, "south": {"y":180}, "west": {"y":-90}, "east": {"y":90}, "up":{}, "down":{} } + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/lang/en_us.lang b/1.12/src/main/resources/assets/engineersdecor/lang/en_us.lang index 6da9ac4..f764978 100644 --- a/1.12/src/main/resources/assets/engineersdecor/lang/en_us.lang +++ b/1.12/src/main/resources/assets/engineersdecor/lang/en_us.lang @@ -108,6 +108,8 @@ tile.engineersdecor.treated_wood_crafting_table.help=§6Robust and weather-proof to clear crafting grid and history. Shift-click stack: player-to-storage stack transfer when crafting \ grid empty, otherwise player-to-grid stack transfer. Automatically distributes the clicked stack. \ Shift-Ctrl-click stack: Move all same stacks. Mouse wheel over crafting slot: Increase/decrease crafting grid items. +tile.engineersdecor.labeled_crate.name=Labeled Crate +tile.engineersdecor.labeled_crate.help=§6§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label. tile.engineersdecor.treated_wood_side_table.name=Treated Wood Side Table tile.engineersdecor.treated_wood_side_table.help=§6Needed after the work's done. tile.engineersdecor.iron_inset_light.name=Inset Light diff --git a/1.12/src/main/resources/assets/engineersdecor/lang/ru_ru.lang b/1.12/src/main/resources/assets/engineersdecor/lang/ru_ru.lang index 77fb5af..2770b8c 100644 --- a/1.12/src/main/resources/assets/engineersdecor/lang/ru_ru.lang +++ b/1.12/src/main/resources/assets/engineersdecor/lang/ru_ru.lang @@ -108,6 +108,8 @@ tile.engineersdecor.treated_wood_crafting_table.help=§6Прочный и уст   очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании \ если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. \ Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке. +tile.engineersdecor.labeled_crate.name=Labeled Crate +tile.engineersdecor.labeled_crate.help=§6§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label. tile.engineersdecor.treated_wood_side_table.name=Столик из обработанного дерева tile.engineersdecor.treated_wood_side_table.help=§6Нужен после того, как работа выполнена. tile.engineersdecor.iron_inset_light.name=Встраиваемый осветитель diff --git a/1.12/src/main/resources/assets/engineersdecor/lang/zh_cn.lang b/1.12/src/main/resources/assets/engineersdecor/lang/zh_cn.lang index fac089b..2a1ab91 100644 --- a/1.12/src/main/resources/assets/engineersdecor/lang/zh_cn.lang +++ b/1.12/src/main/resources/assets/engineersdecor/lang/zh_cn.lang @@ -107,6 +107,8 @@ tile.engineersdecor.treated_wood_crafting_table.help=§6坚固,防风防雨。 单击上/下箭头按钮可选择合成历史,单击输出格自动放置物品,单击X按钮\ 清除合成栏和历史。Shift单击一叠物品:合成格空时转移到存储格,\ 非空时到合成栏。会自动分配转移的物品。 +tile.engineersdecor.labeled_crate.name=Labeled Crate +tile.engineersdecor.labeled_crate.help=§6§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label. tile.engineersdecor.treated_wood_side_table.name=防腐木茶几 tile.engineersdecor.treated_wood_side_table.help=§6干完活后需要喝杯茶。 tile.engineersdecor.iron_inset_light.name=嵌入灯 diff --git a/1.12/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json b/1.12/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json new file mode 100644 index 0000000..7cb6191 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json @@ -0,0 +1,77 @@ +{ + "parent": "block/block", + "textures": { + "f": "engineersdecor:blocks/misc/labeled_crate_front_texture", + "particle": "engineersdecor:blocks/misc/labeled_crate_side_texture", + "s": "engineersdecor:blocks/misc/labeled_crate_side_texture" + }, + "elements": [ + { + "from": [0, 7, 0], + "to": [16, 16, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0.25], + "to": [16, 16, 16], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [7, 0, 0], + "to": [16, 7, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0], + "to": [1, 7, 0.375], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [1, 0, 0], + "to": [7, 1, 0.25], + "faces": { + "north": {"texture": "#f"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + } + ], + "display": { + "ground": { + "translation": [0, 1.75, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.12/src/main/resources/assets/engineersdecor/recipes/alternative/labeled_crate_recipe_standalone.json b/1.12/src/main/resources/assets/engineersdecor/recipes/alternative/labeled_crate_recipe_standalone.json new file mode 100644 index 0000000..ebb2729 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/recipes/alternative/labeled_crate_recipe_standalone.json @@ -0,0 +1,33 @@ +{ + "conditions": [ + { + "type": "engineersdecor:grc", + "result": "engineersdecor:labeled_crate", + "missing": ["immersiveengineering:material"] + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" +], + "key": { + "R": { + "item": "minecraft:iron_nugget", + "data": 0 + }, + "C": { + "item": "minecraft:chest", + "data": 0 + }, + "F": { + "item": "minecraft:item_frame", + "data": 0 + } + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/recipes/dependent/labeled_crate_recipe.json b/1.12/src/main/resources/assets/engineersdecor/recipes/dependent/labeled_crate_recipe.json new file mode 100644 index 0000000..13b93dc --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/recipes/dependent/labeled_crate_recipe.json @@ -0,0 +1,33 @@ +{ + "conditions": [ + { + "type": "engineersdecor:grc", + "result": "engineersdecor:labeled_crate", + "required": ["immersiveengineering:material"] + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" +], + "key": { + "R": { + "item": "#stickIron", + "data": 0 + }, + "C": { + "item": "#crateTreatedWood", + "data": 0 + }, + "F": { + "item": "minecraft:item_frame", + "data": 0 + } + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_front_texture.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_front_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..2e4f4fbc6b8ca6c98eae7e7548ef28938b92c81e GIT binary patch literal 662 zcmV;H0%`q;P)PA8G!wM z-y1{(cXxOE{Cdr~R@9X61|&Kt;R%46a(n%ezh1oI^z^i2nMtjc$L}}1T%bsDqQNr2 zG6(~Ce8X-uUOo}_-)^Y2Qc9teQuulOfms^+%>dzkb5w;)5EXC%lGrv-;art}KfYsm z{)&>BG${<`D8X)?NKw2sk{~=lz_f61r+ESiB23dnskJg^J$?wczgGIjAkrN$6+Hat zOm`xVMP;|!@o+ov^kkqmhYU`}f&IGi$V5xQvq3Rd50HYAhze%b8EmcbMBsGM2nrM=k2&gj9P&K?}zeJHfIi;bhKvGlyp}MlJE1DgfEOCb< zNd$LCMTBP;Z`tR_QiMTaQ1D1xjNdu&OvuE{SY4<{*W++FFpeXqFW&HFHMW-A*Q9w6 ztq~E_6lM(~lg9=sf@fz?A_6mGSr$$%-tzs^dm^AO181eMA$&U&OgbjOA%uuPE-x>$ wlmbAwBdTNsi2R{%X4G1Hlv_iOQI81z2Lv8c)#zKRApigX07*qoM6N<$f=@FYTL1t6 literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_side_texture.png b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_side_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..17f92edef3ade76c26c8227b2e0f9cb60e277f79 GIT binary patch literal 672 zcmV;R0$=@!P)5teB|))1DD!RQ^Grtr#JyPAC!j=cYJeo&H4E`W`<@atu+q6-E*~rBFU)1 zuEMSgl|03;AB-2H@a5w@tu^L(rj%0n`ijtXx7}YvTu-|S-QM`AOAUr_8w6M6-J%I#-VHhZ_H6r6w5FU;b>%}0l5-=4! z{6uCY(E(MZ?Du=-zm&_fk=7kDFf*ps*p!N>()+@8*f1>%ltPk}05e-R=n?$$w0va_ zj)*YzHCIG9&d;bQNg|>Y0(Ymlug!xAJ(XR7xd%fLKqzGZATj`WUYz|<`1CC61`$Ce zXby>UoB@HhoRnB5Oauf3K}e2sqeuPUwS~{AoXKieNQw%XLIUGpmvq0000Pba?s literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png b/1.12/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..e41e8a35a377d622372623bec951f402b500d7c3 GIT binary patch literal 16765 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 literal 0 HcmV?d00001 diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/gui/small_electrical_furnace_gui.png b/1.12/src/main/resources/assets/engineersdecor/textures/gui/small_electrical_furnace_gui.png index 0177a2159c756879307a148d8659e098370cc037..0fdd087725253b78c0bb7f58d18f73bbbfc03449 100644 GIT binary patch literal 25902 zcmV*xKt8{TP)lfsgte|ay zA=)Ml5(r6T$Uj8Oa@YolAmxW-f&#!GX%pZsunS;;-JR~9#q4Xk``%NP{!y7(S*Pzj zw(kM=VsTGkF*E(BTj!jrtjsUJ{E{C3r@sq1X9NOcb8W7#gDV4+Q$nDK-~R32!iRoh z_7ev$;VXanS5N*I0QkEvyNq=>v^99M}KOvdNRH zzkBk_H^0ii{NfSg{eO0P`-2~y|Jr8T*NYy1{Bi!~Z~kU177M)a!VBoS2>=E&z?{KE z$bFC4bzo)?03rf_@^2zA10e=*&dAK55Kt_1KnMXT^Y$**x`P5QqS9ae6ZA&*{A} zG6RG%CvbTl6bR}k<(vSbG8X{EjGQyNuEW;$Ho%O@WMT%AnPnaUT^HS4%B|VIWlltd z5CRs91z5&9Ihg|loQP2_^VP>v#%BOA#^&FU&&Zj}eG?&20E59fmv7A?RX?p7w ze*b^=59UAr!5^OW+f%}q4*C6m^?yG3`OVgM2H??0AH}oJJ_qKqfFYYD^}W0hS?HYY zMbrgN07$-`k#Yvf1`9EQ%T7X02}A@6!4@4eqw6}^%(;w3Ww{cHk$`Lj-T%7L%O=cn z7gQFOES{8-ETCcp&@8OFpqUAoQ}g{0LNQ{x;JI#gUA(%vbVHFd1jT?cz-1mlH3WK( z#RxJOjGR*00J4!%zW|6Z>AGrMh{|Tk8EOfGY?_?%DdQMp1mt&eN}v$Lh>{sSwK_y( zKcio6HX~8_3;;pm#1I1d#iEQ$WWSShMvT$!Kg9apaw_kf0?GOyIRt<%M!Uyia3S+g zb}*;~2_YcmgeYJ8*vCF*_VWY((yV{Sn*#pH)A=v_7ys+Y-}~7gnDuYE9P$5rzJJdL zKR*9Ezw~3<{TB`sZr{NNKKSwZ2R7Ru2>vA31*Z#v-08{U6}Xk-exAXc?ImS36gfAG zj#(E1%4x5QPS$4TESsc!49W4P3o@m8lIR%4D3s61%;G(;oTMz9#?CM>XW6*LNRfIF zZs9{Vx85re6+@<9(FudiSn5XT`(k`RWy9z*WP1iI&$2%0%xpt;vhkfu(0BzzWJZWU zh%q3>h!6upjAo#-7z=%d6bOOpyE22T^UAGJ*G4*`4EuM1E}$Xri&eK{nqAef8wM?FEZSo07*WT0{*& zLRnz!V@V3KEMcJrBzCkh^u%>>DQsS4K?WkQy6`Bcm7a=_xSz#cN;xBjh@6we$SnVJ zu{#kG2sfX54%^$?w%`x;_i^>wZZT2>WI3U8O6CnTn~xct%%u~2Lk?d1JT=TD&%%de zYA`@R&c!3q&>>K8&j`+wsT(rLJ5Y}$sJFr}qf9^zA9Ulp6CKWo%0q2F4}wjAim}iy zA3Xm&wzs$K(D>@DTex~{*RX+@l7Y{E`TMr|z=Yp^I=%C+{rd6mzwe)!^$%YRIDDD^ z$_Ib*s=k@{3tuLIxw36^uVG1SncoXhX1E3BJRK98skB_OAT8lIGrO$~AyLCisB zmbr;x5I0|qkj443IdwA>kgI@~gzBd1Y1yY_pePaH=;#QG`5g24TwH6aI71UYko`^p z�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 literal 22957 zcmV*SKwZCyP)o2jAqGoANH%d_xrkg z9zC;MYP)-*wahh_qDe^+sW=!!2#_!l3^-7LB(Mc3ie=a(8BSdb<0&Rr#apocf)*w`XSi zyQ^s~>j1Mm)BSyQ@2y*P>O6kucO0_ZxN#$*Nt3Su`NSta;rQQw?FTo0@b_-xOMmXC zk3S9ofAfbozvI_m3IFha^fMU?Z8youf z+uf`vL{V3uie{}iU z^S^NNGi}=!aW`(zfKE!-|?|~SRZyKvBwJz@-c9r@$CPOmk7H)$?u za`ZFu3^C*}!GDi%cDD07N#6;w4!lR-b$XB9`}8|r56-2v5CT@KLC4wJ+QR+gWBlH& zTgDRj3;*nL_04-7e&vPXk3avvpZv_9|L*0zC$G5Wm+!`p{Kr3c^0DW?e`B?^ba>^} z_>sT(v&SE6Tb~rbyWjn8eD$^0^hG+_xlf=dLD`&+@55{)Aclw#2KcTkpUayfgdlnqF$UehF@&N8^7Un&LsmR+ z4i1i#ja6{+TrvNQ^%}BrRXrg0Mfa`BM-@q$59gf@mNtKy5l_lSZd})#EH>v6!=Tqt zMddw?j*ifIkL7ZSkAM8*x>!H@&uy&U|Fp-iycqt(fBL^3|E(YWo{iPh*E{?_Us(OX z^S^lVH-7A2-der%>VVho;iJ$0;>kzb_6NLfmb{wfm6T1x2cJ7*m~^721sV0k2}6L{ zZGdX}v?!4m40KUOxs1#A5YzWV2)YpUGOfEYwywdbh_)iVVL0bY4E0Kwe_fZzRcz~0pk2(ImXjsb|d8R&)HzI_|RYJl?& z+uPe|k>}H~DC?xzSxe{bp=P9PMmfdgv~>Ao4k4!R6g3ZrvPh8)OIgH-&};JI3o!yA zEgIxgCjD}30z1h4W>a|NqLdTSdxs&E(=D*oLrPMl>$;?f^5^f|zO7cwl`B`u7|AR$ z7MCN7hEG-97~ZL6A_~rldlbsCT}=NxbNTPZGRgBS@7xtj$+%gvud*VK`NVMEBa(F? zR#{ODLESPr@sUq^&(;uIn`Bjl5CG?K_xA1lGmpzxufS*b$@e`@PEUG)Sa`rVtWZ@B94nf>suKL5+d|I0_edvk>VeDw|dvFCs3`0uo>PZmHq zAEArZIfuofN8fe0d*_axbaI05=@sc@@4QzZR~KXL8M>qpbRjyYC#cUGNEU|oKADVS zdT0Ma7LROH)gk$`DJFlYuI;On25K_X5A>kpliSg0oj&K)72w5~qZYVx`!>3+OV8jv z?%ckelnUKHT(Lgb+Ta+0SV!NnCP;c-`Q;JJc8Hg%(@7%_s@8P=+UEkr}-MczhE-M1L)}Q;X&6ST1|L=>#2mZ|e zeDpIP{>L{~d)pqb-Nj#c{+Ew`;y?UnHjfu@_`N&v-~ID{`>1XHS^?CW-(~-i7lMNg zs5#!&5oFpSFJ>|6Bbkp5^}ANH(AtdRhvf014cOJ+cg~oX)|@AQKZL9hlKB}pC?Q3luc2H@|-TaFp?n|hF~^8gjg#Wnb6*Ms;oi?bOM)oVTB|% zfp=~c>|-DM%y}jcFVg#V-m66?r#A;XjdhXdo0Vx0w@}s*Su{?pLle`n3S>15$%Pt* ztjKJzRX%!j9C3Z=aBb7QqRTWm?7tRo0l>-1buj=4?pxcIpHKju1eD}Y2swhC{7dMf zDt@1H66H-NgqNs0zaZU!#eb9lpqzMOPD>z>(g?a5f z)g<;_edid1F^|~-3L#+o+BFQT6^3EJuo|#+=~9VTWM5fN()^6_`#{ghCon(1DjRXn ze0GV_>_8|dI-6peu8kNe>0ua(J4b=vqNJh*PG!C$ zfU9}#fP5zlP6H^I zkO^N$e);FTzom>VcR&cc0K=_8TImc;K`9`E{Lb%D=g#3&!hswY4k8ZBE7aprqY<$nRY(DYiChk6Ysl(kPd}Qyk z|Lwo{PhDEQb_9I#=IKZO@+Xe|x3={s6hO(=L`|RZf|Ly*i=doVd9eooKKYem&enlC z0iq1Upa2yH#c+gNz%QVz0iPr>r_v-wVf<-f_?HkKH-WV9Th+n zt2C%sAA0I(79{HCbgpbZ*_@Gp3xbr??@Is-mBqj=0)c^?cNw)gwgNa%CuV+#LqXo< z_v28~an6-k1!EefQh4c|lwd5PxR#XLr#R8by3uTpBV|`oz5G2{6aUUXwzc{L+dbZK z$zA*0?+yONFRu=s+3s>CWLf4CF1ca$U07?T^PT$lBZQw>4Y4Rb2a^I7 zB{Xtla?FD*fFJ#PNBx6c+tI(9jDvuDqLct!!QInIYWzZa!JLvK(@i#s)(S9+OoM{H zz(ZpV-$k(!I0$Hi>Bfw#(}k#V>?P&p3~(pr(<^(#Cg4>RQKaCQBeUOWb_52*6OyH( zsYuD2med*|=jwfBF^$u1;Gm?5z}L^5Hdm(*=Cd;(f~YKt-A4O310<3K-k2Z@s2L#~?Qjm&@G^j^`L~&i%%7G#gVH6buoj@BY znbM`uNz-crNb-F81{29Ho0noAqGTojGyI1w5=pIhoi8e>2HBJ}jBX@V>g*{{CZNuM zBn!c&5CwnWE8vwE3ntfVuw@~!2X^Pg-HBC}r6UVY--RQKk^+&S1IN2J59e)4-~kH2 zk-5)izoyGLHKq$85UyN82Vy?f=|bz1nrOdT8gZ180W}y1vpEhMMGyG2BQHxmDor)Ba8Gf z`M1CSg{B0~^oP&*u5>dvOy8=of z^LCsf%R#V?%;oCD6<^&Un&-7~`C@%YDszNiCsVdghp`N+!Ndljk^Z13FCv#T2d!)1 zEC63$m7G=tmO1JBUJGVC1>Rza$!w=gMTzRe&RyQTj(j<-G{S1rEehv$CDke^ zTpBk@YS;Ms<(-raRjd^Iqo3@5=KH;6QqNDn9M-kYV zH?#p^l(?3jj`Fhe00!}=nT8Us))bMZ=1?|<2J=ETUBTt5C8K~?QiWoIcbzvVIJRPf z-e=HF5-7^8{&JmbuFHxkj*(1Rm_j1PPY9w<6l7hmpfw6{4Eix{fo|5KAf>cdBIX`s zu~ilWc|_{#2jOOLB}J=Q5l?77?@eY!PjptiIq1oS6cRVFkaJKexijffc^*-M5^E^& zk~|NDVEohH^;tNdE!GZjT{@7QcW^y`SZ3l+|A{Zbxevvk_^Ds|x>o{RwWBX(D!5Xc z?^2#CKoVKl@^ZVX>Pt^V@$Z}mgg?NM-zbn09vZ+8OmE1RmBp2iO~i!&B;H3LX;Gqp3o?8UpRBf-^P;^o>Q@^FU79 zq+e`bKE|K@SH6Hh^?e_TO#xIc`X5Ue6TgqW;G@;y=;u4tmAX1S}*Xb#J)*^QfrfN^1&oLI(9}DJj zz=MKS5;3PaF)TwBCW0rZJZB+7iNQjIy$L)<41o%uX!HAAfW*PcG&fEGJB0*Eeq z%sg6%8sV3mfSUBEV;zJNg;-5q<2E$}y4Das`BT5_{` zpbEf7?xBI5ihE;0G5K7V{FCP zdQmHnO#di=FF=ceyqU9Dpx%Vh7z1`}-9a=ael#g%sW5bI>|SYh#yi6+Q3qBh>xWTv zwy^+|0WOX#jB8hq@gx8Gi(l7DKovlsQ%g{K%-RxkftHgk<`Y>KqiAcJ$1dq0F@dFm zkbO$6E)xJzZ5A-jo))O!oz(T(oE>qZLENfoCG^w8-oHysWfNBJjQ|!8}=j zD1I%-(h;l3(v=l(jH^;{@_7lu3jLV|%Q%&1=*A3cBVV(m^SaC|q;zd?blS&k+2j&x zCMF?8UDAPZjF=?Up_Z2qVT@p;cchjEZPiGrXHSr9vyh!nJ3czy^i;`gpv)1aoc%xh z@7{&4=U9Lr`%zIBhD~SDNeU1gcf2t<#pN7E>AhG1fjA|^AeUHG%@t%Cj5!Y=*XKJ^ zUTn>EH^u`X8Um3><2lFvw+-6yDHKL^_g?E2+>{bhA3qojy|t&@M1ms+HY+xyv#7kH zP@4gUvP{aRHH`@ypyfIVy(8yLU4sco@@XDH04M@E0m^kyT$2*~n@Xd~1acr(6qK(B zRR7fXeJK8G-}O5M*~!y6MQ4`-(f`F?eK)?|1A%>&_bSm`M6=KeS*NWpXEV8m?{Wc4 zi~$Zlp9TTG^9n4IlQkHKDs)3}WZhT*C|N?axHURWJaS|`Frv{{RA?o-U!b>g%9kJ~ z*YC&CJ#|$uvZhc&mA@C{q2T+|lyLPRjHRFeDNQ>TiZW5gzMiY>+HuspWGF1vOAXi7 zpyh-GW~u>2xuF7c5pgIV%VkbHVjQ%bdBl_~ZbOJl2{%~{DLUAr%1*^f6Qu9_mp}d- ze(bOR;@5o^ptt@zOv$hC1C)gnh!7J-%hzSDo&Z6CXrmERwHFodmkl_IDL6&kVIoV< z+<{WOl9Uz~tdOa#CzvlOCR5V@yZEZbsAa#*h?|K}N(6r>u?MY4bT*hm(RE?@;gdIn zn0X620Jg9yy@o=+Ub{VoIXG51`O4~=_`LTO{(~zhIX_SJ6`UPN0m)94UNC^AG(TPE zEo(B(tz{c3&*_R$Wa|saYWQov^oJj~(0}NAKC2J>U;Sj;{1Z5Us8xWTeEgD=XG}mW zwf>yet4}K4$b1rlnTO*TSVNl+k!!>YZXd)rQ|^H`Z}F=g=e?cN6dH_c;>IaYx+lRP zX#F}|6~UK4SqU0??inB@#IQJb%Ry-Ax9Wl{8}t)OaBr#>nJ!EFCJ;tIKF@BCfRChH zS*^KP{1Bgmdz><4OoDR}-uJ0W(w(h%ty>YbaxwV?od%5A{W6M%t(5$%k7maI)A5JD z@3Z)?|HroZr!4?_xs2Cl^jTC2s`O6ozHz6Jc1{GN0NeP3Hy8))j!#ZfqX<|0c@wC} zE`l(}2*Yqk#1PVigJGFHlo%3ohMkw(9z;)e2jeE)|SJ&DfKbi*YZg zbXUrNhs+8brIa}XU4{^F|L909gekTn*+4=zS}QF_#Z|;*qTI?cM%;bl4fJ`Vr@DWy zu9Ba?=ucgv?|a<2bEnJ~Fd~I<)C8plKh^JzY3XX1bG|tQ*n+M%yNmzQPravY{*4+3LS&HM6Q!E#Y%DSNH zKjAdYnS@K1F0D1Ei{%oxZ{JSHK5=!10Wsg-a{BJbHxl<4wm zNO<+W@3ka&?QxKsW{^vh{$DEo7K;ToHaE_7jS!TRMHyB{OdZeCf%a%_3vU*uQN{H_f&9{Ir|8U zFG^wEdu8i_sj=#E*{mUTdcW=4zE$0+f)}vN$J`5H{rj|81lcUZP*Sw(Tw@pp{r((t z>gs5}8-uvLFZAbOsx#2nj{Lz3rvRMLe*;y^DrbDP5g;Zjk1prF8Q;$7HPpOuA&z{* zb;se;n0xmbRNR`^V7iOMoE%Lbf)E0R)hhG(ue7`Jr$7B^eCxMAS`_VdT$CM#!>1PZ5w#SOCug_{NL0!AQOh!21CFApkD{c>jfQ z0ZvX%6z2{TG54DK67UQQ_h$Qm^tK1cGSV&jJ}jOOBq+q2Vs9^JnWoG}+&*J(9ni8thp+I2WRJzf7AeP^%+ z=N)IcxlERkuijf-7CZp~rl9ii~?9Lmlo(FX`@ITX&iTY zHOZI}Jofnb7+ag0C|JSt>7%0~Y;0_(V)30H`HbfsXR%o1a@Js;gVBpqfjT*T>T8r* z^l}YPgdXBocU^~1ed^N&g;#ejDkP*4pZw%Mz#sV|{|J8Vlb@VqwedBPYX150{rlM3 z+5&U*MgaGYj<7i~ry7(~&b_oDhg<@^?lp!?X1eyhRzc_~@KDVvC5O+VxLAkz|L+2D z1mNI;y8tg=ychsV&fHUYESAP{B z{J;ltiqM$daOmAIBuU*9saXG5@BTxEraP)HefE7y7NTw&&T}CFQ5!%jWEyeedEe|cp16J; z%f({taW*zLHE3BEnn|G42B&iY8gUnpya&M30A8^#g@8y60L;26Qkmc|U{eBm~ zQ?!}io4@~uvvPS)_T|5WO!{X4`~d(b`QPu$f6h`6-*%zWfKjXO3P-&FS3z6Ee{Ozw_g^?`13dk)ga7a5 zhj+jCj9;&w{@B5Pe)Ge-|NH~K|7$lty!$Uc;P<~p|9pS;{oh^11TFv&2;+Y3%uy%i zt}NcdJPVs0pf0W(8yjkRf*`(^E^X=N+}he2`RL~vr|)~s0MyShZcpwEk}g)1+>t1( z%kw*2yLL?jT`^k&F-G+L!oZNnq@-fHmib(*PVv6?y$@e_;RQXNz3)t1K#+9ItgCau z(CjnjLUaBPh@7AM8WmdeyyMt+6iw%-!mS{!;HbJZqbale7G(jB0eq?2gg=)Rgy<;w z|91ZU-^$;M00saH02=_VCLfo^s*gI;II+rPAYK|OQA_uB?G`ydFuy1_(A;UZ~kV9t4OSFqJgI5#JA3vi>-;d@YLL+MAwTi zKF2kt-rKpyaWJgKK^un_u7bj?m|KIzP`@b20z3`iCjI<39*YGoLB3g{c4nlaj`W<>uyS zF8l-LB2sKeViA(ko$DHNjB~nLDdRN9oVc!_ynC<2wZLR8z;ihZ@VjX8CKW(7xwO4k z2&T@zM0)c{0;a@{=z5Q>txE<^Ao<&kjg4GWAB+nz%ImH>j%L2NFR?XynjuD*tI z4qcV*<7<@GV;Sdve2izGeReWWE%MpVehz(~I`F*z{qM(TKJ%H8`CP+jA37JCn-83e zFyzu(0`3U-kXx>=bB(#~)f9WxeI&;asqA+397z5S0Ji~ru5IaaDu5L1ip1samC(Xx zQch{fJ&qTQ8#t7PmQaf4n(cN(?X>1N+}+n~YE}YkUc*uOZHU0Z;h{Ofw08j2Ry_CI zbNKw{KZoa@dk;RMoPVxvFrL$Y6}aF;rzJw9(~uFm%h$8%jGgFsxh;$DfwOF8rQB}!ntBi@ zh5^LSJ@*`5e)(m^TGZ(?j;+iyr*TA}Sx#SEsQ1RP8!Z6xU5?!pt^!9`46lu2CWCAj zQC@lzScJ#p0yu8m3FfynoLhnTNm;qlI%0ue|aKN+;e>T3wrrgP-+2$NB!k^1JRe67VXnf3J`(Ql2R2 zYmX`_kDy$G`5?ZA=hOgq-B~Oa==vUuJclvk_hnxB znOCco`I!KK()U1o`Y6?h`R5@<_!!{xGYJM^YikQ3MkQz&Rx2I9%jLU^#R8WvU(RrB zht4~6eXj_?sr3Xv(U$xSArfkn2ueZ-BXd+*rn|E^>My?B%K^&wW*6YS7bpfWP@C(t zFvWKhV1~4ODt!WhuYTn#WAaKa$jKQ7;l8U`gky~8`W~-+^{b`_+|mWUko5V*Vo{ooM9bdGW#=3)q!h>3io83g6W^C{3-7-OE{h)@ z{ge~u(qC%%B&irvsl}avxZ*2DZSqjJ|DM?1mb{YwaO09fH$6s!dtWi~RHdjfguIbT zr`d?oAxGAgS6+SUoC|JpqNOT@lMlA6)mO~HzCt%@@RdT{OsXo>-rSPQ1P<#Iq_}C? zAF(rJr_z%F#0qShuu#V*R*Fh*ppar4V-YjoME^m2i1L3*MY^h;I3zmak|o0LT}ssf zht)9P^z`&=(E<=G!Earpc*VFFh`RTn>he?gGfU?M!~ISywGyyNn1W#ZLT^YwLF5j$ zxd{7^T-dT&t!Qj!{-M)9o0o>$!0_FrMeeE4DNvt+LOfYI<(Q%fdb%;yRyKFhIZxji!cGOQCbkTfGBO|;{R%kEU_e@ z@kQN);Y`wpsI9c51(j_TR`sN>@5hx6wvK7$BK1L}K6}~~C&HY}?8<1M%lq25&*)G{+K`pa>8NSwD6wwn-9>Q%j2Q?PJsG0`9EA|6 z1CcZMhO$12B~oDKLEk%PQKq8^={}c>g_blonbiVt)IZNFube0ar>A#m0-+~h)#WCJ zSZzS)X;*ja(a3!!g$P9HB_~^q7~$Dn-SLH%OEP!uLgh|DhB=tpQc1r*=Xl|{YR6!* zgRL>s$(-g2LvDD%&!kp@E3LfjX&px;&8F@E&{SN68#U)J4LP*SlN)s>GS|?CD6Sfd zo=J&RwEHV@DLCqX8Y$fwbCFqzi#W0@3PZiu!Y(DW7=p@;%F9CR#G%D|6pGPmMm!vlsSdH_mE2R^&OXhGp#t_h!fC0uDBy13|bi)+y0$54am`6 z?h_Z1jix_KZefDKdLp2BV2TdY=D4J~6vC^%zSESF29+EtLW_dROD@GgY(2SI1uWlv zNsn2|^P)K%ysKS?!Ysr97f;XUU1|IoL++HLhkDIG6p1{Po1cVy!ZA#?aQf*9DwTc! z99ah1g$bn(V2tCOI$Ivz^iNoo@8ka7O1szeE>-$cWY~FEnfJotu1`zD_zhS{%f%zq?evvA(q0Lh^Q^+MkX{x;Xy7`iMp5SHtpJBelB{* z8S@{^FeJWrh=5ONH31T-6XFVPgR3J=VA0zQN!gqgte04i<+=hYDsi54!Vl8f*ZGpO zppC8A1lYD=%n2BVtei1+J5EneTM+QAPyp;FOEs&L{_zz2sq@e4^1`$KtAQ_C9L3xX zqn?6gLzLnir7{n;T9LW=Zr{0sFbueM?HT}wJ9q8?0IpoU3Lp`DoSdBC`t|F1kCk>> zF{Z=OdAbf&2TE2$+kC^qaYvYZpURbOCn74%CIuFW-(Q1hgewqNM)3k2LkPHa z>lU8c+0kyh#iNL$%_*owTS6_dqNs2UN7rM5zfMJCuL2SdjB;B z1GwlGKn`L#I0OVDcBoTbadbimJ8%21$8}A zq?=28OFzS)BokMzT*2YNA@1Ef!tUNKE?>EdTZad@cXWik-CbP1d>MD|-o?SeA$Iq6 z^Y{!#=}ITuJWu=k`=+)(M$7jXsF8?b4SXS3Wu?bVyBvv+C=E%BdqpL;BajpUw1y#I z@98}p9vonIZ%;EFqn?g*kNgfJ^+A+if`E%m=%+H<5ranfL0l8!&WPKDifUZSy6gUk z?D903O961R$7o@iw&`RX2k|mo)j41Y1y!a&JVuCVK+eN=g)++1!s2uucNeaidPA_? zhpju1&0Gq~rRPYW*xlX1&Ha5G9von2cNcqmPhJi`&!hld&THU1#|v$})*&5o)WoDxJs*zk8Fd!J0fk0VJ|Zr>B-|Mn^PE$z+Ae9oH$H zTA4fw*S-emCZf(_+iR+EBDN5fD6;efC>w&5k#ng>U*!Z1?E zcG^oEB*k3VTZ#+Pk~ExOwxYp1R(992^{ItU#1og3>!292{V0X9oudhuGP9D&I!XO=!SCqjah8 z71UUYFy4q1{2aCZa>c4l9hS;>ht-O(1#ZIF7xbssdv7vV76358nW)G-;gj~JhJCeK zjWl(sKFj%OGATz~`!O|*xN_wRUVZgd%|R>W7!??m)FUy+YP+bC$^-H}sFhGsZS^TE zzgNgF{ajA2z+HZ#)25x=9r>mxkKH{;s9wDZ=diQ0Gg6dtVulz}?0{<{D(hu;XGfn? zf?jNa?Mdt*M$65oJ28Fs=KenRc6V`@V*r8Lkd4xd60f6l=`gIQsVQLb#L=Wgomw_1 z*$A=zB(p$e$r4&gxDRK7%yRe?C7RNeDR|hm9Xw|Ypl(j7K6U4hFdq5aQ`JS_~d4O?kbh=tOa(XGmOzyL)>$*x$#&K??Bg?(JcJe;)^jx3IgrgPo_I z!r|c|4i64;z%02d0%!@jy_Q4X;Lc(HU>^>^-rio;Iq4Y>4i8H(kjr}`@KnAITTMLg zVj;+mRM1Y=YdbqTxOMB6ZAnJ`08(HwDV4q5UBn1{!&6Ub5Vi*3h;?Ra^5K+&FOsr# z&S5o#1e)?*0ZCC~En-PJqgY~yHU(J%B1U0LhQvuK5K)P0JLxvmvH)v~yK&=2eD>LA z@!IRJn`mwbHW+1^H{=C(dU}e>SFWJzIt_L)*FFP@Yyi)xFZa%OK8Y7zc)?a1k`*GS zv7-~YZc53d8H_v7z!~|kj#{4I%A0RzX9wPU?CukDL4Z8sTTeUL@+SVHnf} zf%7;x*jM+$_|Y-o@YXHt?(En|I|>-+;9y@BPS7@EWkVhu9AI~M*AlZ(L6c-GqPh&8 zkbqpgmF^WWjAI&{qNF^a_E@Y~kUVh%jOr!0>{!W294Y5w>Wgx$Ge4qGl-n=_^nH)} z_wQq|Sm5V>{^y$(mJj)96?ZFW-p-i-YcYu(<>1Rn&L%mh zG4-S+Mj;IbdJo9_6B1Hj+NFE1RaC~b&kC0z+#tqatvjF;qe8A3K}jRWk!ozRehh#& zllbnwvw3@rdG;kreqOHq)6>&JA4N8;C4b01Va&nB&R1~?#Z(dlI=h!^M#rf2vn0m1x0CWXSjk7~Y$T*D3{95L1R)q{S%4YSfG}haUDuDe+ibgQtM1Rs3orCe zYy~hLfeV60Rdl47#77nAQHeWrY8{B>Qn2tPhaY3X^h^4TGf}ee#iRAP*hc1KcW2i! z;W|`t6Q?)@F8q-|sRE6tqcJKsLj3koAjdE)Rhy2+8A8BeMlMDtWym2bpGZEqw{BOp zQQ@Ms3bIdMXxpf$NV7F@1c-_;^;kq^0}>ZNIVeFWQhkmTly2w$TVw%P?lw0v>tcmI znTKEA8Q;~Ru<>XJi73lsi9#u&j(ty8e-2zmoEdp3h-gSAbE?nRT!K75T~|_~NN{F} zO!J9eqxNKTl*X$W8<9^t1=dW&OEfr(hgH$}1k$UrIX7?KRBP;zf}bD`z!(c4$W;nP zf~lpwScQ@_K}lzc?{5@eIHf zvkl3;$;qhJ04xiVpc|JyLNtL|>!J<~3j7wh0EFe{E;qKYBb9;5%kkc481acV?cCVdz|~w<%M17D=t$Ey z30u&O0(rjbPbk11&|()PSO_J(Kv5`!BHX!Vs{4>*m%*6t zk%&sth8-$S1F=3t3CeYB%Fp`GrHYO-F@bs)rsueID}jFw4-c`kvy+OF_I4>gfQk*6 zco29)R|*cM;*XJ-1Ofw00I`NId*4l33#xE)f7eLwLMlj`%nStb6L|iz&?QYLNWJuu zj!#Z>Asrv57U_q#Zdo&xcE+gQJVv79j%9POsXNY@l???~NJLHgEEZ5o1{MW5d8lKs zRIG8UDfynGetn~Q`xr+#_F{c7#+`EMoExtq`K2XR>W2pkVq&D=EDj)YexF}lzCVd+ z?Bt-QUWb1wu1c|S@P{F^QaEBuS%cxRQ^Z+_R1*(AKB<$>pjC51^~FIh&wPQz zT2oSq4k2d$7EpMz(oJWado-qVNvDlYK{jFiRNX)E{4;eqB5^DLfc3L^?^^ymuXN#D z>`*W|B?rd^Mu08UDfDidohxRzFI{aI5B=Z?xsi~nDu^M!OHD0^^W7G_R?NPc!1H`nMBVWlG~ zYGdY8{d~z)J7WSHe^E(AR%Owd3<8uQ%*6?2qG)}2q2ul{2AzXuqs7QMbvI@-_QZbc zE7)z>U{SjY6%dRw#u8cR{G=#5}=foMqO-WQB%ZPQb3&d zp+*#JDQL;5__eOI6iW)ln-rlgT7%Y$+Dcl??2ucJ#Za1_q?A~~mFvbIb?V{DIO43w z1ceq6nrNCdTM4)C+*Z?d``Wd_eyc1z6qlglCbgQX9C|c?we;Q9YNdPv9EC56LI;j3DNVF-mca1`$-agSiS^*RFqE+`F5uoV@{GPQJ*v?Xx+_1hV6<#FZeHgOTy z0T+W(N~BwUX-$Kf&x9FVgSH^ z6QYwY)`cw^vfX^B6AuT|avolpetn6IbB7)s+jJYEA{^M>2LN#U_1EBYMx^UH+`V&0 zPi+U7=Bu89cm<3V32WesJCS(B_4<9^XG-vry%@Ah5lkvmXx-%m*EDR#IT#?8o5mW{ zxqLP4HDeP{2bc9{4{Yg{=J)pNuVb<3bLZg>w{O30G7WVrw0VTR#bp#5-P*`Eb z@1G=YOrO=Nz^YphSJ83Hu0e`qaDV1Zid`3no$)?pc65do;r*d zxFxy>MA;S9YADh3K<-n$*~%tkXlsnXD$}5iVqU>o1H#Gg8FxS>#nRjZWR;jX%A}z} zyT%-b9P}$~$_aK{D{%Q|C?q4CnJ9lR7Er7kp;C*qhqZJ&IXS@)Lb7hEo(c?6Z!%X5 zfCw111F-k#GsuTecHVqv5jR?s({3_Ot*MegR5B2NnSntjC`{!ao8jjEm_U+)fkdc@ zigZLc13WdxEGV=bXNV>2u4zK@wK>b7RCY8+>{4i+-dI-YPv;BnA;btzCNsNL1+$Qq zmSX#}G9QNI8c5s)6!{0A@O6(zo1F+`>T|!M5+Ei>u@q~$x>>3qLL+fI2pqUrV)BjU zVv#H~=P?W`Lo>z)NRyc?0FF{$yM7&~s}+XTfYoY+tJ~Y`DcaYnJpk;_m4JiVdgYXD{-E`dK+rI*H4bP*T@D>+imCTSfhpKN+5C8;_1XS(m04N*D~#Taqr z>NbX9z>vGyT)lP;H4uq6oXah{WD~=A%Wpv4a!u1z??&J)u|Dd?t=hrIVZsfo(`#f+ zRH#rzccNHJky4jj@gIqny+#*woj2Wsy?3~N{W?}dT6@DV;L6pjYMC1MA~Y2+n*~tk zfUjQNR)WS7&32R?oK87~5UImVq>X1Sg!D3pQt(o7>pP8Z4_XVZ;Fm~IcEZoIFRf|E zPz5O|{lxY1AwawPFeoW~oYIukoj0YcO7vcskUYgCu5Mq`FiEU|KUI)U(06Q>YaKjW zD|N6vRw*=?j^hS-2SPR0bD>`a4B@GDwUYrp5{8UzsQr~0BFi?CEGLAP4pT5r7-kV8g7=84mF>oZs>@BzEe`{= z9vd;@I)v3gr<(1F7e{nw)Cm~Ha^mt=(TvPmJP_s}rQHhVASoj2uO}GvFd|+NS*=#u zB$NxCiiNhy|387xfl#*aq&qWPVQL8iaDgnf5Nt}%ISi}SxJ#5Qjw*Aa5b&oI?UL2`I%%MQ1zjAWG1tF!8BG=<-~F-IkG@BAeH^+&f9J_TEYwhCrwlbMxGGr z!ow$bsNk!S2r}9HuOr)26@T(;q5Sr``8-i-V|1T2*+(at1xloF`8O+;lJ-miO?f=- zpJ=GsNdc6S>_M>w(&CL30MCO4TD>zMD3Rlnlhj$N?f>-^fG&utjg@nS`8QTHT>!?B zZSvpw)C5))cw{xg|69&MTi5SupPqB#pbA25oDnQ=CXfQ4&4-+Vl(B;M=F}eDUlr6c z?8y~p;&hjsLXHwLdvfWC01G;Tr2#7z4#!5)MmnvFidb9n9DE&S7I?6QxmW#4)+9P0kquaL!@1 zS}9oNss)Khv0d@4`b>oy}O|s!i{ykRBJk*Z`D%vVH$*rJPl>x~>3xzn70>fW8-6+*$ z26Ebtqvw$wn^2S24;mm0rh9PfY;f1#fg3DFwOak|x zH^h;8x>&=&joHV_b#m0(ow*QV$*GeIBO6v~8dk%AFa(5QrRKGu=RoOEZuTkeA;mjJnud3-#<3!#(H7bz@e%6Su7SfJ~}DZMGff%CWC?X zc;0)QX80|mE8}FGA)4>;{dn(jbpL+o=@7yh9^kmwBy&(E*R-cOg&rh*-?tq+R~m3? z1NL2qOP4OCQcmjL;v9^*JmTNW_1}Hp|_@aV~Md8X3&DlnqkILCI&+j{qCL@zrW#m@w~fV+@Je%eeUbJj`KW^^Egg6 zCUgpxL2-rS2f|R_sqhwe>AlyHx&gPd-F(?1nC`+`+#Ew!FxPKm*VN8y{>Jcvj7Je= zr0`ip|7o{qJoxjh!Ju@t{o9Z{<}x%oT;6}D)aDhSc)`Jv5L zMetipUE{{hbTe1LY15G>9;q9w`dC(#4ftw1GGn_D)V9K^qu`7L24=brnpuB|4sVlldHTR`6rsljX{N%Eqhlbt`Xt$`uZ=G#+pUQ$k*hY#rX(kj zC=?q{Z0qy7shEU(I{1Czvw2%#F$ba3i;5aW*WGbYUJ=L+eEoTqgIbdy z@8f1}!~65Mw1x1`BGRc(G96zURg;3%2o2JrkBO@>wGeE8Y{<-v8mlgSNET zDtffxCg5Au$^)#c;2jQcpqr>u-s)bLVb$TPG0vF43jmv-h944~* zAOIiRwXwpzYXl^^t9OzHe2bZkMq1SP1AFqADM{UH$_I&L#M6UbxdLwj*iw8`LvXs$ zU*mp(;YwGKD%0s-**<@?DMJqOu*dv-TiL1 zBT^{)O#5SnEpk1vWaMub6K3!#Lm#e*OP}Q;#IIB33?`^-NkRnV%0`YHrV_}+q zUQ$wg*9re%JMBu$xUO7y14qtcOY;ir?0@qVn#tj2AP-55GbNX0_budRdsx6-i#+|g z`sV7R}Oy*EQMezW@yX;5m)lfvy(tDNw*g+E%Z>F$@x(^I(ujrW? zS!$a8Pw#h?$e}aDRf4)LFV7wzQEKSAG zXEd#2Px{>wS&$yE5xKJetM3wSnFG@2d8tB%@1qy5MNvIx6aC;n-*aLCWu6hC6+u`3 zl{k0(S5J4+t&eu;N_m~r7hWlVgD$Dg{~-uM#SpO_+BE!`>%PPOZEM-_ff z`YvE^zn}#?dZt`)!J~j(h~Kb-+xx2Vv1=Y#+41nS>a|WmXv7^l!pOz&;)fTs*tO5! zDE?d8LXO%;8P8UYRMYC+*ckn6u=x=?nBQ6QSNTE$QAq*$JOIE%2Z z*+Nm>FxBR68Kz2hli}=T%mTg0@DQ89{B}$dRpzodoj}pZ8~Gd(nu!pvLiI|;Uu|rR zv6pSp6M__S{Q3qJc9(F?f1X)IUDOfh!_uaIwp-UX7TG6>hnJRf(jwVm7iG=bAQ`5T zsa1g+h%%mql9{6}w1P+wxs|jzcOsMGS;5WF6oN$`H`R}Q?R8hy$xfCAqP&!Qy8*M8 znNTcSc+#wF$4A>g@h1z-3HC2;YA3s{x4{SSe2|k)3QO0?OzD49_YIR zjIwS!5%S;-dwif1n=OwF@~h^Hg@>+P(3ntUost5|@i5Q{Y9<>@5$D+~CV;Baz* z3y4vlfgk6cdsUfz2dp&&U{ctb+i%~K9`)st35$kFU#2D(mdDba06mdZ+8tsZE_LMs zPpiI5LGvUH$b(l68j00}zMM))Ags%FycwpSkg@5n> zCAkTtJ-D>rjXMA&Sf!=?LZ_G)D%rENpWhREI18`9y%_u+O(h3beMpE%CkQjMvLqfz zs;AMb_Ny9pRBerQFFG2b|E#i30;2EnWdqbW%t?0Fkxug&Q=-?XLsGiB|^+~@` zHzeLMn2M)BlJ-Cp!M-?AZSOvIk{sv4TD44dyD-%D^6eMz$oOVgE!_ds9OB&6Dila4 zk=iGA9+-?6o}qc$%1}`^383a{aUeYUns@UMNIPyu$nr^?*A%(W8LH4c4x+$@eQP63 zuF0%-Qo^A|QxHJ~4)nX7?iuO+(;>fOW1{H7!eGVcfBw3H$;!xnw)Y^}u3CYf`%oH8 zH)0Zny`#n7JU$(PH#Zm9P13Tz&oSLG7=y%sTrq_tB=>u8`6VVSL29t*EOg ztPhn?Xi&KRa}aZO3RYQJ*-UCy%Lv|5`CP=7faAdoaESbf96so4Y_hDxruPW;p_u8E#`aeIy$E5+w`a5R$*;BSz61Wp(F>@|Gi?H>~vLlf2noIU%^kymX?oQ`m6G zQ7S%NZ?w^!Ok9GheELA82AaFw?73tYn8BVX(sJP?n+|CC=A4!wv|{PC_6aN^CX>tX z9qhfzA3OsOx#0Mas$Ipz)jsDA)zkgNe6aSmRk>7vxp=@HUikA1E@Lo?8&;@41k-sHK+ z+uCH(eT4!9M)c)6;VTv?rYY_GYQH{#apJcpL?OvJgxX&6+HZ`K2q|+a_!#CjRSXyT z44RkoD3pdDa8{t$YR@$Sna=9` zz`GlD*WIw?pMC&_t-#paV@O9RhqklF;Mcji>yJyofr_a5Ys+*7jL0jF+c})D5`C?d8Fd1;BxcmzL=YN^hX?&Juff$ey_ZrNXOZkOjoTG_cJiBrEs@`bSi!v_qrGQ5g_kza) z8VFyJm9lv%MuS%uYrs$!h;)kSxG@T`WD=xk+@bljP}+<&5m1x#UYC($WvaErbR^Nk z3QXyC67hJFHd#LWUive;<5vp{r-Po;u3X+O5U)t}H9I+_R@TaZJF`8#689`9^Ytqm zoW-}Z9gn_`rn~<7Du2mqhO~B0uv{3gf4$cJOx|}wX-Qd(okP6gKvL;mJ4yB?L(qLe zXqZpa`hBL|JwC&Uai}ra$V0LsN8<6Y+AwTX;_3)*>FZ}iwf@Sg2N?BSfia06sU+{p zu-{kfjtocGsA-}J7bVSkyCg5;MdS81jGL{#?#_<-Gj82r;8lW@Gk>l&f+G~RqAQVd zTgZat-@0xpyq0I|i*t20i!mQ}o#S~T{6(|KcP~hvyTo<>3y0{$;f@tfG7~rb3V-~@ z#*mrhC%#Wie`>PtfbCL7B4=-Um7D@-Uu7u6UL7U%h*~tENX}Ht9x3s#x>sP|b2dMW zuDf-55b}L&P}_R+f&;m!n1aE7%KOxUpFt%I_&B>>t1TBhvhY5I^z?d0Nlw;C2U>ih zp-#8v{t0mIqKs)R%&|fyTlKoMa!zQrw0KWfG&2l+?I>TO6c8|tkRK-mJ}yN7jWM!* zClh9DtS9aWZ$Wt%;>a5q#_(n4hO}C}jG!3%UiL9$!{m--<)m7r{yy!SS2E`APx%cJ z_$#31o_}lN7T|is5|!{`3FW9xj0V9K11l#5mEYA3>8^z>0jce=Cudb{W#DRiN7&>| zrVz39GK3MP2F3P5w9@Z~z(O>jIJ)DPq;_BD$*X*VtrbNfSdJBzv8I`j+49Z*P5@E8 zOvP;q)#;Y|wZ^4kG5sG$@}vD9U9x3!#waJ?y23!t?FANUF;(T)N1HQs4@>};4h#l! z4Fb`P04?1ncK+}#pdQ3-(LxSm=Qh!i3yi|QopTP>*(iLT*L|(r#fX2@$^CaFaZW;R{1kx1kyx?hm9g8ynZkaLGB6DldY?MY9EazEqQxyu-8gBZ;=f zs_2>EcanEOk4+m!x(%n0SkhzWF#k*wI}{uTjHd&LM0epI;4II|$g?fGDYf-Z+h1uu zSP2{7SwzM0J=CDKVs0imGVBHI{!O0xAE4`%mA{N7uq`4B8QN@qO#>XOu6Yv^m{1xB zF2$p%18_!EDR{dlI%fzqD5@Vc`;RFJ^t0=}75q*YQn&6QvGC`%=_04d6-HrNe!rf}U9E)+^zxogsXz~Jm*w+Y&5g8kBWuwo zbH8@e?H=?HYTuC7qF*2$SDz5quOwu8@`Kd z4D_1xZ~;$#nek4DNnnJ)%4K{Ubesez~aM-StNA%YPvq(A!EqHxu6X+HAX@{AmTr6FcE8I;%wt zG<0iw(jV)^j3wZ@*R-4WExadL*aV?(&Y=2Nu|1A=G^HPV71{+}VG9ivOL5%IMSVdg z`1X$V>d2O&6?&`ENmN#wYj!)=eSl;N!W+D>>44B=*l8d__q)|qD+(7LDzE@OZ$pG1 zsb26XoVd2uhb6m&E({ybFiR1Nv8R3zkNRN&BDq|LFN(xV1h;}Ez3j<~Wbc$;RsX|NUl6uW9d0|DEv z?B=Dfrx)(WYYMk^P5n%Ptk>maos^TC&M$Q?XcU;z=sZpM&N?jqK?Dpe4u+eFJTG84 zPm?L}=~s2?>n39+T_FRTjj)*Di?3uT)QZx!6H&=&9(UL9qP$_6nQ&eDhkx8 zURgaB6K;Jp_g#Zq+}^of=fVIIYUhNJKj_-!j|m1*dNx@WMWFpI(o@5W8fW3eWSIMc zwSon=ySO7Q8!8z8vRNa)*|=jI^#M6?d+q}ss;ySOllZglMGXceI1rWdO^jY(!CXgw z>K#wyPG`DQ_`%=f{Ze2?cC`*8%VKgNwLJ`f_PPDhNc0vZiE>mTLN}*K`>9!Oj(oxe zPje;eEumzbI{Ll(2?S}P-6xwrBVIvD263J0e$}4(I@R&~$S>vGs}nv_IrlpLuzy!H z&2dx3W~XlF?!F#VDH+o+(jDu{^+{Eyq&)g;oxa4ep7=pEe@Z+X6_Qh`W1{|DML9hw@utq;BkU9MyuY&K!m+}=L{5>n ztNGo0l`1NL317;Lq|FZ3lV0O~?r_rfsmm76m`Y3NkMl-W{NHbZ1*Jn zzi@yR78OR{%td$ZehYe^?2>ID9;X_wr)1ZCyzK6wvK{X1?T=+v+5h+OzvCxt?dJTIOJ6hg W3(FSP0H!UoS()2ksyFj~^#1_OyMS5% diff --git a/1.14/gradle.properties b/1.14/gradle.properties index 65ce632..d6e478b 100644 --- a/1.14/gradle.properties +++ b/1.14/gradle.properties @@ -5,4 +5,4 @@ version_minecraft=1.14.4 version_forge_minecraft=1.14.4-28.2.3 version_fml_mappings=20190719-1.14.3 version_jei=1.14.4:6.0.0.10 -version_engineersdecor=1.0.20-b1 +version_engineersdecor=1.0.20-b2 diff --git a/1.14/readme.md b/1.14/readme.md index 3366fbf..082e1b2 100644 --- a/1.14/readme.md +++ b/1.14/readme.md @@ -11,6 +11,9 @@ Mod sources for Minecraft version 1.14.4. ## Version history + ~ v1.0.20-b2 [U] Forge version requirement set to >= 28.2.3. + [A] Added Labeled Crate (storage crate with built-in item frame). + - v1.0.20-b1 [A] Electrical Furnace: Added four-position speed switch (off, 100%, 150%, 200%), power consumption increases at higher rate (off, 100%, 200%, 400%). [A] Added Steel Mesh Fence Gate (single or double height gate fitting to the Steel Mesh Fence). diff --git a/1.14/src/main/java/wile/engineersdecor/ModContent.java b/1.14/src/main/java/wile/engineersdecor/ModContent.java index 3b648d5..56d66ab 100644 --- a/1.14/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.14/src/main/java/wile/engineersdecor/ModContent.java @@ -587,6 +587,12 @@ public class ModContent } )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_fluid_funnel")); + public static final BlockDecorLabeledCrate.DecorLabeledCrateBlock LABELED_CRATE = (BlockDecorLabeledCrate.DecorLabeledCrateBlock)(new BlockDecorLabeledCrate.DecorLabeledCrateBlock( + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT, + Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(0.5f, 128f).sound(SoundType.METAL), + Auxiliaries.getPixeledAABB(0,0,0, 16,16,16) + )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "labeled_crate")); + // ------------------------------------------------------------------------------------------------------------------- public static final BlockDecorWall CONCRETE_WALL = (BlockDecorWall)(new BlockDecorWall( @@ -655,6 +661,7 @@ public class ModContent private static final Block modBlocks[] = { TREATED_WOOD_CRAFTING_TABLE, + LABELED_CRATE, SMALL_LAB_FURNACE, SMALL_ELECTRICAL_FURNACE, FACTORY_HOPPER, @@ -750,6 +757,11 @@ public class ModContent .build(null) .setRegistryName(ModEngineersDecor.MODID, "te_treated_wood_crafting_table"); + public static final TileEntityType TET_LABELED_CRATE = TileEntityType.Builder + .create(BlockDecorLabeledCrate.LabeledCrateTileEntity::new, LABELED_CRATE) + .build(null) + .setRegistryName(ModEngineersDecor.MODID, "te_labeled_crate"); + public static final TileEntityType TET_SMALL_LAB_FURNACE = TileEntityType.Builder .create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE) .build(null) @@ -827,6 +839,7 @@ public class ModContent private static final TileEntityType tile_entity_types[] = { TET_TREATED_WOOD_CRAFTING_TABLE, + TET_LABELED_CRATE, TET_SMALL_LAB_FURNACE, TET_SMALL_ELECTRICAL_FURNACE, TET_FACTORY_HOPPER, @@ -872,6 +885,7 @@ public class ModContent public static final ContainerType CT_SMALL_LAB_FURNACE; public static final ContainerType CT_SMALL_ELECTRICAL_FURNACE; public static final ContainerType CT_WASTE_INCINERATOR; + public static final ContainerType CT_LABELED_CRATE; static { CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType(BlockDecorCraftingTable.CraftingTableContainer::new)); @@ -888,11 +902,14 @@ public class ModContent CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace"); CT_WASTE_INCINERATOR = (new ContainerType(BlockDecorWasteIncinerator.BContainer::new)); CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator"); + CT_LABELED_CRATE = (new ContainerType(BlockDecorLabeledCrate.BContainer::new)); + CT_LABELED_CRATE.setRegistryName(ModEngineersDecor.MODID,"ct_labeled_crate"); } // DON'T FORGET TO REGISTER THE GUI in registerContainerGuis(), no list/map format found yet for that. private static final ContainerType container_types[] = { CT_TREATED_WOOD_CRAFTING_TABLE, + CT_LABELED_CRATE, CT_FACTORY_DROPPER, CT_FACTORY_PLACER, CT_FACTORY_HOPPER, @@ -976,6 +993,7 @@ public class ModContent public static final void registerContainerGuis(final FMLClientSetupEvent event) { ScreenManager.registerFactory(CT_TREATED_WOOD_CRAFTING_TABLE, BlockDecorCraftingTable.CraftingTableGui::new); + ScreenManager.registerFactory(CT_LABELED_CRATE, BlockDecorLabeledCrate.BGui::new); ScreenManager.registerFactory(CT_FACTORY_DROPPER, BlockDecorDropper.BGui::new); ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new); ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.BGui::new); @@ -988,5 +1006,6 @@ public class ModContent public static final void registerTileEntityRenderers(final FMLClientSetupEvent event) { ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.CraftingTableTileEntity.class, new wile.engineersdecor.detail.ModTesrs.TesrDecorCraftingTable()); + ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorLabeledCrate.LabeledCrateTileEntity.class, new wile.engineersdecor.detail.ModTesrs.TesrDecorLabeledCrate()); } } diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java index 5b19c34..8110e95 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java @@ -174,7 +174,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace implements ID fifo_timer_ = 0; tick_timer_ = 0; energy_stored_ = 0; - speed_ = 0; + speed_ = 1; field_max_energy_stored_ = getMaxEnergyStored(); field_isburning_ = 0; } diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java index ab26c07..6cd4108 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java @@ -8,8 +8,6 @@ */ package wile.engineersdecor.blocks; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShapes; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.libmc.blocks.StandardBlocks; @@ -38,6 +36,8 @@ import net.minecraft.inventory.container.Slot; import net.minecraft.util.*; import net.minecraft.util.math.*; import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.text.*; import net.minecraft.nbt.CompoundNBT; import net.minecraft.client.gui.screen.inventory.ContainerScreen; diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java new file mode 100644 index 0000000..aeb53bc --- /dev/null +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java @@ -0,0 +1,596 @@ +/* + * @file BlockDecorLabeledCrate.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Storage crate with a content hint. + */ +package wile.engineersdecor.blocks; + +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.libmc.blocks.StandardBlocks; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.World; +import net.minecraft.block.material.PushReaction; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.item.*; +import net.minecraft.inventory.*; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.Slot; +import net.minecraft.util.*; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SUpdateTileEntityPacket; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import com.mojang.blaze3d.platform.GlStateManager; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + + +public class BlockDecorLabeledCrate +{ + public static void on_config(int stack_limit) + { + } + + //-------------------------------------------------------------------------------------------------------------------- + // Block + //-------------------------------------------------------------------------------------------------------------------- + + public static class DecorLabeledCrateBlock extends StandardBlocks.Horizontal implements IDecorBlock + { + public DecorLabeledCrateBlock(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) + { super(config, builder, unrotatedAABB); } + + @Override + @SuppressWarnings("deprecation") + public boolean hasComparatorInputOverride(BlockState state) + { return true; } + + @Override + @SuppressWarnings("deprecation") + public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) + { return Container.calcRedstone(world.getTileEntity(pos)); } + + @Override + public boolean hasTileEntity(BlockState state) + { return true; } + + @Override + @Nullable + public TileEntity createTileEntity(BlockState state, IBlockReader world) + { return new LabeledCrateTileEntity(); } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) + { + if(world.isRemote) return; + if((!stack.hasTag()) || (!stack.getTag().contains("tedata"))) return; + CompoundNBT te_nbt = stack.getTag().getCompound("tedata"); + if(te_nbt.isEmpty()) return; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return; + ((LabeledCrateTileEntity)te).readnbt(te_nbt); + ((LabeledCrateTileEntity)te).markDirty(); + } + + @Override + public boolean hasDynamicDropList() + { return true; } + + @Override + public List dropList(BlockState state, World world, BlockPos pos, boolean explosion) + { + final List stacks = new ArrayList(); + if(world.isRemote) return stacks; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return stacks; + if(!explosion) { + ItemStack stack = new ItemStack(this, 1); + CompoundNBT te_nbt = ((LabeledCrateTileEntity) te).reset_getnbt(); + if(!te_nbt.isEmpty()) { + CompoundNBT nbt = new CompoundNBT(); + nbt.put("tedata", te_nbt); + stack.setTag(nbt); + } + stacks.add(stack); + } else { + for(ItemStack stack: ((LabeledCrateTileEntity)te).stacks_) stacks.add(stack); + ((LabeledCrateTileEntity)te).reset_getnbt(); + } + return stacks; + } + + @Override + @SuppressWarnings("deprecation") + public boolean onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult rayTraceResult) + { + if(world.isRemote) return true; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return true; + if((!(player instanceof ServerPlayerEntity) && (!(player instanceof FakePlayer)))) return true; + NetworkHooks.openGui((ServerPlayerEntity)player,(INamedContainerProvider)te); + return true; + } + + @Override + public PushReaction getPushReaction(BlockState state) + { return PushReaction.BLOCK; } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class LabeledCrateTileEntity extends TileEntity implements INameable, IInventory, INamedContainerProvider, ISidedInventory + { + public static final int NUM_OF_FIELDS = 1; + public static final int NUM_OF_SLOTS = 55; + public static final int ITEMFRAME_SLOTNO = 54; + + // BTileEntity ----------------------------------------------------------------------------- + + protected NonNullList stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + + public LabeledCrateTileEntity() + { this(ModContent.TET_LABELED_CRATE); } + + public LabeledCrateTileEntity(TileEntityType te_type) + { super(te_type); reset(); } + + public CompoundNBT reset_getnbt() + { + CompoundNBT nbt = new CompoundNBT(); + writenbt(nbt); + reset(); + return nbt; + } + + protected void reset() + { + stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + } + + public void readnbt(CompoundNBT compound) + { + NonNullList stacks = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(compound, stacks); + while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY); + stacks_ = stacks; + } + + protected void writenbt(CompoundNBT compound) + { + ItemStackHelper.saveAllItems(compound, stacks_); + } + + public ItemStack getItemFrameStack() + { return (stacks_.size() > ITEMFRAME_SLOTNO) ? (stacks_.get(ITEMFRAME_SLOTNO)) : (ItemStack.EMPTY); } + + // TileEntity ------------------------------------------------------------------------------ + + @Override + public void read(CompoundNBT compound) + { super.read(compound); readnbt(compound); } + + @Override + public CompoundNBT write(CompoundNBT compound) + { super.write(compound); writenbt(compound); return compound; } + + @Override + public CompoundNBT getUpdateTag() + { CompoundNBT nbt = super.getUpdateTag(); writenbt(nbt); return nbt; } + + @Override + @Nullable + public SUpdateTileEntityPacket getUpdatePacket() + { return new SUpdateTileEntityPacket(pos, 1, getUpdateTag()); } + + @Override + public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) // on client + { super.read(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } + + @Override + public void handleUpdateTag(CompoundNBT tag) // on client + { read(tag); } + + // INameable --------------------------------------------------------------------------- + + @Override + public ITextComponent getName() + { final Block block=getBlockState().getBlock(); return new StringTextComponent((block!=null) ? block.getTranslationKey() : "Small Waste Incinerator"); } + + @Override + public boolean hasCustomName() + { return false; } + + @Override + public ITextComponent getCustomName() + { return getName(); } + + // IContainerProvider ---------------------------------------------------------------------- + + @Override + public ITextComponent getDisplayName() + { return INameable.super.getDisplayName(); } + + @Override + public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) + { return new BContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } + + // IInventory ------------------------------------------------------------------------------ + + @Override + public int getSizeInventory() + { return stacks_.size(); } + + @Override + public boolean isEmpty() + { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } + + @Override + public ItemStack getStackInSlot(int index) + { return ((index >= 0) && (index < getSizeInventory())) ? stacks_.get(index) : ItemStack.EMPTY; } + + @Override + public ItemStack decrStackSize(int index, int count) + { return ItemStackHelper.getAndSplit(stacks_, index, count); } + + @Override + public ItemStack removeStackFromSlot(int index) + { return ItemStackHelper.getAndRemove(stacks_, index); } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) + { + if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); + stacks_.set(index, stack); + markDirty(); + if(getWorld() instanceof ServerWorld) { + // This should result in sending TE data (getUpdateTag etc) to the client for the TER. + BlockState state = world.getBlockState(getPos()); + getWorld().notifyBlockUpdate(getPos(), state, state, 2|16|32); + } + } + + @Override + public int getInventoryStackLimit() + { return 64; } + + @Override + public void markDirty() + { super.markDirty(); } + + @Override + public boolean isUsableByPlayer(PlayerEntity player) + { return getPos().distanceSq(player.getPosition()) < 36; } + + @Override + public void openInventory(PlayerEntity player) + {} + + @Override + public void closeInventory(PlayerEntity player) + { markDirty(); } + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) + { return (index != ITEMFRAME_SLOTNO); } + + @Override + public void clear() + { stacks_.clear(); } + + // Fields ----------------------------------------------------------------------------------------------- + + protected final IIntArray fields = new IntArray(LabeledCrateTileEntity.NUM_OF_FIELDS) + { + @Override + public int get(int id) + { + switch(id) { + default: return 0; + } + } + @Override + public void set(int id, int value) + { + switch(id) { + default: break; + } + } + }; + + // ISidedInventory ---------------------------------------------------------------------------- + + private static final int[] SIDED_INV_SLOTS; + static { + // that useless unoptimised language ... no proper inline conv to int[]? + // private static final int[] SIDED_INV_SLOTS = IntStream.rangeClosed(0, BTileEntity.NUM_OF_SLOTS-2).boxed().collect(Collectors.toList()).toArray(); + SIDED_INV_SLOTS = new int[LabeledCrateTileEntity.NUM_OF_SLOTS-1]; + for(int i=0; i= NUM_OF_SLOTS)) || ((slotno == ITEMFRAME_SLOTNO)) ) return ItemStack.EMPTY; + ItemStack slotstack = getStackInSlot(slotno); + if(!slotstack.isEmpty()) { + if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(slotno))) return stack; + if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; + if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)) - slotstack.getCount(); + if(stack.getCount() <= n) { + if(!simulate) { + ItemStack copy = stack.copy(); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + } + return ItemStack.EMPTY; + } else { + stack = stack.copy(); + if(!simulate) { + ItemStack copy = stack.split(n); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + return stack; + } else { + stack.shrink(n); + return stack; + } + } + } else { + if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)); + if(n < stack.getCount()) { + stack = stack.copy(); + if(!simulate) { + te.setInventorySlotContents(slotno, stack.split(n)); + return stack; + } else { + stack.shrink(n); + return stack; + } + } else { + if(!simulate) te.setInventorySlotContents(slotno, stack); + return ItemStack.EMPTY; + } + } + } + + @Override + @Nonnull + public ItemStack extractItem(int index, int amount, boolean simulate) + { + if((index < 0) || ((index >= NUM_OF_SLOTS)) || ((index == ITEMFRAME_SLOTNO)) ) return ItemStack.EMPTY; + if(!simulate) return ItemStackHelper.getAndSplit(te.stacks_, index, amount); + ItemStack stack = te.stacks_.get(index).copy(); + if(stack.getCount() > amount) stack.setCount(amount); + return stack; + } + + @Override + @Nonnull + public ItemStack getStackInSlot(int index) + { return te.getStackInSlot(index); } + } + + // Capability export ---------------------------------------------------------------------------- + + protected LazyOptional item_handler_ = LazyOptional.of(() -> new LabeledCrateTileEntity.BItemHandler(this)); + + @Override + public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) + { + if(!this.removed) { + if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return item_handler_.cast(); + } + return super.getCapability(capability, facing); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // GUI + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class BGui extends ContainerScreen + { + protected final PlayerEntity player_; + + public BGui(BContainer container, PlayerInventory player_inventory, ITextComponent title) + { + super(container, player_inventory, title); + player_ = player_inventory.player; + xSize = 213; + ySize = 206; + } + + @Override + public void init() + { super.init(); } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) + { + renderBackground(); + super.render(mouseX, mouseY, partialTicks); + renderHoveredToolTip(mouseX, mouseY); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) + { + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + this.minecraft.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/labeled_crate_gui.png")); + final int x0=guiLeft, y0=this.guiTop, w=xSize, h=ySize; + blit(x0, y0, 0, 0, w, h); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Container + //-------------------------------------------------------------------------------------------------------------------- + + public static class BContainer extends Container + { + //------------------------------------------------------------------------------------------------------------------ + protected static class StorageSlot extends Slot + { + StorageSlot(IInventory inventory, int index, int x, int y) + { super(inventory, index, x, y); } + + @Override + public int getSlotStackLimit() + { return 64; } + } + + //------------------------------------------------------------------------------------------------------------------ + private static final int PLAYER_INV_START_SLOTNO = LabeledCrateTileEntity.NUM_OF_SLOTS; + protected final PlayerEntity player_; + protected final IInventory inventory_; + protected final IWorldPosCallable wpc_; + private final IIntArray fields_; + private int proc_time_needed_; + //------------------------------------------------------------------------------------------------------------------ + public int field(int index) { return fields_.get(index); } + public PlayerEntity player() { return player_ ; } + public IInventory inventory() { return inventory_ ; } + public World world() { return player_.world; } + //------------------------------------------------------------------------------------------------------------------ + + public BContainer(int cid, PlayerInventory player_inventory) + { this(cid, player_inventory, new Inventory(LabeledCrateTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY, new IntArray(LabeledCrateTileEntity.NUM_OF_FIELDS)); } + + private BContainer(int cid, PlayerInventory player_inventory, IInventory block_inventory, IWorldPosCallable wpc, IIntArray fields) + { + super(ModContent.CT_LABELED_CRATE, cid); + player_ = player_inventory.player; + inventory_ = block_inventory; + wpc_ = wpc; + fields_ = fields; + int i=-1; + // storage slots (stacks 0 to 53) + for(int y=0; y<6; ++y) { + for(int x=0; x<9; ++x) { + int xpos = 28+x*18, ypos = 10+y*18; + addSlot(new StorageSlot(inventory_, ++i, xpos, ypos)); + } + } + // picture frame slot (54) + addSlot(new Slot(inventory_, ++i, 191, 100) { + @Override public int getSlotStackLimit(){return 1;} + }); + // player slots + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x, 28+x*18, 183)); // player slots: 0..8 + } + for(int y=0; y<3; ++y) { + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x+y*9+9, 28+x*18, 125+y*18)); // player slots: 9..35 + } + } + } + + @Override + public boolean canInteractWith(PlayerEntity player) + { return inventory_.isUsableByPlayer(player); } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slot) + { return (slot.getSlotStackLimit() > 1); } + + @Override + public void onContainerClosed(PlayerEntity player) + { super.onContainerClosed(player); } + + @Override + public ItemStack transferStackInSlot(PlayerEntity player, int index) + { + Slot slot = getSlot(index); + if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY; + ItemStack slot_stack = slot.getStack(); + ItemStack transferred = slot_stack.copy(); + if((index>=0) && (index= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) { + // Player slot + if(!mergeItemStack(slot_stack, 0, PLAYER_INV_START_SLOTNO-1, false)) 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; + } + } +} diff --git a/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java b/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java index a78a3ab..3161eaa 100644 --- a/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java +++ b/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java @@ -11,6 +11,7 @@ package wile.engineersdecor.detail; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.blocks.BlockDecorCraftingTable; +import wile.engineersdecor.blocks.BlockDecorLabeledCrate; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderHelper; @@ -19,8 +20,6 @@ import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import com.mojang.blaze3d.platform.GlStateManager; -import wile.engineersdecor.blocks.BlockDecorCraftingTable.CraftingTableBlock; - public class ModTesrs { @@ -48,7 +47,7 @@ public class ModTesrs { if(tesr_error_counter<=0) return; try { - int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).get(CraftingTableBlock.HORIZONTAL_FACING).getHorizontalIndex(), 0, 3); + int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).get(BlockDecorCraftingTable.CraftingTableBlock.HORIZONTAL_FACING).getHorizontalIndex(), 0, 3); long posrnd = te.getPos().toLong(); posrnd = (posrnd>>16)^(posrnd<<1); for(int i=0; i<9; ++i) { @@ -82,4 +81,47 @@ public class ModTesrs } } + //-------------------------------------------------------------------------------------------------------------------- + // Labeled Crate + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class TesrDecorLabeledCrate extends TileEntityRenderer + { + private static int tesr_error_counter = 4; + private static double scaler = 0.35; + double tr[][]= { // [hdirection=S-W-N-E][param] + { +8.0/32, -8.0/32, +15.5/32, 180.0 }, // N + { -15.5/32, -8.0/32, +8.0/32, 90.0 }, // E + { -8.0/32, -8.0/32, -15.5/32, 0.0 }, // S param=tx,ty,tz,ry + { +15.5/32, -8.0/32, -8.0/32, 270.0 }, // W + }; + + @Override + @SuppressWarnings("deprecation") + public void render(final BlockDecorLabeledCrate.LabeledCrateTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) + { + if(tesr_error_counter<=0) return; + try { + final ItemStack stack = te.getItemFrameStack(); + if(stack.isEmpty()) return; + final int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).get(BlockDecorLabeledCrate.DecorLabeledCrateBlock.HORIZONTAL_FACING).getHorizontalIndex(), 0, 3); + double ox = tr[di][0], oy = tr[di][1], oz = tr[di][2], ry = tr[di][3]; + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + RenderHelper.enableStandardItemLighting(); + GlStateManager.translated(x+0.5+ox, y+0.5+oy, z+0.5+oz); + GlStateManager.rotated(ry, 0, 1, 0); + GlStateManager.scaled(scaler, scaler, scaler); + Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED); + RenderHelper.disableStandardItemLighting(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + } catch(Throwable e) { + if(--tesr_error_counter<=0) { + ModEngineersDecor.logger().error("TESR was disabled (because broken), exception was: " + e.getMessage()); + } + } + } + } } diff --git a/1.14/src/main/resources/META-INF/mods.toml b/1.14/src/main/resources/META-INF/mods.toml index 12c2852..d4234ee 100644 --- a/1.14/src/main/resources/META-INF/mods.toml +++ b/1.14/src/main/resources/META-INF/mods.toml @@ -18,7 +18,7 @@ logoFile="logo.png" [[dependencies.engineersdecor]] modId="forge" mandatory=true - versionRange="[28.1.68,)" + versionRange="[28.2.3,)" ordering="NONE" side="BOTH" diff --git a/1.14/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json b/1.14/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json new file mode 100644 index 0000000..b0b5a3f --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json @@ -0,0 +1,8 @@ +{ + "variants": { + "facing=north": { "model": "engineersdecor:block/misc/labeled_crate_model" }, + "facing=south": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":180 }, + "facing=west": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":270 }, + "facing=east": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":90 } + } +} diff --git a/1.14/src/main/resources/assets/engineersdecor/lang/en_us.json b/1.14/src/main/resources/assets/engineersdecor/lang/en_us.json index 13ef2b5..cf787e2 100644 --- a/1.14/src/main/resources/assets/engineersdecor/lang/en_us.json +++ b/1.14/src/main/resources/assets/engineersdecor/lang/en_us.json @@ -57,6 +57,8 @@ "block.engineersdecor.clinker_brick_stained_block.help": "§6A brick block with position dependent texture variations.§r\nLooks slightly darker and more color intensive than the vanilla brick block. Has more visible traces of grime or stain.", "block.engineersdecor.slag_brick_block": "Slag Brick Block", "block.engineersdecor.slag_brick_block.help": "§6A gray-brown brick block with position dependent texture variations.", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.rebar_concrete": "Rebar Concrete Block", "block.engineersdecor.rebar_concrete.help": "§6Steel reinforced concrete block.§r Expensive but Creeper-proof like obsidian.", "block.engineersdecor.gas_concrete": "Gas Concrete Block", diff --git a/1.14/src/main/resources/assets/engineersdecor/lang/ru_ru.json b/1.14/src/main/resources/assets/engineersdecor/lang/ru_ru.json index 980e8b3..5621aa5 100644 --- a/1.14/src/main/resources/assets/engineersdecor/lang/ru_ru.json +++ b/1.14/src/main/resources/assets/engineersdecor/lang/ru_ru.json @@ -51,6 +51,8 @@ "engineersdecor.config.pipevalve_redstone_gain": "Клапаны: спад красного камня", "engineersdecor.config.e_furnace_speed_percent": "Электропечь: скорость плавления %", "engineersdecor.config.e_furnace_power_consumption": "Электропечь: потребление энергии", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.clinker_brick_block": "Клинкерный кирпич", "block.engineersdecor.clinker_brick_block.help": "§6Кирпичный блок с вариациями текстуры, зависящими от положения.§r\nВыглядит темнее и интенсивнее, чем Кирпичный блок.", "block.engineersdecor.clinker_brick_stained_block": "Грязный клинкерный кирпич", diff --git a/1.14/src/main/resources/assets/engineersdecor/lang/zh_cn.json b/1.14/src/main/resources/assets/engineersdecor/lang/zh_cn.json index 4a99805..f17ecae 100644 --- a/1.14/src/main/resources/assets/engineersdecor/lang/zh_cn.json +++ b/1.14/src/main/resources/assets/engineersdecor/lang/zh_cn.json @@ -51,6 +51,8 @@ "engineersdecor.config.pipevalve_redstone_gain": "阀门:红石斜率", "engineersdecor.config.e_furnace_speed_percent": "电炉:熔炉速度 %", "engineersdecor.config.e_furnace_power_consumption": "电炉:能量消耗", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.clinker_brick_block": "过烧砖块", "block.engineersdecor.clinker_brick_block.help": "§6一种放在不同位置贴图有不同变化的砖块。§r\n比原版砖看起来颜色更深,色度也更高。", "block.engineersdecor.clinker_brick_stained_block": "污渍过烧砖块", diff --git a/1.14/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json b/1.14/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json new file mode 100644 index 0000000..377297f --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json @@ -0,0 +1,77 @@ +{ + "parent": "block/block", + "textures": { + "f": "engineersdecor:block/misc/labeled_crate_front_texture", + "particle": "engineersdecor:block/misc/labeled_crate_side_texture", + "s": "engineersdecor:block/misc/labeled_crate_side_texture" + }, + "elements": [ + { + "from": [0, 7, 0], + "to": [16, 16, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0.25], + "to": [16, 16, 16], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [7, 0, 0], + "to": [16, 7, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0], + "to": [1, 7, 0.375], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [1, 0, 0], + "to": [7, 1, 0.25], + "faces": { + "north": {"texture": "#f"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + } + ], + "display": { + "ground": { + "translation": [0, 1.75, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json b/1.14/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json new file mode 100644 index 0000000..1d2c898 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json @@ -0,0 +1 @@ +{ "parent": "engineersdecor:block/misc/labeled_crate_model" } \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..2e4f4fbc6b8ca6c98eae7e7548ef28938b92c81e GIT binary patch literal 662 zcmV;H0%`q;P)PA8G!wM z-y1{(cXxOE{Cdr~R@9X61|&Kt;R%46a(n%ezh1oI^z^i2nMtjc$L}}1T%bsDqQNr2 zG6(~Ce8X-uUOo}_-)^Y2Qc9teQuulOfms^+%>dzkb5w;)5EXC%lGrv-;art}KfYsm z{)&>BG${<`D8X)?NKw2sk{~=lz_f61r+ESiB23dnskJg^J$?wczgGIjAkrN$6+Hat zOm`xVMP;|!@o+ov^kkqmhYU`}f&IGi$V5xQvq3Rd50HYAhze%b8EmcbMBsGM2nrM=k2&gj9P&K?}zeJHfIi;bhKvGlyp}MlJE1DgfEOCb< zNd$LCMTBP;Z`tR_QiMTaQ1D1xjNdu&OvuE{SY4<{*W++FFpeXqFW&HFHMW-A*Q9w6 ztq~E_6lM(~lg9=sf@fz?A_6mGSr$$%-tzs^dm^AO181eMA$&U&OgbjOA%uuPE-x>$ wlmbAwBdTNsi2R{%X4G1Hlv_iOQI81z2Lv8c)#zKRApigX07*qoM6N<$f=@FYTL1t6 literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..17f92edef3ade76c26c8227b2e0f9cb60e277f79 GIT binary patch literal 672 zcmV;R0$=@!P)5teB|))1DD!RQ^Grtr#JyPAC!j=cYJeo&H4E`W`<@atu+q6-E*~rBFU)1 zuEMSgl|03;AB-2H@a5w@tu^L(rj%0n`ijtXx7}YvTu-|S-QM`AOAUr_8w6M6-J%I#-VHhZ_H6r6w5FU;b>%}0l5-=4! z{6uCY(E(MZ?Du=-zm&_fk=7kDFf*ps*p!N>()+@8*f1>%ltPk}05e-R=n?$$w0va_ zj)*YzHCIG9&d;bQNg|>Y0(Ymlug!xAJ(XR7xd%fLKqzGZATj`WUYz|<`1CC61`$Ce zXby>UoB@HhoRnB5Oauf3K}e2sqeuPUwS~{AoXKieNQw%XLIUGpmvq0000Pba?s literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png b/1.14/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..e41e8a35a377d622372623bec951f402b500d7c3 GIT binary patch literal 16765 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 literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json b/1.14/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json new file mode 100644 index 0000000..c519f37 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json @@ -0,0 +1,58 @@ +{ + "type": "forge:conditional", + "recipes": [ + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:labeled_crate", + "required": ["#forge:rods/iron", "immersiveengineering:crate"] + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" + ], + "key": { + "R": { "tag" : "forge:rods/iron"}, + "C": { "item": "immersiveengineering:crate"}, + "F": { "item": "minecraft:item_frame"} + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } + } + }, + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:labeled_crate", + "required": ["#forge:chests/wooden"], + "missing": ["#forge:rods/iron", "immersiveengineering:crate"] + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" + ], + "key": { + "R": { "item": "minecraft:iron_nugget"}, + "C": { "tag": "forge:chests/wooden"}, + "F": { "item": "minecraft:item_frame"} + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/1.15/gradle.properties b/1.15/gradle.properties index 8bb0711..6cf3e7c 100644 --- a/1.15/gradle.properties +++ b/1.15/gradle.properties @@ -2,7 +2,7 @@ org.gradle.daemon=false org.gradle.jvmargs=-Xmx8G version_minecraft=1.15.2 -version_forge_minecraft=1.15.2-31.1.19 +version_forge_minecraft=1.15.2-31.1.25 version_fml_mappings=20200225-1.15.1 version_jei=1.15.2:6.0.0.2 -version_engineersdecor=1.0.20-b1 +version_engineersdecor=1.0.20-b2 diff --git a/1.15/readme.md b/1.15/readme.md index 2412adb..f2e791e 100644 --- a/1.15/readme.md +++ b/1.15/readme.md @@ -11,6 +11,8 @@ Mod sources for Minecraft version 1.15.1. ## Version history + ~ v1.0.20-b2 [A] Added Labeled Crate (storage crate with built-in item frame). + - v1.0.20-b1 [A] Electrical Furnace: Added four-position speed switch (off, 100%, 150%, 200%), power consumption increases at higher rate (off, 100%, 200%, 400%). [A] Added Steel Mesh Fence Gate (single or double height gate fitting to the Steel Mesh Fence). diff --git a/1.15/src/main/java/wile/engineersdecor/ModContent.java b/1.15/src/main/java/wile/engineersdecor/ModContent.java index 2300720..0e3b41c 100644 --- a/1.15/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.15/src/main/java/wile/engineersdecor/ModContent.java @@ -591,6 +591,12 @@ public class ModContent } )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_fluid_funnel")); + public static final BlockDecorLabeledCrate.DecorLabeledCrateBlock LABELED_CRATE = (BlockDecorLabeledCrate.DecorLabeledCrateBlock)(new BlockDecorLabeledCrate.DecorLabeledCrateBlock( + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT, + Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(0.5f, 128f).sound(SoundType.METAL).notSolid(), + Auxiliaries.getPixeledAABB(0,0,0, 16,16,16) + )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "labeled_crate")); + // ------------------------------------------------------------------------------------------------------------------- public static final BlockDecorWall CONCRETE_WALL = (BlockDecorWall)(new BlockDecorWall( @@ -659,6 +665,7 @@ public class ModContent private static final Block modBlocks[] = { TREATED_WOOD_CRAFTING_TABLE, + LABELED_CRATE, SMALL_LAB_FURNACE, SMALL_ELECTRICAL_FURNACE, FACTORY_HOPPER, @@ -754,6 +761,11 @@ public class ModContent .build(null) .setRegistryName(ModEngineersDecor.MODID, "te_treated_wood_crafting_table"); + public static final TileEntityType TET_LABELED_CRATE = TileEntityType.Builder + .create(BlockDecorLabeledCrate.LabeledCrateTileEntity::new, LABELED_CRATE) + .build(null) + .setRegistryName(ModEngineersDecor.MODID, "te_labeled_crate"); + public static final TileEntityType TET_SMALL_LAB_FURNACE = TileEntityType.Builder .create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE) .build(null) @@ -831,6 +843,7 @@ public class ModContent private static final TileEntityType tile_entity_types[] = { TET_TREATED_WOOD_CRAFTING_TABLE, + TET_LABELED_CRATE, TET_SMALL_LAB_FURNACE, TET_SMALL_ELECTRICAL_FURNACE, TET_FACTORY_HOPPER, @@ -878,6 +891,7 @@ public class ModContent public static final ContainerType CT_SMALL_LAB_FURNACE; public static final ContainerType CT_SMALL_ELECTRICAL_FURNACE; public static final ContainerType CT_WASTE_INCINERATOR; + public static final ContainerType CT_LABELED_CRATE; static { CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType(BlockDecorCraftingTable.CraftingTableContainer::new)); @@ -894,11 +908,14 @@ public class ModContent CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace"); CT_WASTE_INCINERATOR = (new ContainerType(BlockDecorWasteIncinerator.BContainer::new)); CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator"); + CT_LABELED_CRATE = (new ContainerType(BlockDecorLabeledCrate.BContainer::new)); + CT_LABELED_CRATE.setRegistryName(ModEngineersDecor.MODID,"ct_labeled_crate"); } // DON'T FORGET TO REGISTER THE GUI in registerContainerGuis(), no list/map format found yet for that. private static final ContainerType container_types[] = { CT_TREATED_WOOD_CRAFTING_TABLE, + CT_LABELED_CRATE, CT_FACTORY_DROPPER, CT_FACTORY_PLACER, CT_FACTORY_HOPPER, @@ -982,6 +999,7 @@ public class ModContent public static final void registerContainerGuis(final FMLClientSetupEvent event) { ScreenManager.registerFactory(CT_TREATED_WOOD_CRAFTING_TABLE, BlockDecorCraftingTable.CraftingTableGui::new); + ScreenManager.registerFactory(CT_LABELED_CRATE, BlockDecorLabeledCrate.BGui::new); ScreenManager.registerFactory(CT_FACTORY_DROPPER, BlockDecorDropper.BGui::new); ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new); ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.BGui::new); @@ -998,6 +1016,10 @@ public class ModContent (TileEntityType)TET_TREATED_WOOD_CRAFTING_TABLE, wile.engineersdecor.detail.ModRenderers.CraftingTableTer::new ); + ClientRegistry.bindTileEntityRenderer( + (TileEntityType)TET_LABELED_CRATE, + wile.engineersdecor.detail.ModRenderers.DecorLabeledCrateTer::new + ); } @OnlyIn(Dist.CLIENT) diff --git a/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java index 885848b..016192f 100644 --- a/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java +++ b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnaceElectrical.java @@ -173,7 +173,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace implements ID fifo_timer_ = 0; tick_timer_ = 0; energy_stored_ = 0; - speed_ = 0; + speed_ = 1; field_max_energy_stored_ = getMaxEnergyStored(); field_isburning_ = 0; } diff --git a/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java index 1a30338..7dbdd8f 100644 --- a/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java +++ b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorHopper.java @@ -8,8 +8,6 @@ */ package wile.engineersdecor.blocks; -import net.minecraft.util.math.shapes.ISelectionContext; -import net.minecraft.util.math.shapes.VoxelShapes; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.libmc.detail.Inventories; @@ -37,6 +35,8 @@ import net.minecraft.inventory.container.Slot; import net.minecraft.util.*; import net.minecraft.util.math.*; import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.text.*; import net.minecraft.nbt.CompoundNBT; import net.minecraft.client.gui.screen.inventory.ContainerScreen; diff --git a/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java new file mode 100644 index 0000000..b1c148b --- /dev/null +++ b/1.15/src/main/java/wile/engineersdecor/blocks/BlockDecorLabeledCrate.java @@ -0,0 +1,597 @@ +/* + * @file BlockDecorLabeledCrate.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Storage crate with a content hint. + */ +package wile.engineersdecor.blocks; + +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.libmc.blocks.StandardBlocks; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.World; +import net.minecraft.block.material.PushReaction; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.item.*; +import net.minecraft.inventory.*; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.Slot; +import net.minecraft.util.*; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SUpdateTileEntityPacket; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import com.mojang.blaze3d.platform.GlStateManager; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + + +public class BlockDecorLabeledCrate +{ + public static void on_config(int stack_limit) + { + } + + //-------------------------------------------------------------------------------------------------------------------- + // Block + //-------------------------------------------------------------------------------------------------------------------- + + public static class DecorLabeledCrateBlock extends StandardBlocks.Horizontal implements IDecorBlock + { + public DecorLabeledCrateBlock(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) + { super(config, builder, unrotatedAABB); } + + @Override + @SuppressWarnings("deprecation") + public boolean hasComparatorInputOverride(BlockState state) + { return true; } + + @Override + @SuppressWarnings("deprecation") + public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) + { return Container.calcRedstone(world.getTileEntity(pos)); } + + @Override + public boolean hasTileEntity(BlockState state) + { return true; } + + @Override + @Nullable + public TileEntity createTileEntity(BlockState state, IBlockReader world) + { return new LabeledCrateTileEntity(); } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) + { + if(world.isRemote) return; + if((!stack.hasTag()) || (!stack.getTag().contains("tedata"))) return; + CompoundNBT te_nbt = stack.getTag().getCompound("tedata"); + if(te_nbt.isEmpty()) return; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return; + ((LabeledCrateTileEntity)te).readnbt(te_nbt); + ((LabeledCrateTileEntity)te).markDirty(); + } + + @Override + public boolean hasDynamicDropList() + { return true; } + + @Override + public List dropList(BlockState state, World world, BlockPos pos, boolean explosion) + { + final List stacks = new ArrayList(); + if(world.isRemote) return stacks; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return stacks; + if(!explosion) { + ItemStack stack = new ItemStack(this, 1); + CompoundNBT te_nbt = ((LabeledCrateTileEntity) te).reset_getnbt(); + if(!te_nbt.isEmpty()) { + CompoundNBT nbt = new CompoundNBT(); + nbt.put("tedata", te_nbt); + stack.setTag(nbt); + } + stacks.add(stack); + } else { + for(ItemStack stack: ((LabeledCrateTileEntity)te).stacks_) stacks.add(stack); + ((LabeledCrateTileEntity)te).reset_getnbt(); + } + return stacks; + } + + @Override + @SuppressWarnings("deprecation") + public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult rayTraceResult) + { + if(world.isRemote) return ActionResultType.SUCCESS; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof LabeledCrateTileEntity)) return ActionResultType.SUCCESS; + if((!(player instanceof ServerPlayerEntity) && (!(player instanceof FakePlayer)))) return ActionResultType.SUCCESS; + NetworkHooks.openGui((ServerPlayerEntity)player,(INamedContainerProvider)te); + return ActionResultType.SUCCESS; + } + + @Override + public PushReaction getPushReaction(BlockState state) + { return PushReaction.BLOCK; } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class LabeledCrateTileEntity extends TileEntity implements INameable, IInventory, INamedContainerProvider, ISidedInventory + { + public static final int NUM_OF_FIELDS = 1; + public static final int NUM_OF_SLOTS = 55; + public static final int ITEMFRAME_SLOTNO = 54; + + // BTileEntity ----------------------------------------------------------------------------- + + protected NonNullList stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + + public LabeledCrateTileEntity() + { this(ModContent.TET_LABELED_CRATE); } + + public LabeledCrateTileEntity(TileEntityType te_type) + { super(te_type); reset(); } + + public CompoundNBT reset_getnbt() + { + CompoundNBT nbt = new CompoundNBT(); + writenbt(nbt); + reset(); + return nbt; + } + + protected void reset() + { + stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + } + + public void readnbt(CompoundNBT compound) + { + NonNullList stacks = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(compound, stacks); + while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY); + stacks_ = stacks; + } + + protected void writenbt(CompoundNBT compound) + { + ItemStackHelper.saveAllItems(compound, stacks_); + } + + public ItemStack getItemFrameStack() + { return (stacks_.size() > ITEMFRAME_SLOTNO) ? (stacks_.get(ITEMFRAME_SLOTNO)) : (ItemStack.EMPTY); } + + // TileEntity ------------------------------------------------------------------------------ + + @Override + public void read(CompoundNBT compound) + { super.read(compound); readnbt(compound); } + + @Override + public CompoundNBT write(CompoundNBT compound) + { super.write(compound); writenbt(compound); return compound; } + + @Override + public CompoundNBT getUpdateTag() + { CompoundNBT nbt = super.getUpdateTag(); writenbt(nbt); return nbt; } + + @Override + @Nullable + public SUpdateTileEntityPacket getUpdatePacket() + { return new SUpdateTileEntityPacket(pos, 1, getUpdateTag()); } + + @Override + public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) // on client + { super.read(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } + + @Override + public void handleUpdateTag(CompoundNBT tag) // on client + { read(tag); } + + // INameable --------------------------------------------------------------------------- + + @Override + public ITextComponent getName() + { final Block block=getBlockState().getBlock(); return new StringTextComponent((block!=null) ? block.getTranslationKey() : "Small Waste Incinerator"); } + + @Override + public boolean hasCustomName() + { return false; } + + @Override + public ITextComponent getCustomName() + { return getName(); } + + // IContainerProvider ---------------------------------------------------------------------- + + @Override + public ITextComponent getDisplayName() + { return INameable.super.getDisplayName(); } + + @Override + public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) + { return new BContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } + + // IInventory ------------------------------------------------------------------------------ + + @Override + public int getSizeInventory() + { return stacks_.size(); } + + @Override + public boolean isEmpty() + { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } + + @Override + public ItemStack getStackInSlot(int index) + { return ((index >= 0) && (index < getSizeInventory())) ? stacks_.get(index) : ItemStack.EMPTY; } + + @Override + public ItemStack decrStackSize(int index, int count) + { return ItemStackHelper.getAndSplit(stacks_, index, count); } + + @Override + public ItemStack removeStackFromSlot(int index) + { return ItemStackHelper.getAndRemove(stacks_, index); } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) + { + if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); + stacks_.set(index, stack); + markDirty(); + if(getWorld() instanceof ServerWorld) { + // This should result in sending TE data (getUpdateTag etc) to the client for the TER. + BlockState state = world.getBlockState(getPos()); + getWorld().notifyBlockUpdate(getPos(), state, state, 2|16|32); + } + } + + @Override + public int getInventoryStackLimit() + { return 64; } + + @Override + public void markDirty() + { super.markDirty(); } + + @Override + public boolean isUsableByPlayer(PlayerEntity player) + { return getPos().distanceSq(player.getPosition()) < 36; } + + @Override + public void openInventory(PlayerEntity player) + {} + + @Override + public void closeInventory(PlayerEntity player) + { markDirty(); } + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) + { return (index != ITEMFRAME_SLOTNO); } + + @Override + public void clear() + { stacks_.clear(); } + + // Fields ----------------------------------------------------------------------------------------------- + + protected final IIntArray fields = new IntArray(LabeledCrateTileEntity.NUM_OF_FIELDS) + { + @Override + public int get(int id) + { + switch(id) { + default: return 0; + } + } + @Override + public void set(int id, int value) + { + switch(id) { + default: break; + } + } + }; + + // ISidedInventory ---------------------------------------------------------------------------- + + private static final int[] SIDED_INV_SLOTS; + static { + // that useless unoptimised language ... no proper inline conv to int[]? + // private static final int[] SIDED_INV_SLOTS = IntStream.rangeClosed(0, BTileEntity.NUM_OF_SLOTS-2).boxed().collect(Collectors.toList()).toArray(); + SIDED_INV_SLOTS = new int[LabeledCrateTileEntity.NUM_OF_SLOTS-1]; + for(int i=0; i= NUM_OF_SLOTS)) || ((slotno == ITEMFRAME_SLOTNO)) ) return ItemStack.EMPTY; + ItemStack slotstack = getStackInSlot(slotno); + if(!slotstack.isEmpty()) { + if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(slotno))) return stack; + if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; + if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)) - slotstack.getCount(); + if(stack.getCount() <= n) { + if(!simulate) { + ItemStack copy = stack.copy(); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + } + return ItemStack.EMPTY; + } else { + stack = stack.copy(); + if(!simulate) { + ItemStack copy = stack.split(n); + copy.grow(slotstack.getCount()); + te.setInventorySlotContents(slotno, copy); + return stack; + } else { + stack.shrink(n); + return stack; + } + } + } else { + if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; + int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)); + if(n < stack.getCount()) { + stack = stack.copy(); + if(!simulate) { + te.setInventorySlotContents(slotno, stack.split(n)); + return stack; + } else { + stack.shrink(n); + return stack; + } + } else { + if(!simulate) te.setInventorySlotContents(slotno, stack); + return ItemStack.EMPTY; + } + } + } + + @Override + @Nonnull + public ItemStack extractItem(int index, int amount, boolean simulate) + { + if((index < 0) || ((index >= NUM_OF_SLOTS)) || ((index == ITEMFRAME_SLOTNO)) ) return ItemStack.EMPTY; + if(!simulate) return ItemStackHelper.getAndSplit(te.stacks_, index, amount); + ItemStack stack = te.stacks_.get(index).copy(); + if(stack.getCount() > amount) stack.setCount(amount); + return stack; + } + + @Override + @Nonnull + public ItemStack getStackInSlot(int index) + { return te.getStackInSlot(index); } + } + + // Capability export ---------------------------------------------------------------------------- + + protected LazyOptional item_handler_ = LazyOptional.of(() -> new LabeledCrateTileEntity.BItemHandler(this)); + + @Override + public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) + { + if(!this.removed) { + if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return item_handler_.cast(); + } + return super.getCapability(capability, facing); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // GUI + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class BGui extends ContainerScreen + { + protected final PlayerEntity player_; + + public BGui(BContainer container, PlayerInventory player_inventory, ITextComponent title) + { + super(container, player_inventory, title); + player_ = player_inventory.player; + xSize = 213; + ySize = 206; + } + + @Override + public void init() + { super.init(); } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) + { + renderBackground(); + super.render(mouseX, mouseY, partialTicks); + renderHoveredToolTip(mouseX, mouseY); + } + + @Override + @SuppressWarnings("deprecation") + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) + { + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + this.minecraft.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/labeled_crate_gui.png")); + final int x0=guiLeft, y0=this.guiTop, w=xSize, h=ySize; + blit(x0, y0, 0, 0, w, h); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Container + //-------------------------------------------------------------------------------------------------------------------- + + public static class BContainer extends Container + { + //------------------------------------------------------------------------------------------------------------------ + protected static class StorageSlot extends Slot + { + StorageSlot(IInventory inventory, int index, int x, int y) + { super(inventory, index, x, y); } + + @Override + public int getSlotStackLimit() + { return 64; } + } + + //------------------------------------------------------------------------------------------------------------------ + private static final int PLAYER_INV_START_SLOTNO = LabeledCrateTileEntity.NUM_OF_SLOTS; + protected final PlayerEntity player_; + protected final IInventory inventory_; + protected final IWorldPosCallable wpc_; + private final IIntArray fields_; + private int proc_time_needed_; + //------------------------------------------------------------------------------------------------------------------ + public int field(int index) { return fields_.get(index); } + public PlayerEntity player() { return player_ ; } + public IInventory inventory() { return inventory_ ; } + public World world() { return player_.world; } + //------------------------------------------------------------------------------------------------------------------ + + public BContainer(int cid, PlayerInventory player_inventory) + { this(cid, player_inventory, new Inventory(LabeledCrateTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY, new IntArray(LabeledCrateTileEntity.NUM_OF_FIELDS)); } + + private BContainer(int cid, PlayerInventory player_inventory, IInventory block_inventory, IWorldPosCallable wpc, IIntArray fields) + { + super(ModContent.CT_LABELED_CRATE, cid); + player_ = player_inventory.player; + inventory_ = block_inventory; + wpc_ = wpc; + fields_ = fields; + int i=-1; + // storage slots (stacks 0 to 53) + for(int y=0; y<6; ++y) { + for(int x=0; x<9; ++x) { + int xpos = 28+x*18, ypos = 10+y*18; + addSlot(new StorageSlot(inventory_, ++i, xpos, ypos)); + } + } + // picture frame slot (54) + addSlot(new Slot(inventory_, ++i, 191, 100) { + @Override public int getSlotStackLimit(){return 1;} + }); + // player slots + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x, 28+x*18, 183)); // player slots: 0..8 + } + for(int y=0; y<3; ++y) { + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x+y*9+9, 28+x*18, 125+y*18)); // player slots: 9..35 + } + } + } + + @Override + public boolean canInteractWith(PlayerEntity player) + { return inventory_.isUsableByPlayer(player); } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slot) + { return (slot.getSlotStackLimit() > 1); } + + @Override + public void onContainerClosed(PlayerEntity player) + { super.onContainerClosed(player); } + + @Override + public ItemStack transferStackInSlot(PlayerEntity player, int index) + { + Slot slot = getSlot(index); + if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY; + ItemStack slot_stack = slot.getStack(); + ItemStack transferred = slot_stack.copy(); + if((index>=0) && (index= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) { + // Player slot + if(!mergeItemStack(slot_stack, 0, PLAYER_INV_START_SLOTNO-1, false)) 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; + } + } +} diff --git a/1.15/src/main/java/wile/engineersdecor/detail/ModRenderers.java b/1.15/src/main/java/wile/engineersdecor/detail/ModRenderers.java index f956719..3c94c61 100644 --- a/1.15/src/main/java/wile/engineersdecor/detail/ModRenderers.java +++ b/1.15/src/main/java/wile/engineersdecor/detail/ModRenderers.java @@ -27,6 +27,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import com.mojang.blaze3d.matrix.MatrixStack; import wile.engineersdecor.blocks.BlockDecorCraftingTable.CraftingTableBlock; +import wile.engineersdecor.blocks.BlockDecorLabeledCrate; public class ModRenderers @@ -106,14 +107,62 @@ public class ModRenderers mxs.translate(rndo, rndo, 0); mxs.scale(scaler, scaler, scaler); Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED, i5, i6, mxs, buf); - mxs.pop(); // mxs.pop() + mxs.pop(); } } catch(Throwable e) { if(--tesr_error_counter<=0) { - ModEngineersDecor.logger().error("TESR was disabled because broken, exception was: " + e.getMessage()); + ModEngineersDecor.logger().error("TER was disabled because broken, exception was: " + e.getMessage()); ModEngineersDecor.logger().error(e.getStackTrace()); } } } } + + //-------------------------------------------------------------------------------------------------------------------- + // Labeled Crate + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class DecorLabeledCrateTer extends TileEntityRenderer + { + private static int tesr_error_counter = 4; + private static float scaler = 0.35f; + double tr[][]= { // [hdirection=S-W-N-E][param] + { +8.0/32, -8.0/32, +15.5/32, 180.0 }, // N + { -15.5/32, -8.0/32, +8.0/32, 90.0 }, // E + { -8.0/32, -8.0/32, -15.5/32, 0.0 }, // S param=tx,ty,tz,ry + { +15.5/32, -8.0/32, -8.0/32, 270.0 }, // W + }; + + public DecorLabeledCrateTer(TileEntityRendererDispatcher dispatcher) + { super(dispatcher); } + + @Override + @SuppressWarnings("deprecation") + public void render(final BlockDecorLabeledCrate.LabeledCrateTileEntity te, float unused1, MatrixStack mxs, IRenderTypeBuffer buf, int i5, int i6) + { + if(tesr_error_counter<=0) return; + try { + final ItemStack stack = te.getItemFrameStack(); + if(stack.isEmpty()) return; + final int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).get(BlockDecorLabeledCrate.DecorLabeledCrateBlock.HORIZONTAL_FACING).getHorizontalIndex(), 0, 3); + double ox = tr[di][0], oy = tr[di][1], oz = tr[di][2]; + float ry = (float)tr[di][3]; + mxs.push(); + //GlStateManager.disableLighting(); + //RenderHelper.enableStandardItemLighting(); + mxs.translate(0.5+ox, 0.5+oy, 0.5+oz); + mxs.rotate(Vector3f.YP.rotationDegrees(ry)); + mxs.scale(scaler, scaler, scaler); + Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED, i5, i6, mxs, buf); + //RenderHelper.disableStandardItemLighting(); + //GlStateManager.enableLighting(); + mxs.pop(); + } catch(Throwable e) { + if(--tesr_error_counter<=0) { + ModEngineersDecor.logger().error("TER was disabled (because broken), exception was: " + e.getMessage()); + } + } + } + } } diff --git a/1.15/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json b/1.15/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json new file mode 100644 index 0000000..b0b5a3f --- /dev/null +++ b/1.15/src/main/resources/assets/engineersdecor/blockstates/labeled_crate.json @@ -0,0 +1,8 @@ +{ + "variants": { + "facing=north": { "model": "engineersdecor:block/misc/labeled_crate_model" }, + "facing=south": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":180 }, + "facing=west": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":270 }, + "facing=east": { "model": "engineersdecor:block/misc/labeled_crate_model", "y":90 } + } +} diff --git a/1.15/src/main/resources/assets/engineersdecor/lang/en_us.json b/1.15/src/main/resources/assets/engineersdecor/lang/en_us.json index 55234f0..13a17ff 100644 --- a/1.15/src/main/resources/assets/engineersdecor/lang/en_us.json +++ b/1.15/src/main/resources/assets/engineersdecor/lang/en_us.json @@ -135,6 +135,8 @@ "block.engineersdecor.treated_wood_stool.help": "§6Robust Wood Stool.§r Indoor and outdoor use.", "block.engineersdecor.treated_wood_crafting_table": "Treated Wood Crafting Table", "block.engineersdecor.treated_wood_crafting_table.help": "§6Robust and weather-proof.§r Eight storage slots, keeps inventory, no vanilla recipe book.\n Click up/down arrow buttons for crafting history selection, output slot for item placement, X-button to clear crafting grid and history. Shift-click stack: player-to-storage stack transfer when crafting grid empty, otherwise player-to-grid stack transfer. Automatically distributes the clicked stack. Shift-Ctrl-click stack: Move all same stacks. Mouse wheel over crafting slot: Increase/decrease crafting grid items.", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.treated_wood_side_table": "Treated Wood Side Table", "block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.", "block.engineersdecor.iron_inset_light": "Inset Light", diff --git a/1.15/src/main/resources/assets/engineersdecor/lang/ru_ru.json b/1.15/src/main/resources/assets/engineersdecor/lang/ru_ru.json index a9ab02b..ac13c2f 100644 --- a/1.15/src/main/resources/assets/engineersdecor/lang/ru_ru.json +++ b/1.15/src/main/resources/assets/engineersdecor/lang/ru_ru.json @@ -135,6 +135,8 @@ "block.engineersdecor.treated_wood_stool.help": "§6Крепкий деревянный табурет.§r Для использования в помещении и на улице.", "block.engineersdecor.treated_wood_crafting_table": "Верстак из обработанного дерева", "block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке.", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.treated_wood_side_table": "Столик из обработанного дерева", "block.engineersdecor.treated_wood_side_table.help": "§6Нужен после того, как работа выполнена.", "block.engineersdecor.iron_inset_light": "Встраиваемый осветитель", diff --git a/1.15/src/main/resources/assets/engineersdecor/lang/zh_cn.json b/1.15/src/main/resources/assets/engineersdecor/lang/zh_cn.json index 4a99805..a65000e 100644 --- a/1.15/src/main/resources/assets/engineersdecor/lang/zh_cn.json +++ b/1.15/src/main/resources/assets/engineersdecor/lang/zh_cn.json @@ -135,6 +135,8 @@ "block.engineersdecor.treated_wood_stool.help": "§6坚固的木凳。§r适用于室内和室外使用。", "block.engineersdecor.treated_wood_crafting_table": "防腐木合成台", "block.engineersdecor.treated_wood_crafting_table.help": "§6坚固,防风防雨。§r内含八个存储格,破坏后保留内容物,没有原版合成书。\n 单击上/下箭头按钮可选择合成历史,单击输出格自动放置物品,单击X按钮 清除合成栏和历史。Shift单击一叠物品:合成格空时转移到存储格, 非空时到合成栏。会自动分配转移的物品。", + "block.engineersdecor.labeled_crate": "Labeled Crate", + "block.engineersdecor.labeled_crate.help": "§6A storage crate with 9x6 slots and a built-in item frame at the front.§r\nPlace an item into the frame slot at the bottom right of the GUI to define the shown label.", "block.engineersdecor.treated_wood_side_table": "防腐木茶几", "block.engineersdecor.treated_wood_side_table.help": "§6干完活后需要喝杯茶。", "block.engineersdecor.iron_inset_light": "嵌入灯", diff --git a/1.15/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json b/1.15/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json new file mode 100644 index 0000000..377297f --- /dev/null +++ b/1.15/src/main/resources/assets/engineersdecor/models/block/misc/labeled_crate_model.json @@ -0,0 +1,77 @@ +{ + "parent": "block/block", + "textures": { + "f": "engineersdecor:block/misc/labeled_crate_front_texture", + "particle": "engineersdecor:block/misc/labeled_crate_side_texture", + "s": "engineersdecor:block/misc/labeled_crate_side_texture" + }, + "elements": [ + { + "from": [0, 7, 0], + "to": [16, 16, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0.25], + "to": [16, 16, 16], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [7, 0, 0], + "to": [16, 7, 0.25], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [0, 0, 0], + "to": [1, 7, 0.375], + "faces": { + "north": {"texture": "#f"}, + "east": {"texture": "#s"}, + "south": {"texture": "#s"}, + "west": {"texture": "#s"}, + "down": {"texture": "#s"} + } + }, + { + "from": [1, 0, 0], + "to": [7, 1, 0.25], + "faces": { + "north": {"texture": "#f"}, + "up": {"texture": "#s"}, + "down": {"texture": "#s"} + } + } + ], + "display": { + "ground": { + "translation": [0, 1.75, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.15/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json b/1.15/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json new file mode 100644 index 0000000..1d2c898 --- /dev/null +++ b/1.15/src/main/resources/assets/engineersdecor/models/item/labeled_crate.json @@ -0,0 +1 @@ +{ "parent": "engineersdecor:block/misc/labeled_crate_model" } \ No newline at end of file diff --git a/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png b/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..2e4f4fbc6b8ca6c98eae7e7548ef28938b92c81e GIT binary patch literal 662 zcmV;H0%`q;P)PA8G!wM z-y1{(cXxOE{Cdr~R@9X61|&Kt;R%46a(n%ezh1oI^z^i2nMtjc$L}}1T%bsDqQNr2 zG6(~Ce8X-uUOo}_-)^Y2Qc9teQuulOfms^+%>dzkb5w;)5EXC%lGrv-;art}KfYsm z{)&>BG${<`D8X)?NKw2sk{~=lz_f61r+ESiB23dnskJg^J$?wczgGIjAkrN$6+Hat zOm`xVMP;|!@o+ov^kkqmhYU`}f&IGi$V5xQvq3Rd50HYAhze%b8EmcbMBsGM2nrM=k2&gj9P&K?}zeJHfIi;bhKvGlyp}MlJE1DgfEOCb< zNd$LCMTBP;Z`tR_QiMTaQ1D1xjNdu&OvuE{SY4<{*W++FFpeXqFW&HFHMW-A*Q9w6 ztq~E_6lM(~lg9=sf@fz?A_6mGSr$$%-tzs^dm^AO181eMA$&U&OgbjOA%uuPE-x>$ wlmbAwBdTNsi2R{%X4G1Hlv_iOQI81z2Lv8c)#zKRApigX07*qoM6N<$f=@FYTL1t6 literal 0 HcmV?d00001 diff --git a/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png b/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..17f92edef3ade76c26c8227b2e0f9cb60e277f79 GIT binary patch literal 672 zcmV;R0$=@!P)5teB|))1DD!RQ^Grtr#JyPAC!j=cYJeo&H4E`W`<@atu+q6-E*~rBFU)1 zuEMSgl|03;AB-2H@a5w@tu^L(rj%0n`ijtXx7}YvTu-|S-QM`AOAUr_8w6M6-J%I#-VHhZ_H6r6w5FU;b>%}0l5-=4! z{6uCY(E(MZ?Du=-zm&_fk=7kDFf*ps*p!N>()+@8*f1>%ltPk}05e-R=n?$$w0va_ zj)*YzHCIG9&d;bQNg|>Y0(Ymlug!xAJ(XR7xd%fLKqzGZATj`WUYz|<`1CC61`$Ce zXby>UoB@HhoRnB5Oauf3K}e2sqeuPUwS~{AoXKieNQw%XLIUGpmvq0000Pba?s literal 0 HcmV?d00001 diff --git a/1.15/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png b/1.15/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..e41e8a35a377d622372623bec951f402b500d7c3 GIT binary patch literal 16765 zcmdsfc{r5e8}2tVma*@w(J!d zgzSbe80NfFzu!66`RiQgpYzA*x-#E<>+`+K{oK#<-0#F#nj5n)3Nk_v#A0&V&>DhZ zU=s!*>A;8mtrA!8L3h>6*bq7fi9$Ta25--SJq*65FZ)9fYYX*1tp2grG6asA80w!7 z`o7$FIq}-3bg6)@mD!QNL@Cvyw_>`kN_|?m>aQgk{Pd~lZ3N4oFUJ`+o?|jlU(r`Y zX7A@@vYLUo#55lnSt>1yHO!V*COodFGjkJ z-W9dV_9O3+9sM`FTqm?qtqXccWW9*981bzVg+fLja70)>axOU?&cC+vs)IfYS)c~N zW5xBna4JxQ2>-P<H5+@4`OVyxUdD`!H9~y8)72+NV za+Q9qXqPQ8D3qwNj0HP+>pvr&c?!y|#vjmtzmsdrw5YU<_Tq#oWQq zKSy8=3Rdgz(WK|dO@Z^%Bk&SFu72XOa*znjP}G1xf6!0LL@ozEOjf;S!Ys#QWH9M& zpS3H(plQM6AspuK+B9hhA+*wV{GmivBWJ5P%J!F3uWiYyCkzB7%q>*B+J}n|Tzr+0 zP;GRcrE;RTsOKG4f}A|Ex)KiXntNnfGe^1C`iEB$k$avfP`6h3l7DEc@P=Yk4D8XHsZdy1_RnjWrm85%rpLMuj zlz|sJ4pR#C^CMvnCT*L7QQ>0zqwr8z`KA=6{NUSj#H+=%wteZ<|G?A;SF_983&7;;u;jOh<_7Lq>&qA4b;q znxE<7u$#Ri;#cvj+w{@=xi#88mWIxm5|hH55ihtkXyGcX@Z4Is3-jf!7XFY}@W|*i zP0DNH+>S|?Si!;YRPRPLQkJ^mbO+PM&z;^GRQg-dr!AjpPAq~3@2gyz3kzK*%Pzqn z{C1snP5-g_{zuP5KV}Xc3@M=`V&Cd2i7AJaFP%Fi4z=;uH0o!nJaWLo^yJhrp~VlJ zbkSS04W#XN+9HR}zTY`=uB9QIaVgfJaD<$6ieC9Vm%S^Z5x~y(s=AY=Q-Ae zDX~8I8On#P9KpL)(xr-^CnkId^g4~{x{(p8%FpW@LqHjBn*d>H(Bb-P+J3e_#lUQqvc3&5h9AcZqCu->G*n)^P~keSw`P4)mx-CuPKB zo(!{)d6-mrL9}fnBXMjAWtjPGA4yjQ8n|l-ChJVuJi!{3G_URbi8~r+oi6{3AZX}q^S&9pv)XE{~K|@Ok!wv+hHIcX)xTPISjcg+%J7()+$`VRh`#bcdzXtioDJt_ z{Kf^H)OF=&WLZN-4hFnn;KJ)HLe@QfpRc-?FAuY<1)smtkbYk^iW~PF$)k2vB*V_L z*!~9PMC{o}8=ctqBq+DGqueGcLNz(%4|tTO7sr$6yo=z#5lToFbI$SUdMgWRV+n0? zd$jeH6;fNvu{gm=SKIK1NUh@Mz@1eM)oYn~*@o03uGvSflWV*fw!ZJ!E$(*NY|25J zLbc~c4$^gt?ov@;2|=;gc$M@ zQ<2{ISXleEiW3J}da~rHBO`oxogS`Ep@n#D45vB+iBfZ^Qw=1G-AFk#;;#mhiEz5V zr$tk2B|cZFC6L&;#W$L|I;G@AMizE2UbA7aW|9nGnAG5u`nohBOM5orL*v}oq9IM* z`5?GfC97UiX+i(9N9`PpSA0Ch)SrBmeRycb2%AT($Q*hSHd_ zrv@JDU~0C0Sdt>GJCKi0TH3l;p9h1j*@@8|Zj=q0VX=kX)GIl_;;L2C7p(L4>6*Q( zPbT&+Mij=O^wp{>+;;yw&(lgUci78$BV#FhjOfBC4ZW{W6SvCi(=!w_g@ivd%a$&G ze{>JHqIVRqfs%8h>dn=MpT=gHAALj$!MmduM7ra=(-mpNZdRB5KD!S$Q>r44jq&k`et zbG0=1veUyj5Pi;;%0gN`_rzoLM3)lf3pk8F2s~5Sn7XNP6pF}DPf)x1d-y5vC%#kqM5k*PLiqiimiF=zg#|H5XHgSOcx=a$_Z32~6h4cNwW)zX+mtaw!of7tcl=OKZe*2P4|AM~Zx8@Axpyj)`V%B~&kY$n> ztvMq4sE4nK1B)J-PPb1YKX_6sDmIu@8fKMv8aF1?Iq(v3W-x;^sE8yJB190h?DvK^ zJOk*i{~qR4?&vzk7||NjW~56SZ5b=h?&3RfW3)EI>|FRGy!Tl8FPj^M=h8DNWtxpcqR{+TDmo%x)yqKM6bv>ZaRtY3cTtLBsC@Z!BW1>@7l1(iuY4w zpJ1!$^DL>YyANF~8ATKG3Xk6TMsu#W`>lZ1*4MI>4pH$xx;r#n*dkVZIDqf5moWMi z@FbFw5ho+Q4IsK3bKjeS(FefKWG4^QRjWpmRLhBr<2^@eUVQw>JnfqE!vz_q3<|#-6w6hBQW0n ztS0+qzKbp19>p>_Vfym%wq1E@cQ+i!tyZ*!pE6dbCOnHQ1N;ZTXy*I=@{U3|71tlD znZ+2$Qr&crcSWLFR4~&9Fs2B!%&A(atvjEhQwyD9;BCJGPaB4v;qFKBKNZ}J$bb4w zskuMGPpbHOCWqT;E#sMmo?5!c>B?6_S~*#{Q}mumTR!tud(kD@hY9uHP%fw4o@pSz z&3Y6k(>?`|QmLzAtDc+MX)Pr+JU&z>XJ#@WuZe2?`GI>5lU>b6hEqAi}pv4UX>;_+jmVYcG z95arnM>@gXuYanMwr@Eu@=g~Qzk8LaDL8-Tpw3RaKRQ3Pb8h`yM-gR(F8K=uquF^g z$A2kcfvG)*LazIvjS=v_?ez*65?GuxJ<=;t(@ztxW)M6z!TT1g6EFB$(nukm?;)D9 zb5lcgl{oO_$^0VU5d8EF#)Kn9w8(6nYT7n}pCK~fnR9;jREXyHpsz|*L#H{6Iq-4! z%{=1O%yN^Xo-kUqah#exv*&DowZW=&I-lda$9>1_sY#nfgU}v+Zg2H8%hTdfeEV=~ zp_}(tS8w;kQ?4qv_%tN+I&J%5^Hq|t3zL{BM2=s ztzofSW6X{Xhkkvi=IV`9yO&iYw^DQTJ%4gZa!1aIu@=h4UMdrDoMK~YF}+%I^f)S+ z%4Lf$w8rXBb_Y@d%IrF;^IvIBSYd7jBGC746S|AJau#=-rvRS|wAIdLW4zh4moaXh zP|0cpuB1GuYZ(3E-FRJ1(3qpZx+K})sdUlr&hJqcGGoye*wf}s2j9M&&=W+5a2{@f z-v3~8F1y?+q^ntUV)5pmv4tDDnz*b0RulZj0nIbykNEGAJA!)Ni4VFqB(4-+=p4X= zE!(UBpEI$nPOL$<*ho-WZJiJx?Fm)s#nf>-S$|*rL%dD*Ur;HZ{^oo?>))5=uWbYR zVL!GGsN4uW>ODmywt0~=yRg=u1r+h0HqjXsl(M>eu!%fcBnI-oREWYan;&voVylQl z>1obf{LJQjGe1m;?LiA0A#QP``*~e0B-67WayQ_L1-_IQXSIe%D@W9yz(DO%J4Y~U z2$Cxq;{6Jbt7&?~D@uZOO&;5U#f78rwmY!H&uN|G98NQ_lcCu~sNyjS5+lK0CZY5` zjHcT{J-8U<;hD?AS1exu0KAXF3s)qe@Qym2N?`jt3D&kWZVQ#3y{G>{ARt4lSPAzH zH+Ym41IhShks;|8Hs^9OWbcIA*=!0q>vf0>9f`e*hWaBupLx2Pg~A)o6X>hVF_6OV zzmJ!}X`^wHF_tz9jeijQd`E#Dk5Tx`_h1Wt5o$-z-Y_lY?T6E#aoS|}x-c7C^dvnV zXS?pW3%lL_?>>BA;caneYayQW%!xu;(aW@G+&~R9(!!?q`rio^O8CpbURqhxm*G|4 zBwe~Pk7X57+j!#+^hT3#XAQxB#&8XBNdk@AX@YzlEaFaj&=%q(XGM+px%5pp92w@^ zRv3T@sx?p#8!k*){`MLIT+XzSx=hcGaPx%8(_XtA>Y0NJ*Y_);Hg#qmt@G#1GMhJN zrhcp;w9MEjH%PGeW^CA@eTa9)NeYciCtEBs`5G|!zP7-dDC(6ZHJ@a1-i4EAheQWq znS<~+wJQb@2IA?psIS9)9TfiN=S;~*?(-EGnT9)wk-(s&_ttt6d@P5Fv>Q&-ZNnho( z%onsJog796=G!!{weAl_SjqidY=RX0Xm;x;>xqxt3C+j9=V)v0FIr@qf6+d~SZZbV zlmEyg-O3sNQtb}Z&xI*I3${kkLybO%oKW$NJFLLRWHU=s(F{`=X8bSq|JtpA*_;{$ z-WomXK3Nu?2S{l1gcspU>toG{Nyo~tN>*bK`?CdWW2y#p>Xab2o1P4_jj*{|C^69p zP?wu0uy0?i4hHMOgxNYCeg1O}{q0sdG`2XbFUo8h6QI~qrXREH8l^Ay^&~kIBbu(WJ-0Ui@Al3=c9&7uqVLN&Dlagv43i0mk00Lz5U6uEN{Owr{zrKT zpz865VI00UtLFhuVrvH4`RGrMEvr+x*Xo$}^hUVY%I!reQihjHHysyt2qxET{4ux( zix!|zg5Ehf)11yz!ozKG7f7(%cC`fhwS+~tfNFqS=@^J_5NFX0#o zHaMX57c%rjUiI-g4{_lZSx(OiEH!Q++&ej_2%v$1V*k+k&LNqZA0iptR2$(F4?y?4 zK*(Cj-c=++QU3rdlh^scoAS#m^0E#Ne?}~0KZDV22Vtlse_w{cUGWztN=_aBhfa5G zp*(eKk>*WJTcNp$&qs7!YoJ2C*V)CmvSpSafOw1?WN7#k8^Pfo?1k!k$iN9lI~k04 zVcoQifi|i30;tuD?Hz#=&N|@+f@zv8?g5;|$pCKib#_D+obUjJ8-V{l=LxI1aO54O zLN8h%q|C>;i52HP5xz!4008%qP4xQVfA)yqgFz8Z(205gtA)Cg0Gk#k=^rU$TmcB% zQmn0hGZDf81nYl4A>W9_K;4o6tS_O^xQ$(S*D4HL>39c{Aw%BUGkXj4xyz#eZs6ZMysGmOBr|&&) zZorf^H;5ZBM;$j)PD7rXF9Pw(!KE~HpHoyu7pXyU9QEHmwR41WU}*4tn>g7(PLwI~ zG`}RU2x3x7TX~u8&JnB(jre^)vMOV!c(TCcE1;@!TWJdh=QZGs$AK|{% z7dC=VWy0#Xd-!P=S?*gsYY*xy0;5!ZI5F&P0?D=_WgHrpMzG1Ku&UV^w6`)-O8OSAT5_^m#Ke)%i8_%oZ;gJJKJ@ z%@gSDx+AB0u?Mftt4_OtJOhO|`8(?#?6s`Hm1h18?8b>L+DkDKea$<3sQi>+q7w?$ zl?f;RO;Kvwn?&y)3R7G%q^T}_zWlO#IX`u8Mz*jcCv;o-U}d|KnvQJrNia6%0wFQB zc?8e*Kmu$vkCaV+nxtYACFmv-mNMk^pPgU7wt=0icZ5h&zP|xs+YV+4-SYIECvJp~ zvu0wCo;LrRsZ8G=Y8WY_f)-ny9cjTguAz|{*HR|CHBQ_c?|fi) zgNk(dSw~LX8*2VT(mu;%nJ5A2JWdV#;RlJ1c=ByDojXFUf z1!rolMSF=ThbPZbq|IRk?aX6~>kj4|#BHSDE-2~@@uYc6U6^?H?%kKW_L;Zu z&_-vNgfHR3%J)}XUrk=bgx0yJ<~J>KoUx3AO4wD3)K{x)AsnA#{&=;-#m}Q zQ3G<23A^OJ3?MqO(DpM)PQLNBqMjup+lrx{@ghOR%9j??xw)7sUJq}c-kk~EvBmW| zrs}f<*-8=a_|i&?*260wE39=p?gQlJ{f0n#;#K8gd4EDy8Q+ie5Mv39?=>p$Wqok( zUyEgQ_8w9Mz0+&5_bmluvP5H$`_{R9o>QbMM#~qtz zTmtOH;vJkyE0VY>@FxH!yjNJGLW9XgXAlZf3KXa@GWMB5RqsA}o-s6?Sj|W^zo+F6 z-8pxrq2#vWNwSd-i4_>B`nCRD=sk}hSj{jX3JIa^3|`q75Gfz z{IS<59ew!HiZ^w3J8vuS-G|ft`@~*mC@Aar>2|sGdCfDvXH>)oc-?D2U?nh+L|&gc zm-pbg&{ZR$eS_zZecP;Pl=BJJwi4Z(vW0mC2HbvzkF^I*@TZRY46c#fBLbe~rWOa) z54~g0QQdkIa<&;a*pWfl)5$uwvypJLRT0Q z&dlETBP}JFAjMtysJ`(l{-^7-;z4W+O~dkTDZpX$K*V?e3z(pmroEvF^c!@1TXUqE zUZt9jEFT2wr}uQb^Zg%L9bImOTqXy~e}hz|WQxbgYP&NWo{@k;H365@2gj9HqVT4| zVF%02WC=+@l2YQ9ThCd_Zc_2URn`Xvo`X*`qnNG*dhOVICJ;N>-Vk#zlzwW0WO10d z`4s@1Z$sAfr@yi1>b79eZ7pie2Hn&U){L!L1^9;Yu2~yu>7!n;s=hWe`4LCifu-AFClH7|FQB6xV>L&o3T@lf%sxERj)qr0pA{h1+q zz`*PdX?K^rl`f>=@9RFNbmHTZVcf8Cz9#ogJWq0UqJLEN~FVhL=*Z@Hj?Voodi{COohf9az?!|l%02!eZrb_`s?q!f>>eNrChECtAj^2( z^99|X$p+GfCmv9R|LjGV{@qtx3cI&LdEJpX06(+0?-ADa?BOvlKaU*#*${a4xPtNr ztGo|f_)w|bbBK<(E7#~-_KN6)6?lMg1$3DsaOHc!%UEIK;);EXA6)z?0OfLQ7=jKB z;xOw0p3#r+uSRq%ao1JrL#w=6XbWPw*i=PLjA1zf3*O5 zBLGu{fmwyrHp{i-why!TK*camypJM-CtlqeAswd#TG~Erj&Ka25?S~HwrxD~!4qFS z=sQ;mQ+m-+*8cUaCqA}>Sn*EK*XrQH1w@DU&OKO-z0*Yk&k&4T%bHQ*Y#RHO=L|G- zudT=Q<+|G?acSB=QcUwBv^AbAbPLqbOx7nqWvdyWF`%Zpm6o6NgBpp&%gwjcpt3zf z7Xl8Xm%qz)IB9i?sr&|Q7N}a~u%{n`EDpTMQgJ!QLl%Xd!m@V1f15kFxdnYZW2fKezAbmo< z`|RqG?}vi2i}k&R4w2rId*5M}ZSR|NigimgeDk1jkV9zAS>krO0veq>ragI#Ij(jE zH2CYinL;UDXgQ*#~Cxebjx}5slFS6W5quVKLvd4&P z;_Ww#8`&afn>e1K2r^}=V6LYj>yBxQc&mfdZ1b!0^*_p{LE@0_Gv(#tHpw@_n(LwU zb8EqTQ_&bLal1;{qt>z`LQgF-PlpM?LXo;)`Z|l8y|Bis!aQK zohI*5@NDDQ-v0c9A3?hE9IAwy&7)33fu6bwuq>I}zH4q~)2*7aQlQq_b4FM5U$r{J zfWJpTEB57Hte%e9E3~{NH>ZKe@lp36qUM4eU13{mId9X6X9UMeYVr>K{#y$ON|yp| zQOTW-5KHJit&S{n>LJy=vcUhFQuUW}$=2a|q@ZF%9#XidX(BC(Jz1l9t;<~cah4Af zl87JGVAz@2a5?`F>hL=ca!7UZu#0|-eK%Y$E^re@kNvbyIfpwuHOWmlG}5c)r*6if z$^pe?tb1&n@&5cEMdQW5#}x^rxM8M#SeW;>%KnIHlgOC9zdX!Yixyc70fq?rJVIl& zUEpL_*w4lXC7(Gxo}TUWwR(Dbpz9CqVYAz>nXg}-`t6L0QJyWh`!u&k!zGWKlx(Ue zH7}%1yY{W!X;=;)AmX&Zjh|T!VN|BCCD!8!mcJ&nJ zq9-q$Og4VIZi^=}#i*ozU|LQNhiGut8K2c&-|G3Y=0Fxu&!q>5(l-OZKM4b)#r}t{ zZi51@5$*5Z|E+HOrLK;}RH4noHU6ZFZ?@hm?qi>D1yRdC*nAf!+1NK|{4)6w0ynm5 zk*>|SXwmb&G{I$@zC0Cpm*)yIjKY_T)61q9$LdmIT6joty-ucW0Up+J@o6e0FKEV| z#280M=knzFZ}2`b;tJPC8E|o0!ED7}qca9(oPaNM1Wv*}%&hz$yIj5FDa+kuj-G=! zrUri_p2)%_478VAHV#e>+8sJW*Qtdea$gn>lZv@4J=)$?@I=d*Ic4~7--*7ooV^!7 zyHddLIt@Ujx*zQ@v=Ec7=NZ5tX6B!ebBnGW5>dH!nPrA3wp*DkmLP${@iT8q>a$M& zkWJ}`55E6uSxP_}_tq32_K09blc&b1qtD5)Td1cv)zQEbA!#aF0G)c=SjG5VWXN}M ztN(R|m5f8!U+4OlL1VA=hIJGBfz;st$gIzK8eFBAkDd!3J-~RC6C`7MG205&^Y&h8 z$Dnf2LOn4lQq0Y>d0l?jKm*|xnSa@bnQ+OUbKm^=7GBK3RDt*U#b|$CP(?BtXUgxS zFD9vWCgFmLfsNOhGG^`Rl4STmhs|MEy`^Jkz3#gTyX4&$^mT;;S5N^O+1;AjI=5&O z(v6yx7qLFu5?5WB_0?b=wsm`Sg3iL9gQ2!Kv4<|_pFR4nivu-EZoyL^3IHC|+Paxi zf%gFZbmSvXeO7U_c5BiBjfz{e)&q8)*T?A-x%3#TBxy}xbfO96)9lE|mydiCw2pG= zDa2N#x0hT60h#w9y%?>Sibw_D>kqAfG0*DZsir4A0-m$#xdh!tvfh_8P&BcOHzIU# ze{yHPDxxoUy^~2Gk9|xo2Dq=e$zuoy`ist&_y4!kR8g(^E&a0eUV z-fh~I>n6Um9lP~#rozXgPNYubq;K1=iy7n6cd^PEH%J_+8-uyUD+qiQdr;pOtJ0tw zAP#WBK$qKy#S=gDC1&{<;srGWY@BBg+x)jg^;zqc;p~|ZNl8$e;tOX0f3ffCB3(c5 z&2E2TjFS3SmZ^lg^i(pNj?cE>nm?Zqc}vpt=L< zOiOPTqfq{Tm|{BY|5q5$MdB)aeDvsw$$fN<>dhuDecm}5uA^#phO_YgCByt$tWrn$PI+!Ud(Sc{N9&P zCbOY_>gi<6@R^2j;Pp>e)1;io-C0U+raVaMAJjlbqE-ULc=D1uWeW|iv!GwA8U4ET zy0G)HqLj29(atpTa6;9Oiu4&M)>ln#WSzmeFhLJ}uLfIGd8}H{u?z#3j^pjah3D+)#1FO=nWirvQ%Ej%gm#!42-0eima%%|98xUdsFSorfO%-jX zJ`!~o>oehGpOamp!KeB0-q$c@l5tWf<23MpFL)MuPC%+rXp~nOv}!N7;-HhCwZ$8b zYgKT6Zo3Q5{`q=G5-X|x%p;CiqNnqPcZ$p7wChx-JtEWPIfGPdmZJX z?yR7#=X7I{x{*PCb_e9)UY@5AQ|}o5bgKMmcQH|cMK${P&I7KnZr5(^(4h5(&87Yw zw-}D1IJzVzV)fu)8ycN$FMn`-BlVg{qLL8WOiTLIohwayWcqy1Nn)!&_*2Gk)4Xio z(}nEBkMHR@rnI6S_5WrPXBF4b{q(|^IZ~Ya0xeEoF8*RZqiB4NuC{H13@+sige4~J zxfgJpm_UhLHR4j6uyeR?nR4}=%<7ZaoM4b#J7ku&9O)m;9ZCd_q^9jfEx`M^550WRAlhof6J}Zm9T0v|NB8 z{1t~%B+Z;~GX_)h8KmtMVVM%_a$O}bG*-8b-tNvh$2{)aPs75)zTJ;!#&HPX6zmm7s(HS|8Y0W=kRG!SH>eL!X?tjWS z;6Y<=U8|K|sUp%CU0tAew-NWYH5)FK>a)?}k%x8CzOdD}fJl&!iQ+MH@8@Trb)T*f zR54KeWXVl?`>K4y3sXI5mD2;v=onHVsnBx5ll%pPaRSj=ku=MdTKI(ffl0*S81or7 zlZVe`n_n#!*Ji)lGm5){mq1!gqVK(Je%d^B(Fg9Epl8nV(fL|+%2BDzf-XTzPJQ;) zYg({Gt}~_#viXBYZ(JT^rZ}H}{?zy8iMb_fVxe?g;r*wdW0j8V>?jmAPU)!6UY|BQ zdk|VW!O>j5HrKqgsS}TWR{pC&!|7n?0^HVEw3zP96Xf;6wI3rV$y=MwK798ZH!saZ zIIj4(kL1IcjU(}8S3u1<@y?HULC5%qkvnzY1+q6M+9rHPi0eT$zT_RU=AxWqVwwNW zoI`WD5zF56tx3|x&V>8$n&+h;AgHh_7q-~@n;R|5n%>F1^qKT_rM+lY9s*>S1 zPgYIMp@E+`16y@bgeOCP^p(nywmOTb{9K?`n;%FaP-(b zVPd~dW^{1~gbb9#n{SBC`?CTo+k({0L8s0k@}31%ljqxE$-p2US(#w!UFYd#_bE_H z2AV_GFskS3)HTX`;>|^-h1i+UXMmUK?I+z#=>ESqd|| zTRVtzv10PX`*&Da30!$>EtqoN28C0G9limtO3*8_M2IlQDiqSaANWKZ=%l}B#6k+T z1U^=Kx-*+qJVsz$vcpO&mqQv?*rE+ri7zaJ1?p&Hh)WA4u*l(yrYxkyfDqF70Z2bg zs9=yq1*v`s%fWHR#?!USOa7N%mZ)0B7?}Jmn!4n92VSVw5K8Vxs(wToL?f*|l9i>O zSU36=q=*Wq-uj+3#INoCzrx&YCYb&G)v45}ZV?>FI-p;iSv7P5L2%6*%q|8f5e#NY z-Kl6HtoF2<`%rFF@9?|o-jq=4c$H~DD3vuVRz11+LTAnJYsv!a7>X}XXH9$h0g@kR ztTzg(da~|SxE{jYp|L#`NboDHJReACG(Uvi3#NR&O@BiEHZ=k!!H}jLcy7GJnI$gI zH0UYK9I`;Z_Rk7lr~Es(=SzGAxGGUYko0HB?>8$sf#~0FL8z-V8vXe9<)yZv0_EW4 z3%BWqQ-3Kn=&S*a;l)y&wU60h4_5H2B4~-imKzUp@2o8OOXWZb+*OodtQ3gCtsP2N z@I_yL4b8KL1|4S{59<{`_ax@t6zWbWbo|kC;^HlM&@C+kiFlj-LqV55DuCEpzb-5X zbIIBb!$ZPPLN9kYE=+9YF>&_SZhAmNEG9l z9I1S8lMEqAX!N~V-uvv&ilnkGd*53WKcOgmzpN)y;p_W>@@XP9{Wul4D3>7p0c>av z@VA-7ct(^NP98Ut}O zjiSWjC4}S6$Wz~TzXdyelEDS;z{ch^L_y}h+OL`2{d&x|Z&F zvPRVpRoo@Ui#S{X`48;D0+eMt1%hnKZyO=X)k zBluK$iKWrSY9JrPHe^hHCAO_Rqe=}{-}r~VLbqi(wgPPpwracsq*Z|&&FTVBe59CD z3!;Sf)71X_SE5|x!rxg(l$-*^%uA|h=tdoLI7)8~QD1|?<$|)X4+gTPN8>J>fZ5BS zafyMq$h-4b{^~mZD%$LU8pJwH7e}B68kr9?&Qxg&BO?X^_XhfN0+7=Dk>R`uO1z)y z!2^IK=f^!bwfu^%PoG3(+aCf~7yYxN;jbN_n%6Zu&O=1hQxVXZ{@<~XzsEjuVG7Am zTyP?=2h_W748!a}adz6kK@N?>h~1}JO?tXbmFeKa9f87H=lxL(RAiz5*V+l!LwNOd zglt4a|L$iJZ0U~1+Cb&@-&ZAVN#m-?P}egZ?ZW1eU~_C>An)1wfo`H%8SUC+!@-{l zRy{_l_SY~@ZT9y}3~2u5kuSuCk&{bmsvtFjp7wr6Rg&yr`^u+BEZDw&7N;gmY*bJ3 z`qxyCf?k-oG4fOc15`l|WpL9i{MH;%){R7juUoa*!s<^Dy&wEhy#t8=hx5f{fX~^| zLkTQmxcbM4iF#AiQ~39%+<&DbN&W7Oc&b3);VaGUaUhXYT7J9?lDkAiw7x8ichcQD zN(Og*5~S+vvV_4J0;@~90YLOz-t%tgOkNCor#e!uyTYeUzpW@#d|+bVs4S|{aXc2K zq7jeHPZvv+xQS`g&OT&OHU4p}#b_MZP4D47bnZW*gjbfMKG*8UyQyyS@%j3%FRs*O zQ44~d(~O$WfCj{e`UMCd<8z*K0;zy4yf(Ct@@IO_y@&&|7krHj@r$ah$n=H z?-iUx`_@#6?&7cZd1<(JriwpJ!;0jgU0g!r?AQ`s&l_4&(0j zgo!7FG|XZX0XrkS5S~?}LH@A4<9QH)`B{n#v;XDiWtG&dTw3=5p3gcm+`@ z!sz@Ih19J&wmPg-NJ|PAIz%2Swjes^&y>Br--*{e8a7XkCy#IXV?dS&j%(#Km2yaH|rYcL8rtozuzqUHPC8{2zB=# znJ@D!qa(;hSU4|1_Zy<#$QB3IAW+tRtvA9bU&mQO*Po;Q-h0;q8ZlvV29mQ%TG_BZ zA!T>i&qM~oF%Q^!gwiP{-{bO@iTP$;FpO`0q=nNVdPTfWheaR!We}LVwz%mJqvxD# zn0zml}P`H!RYUO23Gs_Ne)HJBL38 z?xa4WP9R<&T*0d^u%yWlt%DIFPsRVxF*m{{sHShyy>GVayy>{9G%lnZueCsJnP5Z{ z-yLYASX1;{P7-)aaJB`+J5s7iAl4r>d(tQ5dm|W86 zcvDFJTXyhf&iP?k<}OsuOCg5e@E$p*bnuCsF|QHeSqkJxs8~ky_whf#do%_=^bw}I z7)p;L3a}~4r0a&FF6H_P_BTuYa|S&|y@C!lJ;WmeSXcefnaxq_{Pd2XAyi&!9a#LA z%s?;mp8{)Cj*+mTUL~)^&X3{Oo*dvt^mXsF_?d2ERMpp$9JB53Cwh>L6jff}X-UQR z4jyDErXfDJPxa0@nO%*G0rLkV5u^O(vo5G#Q1&yH>pFVH$*R*%F2G@2y1ze@bC3A~ z52^dh*Ekdurk|9(@XEyNxb6`kyP!XP(u?KqdbAquBF`n^CdvFw$BPGb`#VZPlzW7Y zkKVry{(NnD(Zn_41t-Pkj2TPBuk9QlIS|Pjoh(Lg+v7!qz^bx=b5~vm`;_zWs}2tv z>4=cRnr)jl5TswH)@bY*d)5&o@+LdVdq}0S)Ah|YRYb19Nm|kC%wr<2sA~qpv6qmy zz2yF(E3sbh!WU(B&f^c2Uq}k7bSmYbCaXsf$m{kFW1nIbCVp+vo_+JN)gV)ASFYg0 z+}=sRaItks)8BH}sNVdTb~dXi*wy^w^IDA)HB<>{q-#3PPvrw4LM+FR2~#OYNTc)# z>^OCO*~B;Rsk%yfASk2k(`#BHV*+?3W`#MbF_3r={0PhHI->sDi!imb4)*qb$hk4^ zH7(u1wwKvD&jj^F66MF{hluSh>~-JOl`uLMde7GO?R1YXqg%`W=GZBu9_gloA(ycg z4JzjE{m>1)_h<0f@ZrBc{wNuP1u#EG)z6LtdE3azv2X6wh$h7DZ0KEO{6F2ss!#3O zx3ZSPP76+zw&UaDK+~p5?QHnBbB@Doxk^B@1vnajj7z|YANt`$0IVt8R6L$kxDTxa`jfZr z{xjxqML7yrG(&>LG422nD>FABFF?=r0H{#4MEHQ^q|WhU2b08>kU4tg^z*CbD2PLu zTb=|1sw?~NY=j`|rc?}6_v~B9B0XdYRI4*IzE4qlp9O3$hni!ze`oEFkAEK@gdOgo zKZ6aPW4L7VcY%mWq~z7#Lx0`3qfDzzua?i?UkzV=Jl%|1{4<&49+G%66Sn)f1InQFD{)A+`jqp^qV)wscT90BK3Gx zy?;>`3s7=Xr>psdH3h*bGiWgbUVrajrT;b+6aKq^t|1}E_<{QnbyXC$*um~Qi2(?u zD-p831>AH7R}Jx2QhCv9Nex0~^Q(^Eo?HgF_CFUU37OC+uYl%ax-uBp6v~&QYNr4e zdl4Cc3^Ww@p=kU4Mo_lBXl_;&K~yc_jxxya$B8b|voAnT>w%aOrPrpt@@HY-V9BVr zTkjcuTDrytcXY1iw0N%d>2>Y`hBjP=!IeuU8&1k1{b zEM3eK6{We{(=tA38(-`7)8_`zdh1|g--VqYv*B6wVzq5E7!JBck2B1!@=a3k(w-0t z4w)qh^Gmpod|WQXLdH9(qe-yC0&Y7n2se0h@s&WL%1g;hA4JVy{ere!&$SrADcaOi z?p`L|vhVZ2K-a#Uo7)^Up5_#d4}W1G+{teJ%)x=WYCUD$iB literal 0 HcmV?d00001 diff --git a/1.15/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json b/1.15/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json new file mode 100644 index 0000000..c519f37 --- /dev/null +++ b/1.15/src/main/resources/data/engineersdecor/recipes/dependent/labeled_crate_recipe.json @@ -0,0 +1,58 @@ +{ + "type": "forge:conditional", + "recipes": [ + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:labeled_crate", + "required": ["#forge:rods/iron", "immersiveengineering:crate"] + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" + ], + "key": { + "R": { "tag" : "forge:rods/iron"}, + "C": { "item": "immersiveengineering:crate"}, + "F": { "item": "minecraft:item_frame"} + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } + } + }, + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:labeled_crate", + "required": ["#forge:chests/wooden"], + "missing": ["#forge:rods/iron", "immersiveengineering:crate"] + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "RCR", + "CFC", + "RCR" + ], + "key": { + "R": { "item": "minecraft:iron_nugget"}, + "C": { "tag": "forge:chests/wooden"}, + "F": { "item": "minecraft:item_frame"} + }, + "result": { + "item": "engineersdecor:labeled_crate", + "count": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/meta/update.json b/meta/update.json index 6099951..9b4380d 100644 --- a/meta/update.json +++ b/meta/update.json @@ -2,13 +2,15 @@ "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "promos": { "1.12.2-recommended": "1.0.19", - "1.12.2-latest": "1.0.19", + "1.12.2-latest": "1.0.20-b2", "1.14.4-recommended": "", "1.14.4-latest": "1.0.20-b1", "1.15.2-recommended": "", "1.15.2-latest": "1.0.20-b1" }, "1.12.2": { + "1.0.20-b2": "[A] Backported Electrical Furnace GUI speed selection switch.\n[A] Backported Labeled Crate (storage crate with built-in item frame).", + "1.0.20-b1": "[/] Version skipped for 1.12.2.", "1.0.19": "[R] Release based on v1.0.19-b4. Release-to-release changes: * Transfer fixes for Tree Cutter / Block Breaker, and Factory hopper. * Cleanups, feature backports * Visual fixes and improvements\n[A] Backport of status display for Tree Cutter, Block Breaker and Solar Panel.", "1.0.19-b4": "[A] Creative tab opt-out visibility handling added (issue #90, thx pimalel233).", "1.0.19-b3": "[A] Factory Hopper: Added bottom item handler (CR#227).",