1.12: Backported E-Furnace/Labeled Crate from 1.14/1.15.

This commit is contained in:
stfwi 2020-03-21 18:00:37 +01:00
parent 27a957ba8d
commit 41b48208a0
55 changed files with 2556 additions and 34 deletions

View file

@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx8G
version_minecraft=1.12.2 version_minecraft=1.12.2
version_forge=14.23.5.2768 version_forge=14.23.5.2768
version_jei=4.10.0.198 version_jei=4.10.0.198
version_engineersdecor=1.0.20-b1 version_engineersdecor=1.0.20-b2

View file

@ -1,6 +1,8 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.12.2": { "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": "[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-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).", "1.0.19-b3": "[A] Factory Hopper: Added bottom item handler (CR#227).",
@ -82,6 +84,6 @@
}, },
"promos": { "promos": {
"1.12.2-recommended": "1.0.19", "1.12.2-recommended": "1.0.19",
"1.12.2-latest": "1.0.19" "1.12.2-latest": "1.0.20-b2"
} }
} }

View file

@ -10,7 +10,10 @@ Mod sources for Minecraft version 1.12.2.
---- ----
## Version history ## 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: - v1.0.19 [R] Release based on v1.0.19-b4. Release-to-release changes:

View file

@ -210,6 +210,13 @@ public class ModContent
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16) 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( 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( private static final TileEntityRegistrationData TREATED_WOOD_CRAFTING_TABLE_TEI = new TileEntityRegistrationData(
BlockDecorCraftingTable.BTileEntity.class, "te_crafting_table" 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( private static final TileEntityRegistrationData SMALL_LAB_FURNACE_TEI = new TileEntityRegistrationData(
BlockDecorFurnace.BTileEntity.class, "te_small_lab_furnace" BlockDecorFurnace.BTileEntity.class, "te_small_lab_furnace"
); );
@ -530,6 +540,7 @@ public class ModContent
private static final Object content[] = { private static final Object content[] = {
TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE_TEI, TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE_TEI,
LABELED_CRATE, LABELED_CRATE_TEI,
SMALL_LAB_FURNACE, SMALL_LAB_FURNACE_TEI, SMALL_LAB_FURNACE, SMALL_LAB_FURNACE_TEI,
SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE_TEI, SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE_TEI,
FACTORY_HOPPER,FACTORY_HOPPER_TEI, FACTORY_HOPPER,FACTORY_HOPPER_TEI,
@ -704,6 +715,9 @@ public class ModContent
if(!ModConfig.isOptedOut(TREATED_WOOD_CRAFTING_TABLE)) { if(!ModConfig.isOptedOut(TREATED_WOOD_CRAFTING_TABLE)) {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.BTileEntity.class, new ModTesrs.TesrDecorCraftingTable()); 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)) { if(!ModConfig.isOptedOut(TEST_BLOCK)) {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorTest.BTileEntity.class, new ModTesrs.TesrDecorTest()); ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorTest.BTileEntity.class, new ModTesrs.TesrDecorTest());
} }

View file

@ -161,6 +161,7 @@ public class ModEngineersDecor
public static final int GUIID_FACTORY_DROPPER = 213105; public static final int GUIID_FACTORY_DROPPER = 213105;
public static final int GUIID_FACTORY_HOPPER = 213106; public static final int GUIID_FACTORY_HOPPER = 213106;
public static final int GUIID_FACTORY_PLACER = 213107; public static final int GUIID_FACTORY_PLACER = 213107;
public static final int GUIID_LABELED_CRATE = 213108;
@Override @Override
public Object getServerGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z) 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_DROPPER: return BlockDecorDropper.getServerGuiElement(player, world, pos, te);
case GUIID_FACTORY_HOPPER: return BlockDecorHopper.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_FACTORY_PLACER: return BlockDecorPlacer.getServerGuiElement(player, world, pos, te);
case GUIID_LABELED_CRATE: return BlockDecorLabeledCrate.getServerGuiElement(player, world, pos, te);
} }
return null; return null;
} }
@ -193,6 +195,7 @@ public class ModEngineersDecor
case GUIID_FACTORY_DROPPER: return BlockDecorDropper.getClientGuiElement(player, world, pos, te); 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_HOPPER: return BlockDecorHopper.getClientGuiElement(player, world, pos, te);
case GUIID_FACTORY_PLACER: return BlockDecorPlacer.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; return null;
} }

View file

@ -38,9 +38,11 @@ import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.detail.Networking;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Random; import java.util.Random;
public class BlockDecorFurnaceElectrical extends BlockDecorFurnace 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); drawTexturedModalRect(x0+79, y0+30, 176, 15, 1+progress_px(17), 15);
int we = energy_px(32, 8); int we = energy_px(32, 8);
if(we>0) drawTexturedModalRect(x0+88, y0+53, 185, 30, we, 13); 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) private int progress_px(int pixels)
@ -153,10 +162,33 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
return k; 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 public static class BContainer extends Container
@ -274,7 +306,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
// Tile entity // 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 TICK_INTERVAL = 4;
public static final int FIFO_INTERVAL = 20; 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_ENERGY_CONSUMPTION = 16 ;
public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT/100; 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 energy_consumption_ = DEFAULT_SCALED_ENERGY_CONSUMPTION;
private static int transfer_energy_consumption_ = DEFAULT_SCALED_ENERGY_CONSUMPTION/8; private static int transfer_energy_consumption_ = DEFAULT_SCALED_ENERGY_CONSUMPTION/8;
private static int proc_speed_percent_ = DEFAULT_SPEED_PERCENT; private static int proc_speed_percent_ = DEFAULT_SPEED_PERCENT;
private int burntime_left_; private static double speed_setting_factor_[] = {0.0, 1.0, 1.5, 2.0};
private int proc_time_elapsed_;
private int proc_time_needed_;
private int energy_stored_;
private int speed_;
private int tick_timer_;
private int fifo_timer_;
public static void on_config(int speed_percent, int standard_energy_per_tick) 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_); 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() public BTileEntity()
{ super(); reset(); } { super(); reset(); }
@ -326,7 +365,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
fifo_timer_ = 0; fifo_timer_ = 0;
tick_timer_ = 0; tick_timer_ = 0;
energy_stored_= 0; energy_stored_= 0;
speed_ = 0; speed_ = 1;
} }
public void readnbt(NBTTagCompound compound) public void readnbt(NBTTagCompound compound)
@ -339,6 +378,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
proc_time_needed_ = compound.getInteger("CookTimeTotal"); proc_time_needed_ = compound.getInteger("CookTimeTotal");
energy_stored_ = compound.getInteger("Energy"); energy_stored_ = compound.getInteger("Energy");
speed_ = compound.getInteger("SpeedSetting"); speed_ = compound.getInteger("SpeedSetting");
speed_ = (speed_ < 0) ? (1) : ((speed_>3) ? 3 : speed_);
} }
protected void writenbt(NBTTagCompound compound) protected void writenbt(NBTTagCompound compound)
@ -602,6 +642,19 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
return super.getCapability(capability, facing); 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 ------------------------------------------------------------------------------------ // ITickable ------------------------------------------------------------------------------------
private boolean adjacent_inventory_shift(boolean inp, boolean out) private boolean adjacent_inventory_shift(boolean inp, boolean out)
@ -646,14 +699,24 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
// returns TE dirty // returns TE dirty
private boolean heat_up() 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; if(burntime_left_ >= (HEAT_CAPACITY-HEAT_INCREMENT)) return false;
energy_stored_ -= energy_consumption_; energy_stored_ -= energy_consumption();
burntime_left_ += HEAT_INCREMENT; burntime_left_ += HEAT_INCREMENT;
this.markDirty(); this.markDirty();
return true; 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() private void sync_blockstate()
{ {
final IBlockState state = world.getBlockState(pos); 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_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(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_; final ItemStack last_inp_stack = current_smelting_input_stack_;
current_smelting_input_stack_ = stacks_.get(SMELTING_INPUT_SLOT_NO); 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_)) { if(!current_smelting_input_stack_.isItemEqual(current_smelting_input_stack_)) {
proc_time_elapsed_ = 0; proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_); proc_time_needed_ = getCookTime(current_smelting_input_stack_);
@ -700,7 +768,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
} }
if(isBurning() && can_smelt) { if(isBurning() && can_smelt) {
if(heat_up()) dirty = true; 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_) { if(proc_time_elapsed_ >= proc_time_needed_) {
proc_time_elapsed_ = 0; proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_); proc_time_needed_ = getCookTime(current_smelting_input_stack_);

View file

@ -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<ItemStack> stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
public LabeledCrateTileEntity()
{ reset(); }
protected void reset()
{ stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY); }
public void readnbt(NBTTagCompound compound)
{
NonNullList<ItemStack> stacks = NonNullList.<ItemStack>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> T getCapability(Capability<T> 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)) {
// Crate slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((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; }
}

View file

@ -27,6 +27,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.blocks.BlockDecorLabeledCrate;
import wile.engineersdecor.blocks.BlockDecorLabeledCrate.DecorLabeledCrateBlock;
import wile.engineersdecor.blocks.BlockDecorTest; import wile.engineersdecor.blocks.BlockDecorTest;
public class ModTesrs public class ModTesrs
@ -82,13 +84,58 @@ public class ModTesrs
} }
} catch(Throwable e) { } catch(Throwable e) {
if(--tesr_error_counter<=0) { 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()); ModEngineersDecor.logger.error(e.getStackTrace());
} }
} }
} }
} }
//--------------------------------------------------------------------------------------------------------------------
// Labeled Crate
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
public static class TesrDecorLabeledCrate extends TileEntitySpecialRenderer<BlockDecorLabeledCrate.LabeledCrateTileEntity>
{
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) @SideOnly(Side.CLIENT)

View file

@ -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":{} }
}
}

View file

@ -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 \ 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. \ 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. 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.name=Treated Wood Side Table
tile.engineersdecor.treated_wood_side_table.help=§6Needed after the work's done. tile.engineersdecor.treated_wood_side_table.help=§6Needed after the work's done.
tile.engineersdecor.iron_inset_light.name=Inset Light tile.engineersdecor.iron_inset_light.name=Inset Light

View file

@ -108,6 +108,8 @@ tile.engineersdecor.treated_wood_crafting_table.help=§6Прочный и уст
  очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании \   очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании \
если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. \ если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. \
Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке. 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.name=Столик из обработанного дерева
tile.engineersdecor.treated_wood_side_table.help=§6Нужен после того, как работа выполнена. tile.engineersdecor.treated_wood_side_table.help=§6Нужен после того, как работа выполнена.
tile.engineersdecor.iron_inset_light.name=Встраиваемый осветитель tile.engineersdecor.iron_inset_light.name=Встраиваемый осветитель

View file

@ -107,6 +107,8 @@ tile.engineersdecor.treated_wood_crafting_table.help=§6坚固防风防雨。
单击上/下箭头按钮可选择合成历史单击输出格自动放置物品单击X按钮\ 单击上/下箭头按钮可选择合成历史单击输出格自动放置物品单击X按钮\
清除合成栏和历史。Shift单击一叠物品合成格空时转移到存储格\ 清除合成栏和历史。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.name=防腐木茶几
tile.engineersdecor.treated_wood_side_table.help=§6干完活后需要喝杯茶。 tile.engineersdecor.treated_wood_side_table.help=§6干完活后需要喝杯茶。
tile.engineersdecor.iron_inset_light.name=嵌入灯 tile.engineersdecor.iron_inset_light.name=嵌入灯

View file

@ -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]
}
}
}

View file

@ -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
}
}

View file

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Before After
Before After

View file

@ -5,4 +5,4 @@ version_minecraft=1.14.4
version_forge_minecraft=1.14.4-28.2.3 version_forge_minecraft=1.14.4-28.2.3
version_fml_mappings=20190719-1.14.3 version_fml_mappings=20190719-1.14.3
version_jei=1.14.4:6.0.0.10 version_jei=1.14.4:6.0.0.10
version_engineersdecor=1.0.20-b1 version_engineersdecor=1.0.20-b2

View file

@ -11,6 +11,9 @@ Mod sources for Minecraft version 1.14.4.
## Version history ## 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 - 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%). 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). [A] Added Steel Mesh Fence Gate (single or double height gate fitting to the Steel Mesh Fence).

View file

@ -587,6 +587,12 @@ public class ModContent
} }
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_fluid_funnel")); )).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( public static final BlockDecorWall CONCRETE_WALL = (BlockDecorWall)(new BlockDecorWall(
@ -655,6 +661,7 @@ public class ModContent
private static final Block modBlocks[] = { private static final Block modBlocks[] = {
TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE,
LABELED_CRATE,
SMALL_LAB_FURNACE, SMALL_LAB_FURNACE,
SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE,
FACTORY_HOPPER, FACTORY_HOPPER,
@ -750,6 +757,11 @@ public class ModContent
.build(null) .build(null)
.setRegistryName(ModEngineersDecor.MODID, "te_treated_wood_crafting_table"); .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 public static final TileEntityType<?> TET_SMALL_LAB_FURNACE = TileEntityType.Builder
.create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE) .create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE)
.build(null) .build(null)
@ -827,6 +839,7 @@ public class ModContent
private static final TileEntityType<?> tile_entity_types[] = { private static final TileEntityType<?> tile_entity_types[] = {
TET_TREATED_WOOD_CRAFTING_TABLE, TET_TREATED_WOOD_CRAFTING_TABLE,
TET_LABELED_CRATE,
TET_SMALL_LAB_FURNACE, TET_SMALL_LAB_FURNACE,
TET_SMALL_ELECTRICAL_FURNACE, TET_SMALL_ELECTRICAL_FURNACE,
TET_FACTORY_HOPPER, TET_FACTORY_HOPPER,
@ -872,6 +885,7 @@ public class ModContent
public static final ContainerType<BlockDecorFurnace.BContainer> CT_SMALL_LAB_FURNACE; public static final ContainerType<BlockDecorFurnace.BContainer> CT_SMALL_LAB_FURNACE;
public static final ContainerType<BlockDecorFurnaceElectrical.BContainer> CT_SMALL_ELECTRICAL_FURNACE; public static final ContainerType<BlockDecorFurnaceElectrical.BContainer> CT_SMALL_ELECTRICAL_FURNACE;
public static final ContainerType<BlockDecorWasteIncinerator.BContainer> CT_WASTE_INCINERATOR; public static final ContainerType<BlockDecorWasteIncinerator.BContainer> CT_WASTE_INCINERATOR;
public static final ContainerType<BlockDecorLabeledCrate.BContainer> CT_LABELED_CRATE;
static { static {
CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType<BlockDecorCraftingTable.CraftingTableContainer>(BlockDecorCraftingTable.CraftingTableContainer::new)); CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType<BlockDecorCraftingTable.CraftingTableContainer>(BlockDecorCraftingTable.CraftingTableContainer::new));
@ -888,11 +902,14 @@ public class ModContent
CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace"); CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace");
CT_WASTE_INCINERATOR = (new ContainerType<BlockDecorWasteIncinerator.BContainer>(BlockDecorWasteIncinerator.BContainer::new)); CT_WASTE_INCINERATOR = (new ContainerType<BlockDecorWasteIncinerator.BContainer>(BlockDecorWasteIncinerator.BContainer::new));
CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator"); CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator");
CT_LABELED_CRATE = (new ContainerType<BlockDecorLabeledCrate.BContainer>(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. // DON'T FORGET TO REGISTER THE GUI in registerContainerGuis(), no list/map format found yet for that.
private static final ContainerType<?> container_types[] = { private static final ContainerType<?> container_types[] = {
CT_TREATED_WOOD_CRAFTING_TABLE, CT_TREATED_WOOD_CRAFTING_TABLE,
CT_LABELED_CRATE,
CT_FACTORY_DROPPER, CT_FACTORY_DROPPER,
CT_FACTORY_PLACER, CT_FACTORY_PLACER,
CT_FACTORY_HOPPER, CT_FACTORY_HOPPER,
@ -976,6 +993,7 @@ public class ModContent
public static final void registerContainerGuis(final FMLClientSetupEvent event) public static final void registerContainerGuis(final FMLClientSetupEvent event)
{ {
ScreenManager.registerFactory(CT_TREATED_WOOD_CRAFTING_TABLE, BlockDecorCraftingTable.CraftingTableGui::new); 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_DROPPER, BlockDecorDropper.BGui::new);
ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new); ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new);
ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.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) public static final void registerTileEntityRenderers(final FMLClientSetupEvent event)
{ {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.CraftingTableTileEntity.class, new wile.engineersdecor.detail.ModTesrs.TesrDecorCraftingTable()); ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.CraftingTableTileEntity.class, new wile.engineersdecor.detail.ModTesrs.TesrDecorCraftingTable());
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorLabeledCrate.LabeledCrateTileEntity.class, new wile.engineersdecor.detail.ModTesrs.TesrDecorLabeledCrate());
} }
} }

View file

@ -174,7 +174,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace implements ID
fifo_timer_ = 0; fifo_timer_ = 0;
tick_timer_ = 0; tick_timer_ = 0;
energy_stored_ = 0; energy_stored_ = 0;
speed_ = 0; speed_ = 1;
field_max_energy_stored_ = getMaxEnergyStored(); field_max_energy_stored_ = getMaxEnergyStored();
field_isburning_ = 0; field_isburning_ = 0;
} }

View file

@ -8,8 +8,6 @@
*/ */
package wile.engineersdecor.blocks; 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.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.blocks.StandardBlocks; import wile.engineersdecor.libmc.blocks.StandardBlocks;
@ -38,6 +36,8 @@ import net.minecraft.inventory.container.Slot;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
import net.minecraft.util.math.shapes.VoxelShape; 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.util.text.*;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;

View file

@ -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<ItemStack> dropList(BlockState state, World world, BlockPos pos, boolean explosion)
{
final List<ItemStack> stacks = new ArrayList<ItemStack>();
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<ItemStack> stacks_ = NonNullList.<ItemStack>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.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
}
public void readnbt(CompoundNBT compound)
{
NonNullList<ItemStack> stacks = NonNullList.<ItemStack>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<SIDED_INV_SLOTS.length; ++i) SIDED_INV_SLOTS[i] = i;
}
@Override
public int[] getSlotsForFace(Direction side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, Direction direction)
{ return true; }
@Override
public boolean canExtractItem(int index, ItemStack stack, Direction 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, 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<IItemHandler> item_handler_ = LazyOptional.of(() -> new LabeledCrateTileEntity.BItemHandler(this));
@Override
public <T> LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> 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<BContainer>
{
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)) {
// Crate slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((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;
}
}
}

View file

@ -11,6 +11,7 @@ package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.blocks.BlockDecorCraftingTable; import wile.engineersdecor.blocks.BlockDecorCraftingTable;
import wile.engineersdecor.blocks.BlockDecorLabeledCrate;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderHelper; 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.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import wile.engineersdecor.blocks.BlockDecorCraftingTable.CraftingTableBlock;
public class ModTesrs public class ModTesrs
{ {
@ -48,7 +47,7 @@ public class ModTesrs
{ {
if(tesr_error_counter<=0) return; if(tesr_error_counter<=0) return;
try { 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(); long posrnd = te.getPos().toLong();
posrnd = (posrnd>>16)^(posrnd<<1); posrnd = (posrnd>>16)^(posrnd<<1);
for(int i=0; i<9; ++i) { 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<BlockDecorLabeledCrate.LabeledCrateTileEntity>
{
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());
}
}
}
}
} }

View file

@ -18,7 +18,7 @@ logoFile="logo.png"
[[dependencies.engineersdecor]] [[dependencies.engineersdecor]]
modId="forge" modId="forge"
mandatory=true mandatory=true
versionRange="[28.1.68,)" versionRange="[28.2.3,)"
ordering="NONE" ordering="NONE"
side="BOTH" side="BOTH"

View file

@ -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 }
}
}

View file

@ -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.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": "Slag Brick Block",
"block.engineersdecor.slag_brick_block.help": "§6A gray-brown brick block with position dependent texture variations.", "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": "Rebar Concrete Block",
"block.engineersdecor.rebar_concrete.help": "§6Steel reinforced concrete block.§r Expensive but Creeper-proof like obsidian.", "block.engineersdecor.rebar_concrete.help": "§6Steel reinforced concrete block.§r Expensive but Creeper-proof like obsidian.",
"block.engineersdecor.gas_concrete": "Gas Concrete Block", "block.engineersdecor.gas_concrete": "Gas Concrete Block",

View file

@ -51,6 +51,8 @@
"engineersdecor.config.pipevalve_redstone_gain": "Клапаны: спад красного камня", "engineersdecor.config.pipevalve_redstone_gain": "Клапаны: спад красного камня",
"engineersdecor.config.e_furnace_speed_percent": "Электропечь: скорость плавления %", "engineersdecor.config.e_furnace_speed_percent": "Электропечь: скорость плавления %",
"engineersdecor.config.e_furnace_power_consumption": "Электропечь: потребление энергии", "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": "Клинкерный кирпич",
"block.engineersdecor.clinker_brick_block.help": "§6Кирпичный блок с вариациями текстуры, зависящими от положения.§r\nВыглядит темнее и интенсивнее, чем Кирпичный блок.", "block.engineersdecor.clinker_brick_block.help": "§6Кирпичный блок с вариациями текстуры, зависящими от положения.§r\nВыглядит темнее и интенсивнее, чем Кирпичный блок.",
"block.engineersdecor.clinker_brick_stained_block": "Грязный клинкерный кирпич", "block.engineersdecor.clinker_brick_stained_block": "Грязный клинкерный кирпич",

View file

@ -51,6 +51,8 @@
"engineersdecor.config.pipevalve_redstone_gain": "阀门:红石斜率", "engineersdecor.config.pipevalve_redstone_gain": "阀门:红石斜率",
"engineersdecor.config.e_furnace_speed_percent": "电炉:熔炉速度 %", "engineersdecor.config.e_furnace_speed_percent": "电炉:熔炉速度 %",
"engineersdecor.config.e_furnace_power_consumption": "电炉:能量消耗", "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": "过烧砖块",
"block.engineersdecor.clinker_brick_block.help": "§6一种放在不同位置贴图有不同变化的砖块。§r\n比原版砖看起来颜色更深色度也更高。", "block.engineersdecor.clinker_brick_block.help": "§6一种放在不同位置贴图有不同变化的砖块。§r\n比原版砖看起来颜色更深色度也更高。",
"block.engineersdecor.clinker_brick_stained_block": "污渍过烧砖块", "block.engineersdecor.clinker_brick_stained_block": "污渍过烧砖块",

View file

@ -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]
}
}
}

View file

@ -0,0 +1 @@
{ "parent": "engineersdecor:block/misc/labeled_crate_model" }

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -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
}
}
}
]
}

View file

@ -2,7 +2,7 @@
org.gradle.daemon=false org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G org.gradle.jvmargs=-Xmx8G
version_minecraft=1.15.2 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_fml_mappings=20200225-1.15.1
version_jei=1.15.2:6.0.0.2 version_jei=1.15.2:6.0.0.2
version_engineersdecor=1.0.20-b1 version_engineersdecor=1.0.20-b2

View file

@ -11,6 +11,8 @@ Mod sources for Minecraft version 1.15.1.
## Version history ## 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 - 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%). 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). [A] Added Steel Mesh Fence Gate (single or double height gate fitting to the Steel Mesh Fence).

View file

@ -591,6 +591,12 @@ public class ModContent
} }
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_fluid_funnel")); )).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( public static final BlockDecorWall CONCRETE_WALL = (BlockDecorWall)(new BlockDecorWall(
@ -659,6 +665,7 @@ public class ModContent
private static final Block modBlocks[] = { private static final Block modBlocks[] = {
TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE,
LABELED_CRATE,
SMALL_LAB_FURNACE, SMALL_LAB_FURNACE,
SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE,
FACTORY_HOPPER, FACTORY_HOPPER,
@ -754,6 +761,11 @@ public class ModContent
.build(null) .build(null)
.setRegistryName(ModEngineersDecor.MODID, "te_treated_wood_crafting_table"); .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 public static final TileEntityType<?> TET_SMALL_LAB_FURNACE = TileEntityType.Builder
.create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE) .create(BlockDecorFurnace.BTileEntity::new, SMALL_LAB_FURNACE)
.build(null) .build(null)
@ -831,6 +843,7 @@ public class ModContent
private static final TileEntityType<?> tile_entity_types[] = { private static final TileEntityType<?> tile_entity_types[] = {
TET_TREATED_WOOD_CRAFTING_TABLE, TET_TREATED_WOOD_CRAFTING_TABLE,
TET_LABELED_CRATE,
TET_SMALL_LAB_FURNACE, TET_SMALL_LAB_FURNACE,
TET_SMALL_ELECTRICAL_FURNACE, TET_SMALL_ELECTRICAL_FURNACE,
TET_FACTORY_HOPPER, TET_FACTORY_HOPPER,
@ -878,6 +891,7 @@ public class ModContent
public static final ContainerType<BlockDecorFurnace.BContainer> CT_SMALL_LAB_FURNACE; public static final ContainerType<BlockDecorFurnace.BContainer> CT_SMALL_LAB_FURNACE;
public static final ContainerType<BlockDecorFurnaceElectrical.BContainer> CT_SMALL_ELECTRICAL_FURNACE; public static final ContainerType<BlockDecorFurnaceElectrical.BContainer> CT_SMALL_ELECTRICAL_FURNACE;
public static final ContainerType<BlockDecorWasteIncinerator.BContainer> CT_WASTE_INCINERATOR; public static final ContainerType<BlockDecorWasteIncinerator.BContainer> CT_WASTE_INCINERATOR;
public static final ContainerType<BlockDecorLabeledCrate.BContainer> CT_LABELED_CRATE;
static { static {
CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType<BlockDecorCraftingTable.CraftingTableContainer>(BlockDecorCraftingTable.CraftingTableContainer::new)); CT_TREATED_WOOD_CRAFTING_TABLE = (new ContainerType<BlockDecorCraftingTable.CraftingTableContainer>(BlockDecorCraftingTable.CraftingTableContainer::new));
@ -894,11 +908,14 @@ public class ModContent
CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace"); CT_SMALL_ELECTRICAL_FURNACE.setRegistryName(ModEngineersDecor.MODID,"ct_small_electrical_furnace");
CT_WASTE_INCINERATOR = (new ContainerType<BlockDecorWasteIncinerator.BContainer>(BlockDecorWasteIncinerator.BContainer::new)); CT_WASTE_INCINERATOR = (new ContainerType<BlockDecorWasteIncinerator.BContainer>(BlockDecorWasteIncinerator.BContainer::new));
CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator"); CT_WASTE_INCINERATOR.setRegistryName(ModEngineersDecor.MODID,"ct_small_waste_incinerator");
CT_LABELED_CRATE = (new ContainerType<BlockDecorLabeledCrate.BContainer>(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. // DON'T FORGET TO REGISTER THE GUI in registerContainerGuis(), no list/map format found yet for that.
private static final ContainerType<?> container_types[] = { private static final ContainerType<?> container_types[] = {
CT_TREATED_WOOD_CRAFTING_TABLE, CT_TREATED_WOOD_CRAFTING_TABLE,
CT_LABELED_CRATE,
CT_FACTORY_DROPPER, CT_FACTORY_DROPPER,
CT_FACTORY_PLACER, CT_FACTORY_PLACER,
CT_FACTORY_HOPPER, CT_FACTORY_HOPPER,
@ -982,6 +999,7 @@ public class ModContent
public static final void registerContainerGuis(final FMLClientSetupEvent event) public static final void registerContainerGuis(final FMLClientSetupEvent event)
{ {
ScreenManager.registerFactory(CT_TREATED_WOOD_CRAFTING_TABLE, BlockDecorCraftingTable.CraftingTableGui::new); 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_DROPPER, BlockDecorDropper.BGui::new);
ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new); ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new);
ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.BGui::new); ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.BGui::new);
@ -998,6 +1016,10 @@ public class ModContent
(TileEntityType<BlockDecorCraftingTable.CraftingTableTileEntity>)TET_TREATED_WOOD_CRAFTING_TABLE, (TileEntityType<BlockDecorCraftingTable.CraftingTableTileEntity>)TET_TREATED_WOOD_CRAFTING_TABLE,
wile.engineersdecor.detail.ModRenderers.CraftingTableTer::new wile.engineersdecor.detail.ModRenderers.CraftingTableTer::new
); );
ClientRegistry.bindTileEntityRenderer(
(TileEntityType<BlockDecorLabeledCrate.LabeledCrateTileEntity>)TET_LABELED_CRATE,
wile.engineersdecor.detail.ModRenderers.DecorLabeledCrateTer::new
);
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)

View file

@ -173,7 +173,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace implements ID
fifo_timer_ = 0; fifo_timer_ = 0;
tick_timer_ = 0; tick_timer_ = 0;
energy_stored_ = 0; energy_stored_ = 0;
speed_ = 0; speed_ = 1;
field_max_energy_stored_ = getMaxEnergyStored(); field_max_energy_stored_ = getMaxEnergyStored();
field_isburning_ = 0; field_isburning_ = 0;
} }

View file

@ -8,8 +8,6 @@
*/ */
package wile.engineersdecor.blocks; 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.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Inventories;
@ -37,6 +35,8 @@ import net.minecraft.inventory.container.Slot;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
import net.minecraft.util.math.shapes.VoxelShape; 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.util.text.*;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;

View file

@ -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<ItemStack> dropList(BlockState state, World world, BlockPos pos, boolean explosion)
{
final List<ItemStack> stacks = new ArrayList<ItemStack>();
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<ItemStack> stacks_ = NonNullList.<ItemStack>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.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
}
public void readnbt(CompoundNBT compound)
{
NonNullList<ItemStack> stacks = NonNullList.<ItemStack>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<SIDED_INV_SLOTS.length; ++i) SIDED_INV_SLOTS[i] = i;
}
@Override
public int[] getSlotsForFace(Direction side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, Direction direction)
{ return true; }
@Override
public boolean canExtractItem(int index, ItemStack stack, Direction 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, 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<IItemHandler> item_handler_ = LazyOptional.of(() -> new LabeledCrateTileEntity.BItemHandler(this));
@Override
public <T> LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> 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<BContainer>
{
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)) {
// Crate slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((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;
}
}
}

View file

@ -27,6 +27,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import wile.engineersdecor.blocks.BlockDecorCraftingTable.CraftingTableBlock; import wile.engineersdecor.blocks.BlockDecorCraftingTable.CraftingTableBlock;
import wile.engineersdecor.blocks.BlockDecorLabeledCrate;
public class ModRenderers public class ModRenderers
@ -106,14 +107,62 @@ public class ModRenderers
mxs.translate(rndo, rndo, 0); mxs.translate(rndo, rndo, 0);
mxs.scale(scaler, scaler, scaler); mxs.scale(scaler, scaler, scaler);
Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED, i5, i6, mxs, buf); 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) { } catch(Throwable e) {
if(--tesr_error_counter<=0) { 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()); ModEngineersDecor.logger().error(e.getStackTrace());
} }
} }
} }
} }
//--------------------------------------------------------------------------------------------------------------------
// Labeled Crate
//--------------------------------------------------------------------------------------------------------------------
@OnlyIn(Dist.CLIENT)
public static class DecorLabeledCrateTer extends TileEntityRenderer<BlockDecorLabeledCrate.LabeledCrateTileEntity>
{
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());
}
}
}
}
} }

View file

@ -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 }
}
}

View file

@ -135,6 +135,8 @@
"block.engineersdecor.treated_wood_stool.help": "§6Robust Wood Stool.§r Indoor and outdoor use.", "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": "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.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": "Treated Wood Side Table",
"block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.", "block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.",
"block.engineersdecor.iron_inset_light": "Inset Light", "block.engineersdecor.iron_inset_light": "Inset Light",

View file

@ -135,6 +135,8 @@
"block.engineersdecor.treated_wood_stool.help": "§6Крепкий деревянный табурет.§r Для использования в помещении и на улице.", "block.engineersdecor.treated_wood_stool.help": "§6Крепкий деревянный табурет.§r Для использования в помещении и на улице.",
"block.engineersdecor.treated_wood_crafting_table": "Верстак из обработанного дерева", "block.engineersdecor.treated_wood_crafting_table": "Верстак из обработанного дерева",
"block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке.", "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": "Столик из обработанного дерева",
"block.engineersdecor.treated_wood_side_table.help": "§6Нужен после того, как работа выполнена.", "block.engineersdecor.treated_wood_side_table.help": "§6Нужен после того, как работа выполнена.",
"block.engineersdecor.iron_inset_light": "Встраиваемый осветитель", "block.engineersdecor.iron_inset_light": "Встраиваемый осветитель",

View file

@ -135,6 +135,8 @@
"block.engineersdecor.treated_wood_stool.help": "§6坚固的木凳。§r适用于室内和室外使用。", "block.engineersdecor.treated_wood_stool.help": "§6坚固的木凳。§r适用于室内和室外使用。",
"block.engineersdecor.treated_wood_crafting_table": "防腐木合成台", "block.engineersdecor.treated_wood_crafting_table": "防腐木合成台",
"block.engineersdecor.treated_wood_crafting_table.help": "§6坚固防风防雨。§r内含八个存储格破坏后保留内容物没有原版合成书。\n 单击上/下箭头按钮可选择合成历史单击输出格自动放置物品单击X按钮 清除合成栏和历史。Shift单击一叠物品合成格空时转移到存储格 非空时到合成栏。会自动分配转移的物品。", "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": "防腐木茶几",
"block.engineersdecor.treated_wood_side_table.help": "§6干完活后需要喝杯茶。", "block.engineersdecor.treated_wood_side_table.help": "§6干完活后需要喝杯茶。",
"block.engineersdecor.iron_inset_light": "嵌入灯", "block.engineersdecor.iron_inset_light": "嵌入灯",

View file

@ -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]
}
}
}

View file

@ -0,0 +1 @@
{ "parent": "engineersdecor:block/misc/labeled_crate_model" }

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -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
}
}
}
]
}

View file

@ -2,13 +2,15 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"promos": { "promos": {
"1.12.2-recommended": "1.0.19", "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-recommended": "",
"1.14.4-latest": "1.0.20-b1", "1.14.4-latest": "1.0.20-b1",
"1.15.2-recommended": "", "1.15.2-recommended": "",
"1.15.2-latest": "1.0.20-b1" "1.15.2-latest": "1.0.20-b1"
}, },
"1.12.2": { "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": "[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-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).", "1.0.19-b3": "[A] Factory Hopper: Added bottom item handler (CR#227).",