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 0000000..2e4f4fb Binary files /dev/null and b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_front_texture.png differ 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 0000000..17f92ed Binary files /dev/null and b/1.12/src/main/resources/assets/engineersdecor/textures/blocks/misc/labeled_crate_side_texture.png differ 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 0000000..e41e8a3 Binary files /dev/null and b/1.12/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png differ 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 0177a21..0fdd087 100644 Binary files a/1.12/src/main/resources/assets/engineersdecor/textures/gui/small_electrical_furnace_gui.png and b/1.12/src/main/resources/assets/engineersdecor/textures/gui/small_electrical_furnace_gui.png differ 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 0000000..2e4f4fb Binary files /dev/null and b/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png differ 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 0000000..17f92ed Binary files /dev/null and b/1.14/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png differ 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 0000000..e41e8a3 Binary files /dev/null and b/1.14/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png differ 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 0000000..2e4f4fb Binary files /dev/null and b/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_front_texture.png differ 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 0000000..17f92ed Binary files /dev/null and b/1.15/src/main/resources/assets/engineersdecor/textures/block/misc/labeled_crate_side_texture.png differ 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 0000000..e41e8a3 Binary files /dev/null and b/1.15/src/main/resources/assets/engineersdecor/textures/gui/labeled_crate_gui.png differ 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).",