1.12: Added Fluid Collection Funnel. Added missin config opt-outs. Added Config tweaks for Block Breaker and Tree Cutter (cffr#185). Fixed Block placer discarding metadata (issue #60). Fixed Block Breaker duping shulker boxes. Block Breaker model updated. 1.14: Block breaker model updated.

This commit is contained in:
stfwi 2019-11-08 21:11:08 +01:00
parent 7592c9d494
commit 6c4fbeff56
19 changed files with 639 additions and 511 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.15
version_engineersdecor=1.0.16-b1

View file

@ -1,6 +1,7 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.12.2": {
"1.0.16-b1": "[A] Added Fluid Collection Funnel.\n[A] Added config opt-outs for Breaker, Placer, Fluid Funnel, Mineral Smelter.\n[A] Added configs tweaks for Small Block Breaker and Small Tree Cutter (cffr#185).\n[F] Fixed Block Placer discarding item metadata/variants while placing (issue #60).\n[F] Fixed Block Breaker duping empty shulker boxes, model updated.",
"1.0.15": "[R] Release based on v1.0.15-b2. Release-to-release changes: * Added Small Block Breaker * Small Tree Cutter fixes and compatability improved. * Crafting table compat fixes.\n[M] Small Tree Cutter log detection bug fixed (issue #59).\n[M] Small Tree Cutter supports Menril chopping (issue #54).",
"1.0.15-b2": "[A] Added Small Block Breaker\n[M] Crafting Table: Allowing NBT \"Damage\" mismatch only items that are declared damagable (issue #56).\n[M] Tree Cutter: Loosened the strict mod namespace requirement for Dynamic Trees log detection (issue #52) to enable checking DT compat mod log blocks.",
"1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.",
@ -66,6 +67,6 @@
},
"promos": {
"1.12.2-recommended": "1.0.15",
"1.12.2-latest": "1.0.15"
"1.12.2-latest": "1.0.16-b1"
}
}

View file

@ -10,6 +10,12 @@ Mod sources for Minecraft version 1.12.2.
----
## Version history
- v1.0.16-b1 [A] Added Fluid Collection Funnel.
[A] Added config opt-outs for Breaker, Placer, Fluid Funnel, Mineral Smelter.
[A] Added configs tweaks for Small Block Breaker and Small Tree Cutter (cffr#185).
[F] Fixed Block Placer discarding item metadata/variants while placing (issue #60).
[F] Fixed Block Breaker duping empty shulker boxes, model updated.
-------------------------------------------------------------------
- v1.0.15 [R] Release based on v1.0.15-b2. Release-to-release changes:
* Added Small Block Breaker

View file

@ -523,6 +523,7 @@ public class ModContent
SMALL_SOLAR_PANEL,SMALL_SOLAR_PANEL_TEI,
SMALL_MINERAL_SMELTER, SMALL_MINERAL_SMELTER_TEI,
STRAIGHT_CHECK_VALVE, STRAIGHT_REDSTONE_VALVE, STRAIGHT_REDSTONE_ANALOG_VALVE, STRAIGHT_PIPE_VALVE_TEI,
SMALL_FLUID_FUNNEL,SMALL_FLUID_FUNNEL_TEI,
PASSIVE_FLUID_ACCUMULATOR, PASSIVE_FLUID_ACCUMULATOR_TEI,
CLINKER_BRICK_BLOCK,
CLINKER_BRICK_SLAB,
@ -578,7 +579,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,
SMALL_FLUID_FUNNEL,SMALL_FLUID_FUNNEL_TEI
};
//--------------------------------------------------------------------------------------------------------------------

View file

@ -16,7 +16,6 @@ import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.init.Blocks;
@ -113,16 +112,19 @@ public class BlockDecorBreaker extends BlockDecorDirected
private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY;
private static int breaking_reluctance = DEFAULT_BREAKING_RELUCTANCE;
private static int min_breaking_time = DEFAULT_MIN_BREAKING_TIME;
private static boolean requires_power = false;
private int tick_timer_;
private int active_timer_;
private int proc_time_elapsed_;
private int boost_energy_;
public static void on_config(int boost_energy_per_tick, int breaking_time_per_hardness, int min_breaking_time_ticks)
public static void on_config(int boost_energy_per_tick, int breaking_time_per_hardness, int min_breaking_time_ticks, boolean power_required)
{
boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512);
breaking_reluctance = MathHelper.clamp(breaking_time_per_hardness, 5, 50);
min_breaking_time = MathHelper.clamp(min_breaking_time_ticks, 10, 100);
ModEngineersDecor.logger.info("Config block breaker: Boost energy consumption:" + boost_energy_consumption + "rf/t, reluctance=" + breaking_reluctance + "/hrdn, break time offset=" + min_breaking_time );
requires_power = power_required;
ModEngineersDecor.logger.info("Config block breaker: Boost energy consumption:" + (boost_energy_consumption/TICK_INTERVAL) + "rf/t, reluctance=" + breaking_reluctance + "t/hrdn, break time offset=" + min_breaking_time + "t");
}
public BTileEntity()
@ -208,13 +210,12 @@ public class BlockDecorBreaker extends BlockDecorDirected
return true;
}
private boolean breakBlock(IBlockState state, BlockPos pos, World world)
private static boolean breakBlock(IBlockState state, BlockPos pos, World world)
{
if(world.isRemote || world.restoringBlockSnapshots) return false; // retry next cycle
NonNullList<ItemStack> drops = NonNullList.create();
state.getBlock().getDrops(drops, world, pos, state, 0);
final Block block = state.getBlock();
block.dropBlockAsItem(world, pos, state, 0);
world.setBlockToAir(pos);
for(ItemStack drop:drops) spawnAsEntity(world, pos, drop);
SoundType stype = state.getBlock().getSoundType(state, world, pos, null);
if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true;
@ -252,14 +253,19 @@ public class BlockDecorBreaker extends BlockDecorDirected
tick_timer_ = IDLE_TICK_INTERVAL;
return;
}
proc_time_elapsed_ += TICK_INTERVAL;
boolean active = true;
int time_needed = (int)(target_state.getBlockHardness(world, pos) * breaking_reluctance) + min_breaking_time;
if(boost_energy_ >= boost_energy_consumption) {
boost_energy_ = 0;
proc_time_elapsed_ += TICK_INTERVAL * BOOST_FACTOR;
proc_time_elapsed_ += TICK_INTERVAL * (1+BOOST_FACTOR);
time_needed += min_breaking_time * (3*BOOST_FACTOR/5);
active_timer_ = 2;
} else if(!requires_power) {
proc_time_elapsed_ += TICK_INTERVAL;
active_timer_ = 1024;
} else if(active_timer_ > 0) {
--active_timer_;
}
boolean active = (active_timer_ > 0);
time_needed = MathHelper.clamp(time_needed, min_breaking_time, MAX_BREAKING_TIME);
if(proc_time_elapsed_ >= time_needed) {
proc_time_elapsed_ = 0;

View file

@ -24,6 +24,7 @@ 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.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.item.*;
@ -343,10 +344,12 @@ public class BlockDecorPlacer extends BlockDecorDirected
///
public static final int LOGIC_INVERTED = 0x01;
public static final int LOGIC_CONTINUOUS = 0x02;
public static final int DEFAULT_LOGIC = LOGIC_INVERTED|LOGIC_CONTINUOUS;
///
private boolean block_power_signal_ = false;
private boolean block_power_updated_ = false;
private int logic_ = LOGIC_INVERTED|LOGIC_CONTINUOUS;
private int logic_ = DEFAULT_LOGIC;
private int current_slot_index_ = 0;
private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_;
@ -375,15 +378,16 @@ public class BlockDecorPlacer extends BlockDecorDirected
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");
logic_ = nbt.hasKey("logic") ? nbt.getInteger("logic") : DEFAULT_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_);
boolean stacks_not_empty = stacks_.stream().anyMatch(s->!s.isEmpty());
if(stacks_not_empty) ItemStackHelper.saveAllItems(nbt, stacks_);
if(block_power_signal_) nbt.setBoolean("powered", block_power_signal_);
if(stacks_not_empty) nbt.setInteger("act_slot_index", current_slot_index_);
if(logic_ != DEFAULT_LOGIC) nbt.setInteger("logic", logic_);
}
public void block_updated()
@ -571,11 +575,8 @@ public class BlockDecorPlacer extends BlockDecorDirected
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);
ItemStack drop = stacks_.get(current_slot_index_).copy();
stacks_.set(current_slot_index_, ItemStack.EMPTY);
for(int i=0; i<8; ++i) {
BlockPos p = pos.offset(facing, i);
if(!world.isAirBlock(p)) continue;
@ -586,6 +587,63 @@ public class BlockDecorPlacer extends BlockDecorDirected
return true;
}
private static boolean place_item(ItemStack stack, EntityPlayer placer, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if((stack.isEmpty()) || (!(stack.getItem() instanceof ItemBlock))) return false;
ItemBlock item = (ItemBlock)(stack.getItem());
Block block = world.getBlockState(pos).getBlock();
if(!block.isReplaceable(world, pos)) pos = pos.offset(facing);
if(!world.mayPlace(item.getBlock(), pos, true, facing, (Entity)null)) return false;
int meta = item.getMetadata(stack.getMetadata());
final IBlockState state = item.getBlock().getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand);
if(!item.placeBlockAt(stack, placer, world, pos, facing, hitX, hitY, hitZ, state)) return false;
final IBlockState soundstate = world.getBlockState(pos);
final SoundType stype = soundstate.getBlock().getSoundType(soundstate, world, pos, placer);
world.playSound(placer, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, (stype.getVolume()+1f)/8, stype.getPitch()*1.1f);
return true;
}
private boolean try_plant(BlockPos pos, final EnumFacing facing, final ItemStack stack, final Block block)
{
Item item = stack.getItem();
if(world.isAirBlock(pos)) {
// plant here, block below has to be valid soil.
final IBlockState soilstate = world.getBlockState(pos.down());
if(!soilstate.getBlock().canSustainPlant(soilstate, world, pos.down(), EnumFacing.UP, (IPlantable)block)) {
// Not the right soil for this plant.
return spit_out(facing);
}
} else {
// adjacent block is the soil, plant above if the soil is valid.
final IBlockState soilstate = world.getBlockState(pos);
if(soilstate.getBlock() == block) {
// The plant is already planted from the case above, it's not the assumed soil but the planted plant.
return false;
} else if(!world.isAirBlock(pos.up())) {
// If this is the soil an air block is needed above, if that is blocked we can't plant.
return false;
} 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.
return spit_out(facing);
} else {
// Ok, plant above.
pos = pos.up();
}
}
try {
//println("PLANT " + stack + " --> " + block + " at " + pos.subtract(getPos()) + "( item=" + item + ")");
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
if((placer==null) || (!place_item(stack, placer, world, pos, EnumHand.MAIN_HAND, EnumFacing.DOWN, 0.5f, 0f, 0.5f))) return spit_out(facing);
stack.shrink(1);
stacks_.set(current_slot_index_, stack);
return true;
} catch(Throwable e) {
ModEngineersDecor.logger.error("Exception while trying to plant " + e);
world.setBlockToAir(pos);
return spit_out(facing);
}
}
private boolean try_place(EnumFacing facing)
{
if(world.isRemote) return false;
@ -599,83 +657,39 @@ public class BlockDecorPlacer extends BlockDecorDirected
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;
final Block block = Block.getBlockFromItem(item);
if(block == Blocks.AIR) return (item!=null) && spit_out(facing); // Item not accepted
if(world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(placement_pos)).size() > 0) {
return false;
}
// 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) {
if((block instanceof IPlantable) || (item instanceof IPlantable)) try_plant(placement_pos, facing, current_stack, block);
if(world.getBlockState(placement_pos).getBlock().isReplaceable(world, placement_pos)) {
if(item instanceof ItemBlock) {
try {
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
//println("PLACE ITEMBLOCK" + current_stack + " --> " + block + " at " + placement_pos.subtract(pos) + "( item=" + item + ")");
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());
}
if((placer==null) || (!place_item(placement_stack, placer, world, placement_pos, EnumHand.MAIN_HAND, EnumFacing.DOWN, 0.6f, 0f, 0.5f))) return spit_out(facing);
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.
ModEngineersDecor.logger.error("Exception while trying to place " + e);
world.setBlockToAir(placement_pos);
return spit_out(facing);
}
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);
} else {
// No idea if this is a particulary good idea, as getBlockFromITem
//println("SPIT NON ITEMBLOCK" + current_stack + " --> " + block + " at " + placement_pos.subtract(pos) + "( item=" + item + ")");
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;
}

View file

@ -96,18 +96,22 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
public static final int TICK_INTERVAL = 5;
public static final int BOOST_FACTOR = 6;
public static final int DEFAULT_BOOST_ENERGY = 64;
public static final int DEFAULT_CUTTING_TIME_NEEDED = 20 * 60; // 60 secs, so that people don't come to the bright idea to carry one with them.
public static final int DEFAULT_CUTTING_TIME_NEEDED = 60; // 60 secs, so that people don't come to the bright idea to carry one with them.
private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY;
private static int cutting_time_needed = DEFAULT_CUTTING_TIME_NEEDED;
private static int cutting_time_needed = 20 * DEFAULT_CUTTING_TIME_NEEDED;
private static boolean requires_power = false;
private int tick_timer_;
private int active_timer_;
private int proc_time_elapsed_; // small, not saved in nbt.
private int boost_energy_; // small, not saved in nbt.
public static void on_config(int boost_energy_per_tick)
public static void on_config(int boost_energy_per_tick, int cutting_time_seconds, boolean power_required)
{
boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512);
ModEngineersDecor.logger.info("Config tree cutter: Boost energy consumption:" + boost_energy_consumption + "rf/t");
cutting_time_needed = 20 * MathHelper.clamp(cutting_time_seconds, 10, 240);
requires_power = power_required;
ModEngineersDecor.logger.info("Config tree cutter: Boost energy consumption:" + boost_energy_consumption + "rf/t" + (requires_power?" (power required for operation) ":"") + ", cutting time " + cutting_time_needed + "t." );
}
public BTileEntity()
@ -188,15 +192,24 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) {
if(device_state.getValue(ACTIVE)) world.setBlockState(pos, device_state.withProperty(ACTIVE, false), 1|2);
proc_time_elapsed_ = 0;
active_timer_ = 0;
tick_timer_ = IDLE_TICK_INTERVAL;
return;
}
proc_time_elapsed_ += TICK_INTERVAL;
if(boost_energy_ >= boost_energy_consumption) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL*BOOST_FACTOR; }
boolean active = true;
if(boost_energy_ >= boost_energy_consumption) {
boost_energy_ = 0;
proc_time_elapsed_ += TICK_INTERVAL*BOOST_FACTOR;
active_timer_ = 2;
} else if(!requires_power) {
active_timer_ = 1024;
} else if(active_timer_ > 0) {
--active_timer_;
}
boolean active = (active_timer_ > 0);
if(proc_time_elapsed_ >= cutting_time_needed) {
proc_time_elapsed_ = 0;
TreeCutting.chopTree(world, tree_state, tree_pos, 512, false);
TreeCutting.chopTree(world, tree_state, tree_pos, 2048, false);
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_WOOD_BREAK, SoundCategory.BLOCKS, 1.0f, 1.0f);
active = false;
}

View file

@ -20,6 +20,7 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -52,6 +53,14 @@ public class ModConfig
@Config.RequiresMcRestart
public String includes = "";
@Config.Comment({"Disable CTRL-SHIFT item tooltip display."})
@Config.Name("Without tooltips")
public boolean without_tooltips = false;
@Config.Comment({"Disable all tile entity special renderers."})
@Config.Name("Without TESRs")
public boolean without_tesrs = false;
@Config.Comment({"Disable clinker bricks and derived blocks."})
@Config.Name("Without clinker bricks")
@Config.RequiresMcRestart
@ -87,20 +96,10 @@ public class ModConfig
@Config.RequiresMcRestart
public boolean without_panzer_glass = false;
@Config.Comment({"Disable treated wood crafting table."})
@Config.Name("Without crafting table")
@Config.Comment({"Disable ladders"})
@Config.Name("Without ladders")
@Config.RequiresMcRestart
public boolean without_crafting_table = false;
@Config.Comment({"Disable small lab furnace."})
@Config.Name("Without lab furnace")
@Config.RequiresMcRestart
public boolean without_lab_furnace = false;
@Config.Comment({"Disable small electrical pass-through furnace."})
@Config.Name("Without electrical furnace")
@Config.RequiresMcRestart
public boolean without_electrical_furnace = false;
public boolean without_ladders = false;
@Config.Comment({"Disable treated wood table, stool, windowsill, etc."})
@Config.Name("Without tr. wood furniture")
@ -117,26 +116,50 @@ public class ModConfig
@Config.RequiresMcRestart
public boolean without_light_sources = false;
@Config.Comment({"Disable ladders"})
@Config.Name("Without ladders")
@Config.Comment({"Disable horizontal half-block slab."})
@Config.Name("Without slabs")
@Config.RequiresMcRestart
public boolean without_ladders = false;
public boolean without_slabs = false;
@Config.Comment({"Disable possibility to sit on stools and chairs."})
@Config.Name("Without chair sitting")
public boolean without_chair_sitting = false;
@Config.Comment({"Disable stackable 1/8 block slices."})
@Config.Name("Without slab slices")
@Config.RequiresMcRestart
public boolean without_halfslabs = false;
@Config.Comment({"Disable that mobs will sit on chairs and stools."})
@Config.Name("Without chair mob sitting")
public boolean without_mob_chair_sitting = false;
@Config.Comment({"Disable poles of any material."})
@Config.Name("Without poles")
@Config.RequiresMcRestart
public boolean without_poles = false;
@Config.Comment({"Disable the speed boost of ladders in this mod."})
@Config.Name("Without ladder speed boost")
public boolean without_ladder_speed_boost = false;
@Config.Comment({"Disable horizontal supports like the double-T support."})
@Config.Name("Without h. supports")
@Config.RequiresMcRestart
public boolean without_hsupports = false;
@Config.Comment({"Disable history refabrication feature of the treated wood crafting table."})
@Config.Name("Without crafting table history")
public boolean without_crafting_table_history = false;
@Config.Comment({"Disable decorative sign plates (caution, hazards, etc)."})
@Config.Name("Without signs")
@Config.RequiresMcRestart
public boolean without_sign_plates = false;
@Config.Comment({"Disable the Floor Grating."})
@Config.Name("Without floor gratings")
@Config.RequiresMcRestart
public boolean without_floor_grating = false;
@Config.Comment({"Disable treated wood crafting table."})
@Config.Name("Without crafting table")
@Config.RequiresMcRestart
public boolean without_crafting_table = false;
@Config.Comment({"Disable small lab furnace."})
@Config.Name("Without lab furnace")
@Config.RequiresMcRestart
public boolean without_lab_furnace = false;
@Config.Comment({"Disable small electrical pass-through furnace."})
@Config.Name("Without electrical furnace")
@Config.RequiresMcRestart
public boolean without_electrical_furnace = false;
@Config.Comment({"Disable check valve, and redstone controlled valves."})
@Config.Name("Without valves")
@ -153,11 +176,6 @@ public class ModConfig
@Config.RequiresMcRestart
public boolean without_waste_incinerator = false;
@Config.Comment({"Disable decorative sign plates (caution, hazards, etc)."})
@Config.Name("Without signs")
@Config.RequiresMcRestart
public boolean without_sign_plates = false;
@Config.Comment({"Disable the factory dropper."})
@Config.Name("Without factory dropper")
@Config.RequiresMcRestart
@ -169,42 +187,49 @@ public class ModConfig
public boolean without_factory_hopper = false;
@Config.Comment({"Disable the Factory Block Placer."})
@Config.Name("Without factory placer")
@Config.Name("Without block placer")
@Config.RequiresMcRestart
public boolean without_factory_placer = false;
@Config.Comment({"Disable horizontal half-block slab."})
@Config.Name("Without slabs")
@Config.Comment({"Disable the Small Block Breaker."})
@Config.Name("Without block breaker")
@Config.RequiresMcRestart
public boolean without_slabs = false;
public boolean without_block_breaker = false;
@Config.Comment({"Disable stackable 1/8 block slices."})
@Config.Name("Without slab slices")
@Config.Comment({"Disable the Small Solar Panel."})
@Config.Name("Without solar panel")
@Config.RequiresMcRestart
public boolean without_halfslabs = false;
public boolean without_solar_panel = false;
@Config.Comment({"Disable directly picking up layers from slabs and slab " +
"slices by left clicking while looking up/down."})
@Config.Comment({"Disable the Small Fluid Collection Funnel."})
@Config.Name("Without fluid collector")
@Config.RequiresMcRestart
public boolean without_fluid_funnel = false;
@Config.Comment({"Disable the Small Mineral Smelter."})
@Config.Name("Without mineral smelter")
@Config.RequiresMcRestart
public boolean without_mineral_smelter = false;
@Config.Comment({"Disable directly picking up layers from slabs and slab slices by left clicking while looking up/down."})
@Config.Name("Without slab pickup")
public boolean without_direct_slab_pickup = false;
@Config.Comment({"Disable poles of any material."})
@Config.Name("Without poles")
@Config.RequiresMcRestart
public boolean without_poles = false;
@Config.Comment({"Disable possibility to sit on stools and chairs."})
@Config.Name("Without chair sitting")
public boolean without_chair_sitting = false;
@Config.Comment({"Disable horizontal supports like the double-T support."})
@Config.Name("Without h. supports")
@Config.RequiresMcRestart
public boolean without_hsupports = false;
@Config.Comment({"Disable that mobs will sit on chairs and stools."})
@Config.Name("Without chair mob sitting")
public boolean without_mob_chair_sitting = false;
@Config.Comment({"Disable CTRL-SHIFT item tooltip display."})
@Config.Name("Without tooltips")
public boolean without_tooltips = false;
@Config.Comment({"Disable the speed boost of ladders in this mod."})
@Config.Name("Without ladder speed boost")
public boolean without_ladder_speed_boost = false;
@Config.Comment({"Disable all tile entity special renderers."})
@Config.Name("Without TESRs")
public boolean without_tesrs = false;
@Config.Comment({"Disable history refabrication feature of the treated wood crafting table."})
@Config.Name("Without crafting table history")
public boolean without_crafting_table_history = false;
}
@Config.Comment({
@ -346,6 +371,51 @@ public class ModConfig
@Config.Name("Solar panel: Peak power")
@Config.RangeInt(min=5, max=128)
public int solar_panel_peak_power = BlockDecorSolarPanel.BTileEntity.DEFAULT_PEAK_POWER;
@Config.Comment({
"Defines how much RF power the Small Block Breaker requires to magnificently increase the processing speed. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Power consumption")
@Config.RangeInt(min=16, max=512)
public int block_breaker_power_consumption = BlockDecorBreaker.BTileEntity.DEFAULT_BOOST_ENERGY;
@Config.Comment({
"Defines how much time the Small Block Breaker needs per block hardness, " +
"means: 'reluctance' * hardness + min_time, you change the 'reluctance' here." +
"The unit is ticks/hardness. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Breaking reluctance")
@Config.RangeInt(min=5, max=50)
public int block_breaker_reluctance = BlockDecorBreaker.BTileEntity.DEFAULT_BREAKING_RELUCTANCE;
@Config.Comment({
"Defines how much time the Small Block Breaker needs at least, better said it's an offset: " +
"'reluctance' * hardness + min_time, you change the 'min_time' here, value " +
"in ticks." +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Min breaking time")
@Config.RangeInt(min=10, max=100)
public int block_breaker_min_breaking_time = BlockDecorBreaker.BTileEntity.DEFAULT_MIN_BREAKING_TIME;
@Config.Comment({
"Defines how much RF power the Small Tree Cutter requires to magnificently increase the processing speed. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Tree Cutter: Power consumption")
@Config.RangeInt(min=16, max=512)
public int tree_cuttter_energy_consumption = BlockDecorTreeCutter.BTileEntity.DEFAULT_BOOST_ENERGY;
@Config.Comment({
"Defines how much time the Small Tree Cutter needs to cut a tree without RF power. " +
"The value is in seconds. With energy it is 6 times faster. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Tree Cutter: Cutting time")
@Config.RangeInt(min=10, max=240)
public int tree_cuttter_cutting_time_needed = BlockDecorTreeCutter.BTileEntity.DEFAULT_CUTTING_TIME_NEEDED;
}
@SuppressWarnings("unused")
@ -409,6 +479,11 @@ public class ModConfig
excludes_.clear();
}
// Early non-opt out type based evaluation
if(block instanceof BlockDecorHalfSlab) return optout.without_halfslabs;
if(block instanceof BlockDecorLadder) return optout.without_ladders;
if(block instanceof BlockDecorWindow) return optout.without_windows;
if(block instanceof BlockDecorHorizontalSupport) return optout.without_hsupports;
if(block instanceof BlockDecorFloorGrating) return optout.without_floor_grating;
if(block instanceof BlockDecorCraftingTable) return optout.without_crafting_table;
if(block instanceof BlockDecorFurnaceElectrical) return optout.without_electrical_furnace;
if((block instanceof BlockDecorFurnace) && (!(block instanceof BlockDecorFurnaceElectrical))) return optout.without_lab_furnace;
@ -417,11 +492,12 @@ public class ModConfig
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;
if(block instanceof BlockDecorBreaker) return optout.without_block_breaker;
if(block instanceof BlockDecorSolarPanel) return optout.without_solar_panel;
if(block instanceof BlockDecorFluidFunnel) return optout.without_fluid_funnel;
if(block instanceof BlockDecorMineralSmelter) return optout.without_mineral_smelter;
if(block instanceof BlockDecorPipeValve) return optout.without_valves;
if(block instanceof BlockDecorHorizontalSupport) return optout.without_hsupports;
// Type based evaluation where later filters may match, too
if(optout.without_slabs && (block instanceof BlockDecorSlab)) return true;
if(optout.without_stairs && (block instanceof BlockDecorStairs)) return true;
@ -461,6 +537,8 @@ public class ModConfig
BlockDecorPipeValve.on_config(tweaks.pipevalve_max_flowrate, tweaks.pipevalve_redstone_slope);
BlockDecorFurnaceElectrical.BTileEntity.on_config(tweaks.e_furnace_speed_percent, tweaks.e_furnace_power_consumption);
BlockDecorSolarPanel.BTileEntity.on_config(tweaks.solar_panel_peak_power);
BlockDecorBreaker.BTileEntity.on_config(tweaks.block_breaker_power_consumption, tweaks.block_breaker_reluctance, tweaks.block_breaker_min_breaking_time, false);
BlockDecorTreeCutter.BTileEntity.on_config(tweaks.tree_cuttter_energy_consumption, tweaks.tree_cuttter_cutting_time_needed, false);
{
optout.includes = optout.includes.toLowerCase().replaceAll(ModEngineersDecor.MODID+":", "").replaceAll("[^*_,a-z0-9]", "");
if(!optout.includes.isEmpty()) ModEngineersDecor.logger.info("Pattern includes: '" + optout.includes + "'");

View file

@ -138,7 +138,7 @@ public class TreeCutting
final int dx = Math.abs(pos.getX()-start.getX());
final int dz = Math.abs(pos.getZ()-start.getZ());
if(dy > max_cutting_radius) dy = max_cutting_radius;
if((dx >= dy+3) || (dz >= dy+3)) return true;
if((dx >= dy+4) || (dz >= dy+4)) return true;
return false;
}
@ -152,60 +152,61 @@ public class TreeCutting
{
if((Compat.canChop(broken_state))) return Compat.chop(world, broken_state, startPos, max_blocks_to_break, without_target_block);
if(!BlockCategories.isLog(broken_state)) return 0;
final long ymin = startPos.getY();
final long max_leaf_distance = 6;
Set<BlockPos> checked = new HashSet<BlockPos>();
ArrayList<BlockPos> to_break = new ArrayList<BlockPos>();
ArrayList<BlockPos> to_decay = new ArrayList<BlockPos>();
checked.add(startPos);
// Initial simple layer-up search of same logs. This forms the base corpus, and only leaves and
// leaf-enclosed logs attached to this corpus may be broken/decayed.
{
LinkedList<BlockPos> queue = new LinkedList<BlockPos>();
LinkedList<BlockPos> upqueue = new LinkedList<BlockPos>();
queue.add(startPos);
int cutlevel = 0;
int steps_left = max_log_tracing_steps;
IBlockState tracked_leaves_state = null;
while(!queue.isEmpty() && (--steps_left >= 0)) {
while(!queue.isEmpty() && (--steps_left >= 0) && (to_break.size()<max_blocks_to_break)) {
final BlockPos pos = queue.removeFirst();
if(checked.contains(pos)) continue;
checked.add(pos);
if(too_far(startPos, pos)) continue;
// Vertical search
final BlockPos uppos = pos.up();
if(too_far(startPos, uppos)) { checked.add(uppos); continue; }
final IBlockState upstate = world.getBlockState(uppos);
if(!checked.contains(uppos)) {
checked.add(uppos);
if(BlockCategories.isSameLog(upstate, broken_state)) {
// Up is log
upqueue.add(uppos);
to_break.add(uppos);
steps_left = max_log_tracing_steps;
} else {
boolean isleaf = BlockCategories.isLeaves(upstate);
if(isleaf || world.isAirBlock(uppos) || (upstate.getBlock() instanceof BlockVine)) {
if(isleaf) {
if(tracked_leaves_state==null) {
tracked_leaves_state=upstate;
to_decay.add(uppos);
} else if(BlockCategories.isSameLeaves(upstate, tracked_leaves_state)) {
to_decay.add(uppos);
}
if(BlockCategories.isSameLog(upstate, broken_state)) {
queue.add(uppos);
to_break.add(uppos);
steps_left = max_log_tracing_steps;
} else {
boolean isleaf = BlockCategories.isLeaves(upstate);
if(isleaf || world.isAirBlock(uppos) || (upstate.getBlock() instanceof BlockVine)) {
if(isleaf) {
if(tracked_leaves_state==null) {
tracked_leaves_state=upstate;
to_decay.add(uppos);
queue.add(uppos);
} else if(BlockCategories.isSameLeaves(upstate, tracked_leaves_state)) {
to_decay.add(uppos);
queue.add(uppos);
} else {
checked.add(uppos); // no block of interest
}
// Up is air, check adjacent for diagonal up (e.g. Accacia)
for(Vec3i v:hoffsets) {
final BlockPos p = uppos.add(v);
if(checked.contains(p)) continue;
checked.add(p);
final IBlockState st = world.getBlockState(p);
final Block bl = st.getBlock();
if(BlockCategories.isSameLog(st, broken_state)) {
queue.add(p);
to_break.add(p);
} else if(BlockCategories.isLeaves(st)) {
if((tracked_leaves_state==null) || (BlockCategories.isSameLeaves(st, tracked_leaves_state))) {
to_decay.add(p);
}
} else {
checked.add(uppos);
}
// Up is air, check adjacent for diagonal up (e.g. Accacia)
for(Vec3i v:hoffsets) {
final BlockPos p = uppos.add(v);
final IBlockState st = world.getBlockState(p);
if(BlockCategories.isSameLog(st, broken_state)) {
queue.add(p);
to_break.add(p);
} else if(BlockCategories.isLeaves(st)) {
if(tracked_leaves_state==null) {
tracked_leaves_state=st;
to_decay.add(p);
} else if(BlockCategories.isSameLeaves(st, tracked_leaves_state)) {
to_decay.add(p);
} else {
checked.add(uppos);
}
} else {
checked.add(uppos);
}
}
}
@ -214,63 +215,63 @@ public class TreeCutting
for(Vec3i v:hoffsets) {
final BlockPos p = pos.add(v);
if(checked.contains(p)) continue;
checked.add(p);
final IBlockState st = world.getBlockState(p);
final Block bl = st.getBlock();
if(BlockCategories.isSameLog(st, broken_state)) {
queue.add(p);
to_break.add(p);
} else if(BlockCategories.isLeaves(st)) {
if((tracked_leaves_state==null) || (BlockCategories.isSameLeaves(st, tracked_leaves_state))) {
to_decay.add(p);
} else {
checked.add(p);
}
} else {
checked.add(p);
}
}
if(queue.isEmpty() && (!upqueue.isEmpty())) {
queue = upqueue;
upqueue = new LinkedList<BlockPos>();
++cutlevel;
}
}
// Determine lose logs between the leafs
{
for(BlockPos pos:to_decay) {
int distance = 2;
to_break.addAll(findBlocksAround(world, pos, broken_state, checked, distance));
}
if(!to_decay.isEmpty()) {
final IBlockState leaf_type_state = world.getBlockState(to_decay.get(0));
final ArrayList<BlockPos> leafs = to_decay;
to_decay = new ArrayList<BlockPos>();
for(BlockPos pos:leafs) {
int dist = 3;
to_decay.add(pos);
to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, dist));
}
}
}
// Break blocks
{
// Determine lose logs between the leafs
if(without_target_block) {
checked.remove(startPos);
} else {
to_break.add(startPos);
}
int num_broken = 0;
Collections.reverse(to_break);
for(BlockPos pos:to_break) {
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
for(BlockPos pos:to_decay) {
int dist = 1;
to_break.addAll(findBlocksAround(world, pos, broken_state, checked, dist));
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
}
if(!to_decay.isEmpty()) {
final IBlockState leaf_type_state = world.getBlockState(to_decay.get(0));
final ArrayList<BlockPos> leafs = to_decay;
to_decay = new ArrayList<BlockPos>();
for(BlockPos pos:leafs) {
int dist = 2;
to_decay.add(pos);
to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, dist));
}
}
if(without_target_block) {
checked.remove(startPos);
} else {
to_break.add(startPos);
}
int num_broken = 0;
Collections.reverse(to_break);
for(BlockPos pos:to_break) {
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
for(BlockPos pos:to_decay) {
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
// And the bill.
{
// And now the bill.
return MathHelper.clamp(((to_break.size()*6/5)+(to_decay.size()/10)-1), 1, 65535);
}
}

View file

@ -128,22 +128,22 @@
}
},
{
"from": [4, 9.5, -2],
"to": [5, 10.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, 2.5, 5.5]},
"from": [4, 9.5, 0],
"to": [5, 10.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, 2.5, 6.5]},
"faces": {
"north": {"uv": [11, 5.5, 12, 6.5], "texture": "#sh"},
"east": {"uv": [16, 5.5, 16, 6.5], "texture": "#sh"},
"east": {"uv": [15.5, 5.5, 16, 6.5], "texture": "#sh"},
"south": {"uv": [4, 5.5, 5, 6.5], "texture": "#sh"},
"west": {"uv": [0, 5.5, 0, 6.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0], "texture": "#sh"},
"down": {"uv": [4, 16, 5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 5.5, 0.5, 6.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0.5], "texture": "#sh"},
"down": {"uv": [4, 15.5, 5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [3, 7, 0.5],
"from": [3, 7, 1.5],
"to": [3.5, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [2.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [2.5, 1, 6]},
"faces": {
"north": {"uv": [12.5, 7, 13, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -154,9 +154,9 @@
}
},
{
"from": [2.5, 6, -0.5],
"to": [6.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 6.5]},
"from": [2.5, 6, 0.5],
"to": [6.5, 10, 1.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 7.5]},
"faces": {
"north": {"uv": [11, 11, 15, 15], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 10], "texture": "#sh"},
@ -167,113 +167,113 @@
}
},
{
"from": [2.5, 9, -2],
"to": [3.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, 2, 5.5]},
"from": [2.5, 9, 0],
"to": [3.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, 2, 6.5]},
"faces": {
"north": {"uv": [12.5, 6, 13.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [2.5, 6, 3.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [3, 2, 4, 3], "texture": "#sh"},
"down": {"uv": [2.5, 16, 3.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0.5], "texture": "#sh"},
"down": {"uv": [2.5, 15.5, 3.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [2, 7.5, -2],
"to": [3, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 0.5, 5.5]},
"from": [2, 7.5, 0],
"to": [3, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 0.5, 6.5]},
"faces": {
"north": {"uv": [13, 7.5, 14, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [2, 7.5, 3, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [2, 0, 3, 0], "texture": "#sh"},
"down": {"uv": [2, 16, 3, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [2, 0, 3, 0.5], "texture": "#sh"},
"down": {"uv": [2, 15.5, 3, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [2.5, 6, -2],
"to": [3.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, -1, 5.5]},
"from": [2.5, 6, 0],
"to": [3.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, -1, 6.5]},
"faces": {
"north": {"uv": [12.5, 9, 13.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [2.5, 9, 3.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0], "texture": "#sh"},
"down": {"uv": [2.5, 16, 3.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0.5], "texture": "#sh"},
"down": {"uv": [2.5, 15.5, 3.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [4, 5.5, -2],
"to": [5, 6.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, -1.5, 5.5]},
"from": [4, 5.5, 0],
"to": [5, 6.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, -1.5, 6.5]},
"faces": {
"north": {"uv": [11, 9.5, 12, 10.5], "texture": "#sh"},
"east": {"uv": [16, 9.5, 16, 10.5], "texture": "#sh"},
"east": {"uv": [15.5, 9.5, 16, 10.5], "texture": "#sh"},
"south": {"uv": [4, 9.5, 5, 10.5], "texture": "#sh"},
"west": {"uv": [0, 9.5, 0, 10.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0], "texture": "#sh"},
"down": {"uv": [4, 16, 5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9.5, 0.5, 10.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0.5], "texture": "#sh"},
"down": {"uv": [4, 15.5, 5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 6, -2],
"to": [6.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, -1, 5.5]},
"from": [5.5, 6, 0],
"to": [6.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, -1, 6.5]},
"faces": {
"north": {"uv": [9.5, 9, 10.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [5.5, 9, 6.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0], "texture": "#sh"},
"down": {"uv": [5.5, 16, 6.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0.5], "texture": "#sh"},
"down": {"uv": [5.5, 15.5, 6.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 9, -2],
"to": [6.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, 2, 5.5]},
"from": [5.5, 9, 0],
"to": [6.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, 2, 6.5]},
"faces": {
"north": {"uv": [9.5, 6, 10.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [5.5, 6, 6.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0], "texture": "#sh"},
"down": {"uv": [5.5, 16, 6.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0.5], "texture": "#sh"},
"down": {"uv": [5.5, 15.5, 6.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [6, 7.5, -2],
"to": [7, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, 0.5, 5.5]},
"from": [6, 7.5, 0],
"to": [7, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, 0.5, 6.5]},
"faces": {
"north": {"uv": [9, 7.5, 10, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [6, 7.5, 7, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [6, 0, 7, 0], "texture": "#sh"},
"down": {"uv": [6, 16, 7, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [6, 0, 7, 0.5], "texture": "#sh"},
"down": {"uv": [6, 15.5, 7, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 7, 0.5],
"from": [5.5, 7, 1.5],
"to": [6, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [5.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [5.5, 1, 6]},
"faces": {
"north": {"uv": [10, 7, 10.5, 9], "texture": "#sh"},
"east": {"uv": [8, 7, 14.5, 9], "texture": "#sh"},
"south": {"uv": [5.5, 7, 6, 9], "texture": "#sh"},
"west": {"uv": [0.5, 7, 7, 9], "texture": "#sh"},
"up": {"uv": [5, 2, 11.5, 2.5], "texture": "#sh"},
"up": {"uv": [5, 2, 11.5, 2.5], "rotation": 90, "texture": "#sh"},
"down": {"uv": [5.5, 9, 6, 15.5], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [3.5, 6.5, 0.5],
"from": [3.5, 6.5, 1.5],
"to": [5.5, 9.5, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 1, 6]},
"faces": {
"north": {"uv": [10.5, 6.5, 12.5, 9.5], "texture": "#sh"},
"east": {"uv": [9, 6.5, 15.5, 9.5], "texture": "#sh"},
@ -284,9 +284,9 @@
}
},
{
"from": [12.5, 7, 0.5],
"from": [12.5, 7, 1.5],
"to": [13, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 6]},
"faces": {
"north": {"uv": [3, 7, 3.5, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -297,9 +297,9 @@
}
},
{
"from": [10.5, 6.5, 0.5],
"from": [10.5, 6.5, 1.5],
"to": [12.5, 9.5, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, 1, 6]},
"faces": {
"north": {"uv": [3.5, 6.5, 5.5, 9.5], "texture": "#sh"},
"east": {"uv": [9, 6.5, 15.5, 9.5], "texture": "#sh"},
@ -310,9 +310,9 @@
}
},
{
"from": [10, 7, 0.5],
"from": [10, 7, 1.5],
"to": [10.5, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [9.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [9.5, 1, 6]},
"faces": {
"north": {"uv": [5.5, 7, 6, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -323,9 +323,9 @@
}
},
{
"from": [9.5, 6, -0.5],
"to": [13.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19.5, 1, 6.5]},
"from": [9.5, 6, 0.5],
"to": [13.5, 10, 1.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19.5, 1, 7.5]},
"faces": {
"north": {"uv": [10, 12, 14, 16], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 10], "texture": "#sh"},
@ -336,107 +336,107 @@
}
},
{
"from": [12.5, 9, -2],
"to": [13.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, 2, 5.5]},
"from": [12.5, 9, 0],
"to": [13.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, 2, 6.5]},
"faces": {
"north": {"uv": [2.5, 6, 3.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [12.5, 6, 13.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0], "texture": "#sh"},
"down": {"uv": [12.5, 16, 13.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0.5], "texture": "#sh"},
"down": {"uv": [12.5, 15.5, 13.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [11, 9.5, -2],
"to": [12, 10.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, 2.5, 5.5]},
"from": [11, 9.5, 0],
"to": [12, 10.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, 2.5, 6.5]},
"faces": {
"north": {"uv": [4, 5.5, 5, 6.5], "texture": "#sh"},
"east": {"uv": [16, 5.5, 16, 6.5], "texture": "#sh"},
"east": {"uv": [15.5, 5.5, 16, 6.5], "texture": "#sh"},
"south": {"uv": [11, 5.5, 12, 6.5], "texture": "#sh"},
"west": {"uv": [0, 5.5, 0, 6.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0], "texture": "#sh"},
"down": {"uv": [11, 16, 12, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 5.5, 0.5, 6.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0.5], "texture": "#sh"},
"down": {"uv": [11, 15.5, 12, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9.5, 9, -2],
"to": [10.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, 2, 5.5]},
"from": [9.5, 9, 0],
"to": [10.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, 2, 6.5]},
"faces": {
"north": {"uv": [5.5, 6, 6.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [9.5, 6, 10.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0], "texture": "#sh"},
"down": {"uv": [9.5, 16, 10.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0.5], "texture": "#sh"},
"down": {"uv": [9.5, 15.5, 10.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9, 7.5, -2],
"to": [10, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17, 0.5, 5.5]},
"from": [9, 7.5, 0],
"to": [10, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17, 0.5, 6.5]},
"faces": {
"north": {"uv": [6, 7.5, 7, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [9, 7.5, 10, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [9, 0, 10, 0], "texture": "#sh"},
"down": {"uv": [9, 16, 10, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [9, 0, 10, 0.5], "texture": "#sh"},
"down": {"uv": [9, 15.5, 10, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9.5, 6, -2],
"to": [10.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, -1, 5.5]},
"from": [9.5, 6, 0],
"to": [10.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, -1, 6.5]},
"faces": {
"north": {"uv": [5.5, 9, 6.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [9.5, 9, 10.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0], "texture": "#sh"},
"down": {"uv": [9.5, 16, 10.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0.5], "texture": "#sh"},
"down": {"uv": [9.5, 15.5, 10.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [11, 5.5, -2],
"to": [12, 6.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, -1.5, 5.5]},
"from": [11, 5.5, 0],
"to": [12, 6.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, -1.5, 6.5]},
"faces": {
"north": {"uv": [4, 9.5, 5, 10.5], "texture": "#sh"},
"east": {"uv": [16, 9.5, 16, 10.5], "texture": "#sh"},
"east": {"uv": [15.5, 9.5, 16, 10.5], "texture": "#sh"},
"south": {"uv": [11, 9.5, 12, 10.5], "texture": "#sh"},
"west": {"uv": [0, 9.5, 0, 10.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0], "texture": "#sh"},
"down": {"uv": [11, 16, 12, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9.5, 0.5, 10.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0.5], "texture": "#sh"},
"down": {"uv": [11, 15.5, 12, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [12.5, 6, -2],
"to": [13.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, -1, 5.5]},
"from": [12.5, 6, 0],
"to": [13.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, -1, 6.5]},
"faces": {
"north": {"uv": [2.5, 9, 3.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [12.5, 9, 13.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0], "texture": "#sh"},
"down": {"uv": [12.5, 16, 13.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0.5], "texture": "#sh"},
"down": {"uv": [12.5, 15.5, 13.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [13, 7.5, -2],
"to": [14, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [21, 0.5, 5.5]},
"from": [13, 7.5, 0],
"to": [14, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [21, 0.5, 6.5]},
"faces": {
"north": {"uv": [2, 7.5, 3, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [13, 7.5, 14, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [13, 0, 14, 0], "texture": "#sh"},
"down": {"uv": [13, 16, 14, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [13, 0, 14, 0.5], "texture": "#sh"},
"down": {"uv": [13, 15.5, 14, 16], "rotation": 270, "texture": "#sh"}
}
}
],

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.68
version_forge_minecraft=1.14.4-28.1.79
version_fml_mappings=20190719-1.14.3
version_jei=1.14.4:6.0.0.10
version_engineersdecor=1.0.15-b4
version_engineersdecor=1.0.16-b2

View file

@ -1,9 +1,10 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.14.4": {
"1.0.16-b1": "[U] Updated to Forge 1.14.4-28.1.79/20190719-1.14.3.\n[A] Added Fluid Collection Funnel.",
"1.0.15-b3": "[A] Added Small Block Breaker.\n[M] Mineral Smelter fluid handler/transfer added.",
"1.0.15-b2": "[!] Forge version requirement set to 1.14.4-28.1.68 or higher.\n[A] Added Factory Block Placer and Planter.\n[A] Added Small Tree Cutter.",
"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.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge 1.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.",
@ -30,6 +31,6 @@
},
"promos": {
"1.14.4-recommended": "",
"1.14.4-latest": "1.0.15-b3"
"1.14.4-latest": "1.0.16-b1"
}
}

View file

@ -11,7 +11,10 @@ Mod sources for Minecraft version 1.14.4.
## Version history
~ v1.0.15-b4 [A] Added Fluid Collection Funnel.
~ v1.0.16-b2 [F] Fixed Small Block Breaker active model updated.
- v1.0.16-b1 [U] Updated to Forge 1.14.4-28.1.79/20190719-1.14.3.
[A] Added Fluid Collection Funnel.
- v1.0.15-b3 [A] Added Small Block Breaker.
[M] Mineral Smelter fluid handler/transfer added.
@ -21,7 +24,7 @@ Mod sources for Minecraft version 1.14.4.
[A] Added Small Tree Cutter.
- v1.0.15-b1 [A] Added Floor Edge Light.
[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.
[U] Updated to Forge 1.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

@ -128,22 +128,22 @@
}
},
{
"from": [4, 9.5, -2],
"to": [5, 10.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, 2.5, 5.5]},
"from": [4, 9.5, 0],
"to": [5, 10.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, 2.5, 6.5]},
"faces": {
"north": {"uv": [11, 5.5, 12, 6.5], "texture": "#sh"},
"east": {"uv": [16, 5.5, 16, 6.5], "texture": "#sh"},
"east": {"uv": [15.5, 5.5, 16, 6.5], "texture": "#sh"},
"south": {"uv": [4, 5.5, 5, 6.5], "texture": "#sh"},
"west": {"uv": [0, 5.5, 0, 6.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0], "texture": "#sh"},
"down": {"uv": [4, 16, 5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 5.5, 0.5, 6.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0.5], "texture": "#sh"},
"down": {"uv": [4, 15.5, 5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [3, 7, 0.5],
"from": [3, 7, 1.5],
"to": [3.5, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [2.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [2.5, 1, 6]},
"faces": {
"north": {"uv": [12.5, 7, 13, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -154,9 +154,9 @@
}
},
{
"from": [2.5, 6, -0.5],
"to": [6.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 6.5]},
"from": [2.5, 6, 0.5],
"to": [6.5, 10, 1.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 7.5]},
"faces": {
"north": {"uv": [11, 11, 15, 15], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 10], "texture": "#sh"},
@ -167,113 +167,113 @@
}
},
{
"from": [2.5, 9, -2],
"to": [3.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, 2, 5.5]},
"from": [2.5, 9, 0],
"to": [3.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, 2, 6.5]},
"faces": {
"north": {"uv": [12.5, 6, 13.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [2.5, 6, 3.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [3, 2, 4, 3], "texture": "#sh"},
"down": {"uv": [2.5, 16, 3.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0.5], "texture": "#sh"},
"down": {"uv": [2.5, 15.5, 3.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [2, 7.5, -2],
"to": [3, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 0.5, 5.5]},
"from": [2, 7.5, 0],
"to": [3, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10, 0.5, 6.5]},
"faces": {
"north": {"uv": [13, 7.5, 14, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [2, 7.5, 3, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [2, 0, 3, 0], "texture": "#sh"},
"down": {"uv": [2, 16, 3, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [2, 0, 3, 0.5], "texture": "#sh"},
"down": {"uv": [2, 15.5, 3, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [2.5, 6, -2],
"to": [3.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, -1, 5.5]},
"from": [2.5, 6, 0],
"to": [3.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [10.5, -1, 6.5]},
"faces": {
"north": {"uv": [12.5, 9, 13.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [2.5, 9, 3.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0], "texture": "#sh"},
"down": {"uv": [2.5, 16, 3.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [2.5, 0, 3.5, 0.5], "texture": "#sh"},
"down": {"uv": [2.5, 15.5, 3.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [4, 5.5, -2],
"to": [5, 6.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, -1.5, 5.5]},
"from": [4, 5.5, 0],
"to": [5, 6.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [12, -1.5, 6.5]},
"faces": {
"north": {"uv": [11, 9.5, 12, 10.5], "texture": "#sh"},
"east": {"uv": [16, 9.5, 16, 10.5], "texture": "#sh"},
"east": {"uv": [15.5, 9.5, 16, 10.5], "texture": "#sh"},
"south": {"uv": [4, 9.5, 5, 10.5], "texture": "#sh"},
"west": {"uv": [0, 9.5, 0, 10.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0], "texture": "#sh"},
"down": {"uv": [4, 16, 5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9.5, 0.5, 10.5], "texture": "#sh"},
"up": {"uv": [4, 0, 5, 0.5], "texture": "#sh"},
"down": {"uv": [4, 15.5, 5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 6, -2],
"to": [6.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, -1, 5.5]},
"from": [5.5, 6, 0],
"to": [6.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, -1, 6.5]},
"faces": {
"north": {"uv": [9.5, 9, 10.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [5.5, 9, 6.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0], "texture": "#sh"},
"down": {"uv": [5.5, 16, 6.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0.5], "texture": "#sh"},
"down": {"uv": [5.5, 15.5, 6.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 9, -2],
"to": [6.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, 2, 5.5]},
"from": [5.5, 9, 0],
"to": [6.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [13.5, 2, 6.5]},
"faces": {
"north": {"uv": [9.5, 6, 10.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [5.5, 6, 6.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0], "texture": "#sh"},
"down": {"uv": [5.5, 16, 6.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [5.5, 0, 6.5, 0.5], "texture": "#sh"},
"down": {"uv": [5.5, 15.5, 6.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [6, 7.5, -2],
"to": [7, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, 0.5, 5.5]},
"from": [6, 7.5, 0],
"to": [7, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [14, 0.5, 6.5]},
"faces": {
"north": {"uv": [9, 7.5, 10, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [6, 7.5, 7, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [6, 0, 7, 0], "texture": "#sh"},
"down": {"uv": [6, 16, 7, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [6, 0, 7, 0.5], "texture": "#sh"},
"down": {"uv": [6, 15.5, 7, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [5.5, 7, 0.5],
"from": [5.5, 7, 1.5],
"to": [6, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [5.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [5.5, 1, 6]},
"faces": {
"north": {"uv": [10, 7, 10.5, 9], "texture": "#sh"},
"east": {"uv": [8, 7, 14.5, 9], "texture": "#sh"},
"south": {"uv": [5.5, 7, 6, 9], "texture": "#sh"},
"west": {"uv": [0.5, 7, 7, 9], "texture": "#sh"},
"up": {"uv": [5, 2, 11.5, 2.5], "texture": "#sh"},
"up": {"uv": [5, 2, 11.5, 2.5], "rotation": 90, "texture": "#sh"},
"down": {"uv": [5.5, 9, 6, 15.5], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [3.5, 6.5, 0.5],
"from": [3.5, 6.5, 1.5],
"to": [5.5, 9.5, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [4.5, 1, 6]},
"faces": {
"north": {"uv": [10.5, 6.5, 12.5, 9.5], "texture": "#sh"},
"east": {"uv": [9, 6.5, 15.5, 9.5], "texture": "#sh"},
@ -284,9 +284,9 @@
}
},
{
"from": [12.5, 7, 0.5],
"from": [12.5, 7, 1.5],
"to": [13, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [12.5, 1, 6]},
"faces": {
"north": {"uv": [3, 7, 3.5, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -297,9 +297,9 @@
}
},
{
"from": [10.5, 6.5, 0.5],
"from": [10.5, 6.5, 1.5],
"to": [12.5, 9.5, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [11.5, 1, 6]},
"faces": {
"north": {"uv": [3.5, 6.5, 5.5, 9.5], "texture": "#sh"},
"east": {"uv": [9, 6.5, 15.5, 9.5], "texture": "#sh"},
@ -310,9 +310,9 @@
}
},
{
"from": [10, 7, 0.5],
"from": [10, 7, 1.5],
"to": [10.5, 9, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [9.5, 1, 5]},
"rotation": {"angle": 0, "axis": "y", "origin": [9.5, 1, 6]},
"faces": {
"north": {"uv": [5.5, 7, 6, 9], "texture": "#sh"},
"east": {"uv": [9, 7, 15.5, 9], "texture": "#sh"},
@ -323,9 +323,9 @@
}
},
{
"from": [9.5, 6, -0.5],
"to": [13.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19.5, 1, 6.5]},
"from": [9.5, 6, 0.5],
"to": [13.5, 10, 1.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19.5, 1, 7.5]},
"faces": {
"north": {"uv": [10, 12, 14, 16], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 10], "texture": "#sh"},
@ -336,107 +336,107 @@
}
},
{
"from": [12.5, 9, -2],
"to": [13.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, 2, 5.5]},
"from": [12.5, 9, 0],
"to": [13.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, 2, 6.5]},
"faces": {
"north": {"uv": [2.5, 6, 3.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [12.5, 6, 13.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0], "texture": "#sh"},
"down": {"uv": [12.5, 16, 13.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0.5], "texture": "#sh"},
"down": {"uv": [12.5, 15.5, 13.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [11, 9.5, -2],
"to": [12, 10.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, 2.5, 5.5]},
"from": [11, 9.5, 0],
"to": [12, 10.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, 2.5, 6.5]},
"faces": {
"north": {"uv": [4, 5.5, 5, 6.5], "texture": "#sh"},
"east": {"uv": [16, 5.5, 16, 6.5], "texture": "#sh"},
"east": {"uv": [15.5, 5.5, 16, 6.5], "texture": "#sh"},
"south": {"uv": [11, 5.5, 12, 6.5], "texture": "#sh"},
"west": {"uv": [0, 5.5, 0, 6.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0], "texture": "#sh"},
"down": {"uv": [11, 16, 12, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 5.5, 0.5, 6.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0.5], "texture": "#sh"},
"down": {"uv": [11, 15.5, 12, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9.5, 9, -2],
"to": [10.5, 10, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, 2, 5.5]},
"from": [9.5, 9, 0],
"to": [10.5, 10, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, 2, 6.5]},
"faces": {
"north": {"uv": [5.5, 6, 6.5, 7], "texture": "#sh"},
"east": {"uv": [16, 6, 16, 7], "texture": "#sh"},
"east": {"uv": [15.5, 6, 16, 7], "texture": "#sh"},
"south": {"uv": [9.5, 6, 10.5, 7], "texture": "#sh"},
"west": {"uv": [0, 6, 0, 7], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0], "texture": "#sh"},
"down": {"uv": [9.5, 16, 10.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 6, 0.5, 7], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0.5], "texture": "#sh"},
"down": {"uv": [9.5, 15.5, 10.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9, 7.5, -2],
"to": [10, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17, 0.5, 5.5]},
"from": [9, 7.5, 0],
"to": [10, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17, 0.5, 6.5]},
"faces": {
"north": {"uv": [6, 7.5, 7, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [9, 7.5, 10, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [9, 0, 10, 0], "texture": "#sh"},
"down": {"uv": [9, 16, 10, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [9, 0, 10, 0.5], "texture": "#sh"},
"down": {"uv": [9, 15.5, 10, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [9.5, 6, -2],
"to": [10.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, -1, 5.5]},
"from": [9.5, 6, 0],
"to": [10.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [17.5, -1, 6.5]},
"faces": {
"north": {"uv": [5.5, 9, 6.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [9.5, 9, 10.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0], "texture": "#sh"},
"down": {"uv": [9.5, 16, 10.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [9.5, 0, 10.5, 0.5], "texture": "#sh"},
"down": {"uv": [9.5, 15.5, 10.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [11, 5.5, -2],
"to": [12, 6.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, -1.5, 5.5]},
"from": [11, 5.5, 0],
"to": [12, 6.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [19, -1.5, 6.5]},
"faces": {
"north": {"uv": [4, 9.5, 5, 10.5], "texture": "#sh"},
"east": {"uv": [16, 9.5, 16, 10.5], "texture": "#sh"},
"east": {"uv": [15.5, 9.5, 16, 10.5], "texture": "#sh"},
"south": {"uv": [11, 9.5, 12, 10.5], "texture": "#sh"},
"west": {"uv": [0, 9.5, 0, 10.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0], "texture": "#sh"},
"down": {"uv": [11, 16, 12, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9.5, 0.5, 10.5], "texture": "#sh"},
"up": {"uv": [11, 0, 12, 0.5], "texture": "#sh"},
"down": {"uv": [11, 15.5, 12, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [12.5, 6, -2],
"to": [13.5, 7, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, -1, 5.5]},
"from": [12.5, 6, 0],
"to": [13.5, 7, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [20.5, -1, 6.5]},
"faces": {
"north": {"uv": [2.5, 9, 3.5, 10], "texture": "#sh"},
"east": {"uv": [16, 9, 16, 10], "texture": "#sh"},
"east": {"uv": [15.5, 9, 16, 10], "texture": "#sh"},
"south": {"uv": [12.5, 9, 13.5, 10], "texture": "#sh"},
"west": {"uv": [0, 9, 0, 10], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0], "texture": "#sh"},
"down": {"uv": [12.5, 16, 13.5, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 9, 0.5, 10], "texture": "#sh"},
"up": {"uv": [12.5, 0, 13.5, 0.5], "texture": "#sh"},
"down": {"uv": [12.5, 15.5, 13.5, 16], "rotation": 270, "texture": "#sh"}
}
},
{
"from": [13, 7.5, -2],
"to": [14, 8.5, -0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [21, 0.5, 5.5]},
"from": [13, 7.5, 0],
"to": [14, 8.5, 0.5],
"rotation": {"angle": 0, "axis": "y", "origin": [21, 0.5, 6.5]},
"faces": {
"north": {"uv": [2, 7.5, 3, 8.5], "texture": "#sh"},
"east": {"uv": [16, 7.5, 16, 8.5], "texture": "#sh"},
"east": {"uv": [15.5, 7.5, 16, 8.5], "texture": "#sh"},
"south": {"uv": [13, 7.5, 14, 8.5], "texture": "#sh"},
"west": {"uv": [0, 7.5, 0, 8.5], "texture": "#sh"},
"up": {"uv": [13, 0, 14, 0], "texture": "#sh"},
"down": {"uv": [13, 16, 14, 16], "rotation": 270, "texture": "#sh"}
"west": {"uv": [0, 7.5, 0.5, 8.5], "texture": "#sh"},
"up": {"uv": [13, 0, 14, 0.5], "texture": "#sh"},
"down": {"uv": [13, 15.5, 14, 16], "rotation": 270, "texture": "#sh"}
}
}
],

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

View file

@ -25,3 +25,6 @@
![](engineers-decor-small-solar-panel.png)
![](engineers-decor-small-tree-cutter.png)
![](engineers-decor-mesh-fence.png)
![](engineers-decor-factory-block-placer.png)
![](engineers-decor-small-block-breaker.png)
![](engineers-decor-small-fluid-collection-funnel.png)

View file

@ -2,11 +2,12 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"promos": {
"1.12.2-recommended": "1.0.15",
"1.12.2-latest": "1.0.15",
"1.12.2-latest": "1.0.16-b1",
"1.14.4-recommended": "",
"1.14.4-latest": "1.0.15-b3"
"1.14.4-latest": "1.0.16-b1"
},
"1.12.2": {
"1.0.16-b1": "[A] Added Fluid Collection Funnel.\n[A] Added config opt-outs for Breaker, Placer, Fluid Funnel, Mineral Smelter.\n[A] Added configs tweaks for Small Block Breaker and Small Tree Cutter (cffr#185).\n[F] Fixed Block Placer discarding item metadata/variants while placing (issue #60).\n[F] Fixed Block Breaker duping empty shulker boxes, model updated.",
"1.0.15": "[R] Release based on v1.0.15-b2. Release-to-release changes: * Added Small Block Breaker * Small Tree Cutter fixes and compatability improved. * Crafting table compat fixes.\n[M] Small Tree Cutter log detection bug fixed (issue #59).\n[M] Small Tree Cutter supports Menril chopping (issue #54).",
"1.0.15-b2": "[A] Added Small Block Breaker\n[M] Crafting Table: Allowing NBT \"Damage\" mismatch only items that are declared damagable (issue #56).\n[M] Tree Cutter: Loosened the strict mod namespace requirement for Dynamic Trees log detection (issue #52) to enable checking DT compat mod log blocks.",
"1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.",
@ -71,9 +72,10 @@
"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.16-b1": "[U] Updated to Forge 1.14.4-28.1.79/20190719-1.14.3.\n[A] Added Fluid Collection Funnel.",
"1.0.15-b3": "[A] Added Small Block Breaker.\n[M] Mineral Smelter fluid handler/transfer added.",
"1.0.15-b2": "[!] Forge version requirement set to 1.14.4-28.1.68 or higher.\n[A] Added Factory Block Placer and Planter.\n[A] Added Small Tree Cutter.",
"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.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge 1.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.",