1.12: Added Factory Block Placer/Planter.

This commit is contained in:
stfwi 2019-10-26 19:08:05 +02:00
parent 17ab68eb78
commit 297b840b65
33 changed files with 1190 additions and 49 deletions

View file

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

View file

@ -1,6 +1,7 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.12.2": {
"1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.",
"1.0.14": "[R] Release based on v1.0.14-b1. Release-to-release changes: * Factory Hopper added. * Small Waste Incinerator improved. * Lang updates. * Recipe fixes.",
"1.0.14-b1": "[A] Factory Hopper added (configurable hopper and item collector).\n[M] Small Waste Incinerator Fifo shifting improved.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).\n[F] Fixed conditional recipe constant for redstone pipe valve (thx @albert_ac).",
"1.0.13": "[R] Release based on v1.0.13-b2. Release-to-release changes: * Small Tree Cutter device added. * Small Solar Panel added. * Steel Mesh Fence added. * Broad Window Sill added.",
@ -63,6 +64,6 @@
},
"promos": {
"1.12.2-recommended": "1.0.14",
"1.12.2-latest": "1.0.14"
"1.12.2-latest": "1.0.15-b1"
}
}

View file

@ -10,6 +10,9 @@ Mod sources for Minecraft version 1.12.2.
----
## Version history
- v1.0.15-b1 [A] Added Floor Edge Light.
[A] Added Factory Block Placer and Planter.
-------------------------------------------------------------------
- v1.0.14 [R] Release based on v1.0.14-b1. Release-to-release changes:
* Factory Hopper added.

View file

@ -32,34 +32,7 @@ import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.blocks.BlockDecor;
import wile.engineersdecor.blocks.BlockDecorChair;
import wile.engineersdecor.blocks.BlockDecorCraftingTable;
import wile.engineersdecor.blocks.BlockDecorDirected;
import wile.engineersdecor.blocks.BlockDecorDropper;
import wile.engineersdecor.blocks.BlockDecorFence;
import wile.engineersdecor.blocks.BlockDecorFloorGrating;
import wile.engineersdecor.blocks.BlockDecorFull;
import wile.engineersdecor.blocks.BlockDecorFurnace;
import wile.engineersdecor.blocks.BlockDecorFurnaceElectrical;
import wile.engineersdecor.blocks.BlockDecorGlassBlock;
import wile.engineersdecor.blocks.BlockDecorHalfSlab;
import wile.engineersdecor.blocks.BlockDecorHopper;
import wile.engineersdecor.blocks.BlockDecorHorizontalSupport;
import wile.engineersdecor.blocks.BlockDecorLadder;
import wile.engineersdecor.blocks.BlockDecorMineralSmelter;
import wile.engineersdecor.blocks.BlockDecorPassiveFluidAccumulator;
import wile.engineersdecor.blocks.BlockDecorPipeValve;
import wile.engineersdecor.blocks.BlockDecorSlab;
import wile.engineersdecor.blocks.BlockDecorSolarPanel;
import wile.engineersdecor.blocks.BlockDecorStairs;
import wile.engineersdecor.blocks.BlockDecorStraightPole;
import wile.engineersdecor.blocks.BlockDecorTest;
import wile.engineersdecor.blocks.BlockDecorTreeCutter;
import wile.engineersdecor.blocks.BlockDecorWall;
import wile.engineersdecor.blocks.BlockDecorWasteIncinerator;
import wile.engineersdecor.blocks.BlockDecorWindow;
import wile.engineersdecor.blocks.BlockDecorWindowSill;
import wile.engineersdecor.blocks.*;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import wile.engineersdecor.detail.ModTesrs;
@ -144,6 +117,13 @@ public class ModContent
ModAuxiliaries.getPixeledAABB(2,2,2, 14,14,14)
);
public static final BlockDecorPlacer FACTORY_PLACER = new BlockDecorPlacer(
"factory_placer",
BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(2,2,2, 14,14,14)
);
public static final BlockDecorWasteIncinerator SMALL_WASTE_INCINERATOR = new BlockDecorWasteIncinerator(
"small_waste_incinerator",
BlockDecor.CFG_DEFAULT|BlockDecor.CFG_ELECTRICAL,
@ -490,6 +470,9 @@ public class ModContent
private static final TileEntityRegistrationData FACTORY_HOPPER_TEI = new TileEntityRegistrationData(
BlockDecorHopper.BTileEntity.class, "te_factory_hopper"
);
private static final TileEntityRegistrationData FACTORY_PLACER_TEI = new TileEntityRegistrationData(
BlockDecorPlacer.BTileEntity.class, "te_factory_placer"
);
private static final TileEntityRegistrationData SMALL_MINERAL_SMELTER_TEI = new TileEntityRegistrationData(
BlockDecorMineralSmelter.BTileEntity.class, "te_small_mineral_smelter"
);
@ -513,6 +496,7 @@ public class ModContent
SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE_TEI,
FACTORY_HOPPER,FACTORY_HOPPER_TEI,
FACTORY_DROPPER, FACTORY_DROPPER_TEI,
FACTORY_PLACER, FACTORY_PLACER_TEI,
SMALL_WASTE_INCINERATOR, WASTE_INCINERATOR_TEI,
STRAIGHT_CHECK_VALVE, STRAIGHT_REDSTONE_VALVE, STRAIGHT_REDSTONE_ANALOG_VALVE, STRAIGHT_PIPE_VALVE_TEI,
PASSIVE_FLUID_ACCUMULATOR, PASSIVE_FLUID_ACCUMULATOR_TEI,
@ -551,6 +535,7 @@ public class ModContent
TREATED_WOOD_WINDOWSILL,
TREATED_WOOD_BROAD_WINDOWSILL,
INSET_LIGHT_IRON,
FLOOR_EDGE_LIGHT_IRON,
TREATED_WOOD_POLE_SUPPORT,
TREATED_WOOD_POLE_HEAD,
THIN_STEEL_POLE,
@ -572,7 +557,6 @@ public class ModContent
PANZERGLASS_SLAB, // @todo: check if another class is needed due to is_side_visible
TREATED_WOOD_FLOOR, // @todo: check if textures need improvement
TEST_BLOCK,TEST_BLOCK_TEI,
FLOOR_EDGE_LIGHT_IRON
};
//--------------------------------------------------------------------------------------------------------------------

View file

@ -159,6 +159,7 @@ public class ModEngineersDecor
public static final int GUIID_SMALL_WASTE_INCINERATOR = 213104;
public static final int GUIID_FACTORY_DROPPER = 213105;
public static final int GUIID_FACTORY_HOPPER = 213106;
public static final int GUIID_FACTORY_PLACER = 213107;
@Override
public Object getServerGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z)
@ -172,6 +173,7 @@ public class ModEngineersDecor
case GUIID_SMALL_WASTE_INCINERATOR: return BlockDecorWasteIncinerator.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_PLACER: return BlockDecorPlacer.getServerGuiElement(player, world, pos, te);
}
return null;
}
@ -189,6 +191,7 @@ public class ModEngineersDecor
case GUIID_SMALL_WASTE_INCINERATOR: return BlockDecorWasteIncinerator.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_PLACER: return BlockDecorPlacer.getClientGuiElement(player, world, pos, te);
}
return null;
}

View file

@ -0,0 +1,714 @@
/*
* @file BlockDecorPlacer.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Block placer and planter, factory automation suitable.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.Networking;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.world.IBlockAccess;
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.block.state.BlockFaceShape;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.math.*;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
public class BlockDecorPlacer extends BlockDecorDirected
{
public BlockDecorPlacer(@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 BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@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)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("tedata"))) return;
NBTTagCompound te_nbt = stack.getTagCompound().getCompoundTag("tedata");
if(te_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).readnbt(te_nbt, false);
((BTileEntity)te).reset_rtstate();
((BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound te_nbt = new NBTTagCompound();
((BTileEntity) te).writenbt(te_nbt, false);
if(!te_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
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;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset_rtstate();
super.onBlockExploded(world, pos, explosion);
}
@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_FACTORY_PLACER, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighborPos)
{
if(!(world instanceof World) || (((World) world).isRemote)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).block_updated();
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
{
super.mouseClicked(mouseX, mouseY, mouseButton);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 3) return;
int mx = mouseX - getGuiLeft(), my = mouseY - getGuiTop();
if(!isPointInRegion(126, 1, 49, 60, mouseX, mouseY)) {
return;
} else if(isPointInRegion(133, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("manual_trigger", 1);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(145, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[0] ^ BTileEntity.LOGIC_INVERTED);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(159, 49, 7, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[0] ^ BTileEntity.LOGIC_CONTINUOUS);
Networking.PacketTileNotify.sendToServer(te, nbt);
}
}
@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/factory_placer_gui.png"));
final int x0=getGuiLeft(), y0=getGuiTop(), w=getXSize(), h=getYSize();
drawTexturedModalRect(x0, y0, 0, 0, w, h);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 3) return; // no init, no cake.
// active slot
{
int slot_index = container.fields_[2];
if((slot_index < 0) || (slot_index >= BTileEntity.NUM_OF_SLOTS)) slot_index = 0;
int x = (x0+10+((slot_index % 6) * 18));
int y = (y0+8+((slot_index / 6) * 17));
drawTexturedModalRect(x, y, 200, 8, 18, 18);
}
// redstone input
{
if(container.fields_[1] != 0) {
drawTexturedModalRect(x0+133, y0+49, 217, 49, 9, 9);
}
}
// trigger logic
{
int inverter_offset = ((container.fields_[0] & BTileEntity.LOGIC_INVERTED) != 0) ? 11 : 0;
drawTexturedModalRect(x0+145, y0+49, 177+inverter_offset, 49, 9, 9);
int pulse_mode_offset = ((container.fields_[0] & BTileEntity.LOGIC_CONTINUOUS ) != 0) ? 9 : 0;
drawTexturedModalRect(x0+159, y0+49, 199+pulse_mode_offset, 49, 9, 9);
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int fields_[] = new int[3];
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
// device slots (stacks 0 to 17)
for(int y=0; y<3; ++y) {
for(int x=0; x<6; ++x) {
int xpos = 11+x*18, ypos = 9+y*17;
addSlotToContainer(new Slot(te, ++i, xpos, ypos));
}
}
// player slots
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 129)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 71+y*18)); // player slots: 9..35
}
}
}
public BlockPos getPos()
{ return pos; }
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int il=0; il<listeners.size(); ++il) {
IContainerListener lis = listeners.get(il);
for(int k=0; k<fields_.length; ++k) {
int f = te.getField(k);
if(fields_[k] != f) {
fields_[k] = f;
lis.sendWindowProperty(this, k, f);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int value)
{
if((id < 0) || (id >= fields_.length)) return;
fields_[id] = value;
te.setField(id, value);
}
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorPlacer) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(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)) {
// Device 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, BTileEntity.NUM_OF_SLOTS, 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;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, Networking.IPacketReceiver
{
public static final int TICK_INTERVAL = 40;
public static final int NUM_OF_SLOTS = 18;
///
public static final int LOGIC_INVERTED = 0x01;
public static final int LOGIC_CONTINUOUS = 0x02;
///
private boolean block_power_signal_ = false;
private boolean block_power_updated_ = false;
private int logic_ = LOGIC_INVERTED|LOGIC_CONTINUOUS;
private int current_slot_index_ = 0;
private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_;
public static void on_config(int cooldown_ticks)
{
// ModEngineersDecor.logger.info("Config factory placer:");
}
public BTileEntity()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
reset_rtstate();
}
public void reset_rtstate()
{
block_power_signal_ = false;
block_power_updated_ = false;
}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(nbt, stacks_);
while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY);
block_power_signal_ = nbt.getBoolean("powered");
current_slot_index_ = nbt.getInteger("act_slot_index");
logic_ = nbt.getInteger("logic");
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
ItemStackHelper.saveAllItems(nbt, stacks_);
nbt.setBoolean("powered", block_power_signal_);
nbt.setInteger("act_slot_index", current_slot_index_);
nbt.setInteger("logic", logic_);
}
public void block_updated()
{
boolean powered = world.isBlockPowered(pos);
if(block_power_signal_ != powered) block_power_updated_ = true;
block_power_signal_ = powered;
if(block_power_updated_) {
tick_timer_ = 1;
} else if(tick_timer_ > 4) {
tick_timer_ = 4;
}
}
public boolean is_input_slot(int index)
{ return (index >= 0) && (index < NUM_OF_SLOTS); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorPlacer)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// IWorldNamable ---------------------------------------------------------------------------
@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 < 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)
{
stacks_.set(index, stack);
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
if(tick_timer_ > 8) tick_timer_ = 8;
markDirty();
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return true; }
@Override
public int getField(int id)
{
switch(id) {
case 0: return logic_;
case 1: return block_power_signal_ ? 1 : 0;
case 2: return current_slot_index_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: logic_ = value; return;
case 1: block_power_signal_ = (value != 0); return;
case 2: current_slot_index_ = MathHelper.clamp(value, 0, NUM_OF_SLOTS-1); return;
default: return;
}
}
@Override
public int getFieldCount()
{ return 3; }
@Override
public void clear()
{ stacks_.clear(); }
// ISidedInventory ----------------------------------------------------------------------------
private final IItemHandler item_handler_ = new SidedInvWrapper(this, EnumFacing.UP);
private static final int[] SIDED_INV_SLOTS;
static {
SIDED_INV_SLOTS = new int[NUM_OF_SLOTS];
for(int i=0; i<NUM_OF_SLOTS; ++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 is_input_slot(index) && isItemValidForSlot(index, stack); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return false; }
// Capability export ----------------------------------------------------------------------------
@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);
}
// IPacketReceiver -------------------------------------------------------------------------------
@Override
public void onServerPacketReceived(NBTTagCompound nbt)
{}
@Override
public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt)
{
if(nbt.hasKey("logic")) logic_ = nbt.getInteger("logic");
if(nbt.hasKey("manual_trigger") && (nbt.getInteger("manual_trigger")!=0)) { block_power_signal_=true; block_power_updated_=true; tick_timer_=1; }
markDirty();
}
// ITickable and aux methods ---------------------------------------------------------------------
private static int next_slot(int i)
{ return (i<NUM_OF_SLOTS-1) ? (i+1) : 0; }
private boolean spit_out(EnumFacing facing)
{
ItemStack stack = stacks_.get(current_slot_index_);
ItemStack drop = stack.copy();
stack.shrink(1);
stacks_.set(current_slot_index_, stack);
drop.setCount(1);
for(int i=0; i<8; ++i) {
BlockPos p = pos.offset(facing, i);
if(!world.isAirBlock(p)) continue;
world.spawnEntity(new EntityItem(world, (p.getX()+0.5), (p.getY()+0.5), (p.getZ()+0.5), drop));
world.playSound(null, p, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 0.7f, 0.8f);
break;
}
return true;
}
private boolean try_place(EnumFacing facing)
{
if(world.isRemote) return false;
BlockPos placement_pos = pos.offset(facing);
if(world.getTileEntity(placement_pos) != null) return false;
ItemStack current_stack = ItemStack.EMPTY;
for(int i=0; i<NUM_OF_SLOTS; ++i) {
if(current_slot_index_ >= NUM_OF_SLOTS) current_slot_index_ = 0;
current_stack = stacks_.get(current_slot_index_);
if(!current_stack.isEmpty()) break;
current_slot_index_ = next_slot(current_slot_index_);
}
if(current_stack.isEmpty()) { current_slot_index_ = 0; return false; }
boolean no_space = false;
final Item item = current_stack.getItem();
Block block = (item instanceof IPlantable) ? (((IPlantable)item).getPlant(world, pos).getBlock()) : Block.getBlockFromItem(item);
if(block == Blocks.AIR) {
if(item != null) {
return spit_out(facing); // Item not accepted
} else {
// try next slot
}
} else if(block instanceof IPlantable) {
if(world.isAirBlock(placement_pos)) {
// plant here, block below has to be valid soil.
IBlockState soilstate = world.getBlockState(placement_pos.down());
if(!soilstate.getBlock().canSustainPlant(soilstate, world, pos, EnumFacing.UP, (IPlantable)block)) {
block = Blocks.AIR;
}
} else {
// adjacent block is the soil, plant above if the soil is valid.
IBlockState soilstate = world.getBlockState(placement_pos);
if(soilstate.getBlock() == block) {
// The plant is already planted from the case above.
block = Blocks.AIR;
no_space = true;
} else if(!world.isAirBlock(placement_pos.up())) {
// If this is the soil an air block is needed above, if that is blocked we can't plant.
block = Blocks.AIR;
no_space = true;
} else if(!soilstate.getBlock().canSustainPlant(soilstate, world, pos, EnumFacing.UP, (IPlantable)block)) {
// Would be space above, but it's not the right soil for the plant.
block = Blocks.AIR;
} else {
// Ok, plant above.
placement_pos = placement_pos.up();
}
}
} else if(!world.getBlockState(placement_pos).getBlock().isReplaceable(world, placement_pos)) {
block = Blocks.AIR;
no_space = true;
}
// System.out.println("PLACE " + current_stack + " --> " + block + " at " + placement_pos.subtract(pos) + "( item=" + item + ")");
if(block != Blocks.AIR) {
try {
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
final IBlockState placement_state = (placer==null) ? (block.getDefaultState()) : (block.getStateForPlacement(world, placement_pos, EnumFacing.DOWN,0.5f,0.5f,0f, 0, placer, EnumHand.MAIN_HAND));
if(placement_state == null) {
return spit_out(facing);
} else if(item instanceof ItemBlock) {
ItemStack placement_stack = current_stack.copy();
placement_stack.setCount(1);
((ItemBlock)item).placeBlockAt(placement_stack, placer, world, placement_pos, EnumFacing.DOWN, 0.5f,0.5f,0f, placement_state);
SoundType stype = block.getSoundType(placement_state, world, pos, null);
if(stype != null) world.playSound(null, placement_pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
} else {
if(world.setBlockState(placement_pos, placement_state, 1|2|8)) {
SoundType stype = block.getSoundType(placement_state, world, pos, null);
if(stype != null) world.playSound(null, placement_pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
}
}
current_stack.shrink(1);
stacks_.set(current_slot_index_, current_stack);
return true;
} catch(Throwable e) {
// The block really needs a player or other issues happened during placement.
// A hard crash should not be fired here, instead spit out the item to indicated that this
// block is not compatible.
System.out.println("Exception while trying to place " + e);
world.setBlockToAir(placement_pos);
return spit_out(facing);
}
}
if((!no_space) && (!current_stack.isEmpty())) {
// There is space, but the current plant cannot be planted there, so try next.
for(int i=0; i<NUM_OF_SLOTS; ++i) {
current_slot_index_ = next_slot(current_slot_index_);
if(!stacks_.get(current_slot_index_).isEmpty()) break;
}
}
return false;
}
@Override
public void update()
{
// Tick cycle pre-conditions
if(world.isRemote) return;
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
// Cycle init
boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0)));
final IBlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final EnumFacing placer_facing = state.getValue(FACING);
// Trigger edge detection for next cycle
{
boolean tr = world.isBlockPowered(pos);
block_power_updated_ = (block_power_signal_ != tr);
block_power_signal_ = tr;
if(block_power_updated_) dirty = true;
}
// Placing
if(trigger && try_place(placer_facing)) dirty = true;
if(dirty) markDirty();
if(trigger && (tick_timer_ > TICK_INTERVAL)) tick_timer_ = TICK_INTERVAL;
}
}
}

View file

@ -168,6 +168,11 @@ public class ModConfig
@Config.RequiresMcRestart
public boolean without_factory_hopper = false;
@Config.Comment({"Disable the Factory Block Placer."})
@Config.Name("Without factory placer")
@Config.RequiresMcRestart
public boolean without_factory_placer = false;
@Config.Comment({"Disable horizontal half-block slab."})
@Config.Name("Without slabs")
@Config.RequiresMcRestart
@ -411,6 +416,7 @@ public class ModConfig
if(block instanceof BlockDecorWasteIncinerator) return optout.without_waste_incinerator;
if(block instanceof BlockDecorDropper) return optout.without_factory_dropper;
if(block instanceof BlockDecorHopper) return optout.without_factory_hopper;
if(block instanceof BlockDecorPlacer) return optout.without_factory_placer;
if(block instanceof BlockDecorHalfSlab) return optout.without_halfslabs;
if(block instanceof BlockDecorLadder) return optout.without_ladders;
if(block instanceof BlockDecorWindow) return optout.without_windows;

View file

@ -0,0 +1,11 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:device/factory_placer_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} }
}
}

View file

@ -159,7 +159,13 @@ tile.engineersdecor.factory_dropper.help=§6Dropper suitable for advanced factor
Pre-opens shutter door when internal trigger conditions are met. Drops all matching stacks \
simultaneously. Click on all elements in the GUI to see how it works.
tile.engineersdecor.factory_hopper.name=Factory Hopper
tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r
tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r Can transfer half-stacks, max collection range 9x9.\n\
GUI Slider controls: Collection range (0 to 4), insertion delay (0.5s to 10s), insertion stack size (1 to 32).\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).
tile.engineersdecor.factory_placer.name=Factory Block Placer
tile.engineersdecor.factory_placer.help=§6Allows placing blocks and planting crops or trees.§r\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).\n\
Also supports spike planing from underneath the soil. Spits out items that it cannot place or plant.
tile.engineersdecor.small_mineral_smelter.name=Small Mineral Melting Furnace
tile.engineersdecor.small_mineral_smelter.help=§6High temperature, high insulation electrical stone melting furnace.§r\n\
Heats up mineral blocks to magma blocks, and finally to lava. Due to the \

View file

@ -155,7 +155,13 @@ tile.engineersdecor.factory_dropper.help=§6Выбрасыватель подх
когда выполняются условия внутреннего запуска. Сбрасывает все соответствующие стеки одновременно. \
Нажмите на все элементы в GUI, чтобы увидеть, как это работает.
tile.engineersdecor.factory_hopper.name=Factory Hopper
#tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r
#tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r Can transfer half-stacks, max collection range 9x9.\n\
GUI Slider controls: Collection range (0 to 4), insertion delay (0.5s to 10s), insertion stack size (1 to 32).\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).
tile.engineersdecor.factory_placer.name=Factory Block Placer
#tile.engineersdecor.factory_placer.help=§6Allows placing blocks and planting crops or trees.§r\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).\n\
Also supports spike planing from underneath the soil. Spits out items that it cannot place or plant.
tile.engineersdecor.small_mineral_smelter.name=Small Mineral Melting Furnace
#tile.engineersdecor.small_mineral_smelter.help=§6High temperature, high insulation electrical stone melting furnace.§r\n\
Heats up mineral blocks to magma blocks, and finally to lava. Due to the \

View file

@ -158,7 +158,13 @@ tile.engineersdecor.factory_dropper.help=§6适用于高级工厂自动化的掉
当内部触发条件满足时,预先打开卷帘门。所有符合条件的物品\
会同时掉落。点击GUI的各处来了解如何运作。
tile.engineersdecor.factory_hopper.name=Factory Hopper
#tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r
#tile.engineersdecor.factory_hopper.help=§6Hopper suitable for advanced factory automation.§r Can transfer half-stacks, max collection range 9x9.\n\
GUI Slider controls: Collection range (0 to 4), insertion delay (0.5s to 10s), insertion stack size (1 to 32).\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).
tile.engineersdecor.factory_placer.name=Factory Block Placer
#tile.engineersdecor.factory_placer.help=§6Allows placing blocks and planting crops or trees.§r\n\
GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).\n\
Also supports spike planing from underneath the soil. Spits out items that it cannot place or plant.
tile.engineersdecor.small_mineral_smelter.name=小型矿物熔炼炉
tile.engineersdecor.small_mineral_smelter.help=§6高温、高绝缘电熔石炉。§r\n\
把矿物块加热成岩浆块,最后变成熔岩。由于\

View file

@ -0,0 +1,170 @@
{
"parent": "block/cube",
"textures": {
"top": "engineersdecor:blocks/device/factory_placer_top",
"bottom": "engineersdecor:blocks/device/factory_placer_bottom",
"side": "engineersdecor:blocks/device/factory_placer_side",
"particle": "engineersdecor:blocks/device/factory_placer_side"
},
"elements": [
{
"from": [0, 0, 3],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 16, 16], "texture": "#bottom"},
"east": {"uv": [3, 0, 16, 16], "rotation": 180, "texture": "#side"},
"south": {"uv": [0, 0, 16, 16], "texture": "#top"},
"west": {"uv": [3, 0, 16, 16], "texture": "#side"},
"up": {"uv": [3, 0, 16, 16], "rotation": 90, "texture": "#side"},
"down": {"uv": [3, 0, 16, 16], "rotation": 270, "texture": "#side"}
}
},
{
"from": [15, 0, 0],
"to": [16, 16, 1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 1, 16], "texture": "#bottom"},
"east": {"uv": [15, 0, 16, 16], "texture": "#side"},
"south": {"uv": [14, 0, 16, 16], "texture": "#top"},
"west": {"uv": [0, 0, 1, 16], "texture": "#side"},
"up": {"uv": [14, 0, 15, 1], "rotation": 90, "texture": "#side"},
"down": {"uv": [14, 15, 16, 16], "texture": "#side"}
}
},
{
"from": [15, 0, 2],
"to": [16, 16, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]},
"faces": {
"north": {"uv": [0, 0, 1, 16], "texture": "#bottom"},
"east": {"uv": [2, 0, 3, 16], "rotation": 180, "texture": "#side"},
"south": {"uv": [15, 0, 16, 16], "texture": "#top"},
"west": {"uv": [2, 0, 4, 16], "texture": "#side"},
"up": {"uv": [15, 2, 16, 4], "rotation": 90, "texture": "#side"},
"down": {"uv": [15, 12, 16, 14], "rotation": 270, "texture": "#side"}
}
},
{
"from": [0, 0, 0],
"to": [1, 16, 1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [15, 0, 16, 16], "texture": "#bottom"},
"east": {"uv": [15, 0, 16, 16], "texture": "#side"},
"south": {"uv": [0, 0, 2, 16], "texture": "#top"},
"west": {"uv": [0, 0, 1, 16], "texture": "#side"},
"up": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 15, 2, 16], "texture": "#side"}
}
},
{
"from": [0, 0, 2],
"to": [1, 16, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]},
"faces": {
"north": {"uv": [15, 0, 16, 16], "texture": "#bottom"},
"east": {"uv": [2, 0, 3, 16], "texture": "#side"},
"south": {"uv": [0, 0, 1, 16], "texture": "#top"},
"west": {"uv": [2, 0, 3, 16], "texture": "#side"},
"up": {"uv": [0, 2, 1, 3], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 13, 1, 14], "rotation": 270, "texture": "#side"}
}
},
{
"from": [0, 15, 1],
"to": [1, 16, 2],
"faces": {
"north": {"uv": [15, 0, 16, 1], "texture": "#bottom"},
"east": {"uv": [14, 0, 15, 1], "texture": "#side"},
"south": {"uv": [0, 0, 1, 1], "texture": "#top"},
"west": {"uv": [1, 0, 2, 1], "texture": "#side"},
"up": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 14, 1, 15], "rotation": 270, "texture": "#side"}
}
},
{
"from": [15, 15, 1],
"to": [16, 16, 2],
"rotation": {"angle": 0, "axis": "y", "origin": [23, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 1, 1], "texture": "#bottom"},
"east": {"uv": [14, 0, 15, 1], "texture": "#side"},
"south": {"uv": [15, 0, 16, 1], "texture": "#top"},
"west": {"uv": [1, 0, 2, 1], "texture": "#side"},
"up": {"uv": [15, 1, 16, 2], "rotation": 90, "texture": "#side"},
"down": {"uv": [15, 14, 16, 15], "rotation": 270, "texture": "#side"}
}
},
{
"from": [15, 0, 1],
"to": [16, 1, 2],
"rotation": {"angle": 0, "axis": "y", "origin": [23, -7, 8]},
"faces": {
"north": {"uv": [0, 15, 1, 16], "texture": "#bottom"},
"east": {"uv": [14, 15, 15, 16], "texture": "#side"},
"south": {"uv": [15, 15, 16, 16], "texture": "#top"},
"west": {"uv": [1, 15, 2, 16], "texture": "#side"},
"up": {"uv": [15, 1, 16, 2], "rotation": 90, "texture": "#side"},
"down": {"uv": [15, 14, 16, 15], "rotation": 270, "texture": "#side"}
}
},
{
"from": [0, 0, 1],
"to": [1, 1, 2],
"rotation": {"angle": 0, "axis": "y", "origin": [8, -7, 8]},
"faces": {
"north": {"uv": [15, 15, 16, 16], "texture": "#bottom"},
"east": {"uv": [14, 15, 15, 16], "texture": "#side"},
"south": {"uv": [0, 15, 1, 16], "texture": "#top"},
"west": {"uv": [1, 15, 2, 16], "texture": "#side"},
"up": {"uv": [0, 1, 1, 2], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 14, 1, 15], "texture": "#side"}
}
},
{
"from": [1, 15, 2],
"to": [15, 16, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]},
"faces": {
"north": {"uv": [1, 0, 15, 1], "texture": "#bottom"},
"east": {"uv": [12, 0, 14, 1], "texture": "#side"},
"south": {"uv": [1, 0, 15, 1], "texture": "#top"},
"west": {"uv": [2, 0, 4, 1], "texture": "#side"},
"up": {"uv": [2, 1, 3, 15], "rotation": 90, "texture": "#side"},
"down": {"uv": [2, 1, 3, 15], "rotation": 270, "texture": "#side"}
}
},
{
"from": [1, 0, 2],
"to": [15, 1, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]},
"faces": {
"north": {"uv": [1, 15, 15, 16], "texture": "#bottom"},
"east": {"uv": [12, 15, 14, 16], "texture": "#side"},
"south": {"uv": [1, 15, 15, 16], "texture": "#top"},
"west": {"uv": [2, 15, 4, 16], "texture": "#side"},
"up": {"uv": [2, 1, 3, 15], "rotation": 180, "texture": "#side"},
"down": {"uv": [2, 1, 3, 15], "rotation": 270, "texture": "#side"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [85, 3, -10],
"translation": [1.75, -0.75, -2.25],
"scale": [0.35, 0.35, 0.35]
},
"ground": {
"translation": [0, -0.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:factory_placer",
"missing": ["immersiveengineering:material"]
}
],
"type": "minecraft:crafting_shaped",
"pattern": [
"WWW",
"WDP",
"WWW"
],
"key": {
"D": {
"item": "minecraft:dispenser",
"data": 0
},
"P": {
"item": "#ingotIron",
"data": 0
},
"W": {
"item": "#plankWood",
"data": 0
}
},
"result": {
"item": "engineersdecor:factory_placer",
"count": 1
}
}

View file

@ -0,0 +1,33 @@
{
"conditions": [
{
"type": "engineersdecor:grc",
"result": "engineersdecor:factory_placer",
"required": ["immersiveengineering:material"]
}
],
"type": "minecraft:crafting_shaped",
"pattern": [
"WWW",
"WDP",
"WWW"
],
"key": {
"D": {
"item": "minecraft:dispenser",
"data": 0
},
"P": {
"item": "#plateIron",
"data": 0
},
"W": {
"item": "#plankTreatedWood",
"data": 0
}
},
"result": {
"item": "engineersdecor:factory_placer",
"count": 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -2,7 +2,7 @@
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G
version_minecraft=1.14.4
version_forge_minecraft=1.14.4-28.1.61
version_forge_minecraft=1.14.4-28.1.68
version_fml_mappings=20190719-1.14.3
version_jei=1.14.4:6.0.0.10
version_engineersdecor=1.0.15-b1

View file

@ -1,6 +1,7 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.14.4": {
"1.0.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.",
"1.0.14-b1": "[U] Updated to Forge 1.14.4-28.1.40/20190719-1.14.3.\n[A] Factory Hopper added (configurable hopper and item collector).\n[M] Switched to integrated loot table generation.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).",
"1.0.13-b2": "[A] Added Steel Mesh Fence.\n[A] Added Broad Window Sill.",
"1.0.12-b3": "[U] Updated to Forge 1.14.4-28.1.10/20190719-1.14.3.\n[A] Crafting Table: Added recipe collision resolver, also applies to crafting history refabrication.\n[A] Crafting Table: Added rendering of placed items on the top surface of the table.\n[A] Waterlogging of non-full-blocks added.",
@ -27,6 +28,6 @@
},
"promos": {
"1.14.4-recommended": "",
"1.14.4-latest": "1.0.14-b1"
"1.14.4-latest": "1.0.15-b1"
}
}

View file

@ -11,7 +11,8 @@ Mod sources for Minecraft version 1.14.4.
## Version history
~ v1.0.15-b1 [U] Updated to Forge1.14.4-28.1.61/20190719-1.14.3.
- v1.0.15-b1 [A] Added Floor Edge Light.
[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.
- v1.0.14-b1 [U] Updated to Forge 1.14.4-28.1.40/20190719-1.14.3.
[A] Factory Hopper added (configurable hopper and item collector).

View file

@ -222,6 +222,12 @@ public class ModContent
ModAuxiliaries.getPixeledAABB(5.2,5.2,15.7, 10.8,10.8,16.0)
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "iron_inset_light"));
public static final BlockDecorDirected.WaterLoggable FLOOR_EDGE_LIGHT_IRON = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable(
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_HORIZIONTAL,
Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(2f, 15f).sound(SoundType.METAL).lightValue(15),
ModAuxiliaries.getPixeledAABB(5,0,0, 11,2,1)
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "iron_floor_edge_light"));
public static final BlockDecor.WaterLoggable STEEL_TABLE = (BlockDecor.WaterLoggable)(new BlockDecor.WaterLoggable(
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.WOOD),
@ -511,6 +517,7 @@ public class ModContent
STEEL_FRAMED_WINDOW,
STEEL_TABLE,
INSET_LIGHT_IRON,
FLOOR_EDGE_LIGHT_IRON,
STEEL_FLOOR_GRATING,
STEEL_MESH_FENCE,
TREATED_WOOD_POLE,

View file

@ -0,0 +1,7 @@
{
"forge_marker": 1,
"defaults": { "model": "engineersdecor:block/light/floor_edge_light_model" },
"variants": {
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} }
}
}

View file

@ -1,13 +1,6 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:block/light/inset_light_model",
"textures": {
"light": "engineersdecor:block/light/lamp_glass_warm_square_texture",
"side": "engineersdecor:block/iestyle/steel_texture",
"particle": "engineersdecor:block/iestyle/steel_texture"
}
},
"defaults": { "model": "engineersdecor:block/light/inset_light_model" },
"variants": {
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} }
}

View file

@ -128,7 +128,9 @@
"block.engineersdecor.treated_wood_side_table": "Treated Wood Side Table",
"block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.",
"block.engineersdecor.iron_inset_light": "Inset Light",
"block.engineersdecor.iron_inset_light.help": "§6Small glowstone light source, sunk into the floor, ceiling or wall.§r\n Useful to light up places where electrical light installations are problematic. Light level like a torch.",
"block.engineersdecor.iron_inset_light.help": "§6Small glowstone light source, sunk into the floor, ceiling or wall.§r\n Useful to light up places where electrical light installations are problematic.",
"block.engineersdecor.iron_floor_edge_light": "Inset Floor Edge Light",
"block.engineersdecor.iron_floor_edge_light.help": "§6Small glowstone light source, placed at the edge of a floor block.§r\n Useful to light up places where electrical light installations are problematic.",
"block.engineersdecor.treated_wood_window": "Treated Wood Window",
"block.engineersdecor.treated_wood_window.help": "§6Wood framed triple glazed window. Well insulating.§r Does not connect to adjacent blocks like glass panes.",
"block.engineersdecor.treated_wood_windowsill": "Treated Wood Window Sill",
@ -156,7 +158,9 @@
"block.engineersdecor.factory_dropper": "Factory Dropper",
"block.engineersdecor.factory_dropper.help": "§6Dropper suitable for advanced factory automation.§r Has twelve round-robin selected slots. Drop force, angle, stack size, and cool-down delay adjustable in the GUI. Three stack compare slots with logical AND or OR can be used as internal trigger source. Internal trigger can be AND'ed or OR'ed with the external redstone signal trigger. Trigger simulation buttons for testing. Pre-opens shutter door when internal trigger conditions are met. Drops all matching stacks simultaneously. Click on all elements in the GUI to see how it works.",
"block.engineersdecor.factory_hopper": "Factory Hopper",
"block.engineersdecor.factory_hopper.help": "§6Hopper suitable for advanced factory automation.§r",
"block.engineersdecor.factory_hopper.help": "§6Hopper suitable for advanced factory automation.§r Can transfer half-stacks, max collection range 9x9.\n GUI Slider controls: Collection range (0 to 4), insertion delay (0.5s to 10s), insertion stack size (1 to 32).\\n GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).",
"block.engineersdecor.factory_placer": "Factory Block Placer",
"block.engineersdecor.factory_placer.help": "§6Allows placing blocks and planting crops or trees.§r\n GUI Redstone controls: Not inverted / inverted (default), pulse mode / continuous mode (default).\\n Also supports spike planing from underneath the soil. Spits out items that it cannot place or plant.",
"block.engineersdecor.small_mineral_smelter": "Small Mineral Melting Furnace",
"block.engineersdecor.small_mineral_smelter.help": "§6High temperature, high insulation electrical stone melting furnace.§r\n Heats up mineral blocks to magma blocks, and finally to lava. Due to the miniturized device size the process is rather inefficient - much time and energy is needed to liquefy a stone block.",
"block.engineersdecor.small_solar_panel": "Small Solar Panel",

View file

@ -128,6 +128,7 @@
"block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.",
"block.engineersdecor.iron_inset_light": "Встраиваемый осветитель",
"block.engineersdecor.iron_inset_light.help": "§6Маленький источник света, интегрируемый в стены, пол или потолок.§r\n Полезно для освещения мест, где проблематичны электрические осветительные установки. Уровень света - как факел.",
"block.engineersdecor.iron_floor_edge_light": "Inset Floor Edge Light",
"block.engineersdecor.treated_wood_window": "Обработанное деревянное окно",
"block.engineersdecor.treated_wood_window.help": "§6Деревянный каркас окна с тройным остеклением. Ну и шумоизоляция.",
"block.engineersdecor.treated_wood_windowsill": "Обработанный деревянный подоконник",
@ -153,6 +154,7 @@
"block.engineersdecor.factory_dropper": "Фабричный выбрасыватель",
"block.engineersdecor.factory_dropper.help": "§6Выбрасыватель подходит для продвинутой автоматизации производства.§r Имеет 12 выборочных слотов. Сила броска, угол, размер стопки и задержка настраиваются в GUI. 3 слота сравнения стека с логическим И или ИЛИ могут использоваться в качестве внутреннего источника запуска. Внутренний триггер может быть И или ИЛИ с внешним триггерным сигналом красного камня. Триггерные кнопки симуляции для тестирования. Предварительно открывает дверцу затвора, когда выполняются условия внутреннего запуска. Сбрасывает все соответствующие стеки одновременно. Нажмите на все элементы в GUI, чтобы увидеть, как это работает.",
"block.engineersdecor.factory_hopper": "Factory Hopper",
"block.engineersdecor.factory_placer": "Factory Block Placer",
"block.engineersdecor.small_mineral_smelter": "Small Mineral Melting Furnace",
"block.engineersdecor.small_solar_panel": "Small Solar Panel",
"block.engineersdecor.small_tree_cutter": "Small Tree Cutter",

View file

@ -129,6 +129,7 @@
"block.engineersdecor.treated_wood_side_table.help": "§6干完活后需要喝杯茶。",
"block.engineersdecor.iron_inset_light": "嵌入灯",
"block.engineersdecor.iron_inset_light.help": "§6小型荧石光源能嵌入地板、天花板或墙里。§r\n 用于照亮电力光源难以安装的地方。 亮度与火把一样。",
"block.engineersdecor.iron_floor_edge_light": "Inset Floor Edge Light",
"block.engineersdecor.treated_wood_window": "防腐木窗",
"block.engineersdecor.treated_wood_window.help": "§6木框三层玻璃窗。绝缘良好。§r不像玻璃板一样连接到相邻方块。",
"block.engineersdecor.treated_wood_windowsill": "防腐木窗台",
@ -156,6 +157,7 @@
"block.engineersdecor.factory_dropper": "工厂掉落器",
"block.engineersdecor.factory_dropper.help": "§6适用于高级工厂自动化的掉落器。§r有十二个轮询选择的储物格。 掉落的力度、角度、一叠数量和冷却延时可在GUI调节。三个 内部比较槽带有逻辑与或逻辑或功能,可用作内部触发源。内部触发 还能和外部红石信号触发再进行逻辑与或逻辑或。触发模拟按钮仅作测试用途。 当内部触发条件满足时,预先打开卷帘门。所有符合条件的物品 会同时掉落。点击GUI的各处来了解如何运作。",
"block.engineersdecor.factory_hopper": "Factory Hopper",
"block.engineersdecor.factory_placer": "Factory Block Placer",
"block.engineersdecor.small_mineral_smelter": "小型矿物熔炼炉",
"block.engineersdecor.small_mineral_smelter.help": "§6高温、高绝缘电熔石炉。§r\n 把矿物块加热成岩浆块,最后变成熔岩。由于 小型化的设备大小,该过程效率不高,需要大量时间和能源 来液化一块石头。",
"block.engineersdecor.small_solar_panel": "小型太阳能板",

View file

@ -0,0 +1,92 @@
{
"parent": "block/cube",
"textures": {
"light": "engineersdecor:block/light/lamp_glass_warm_square_texture",
"side": "engineersdecor:block/iestyle/steel_texture",
"particle": "engineersdecor:block/iestyle/steel_texture"
},
"elements": [
{
"from": [6, 0.1875, 0.5],
"to": [10, 1.8125, 1],
"faces": {
"north": {"uv": [6, 14.1875, 10, 15.8125], "texture": "#light"},
"south": {"uv": [6, 14.1875, 10, 15.8125], "texture": "#light"},
"up": {"uv": [6, 0.5, 10, 1], "texture": "#light"}
}
},
{
"from": [10, 0.1875, 0.5],
"to": [11, 1.8125, 1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.125]},
"faces": {
"north": {"uv": [5, 14.1875, 6, 15.8125], "texture": "#side"},
"east": {"uv": [15, 14.1875, 15.5, 15.8125], "texture": "#side"},
"south": {"uv": [10, 14.1875, 11, 15.8125], "texture": "#side"},
"west": {"uv": [0.5, 14.1875, 1, 15.8125], "texture": "#side"},
"up": {"uv": [10, 0.5, 11, 1], "texture": "#side"},
"down": {"uv": [10, 15, 11, 15.5], "texture": "#side"}
}
},
{
"from": [5, 0.1875, 0.5],
"to": [6, 1.8125, 1],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 8.125]},
"faces": {
"north": {"uv": [10, 14.1875, 11, 15.8125], "texture": "#side"},
"east": {"uv": [15, 14.1875, 15.5, 15.8125], "texture": "#side"},
"south": {"uv": [5, 14.1875, 6, 15.8125], "texture": "#side"},
"west": {"uv": [0.5, 14.1875, 1, 15.8125], "texture": "#side"},
"up": {"uv": [5, 0.5, 6, 1], "texture": "#side"},
"down": {"uv": [5, 15, 6, 15.5], "texture": "#side"}
}
},
{
"from": [5, 0, 0],
"to": [11, 2, 0.5],
"faces": {
"north": {"uv": [5, 14, 11, 16], "texture": "#side"},
"east": {"uv": [15.5, 14, 16, 16], "texture": "#side"},
"south": {"uv": [5, 14, 11, 16], "texture": "#side"},
"west": {"uv": [0, 14, 0.5, 16], "texture": "#side"},
"up": {"uv": [5, 0, 11, 0.5], "texture": "#side"},
"down": {"uv": [5, 15.5, 11, 16], "texture": "#side"}
}
},
{
"from": [5, 0, 0.5],
"to": [11, 0.1875, 1],
"faces": {
"north": {"uv": [5, 15.8125, 11, 16], "texture": "#side"},
"east": {"uv": [15, 15.8125, 15.5, 16], "texture": "#side"},
"south": {"uv": [5, 15.8125, 11, 16], "texture": "#side"},
"west": {"uv": [0.5, 15.8125, 1, 16], "texture": "#side"},
"up": {"uv": [5, 0.5, 11, 1], "texture": "#side"},
"down": {"uv": [5, 15, 11, 15.5], "texture": "#side"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [0, -6, 96],
"translation": [-5.5, 0.5, 4.75],
"scale": [0.7, 0.7, 0.7]
},
"firstperson_righthand": {
"translation": [-3, -0.75, 1.25]
},
"ground": {
"translation": [0, 2.5, 6],
"scale": [0.7, 0.7, 0.7]
},
"gui": {
"rotation": [30, 30, 0],
"translation": [7.5, 3, 0],
"scale": [2, 2, 2]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 0, -7.8]
}
}
}

View file

@ -0,0 +1 @@
{ "parent": "engineersdecor:block/light/floor_edge_light_model" }

View file

@ -0,0 +1,21 @@
{
"type": "minecraft:block",
"pools": [
{
"name": "iron_floor_edge_light_dlt",
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"functions": [
{
"function": "minecraft:copy_name",
"source": "block_entity"
}
],
"name": "engineersdecor:iron_floor_edge_light"
}
]
}
]
}

View file

@ -0,0 +1,16 @@
{
"conditions": [
{
"type": "engineersdecor:optional",
"result": "engineersdecor:iron_floor_edge_light",
"required": ["engineersdecor:iron_inset_light"]
}
],
"type": "minecraft:crafting_shapeless",
"ingredients": [
{ "item": "engineersdecor:iron_inset_light" }
],
"result": {
"item": "engineersdecor:iron_floor_edge_light"
}
}

View file

@ -0,0 +1,16 @@
{
"conditions": [
{
"type": "engineersdecor:optional",
"result": "engineersdecor:iron_inset_light",
"required": ["engineersdecor:iron_floor_edge_light"]
}
],
"type": "minecraft:crafting_shapeless",
"ingredients": [
{ "item": "engineersdecor:iron_floor_edge_light" }
],
"result": {
"item": "engineersdecor:iron_inset_light"
}
}

View file

@ -2,11 +2,12 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"promos": {
"1.12.2-recommended": "1.0.14",
"1.12.2-latest": "1.0.14",
"1.12.2-latest": "1.0.15-b1",
"1.14.4-recommended": "",
"1.14.4-latest": "1.0.14-b1"
"1.14.4-latest": "1.0.15-b1"
},
"1.12.2": {
"1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.",
"1.0.14": "[R] Release based on v1.0.14-b1. Release-to-release changes: * Factory Hopper added. * Small Waste Incinerator improved. * Lang updates. * Recipe fixes.",
"1.0.14-b1": "[A] Factory Hopper added (configurable hopper and item collector).\n[M] Small Waste Incinerator Fifo shifting improved.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).\n[F] Fixed conditional recipe constant for redstone pipe valve (thx @albert_ac).",
"1.0.13": "[R] Release based on v1.0.13-b2. Release-to-release changes: * Small Tree Cutter device added. * Small Solar Panel added. * Steel Mesh Fence added. * Broad Window Sill added.",
@ -68,6 +69,7 @@
"1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table."
},
"1.14.4": {
"1.0.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.",
"1.0.14-b1": "[U] Updated to Forge 1.14.4-28.1.40/20190719-1.14.3.\n[A] Factory Hopper added (configurable hopper and item collector).\n[M] Switched to integrated loot table generation.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).",
"1.0.13-b2": "[A] Added Steel Mesh Fence.\n[A] Added Broad Window Sill.",
"1.0.12-b3": "[U] Updated to Forge 1.14.4-28.1.10/20190719-1.14.3.\n[A] Crafting Table: Added recipe collision resolver, also applies to crafting history refabrication.\n[A] Crafting Table: Added rendering of placed items on the top surface of the table.\n[A] Waterlogging of non-full-blocks added.",