1.15: Forge 31.2.20 requirement declared. All: Placer checks for collidable entities (issue #98). Breaker drop trajectory tuned. Pipe valve Redstone connector conditions. All tickable TEs verify their current blockstate to prevent crashes when blocks are forcefully moved (issue #101).

This commit is contained in:
stfwi 2020-06-21 17:01:55 +02:00
parent f46b2b6bc7
commit e8f32e29a1
67 changed files with 219 additions and 125 deletions

View file

@ -63,7 +63,7 @@ run:
@$(GRADLE) runClient @$(GRADLE) runClient
sanitize: sanitize:
@echo "[1.12] Running sanatising tasks ..." @echo "[1.12] Running sanitising tasks ..."
@$(TASK) sanitize @$(TASK) sanitize
@$(TASK) sync-languages @$(TASK) sync-languages
@$(TASK) version-check @$(TASK) version-check

View file

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

View file

@ -1,6 +1,7 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.12.2": { "1.12.2": {
"1.1.0-b2": "[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[M] Changed Labeled Crate Nesting to circumvent server crashing in combination with the Sponge mod.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[M] Changed Labeled Crate Nesting to circumvent server crashing in combination with the Sponge mod.",
"1.0.20": "[R] Release based on v1.0.20-b6. Release-to-release changes: * Manual back ported. * Steel Mesh Fence Gate back ported. * E-Furnace speed selection switch back ported. * Labeled Crate back ported. * Minor bug fixes, compatibility changes.", "1.0.20": "[R] Release based on v1.0.20-b6. Release-to-release changes: * Manual back ported. * Steel Mesh Fence Gate back ported. * E-Furnace speed selection switch back ported. * Labeled Crate back ported. * Minor bug fixes, compatibility changes.",
"1.0.20-b6": "[F] Implemented compat related to issue #91.", "1.0.20-b6": "[F] Implemented compat related to issue #91.",
@ -90,6 +91,6 @@
}, },
"promos": { "promos": {
"1.12.2-recommended": "1.0.20", "1.12.2-recommended": "1.0.20",
"1.12.2-latest": "1.1.0-b1" "1.12.2-latest": "1.1.0-b2"
} }
} }

View file

@ -10,7 +10,8 @@ Mod sources for Minecraft version 1.12.2.
---- ----
## Version history ## Version history
~ v1.1.0-b2 [F] - v1.1.0-b2 [F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).
[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).
- v1.1.0-b1 [F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace). - v1.1.0-b1 [F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).
[M] Changed Labeled Crate Nesting to circumvent server crashing [M] Changed Labeled Crate Nesting to circumvent server crashing

View file

@ -266,15 +266,16 @@ public class BlockDecorBreaker extends BlockDecorDirectedHorizontal
public void update() public void update()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final IBlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BlockDecorBreaker)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) { if(world.isRemote) {
IBlockState state = world.getBlockState(pos); if(!device_state.getValue(ACTIVE)) {
if(!state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
// not sure if is so cool to do this each tick ... may be simplified/removed again. // not sure if is so cool to do this each tick ... may be simplified/removed again.
SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT; SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT;
SoundType stype = world.getBlockState(pos.offset(state.getValue(FACING))).getBlock().getSoundType(); SoundType stype = world.getBlockState(pos.offset(device_state.getValue(FACING))).getBlock().getSoundType();
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) { if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_CLOTH_HIT; sound = SoundEvents.BLOCK_CLOTH_HIT;
} else if((stype == SoundType.GROUND) || (stype == SoundType.SAND)) { } else if((stype == SoundType.GROUND) || (stype == SoundType.SAND)) {
@ -284,7 +285,6 @@ public class BlockDecorBreaker extends BlockDecorDirectedHorizontal
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.getValue(FACING)); final BlockPos target_pos = pos.offset(device_state.getValue(FACING));
final IBlockState target_state = world.getBlockState(target_pos); final IBlockState target_state = world.getBlockState(target_pos);
if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) { if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) {

View file

@ -801,6 +801,7 @@ public class BlockDecorDropper extends BlockDecorDirected
if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty(); if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof BlockDecorDropper)) return;
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0; final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode))); boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode)));

View file

@ -356,10 +356,12 @@ public class BlockDecorFluidFunnel extends BlockDecor
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL; collection_timer_ += TICK_INTERVAL;
final IBlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof BlockDecorFluidFunnel)) return;
boolean dirty = false; boolean dirty = false;
// Collection // Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.amount <= (TANK_CAPACITY-1000)))) { if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.amount <= (TANK_CAPACITY-1000)))) {
collection_timer_ = 0; collection_timer_ = 0;
if(!world.isBlockPowered(pos)) { // redstone disable feature if(!world.isBlockPowered(pos)) { // redstone disable feature
if(last_pick_pos_==null) last_pick_pos_ = pos.up(); if(last_pick_pos_==null) last_pick_pos_ = pos.up();
if(try_collect(pos.up())) dirty = true; if(try_collect(pos.up())) dirty = true;
@ -378,7 +380,6 @@ public class BlockDecorFluidFunnel extends BlockDecor
} }
// Block state // Block state
int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.amount/1000,0,FILL_LEVEL_MAX)); int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.amount/1000,0,FILL_LEVEL_MAX));
final IBlockState funnel_state = world.getBlockState(pos);
if(funnel_state.getValue(FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.withProperty(FILL_LEVEL, fill_level), 2|16); if(funnel_state.getValue(FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.withProperty(FILL_LEVEL, fill_level), 2|16);
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -809,6 +809,8 @@ public class BlockDecorFurnace extends BlockDecorDirected
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorFurnace)) return;
final boolean was_burning = isBurning(); final boolean was_burning = isBurning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(fuel_burntime_ < 0) fuel_burntime_ = getItemBurnTime(stacks_.get(SMELTING_FUEL_SLOT_NO)); if(fuel_burntime_ < 0) fuel_burntime_ = getItemBurnTime(stacks_.get(SMELTING_FUEL_SLOT_NO));
@ -866,10 +868,7 @@ public class BlockDecorFurnace extends BlockDecorDirected
} }
if(was_burning != isBurning()) { if(was_burning != isBurning()) {
dirty = true; dirty = true;
final IBlockState state = world.getBlockState(pos); world.setBlockState(pos, state.withProperty(LIT, isBurning()));
if(state.getBlock() instanceof BlockDecorFurnace) {
world.setBlockState(pos, state.withProperty(LIT, isBurning()));
}
} }
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -738,6 +738,7 @@ public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof BlockDecorFurnaceElectrical)) return;
final boolean was_burning = isBurning(); final boolean was_burning = isBurning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0; if(burntime_left_ < 0) burntime_left_ = 0;

View file

@ -831,12 +831,12 @@ public class BlockDecorHopper extends BlockDecorDirected
if((delay_timer_ > 0) && ((--delay_timer_) == 0)) markDirty(); if((delay_timer_ > 0) && ((--delay_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorHopper)) { block_power_signal_= false; return; }
// Cycle init // Cycle init
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0))); 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 hopper_facing = state.getValue(FACING); final EnumFacing hopper_facing = state.getValue(FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -531,6 +531,7 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
if((world.isRemote) || ((--tick_timer_ > 0))) return; if((world.isRemote) || ((--tick_timer_ > 0))) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState block_state = world.getBlockState(pos); final IBlockState block_state = world.getBlockState(pos);
if(!(block_state.getBlock() instanceof BlockDecorMilker)) return;
boolean dirty = false; boolean dirty = false;
if(energy_consumption > 0) { if(energy_consumption > 0) {
if(energy_stored_ <= 0) return; if(energy_stored_ <= 0) return;

View file

@ -627,6 +627,8 @@ public class BlockDecorMineralSmelter extends BlockDecorDirectedHorizontal
if(world.isRemote) return; if(world.isRemote) return;
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorMineralSmelter)) return;
boolean dirty = false; boolean dirty = false;
final int last_phase = phase(); final int last_phase = phase();
final ItemStack istack = stacks_.get(0); final ItemStack istack = stacks_.get(0);
@ -702,8 +704,7 @@ public class BlockDecorMineralSmelter extends BlockDecorDirectedHorizontal
} }
} }
} }
IBlockState state = world.getBlockState(pos); if(force_block_update_ || (state.getValue(PHASE) != new_phase)) {
if((state.getBlock() instanceof BlockDecorMineralSmelter) && (force_block_update_ || (state.getValue(PHASE) != new_phase))) {
state = state.withProperty(PHASE, new_phase); state = state.withProperty(PHASE, new_phase);
world.setBlockState(pos, state,3|16); world.setBlockState(pos, state,3|16);
world.notifyNeighborsOfStateChange(pos, state.getBlock(),false); world.notifyNeighborsOfStateChange(pos, state.getBlock(),false);

View file

@ -207,10 +207,10 @@ public class BlockDecorPassiveFluidAccumulator extends BlockDecorDirected
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = tick_idle_interval; tick_timer_ = tick_idle_interval;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorPassiveFluidAccumulator)) return;
if(!initialized_) { if(!initialized_) {
initialized_ = true; initialized_ = true;
IBlockState state = world.getBlockState(pos);
if((state==null) || (!(state.getBlock() instanceof BlockDecorPassiveFluidAccumulator))) return;
block_facing_ = state.getValue(FACING); block_facing_ = state.getValue(FACING);
} }
int n_requested = last_drain_request_amount_; int n_requested = last_drain_request_amount_;

View file

@ -720,7 +720,7 @@ public class BlockDecorPlacer extends BlockDecorDirected
} }
return spit_out(facing); return spit_out(facing);
} }
if(world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(placement_pos)).size() > 0) return false; if(world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(placement_pos), Entity::canBeCollidedWith).size() > 0) return false;
if(!world.getBlockState(placement_pos).getBlock().isReplaceable(world, placement_pos)) return false; if(!world.getBlockState(placement_pos).getBlock().isReplaceable(world, placement_pos)) return false;
try { try {
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world); final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
@ -748,12 +748,12 @@ public class BlockDecorPlacer extends BlockDecorDirected
if(world.isRemote) return; if(world.isRemote) return;
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorPlacer)) { block_power_signal_= false; return; }
// Cycle init // Cycle init
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0))); 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); final EnumFacing placer_facing = state.getValue(FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -167,6 +167,8 @@ public class BlockDecorSolarPanel extends BlockDecor
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorSolarPanel)) return;
current_feedin_ = 0; current_feedin_ = 0;
if(accumulated_power_ > 0) { if(accumulated_power_ > 0) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) { for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
@ -184,13 +186,11 @@ public class BlockDecorSolarPanel extends BlockDecor
if(!world.canSeeSky(pos)) { if(!world.canSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5; tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0; current_production_ = 0;
IBlockState state = world.getBlockState(pos);
if(state.getValue((EXPOSITION))!=2) world.setBlockState(pos, state.withProperty(EXPOSITION, 2)); if(state.getValue((EXPOSITION))!=2) world.setBlockState(pos, state.withProperty(EXPOSITION, 2));
return; return;
} }
if(--recalc_timer_ > 0) return; if(--recalc_timer_ > 0) return;
recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5)); recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5));
IBlockState state = world.getBlockState(pos);
int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360); int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360);
int e = 2; int e = 2;
if(theta > 340) e = 2; if(theta > 340) e = 2;
@ -199,7 +199,7 @@ public class BlockDecorSolarPanel extends BlockDecor
else if(theta < 100) e = 2; else if(theta < 100) e = 2;
else if(theta < 135) e = 3; else if(theta < 135) e = 3;
else if(theta < 190) e = 4; else if(theta < 190) e = 4;
IBlockState nstate = state.withProperty(EXPOSITION, e); final IBlockState nstate = state.withProperty(EXPOSITION, e);
if(nstate != state) world.setBlockState(pos, nstate, 1|2); if(nstate != state) world.setBlockState(pos, nstate, 1|2);
final double eff = (1.0-((world.getRainStrength(1f)*0.6)+(world.getThunderStrength(1f)*0.3))); final double eff = (1.0-((world.getRainStrength(1f)*0.6)+(world.getThunderStrength(1f)*0.3)));
final double rf = Math.sin((Math.PI/2) * Math.sqrt(((double)(((theta<0)||(theta>180))?(0):((theta>90)?(180-theta):(theta))))/90)); final double rf = Math.sin((Math.PI/2) * Math.sqrt(((double)(((theta<0)||(theta>180))?(0):((theta>90)?(180-theta):(theta))))/90));

View file

@ -215,8 +215,10 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
public void update() public void update()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final IBlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BlockDecorTreeCutter)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) { if(world.isRemote) {
if(!world.getBlockState(pos).getValue(ACTIVE)) { if(!device_state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
@ -224,7 +226,6 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final IBlockState device_state = world.getBlockState(pos);
final BlockPos tree_pos = pos.offset(device_state.getValue(FACING)); final BlockPos tree_pos = pos.offset(device_state.getValue(FACING));
final IBlockState tree_state = world.getBlockState(tree_pos); final IBlockState tree_state = world.getBlockState(tree_pos);
if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) { if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) {

View file

@ -656,6 +656,8 @@ public class BlockDecorWasteIncinerator extends BlockDecor
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(world.isRemote) return; if(world.isRemote) return;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorWasteIncinerator)) return;
boolean dirty = false; boolean dirty = false;
ItemStack processing_stack = stacks_.get(BURN_SLOT_NO); ItemStack processing_stack = stacks_.get(BURN_SLOT_NO);
final boolean was_processing = !processing_stack.isEmpty(); final boolean was_processing = !processing_stack.isEmpty();
@ -694,10 +696,7 @@ public class BlockDecorWasteIncinerator extends BlockDecor
} }
if((was_processing != is_processing) || (new_stack_processing)) { if((was_processing != is_processing) || (new_stack_processing)) {
if(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f); if(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f);
final IBlockState state = world.getBlockState(pos); world.setBlockState(pos, state.withProperty(LIT, is_processing), 2|16);
if(state.getBlock() instanceof BlockDecorWasteIncinerator) {
world.setBlockState(pos, state.withProperty(LIT, is_processing), 2|16);
}
} }
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -70,7 +70,7 @@ init:
@$(GRADLE) eclipse @$(GRADLE) eclipse
sanitize: sanitize:
@echo "[1.14] Running sanatising tasks ..." @echo "[1.14] Running sanitising tasks ..."
@$(TASK) sanitize @$(TASK) sanitize
@$(TASK) sync-languages @$(TASK) sync-languages
@$(TASK) version-check @$(TASK) version-check

View file

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

View file

@ -1,6 +1,7 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.14.4": { "1.14.4": {
"1.1.0-b3": "[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).\n[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).", "1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.",
"1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.", "1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.",
@ -58,6 +59,6 @@
}, },
"promos": { "promos": {
"1.14.4-recommended": "", "1.14.4-recommended": "",
"1.14.4-latest": "1.1.0-b2" "1.14.4-latest": "1.1.0-b3"
} }
} }

View file

@ -11,6 +11,11 @@ Mod sources for Minecraft version 1.14.4.
## Version history ## Version history
- v1.1.0-b3 [F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).
[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).
[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.
[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).
- v1.1.0-b2 [A] Added tooltips for buttons/settings in device GUIs (1.5s display delay). - v1.1.0-b2 [A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).
- v1.1.0-b1 [F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace). - v1.1.0-b1 [F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).

View file

@ -195,12 +195,12 @@ public class ModContent
public static final EdGlassBlock PANZERGLASS_BLOCK = (EdGlassBlock)(new EdGlassBlock( public static final EdGlassBlock PANZERGLASS_BLOCK = (EdGlassBlock)(new EdGlassBlock(
DecorBlock.CFG_TRANSLUCENT, DecorBlock.CFG_TRANSLUCENT,
Block.Properties.create(Material.GLASS, MaterialColor.AIR).hardnessAndResistance(5f, 2000f).sound(SoundType.METAL) Block.Properties.create(Material.GLASS, MaterialColor.AIR).hardnessAndResistance(0.7f, 2000f).sound(SoundType.METAL)
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_block")); )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_block"));
public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock( public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock(
DecorBlock.CFG_TRANSLUCENT, DecorBlock.CFG_TRANSLUCENT,
Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(5f, 2000f).sound(SoundType.METAL) Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(0.7f, 2000f).sound(SoundType.METAL)
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_slab")); )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_slab"));
// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------

View file

@ -13,8 +13,9 @@ import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.blocks.StandardBlocks; import wile.engineersdecor.libmc.blocks.StandardBlocks;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Overlay; import wile.engineersdecor.libmc.detail.Overlay;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.GameRules;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer; import net.minecraft.state.StateContainer;
@ -26,6 +27,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
@ -272,6 +274,19 @@ public class EdBreaker
return true; return true;
} }
private static void spawnBlockAsEntity(World world, BlockPos pos, ItemStack stack) {
if(world.isRemote || stack.isEmpty() || (!world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) || world.restoringBlockSnapshots) return;
ItemEntity e = new ItemEntity(world,
((world.rand.nextFloat()*0.1)+0.5) + pos.getX(),
((world.rand.nextFloat()*0.1)+0.5) + pos.getY(),
((world.rand.nextFloat()*0.1)+0.5) + pos.getZ(),
stack
);
e.setDefaultPickupDelay();
e.setMotion((world.rand.nextFloat()*0.1-0.05), (world.rand.nextFloat()*0.1-0.03), (world.rand.nextFloat()*0.1-0.05));
world.addEntity(e);
}
private boolean breakBlock(BlockState state, BlockPos pos, World world) private boolean breakBlock(BlockState state, BlockPos pos, World world)
{ {
if(world.isRemote || (!(world instanceof ServerWorld)) || world.restoringBlockSnapshots) return false; // retry next cycle if(world.isRemote || (!(world instanceof ServerWorld)) || world.restoringBlockSnapshots) return false; // retry next cycle
@ -279,7 +294,7 @@ public class EdBreaker
final Block block = state.getBlock(); final Block block = state.getBlock();
drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos)); drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos));
world.removeBlock(pos, false); world.removeBlock(pos, false);
for(ItemStack drop:drops) Block.spawnAsEntity(world, pos, drop); for(ItemStack drop:drops) spawnBlockAsEntity(world, pos, drop);
SoundType stype = state.getBlock().getSoundType(state, world, pos, null); 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()); if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true; return true;
@ -290,15 +305,16 @@ public class EdBreaker
public void tick() public void tick()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BreakerBlock)) return;
if(world.isRemote) { if(world.isRemote) {
BlockState state = world.getBlockState(pos); if(!device_state.get(BreakerBlock.ACTIVE)) {
if(!state.get(BreakerBlock.ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
// not sure if is so cool to do this each tick ... may be simplified/removed again. // not sure if is so cool to do this each tick ... may be simplified/removed again.
SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT; SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT;
BlockState target_state = world.getBlockState(pos.offset(state.get(BreakerBlock.HORIZONTAL_FACING))); BlockState target_state = world.getBlockState(pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING)));
SoundType stype = target_state.getBlock().getSoundType(target_state); SoundType stype = target_state.getBlock().getSoundType(target_state);
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) { if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_WOOL_HIT; sound = SoundEvents.BLOCK_WOOL_HIT;
@ -309,7 +325,6 @@ public class EdBreaker
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING)); final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING));
final BlockState target_state = world.getBlockState(target_pos); final BlockState target_state = world.getBlockState(target_pos);
if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) { if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) {

View file

@ -553,6 +553,7 @@ public class EdDropper
if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty(); if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof DropperBlock)) return;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0; final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode))); boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode)));

View file

@ -475,6 +475,7 @@ public class EdElectricalFurnace
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof ElectricalFurnaceBlock)) return;
final boolean was_burning = burning(); final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0; if(burntime_left_ < 0) burntime_left_ = 0;

View file

@ -212,10 +212,10 @@ public class EdFluidAccumulator
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = tick_idle_interval; tick_timer_ = tick_idle_interval;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof FluidAccumulatorBlock)) return;
if(!initialized_) { if(!initialized_) {
initialized_ = true; initialized_ = true;
BlockState state = world.getBlockState(pos);
if((state==null) || (!(state.getBlock() instanceof FluidAccumulatorBlock))) return;
block_facing_ = state.get(FluidAccumulatorBlock.FACING); block_facing_ = state.get(FluidAccumulatorBlock.FACING);
} }
int n_requested = last_drain_request_amount_; int n_requested = last_drain_request_amount_;

View file

@ -406,6 +406,8 @@ public class EdFluidFunnel
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL; collection_timer_ += TICK_INTERVAL;
final BlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof FluidFunnelBlock)) return;
boolean dirty = false; boolean dirty = false;
// Collection // Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) { if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) {
@ -427,7 +429,6 @@ public class EdFluidFunnel
} }
// Block state // Block state
int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX)); int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX));
final BlockState funnel_state = world.getBlockState(pos);
if(funnel_state.get(FluidFunnelBlock.FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.with(FluidFunnelBlock.FILL_LEVEL, fill_level), 2|16); if(funnel_state.get(FluidFunnelBlock.FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.with(FluidFunnelBlock.FILL_LEVEL, fill_level), 2|16);
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -546,6 +546,8 @@ public class EdFurnace
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof FurnaceBlock)) return;
final boolean was_burning = burning(); final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0; if(burntime_left_ < 0) burntime_left_ = 0;
@ -602,10 +604,7 @@ public class EdFurnace
} }
if(was_burning != burning()) { if(was_burning != burning()) {
dirty = true; dirty = true;
final BlockState state = world.getBlockState(pos); world.setBlockState(pos, state.with(FurnaceBlock.LIT, burning()));
if(state.getBlock() instanceof FurnaceBlock) {
world.setBlockState(pos, state.with(FurnaceBlock.LIT, burning()));
}
} }
if(dirty) { if(dirty) {
markDirty(); markDirty();

View file

@ -619,13 +619,13 @@ public class EdHopper
if((delay_timer_ > 0) && ((--delay_timer_) == 0)) markDirty(); if((delay_timer_ > 0) && ((--delay_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof HopperBlock)) { block_power_signal_= false; return; }
// Cycle init // Cycle init
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
final boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); final boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
final boolean pulse_mode = ((logic_ & LOGIC_CONTINUOUS)==0); final boolean pulse_mode = ((logic_ & LOGIC_CONTINUOUS)==0);
boolean trigger = (rssignal && ((block_power_updated_) || (!pulse_mode))); boolean trigger = (rssignal && ((block_power_updated_) || (!pulse_mode)));
final BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final Direction hopper_facing = state.get(HopperBlock.FACING); final Direction hopper_facing = state.get(HopperBlock.FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -529,6 +529,7 @@ public class EdMilker
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
boolean dirty = false; boolean dirty = false;
final BlockState block_state = world.getBlockState(pos); final BlockState block_state = world.getBlockState(pos);
if(!(block_state.getBlock() instanceof MilkerBlock)) return;
if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) { if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) {
if(energy_consumption > 0) { if(energy_consumption > 0) {
if(energy_stored_ <= 0) return; if(energy_stored_ <= 0) return;

View file

@ -566,6 +566,8 @@ public class EdMineralSmelter
if(world.isRemote) return; if(world.isRemote) return;
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof MineralSmelterBlock)) return;
boolean dirty = false; boolean dirty = false;
final int last_phase = phase(); final int last_phase = phase();
final ItemStack istack = stacks_.get(0); final ItemStack istack = stacks_.get(0);
@ -655,8 +657,7 @@ public class EdMineralSmelter
} }
} }
// Block state // Block state
BlockState state = world.getBlockState(pos); if(force_block_update_ || (state.get(MineralSmelterBlock.PHASE) != new_phase)) {
if((state.getBlock() instanceof MineralSmelterBlock) && (force_block_update_ || (state.get(MineralSmelterBlock.PHASE) != new_phase))) {
state = state.with(MineralSmelterBlock.PHASE, new_phase); state = state.with(MineralSmelterBlock.PHASE, new_phase);
world.setBlockState(pos, state,3|16); world.setBlockState(pos, state,3|16);
world.notifyNeighborsOfStateChange(getPos(), state.getBlock()); world.notifyNeighborsOfStateChange(getPos(), state.getBlock());

View file

@ -77,14 +77,13 @@ public class EdPipeValve
{ {
if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state; if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state;
Direction.Axis bfa = state.get(FACING).getAxis(); Direction.Axis bfa = state.get(FACING).getAxis();
int bfi = state.get(FACING).getIndex();
for(Direction f:Direction.values()) { for(Direction f:Direction.values()) {
boolean cn = (f.getAxis() != bfa); boolean cn = (f.getAxis() != bfa);
if(cn) { if(cn) {
BlockPos nbp = pos.offset(f); BlockPos nbp = pos.offset(f);
if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos. if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos.
BlockState nbs = world.getBlockState(nbp); BlockState nbs = world.getBlockState(nbp);
if(!nbs.canProvidePower()) cn = false; // @todo check if there is a direction selective canProvidePower(). if((!nbs.canProvidePower()) && (!nbs.canConnectRedstone(world, nbp, f.getOpposite()))) cn = false;
} }
switch(f) { switch(f) {
case NORTH: state = state.with(RS_CN_N, cn); break; case NORTH: state = state.with(RS_CN_N, cn); break;

View file

@ -21,6 +21,7 @@ import net.minecraft.world.server.ServerWorld;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
@ -490,7 +491,10 @@ public class EdPlacer
placement_pos = placement_pos.up(); placement_pos = placement_pos.up();
} }
} }
} else if(!world.getBlockState(placement_pos).getMaterial().isReplaceable()) { } else if(
(!world.getBlockState(placement_pos).getMaterial().isReplaceable()) ||
(!world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(placement_pos), Entity::canBeCollidedWith).isEmpty())
) {
block = Blocks.AIR; block = Blocks.AIR;
no_space = true; no_space = true;
} }
@ -559,12 +563,12 @@ public class EdPlacer
if(world.isRemote) return; if(world.isRemote) return;
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof PlacerBlock)) { block_power_signal_= false; return; }
// Cycle init // Cycle init
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0))); boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0)));
final BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final Direction placer_facing = state.get(PlacerBlock.FACING); final Direction placer_facing = state.get(PlacerBlock.FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -193,6 +193,8 @@ public class EdSolarPanel
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof SolarPanelBlock)) return;
current_feedin_ = 0; current_feedin_ = 0;
if(output_enabled_) { if(output_enabled_) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) { for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
@ -211,13 +213,11 @@ public class EdSolarPanel
if(!world.canBlockSeeSky(pos)) { if(!world.canBlockSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5; tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0; current_production_ = 0;
BlockState state = world.getBlockState(pos);
if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2)); if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2));
return; return;
} }
if(--recalc_timer_ > 0) return; if(--recalc_timer_ > 0) return;
recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5)); recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5));
BlockState state = world.getBlockState(pos);
int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360); int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360);
int e = 2; int e = 2;
if(theta > 340) e = 2; if(theta > 340) e = 2;

View file

@ -214,8 +214,10 @@ public class EdTreeCutter
public void tick() public void tick()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof TreeCutterBlock)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) { if(world.isRemote) {
if(!world.getBlockState(pos).get(TreeCutterBlock.ACTIVE)) { if(!device_state.get(TreeCutterBlock.ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
@ -223,7 +225,6 @@ public class EdTreeCutter
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos tree_pos = pos.offset(device_state.get(TreeCutterBlock.HORIZONTAL_FACING)); final BlockPos tree_pos = pos.offset(device_state.get(TreeCutterBlock.HORIZONTAL_FACING));
final BlockState tree_state = world.getBlockState(tree_pos); final BlockState tree_state = world.getBlockState(tree_pos);
if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) { if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) {

View file

@ -509,6 +509,8 @@ public class EdWasteIncinerator
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(world.isRemote) return; if(world.isRemote) return;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof WasteIncineratorBlock)) return;
boolean dirty = false; boolean dirty = false;
ItemStack processing_stack = stacks_.get(BURN_SLOT_NO); ItemStack processing_stack = stacks_.get(BURN_SLOT_NO);
final boolean was_processing = !processing_stack.isEmpty(); final boolean was_processing = !processing_stack.isEmpty();
@ -542,10 +544,7 @@ public class EdWasteIncinerator
} }
if((was_processing != is_processing) || (new_stack_processing)) { if((was_processing != is_processing) || (new_stack_processing)) {
if(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f); if(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f);
final BlockState state = world.getBlockState(pos); world.setBlockState(pos, state.with(WasteIncineratorBlock.LIT, is_processing), 2|16);
if(state.getBlock() instanceof WasteIncineratorBlock) {
world.setBlockState(pos, state.with(WasteIncineratorBlock.LIT, is_processing), 2|16);
}
} }
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -70,7 +70,7 @@ init:
@$(GRADLE) eclipse @$(GRADLE) eclipse
sanitize: sanitize:
@echo "[1.15] Running sanatising tasks ..." @echo "[1.15] Running sanitising tasks ..."
@$(TASK) sanitize @$(TASK) sanitize
@$(TASK) sync-languages @$(TASK) sync-languages
@$(TASK) version-check @$(TASK) version-check

View file

@ -2,7 +2,7 @@
org.gradle.daemon=false org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G org.gradle.jvmargs=-Xmx8G
version_minecraft=1.15.2 version_minecraft=1.15.2
version_forge_minecraft=1.15.2-31.2.5 version_forge_minecraft=1.15.2-31.2.20
version_fml_mappings=20200514-1.15.1 version_fml_mappings=20200514-1.15.1
version_jei=1.15.2:6.0.0.2 version_jei=1.15.2:6.0.0.2
version_engineersdecor=1.1.0-b2 version_engineersdecor=1.1.0-b3

View file

@ -1,6 +1,7 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.15.2": { "1.15.2": {
"1.1.0-b3": "[!] Forge update, requires Forge 1.15.2-31.2.20.\n[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).\n[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).\n[U] Updated Forge/Mappings.", "1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).\n[U] Updated Forge/Mappings.",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] IE Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] GUI models updated to circumvent too dark representations.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] IE Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] GUI models updated to circumvent too dark representations.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.",
"1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.", "1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.",
@ -23,6 +24,6 @@
}, },
"promos": { "promos": {
"1.15.2-recommended": "", "1.15.2-recommended": "",
"1.15.2-latest": "1.1.0-b2" "1.15.2-latest": "1.1.0-b3"
} }
} }

View file

@ -11,6 +11,12 @@ Mod sources for Minecraft version 1.15.1.
## Version history ## Version history
- v1.1.0-b3 [!] Forge update, requires Forge 1.15.2-31.2.20.
[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).
[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).
[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.
[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).
- v1.1.0-b2 [A] Added tooltips for buttons/settings in device GUIs (1.5s display delay). - v1.1.0-b2 [A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).
[U] Updated Forge/Mappings. [U] Updated Forge/Mappings.

View file

@ -202,12 +202,12 @@ public class ModContent
public static final EdGlassBlock PANZERGLASS_BLOCK = (EdGlassBlock)(new EdGlassBlock( public static final EdGlassBlock PANZERGLASS_BLOCK = (EdGlassBlock)(new EdGlassBlock(
DecorBlock.CFG_TRANSLUCENT, DecorBlock.CFG_TRANSLUCENT,
Block.Properties.create(Material.GLASS, MaterialColor.AIR).hardnessAndResistance(5f, 2000f).sound(SoundType.METAL).notSolid() Block.Properties.create(Material.GLASS, MaterialColor.AIR).hardnessAndResistance(0.7f, 2000f).sound(SoundType.METAL).notSolid()
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_block")); )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_block"));
public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock( public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock(
DecorBlock.CFG_TRANSLUCENT, DecorBlock.CFG_TRANSLUCENT,
Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(5f, 2000f).sound(SoundType.METAL).notSolid() Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(0.7f, 2000f).sound(SoundType.METAL).notSolid()
)).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_slab")); )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "panzerglass_slab"));
// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------

View file

@ -12,8 +12,9 @@ import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Overlay; import wile.engineersdecor.libmc.detail.Overlay;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.GameRules;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer; import net.minecraft.state.StateContainer;
@ -25,6 +26,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
@ -269,6 +271,19 @@ public class EdBreaker
return true; return true;
} }
private static void spawnBlockAsEntity(World world, BlockPos pos, ItemStack stack) {
if(world.isRemote || stack.isEmpty() || (!world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) || world.restoringBlockSnapshots) return;
ItemEntity e = new ItemEntity(world,
((world.rand.nextFloat()*0.1)+0.5) + pos.getX(),
((world.rand.nextFloat()*0.1)+0.5) + pos.getY(),
((world.rand.nextFloat()*0.1)+0.5) + pos.getZ(),
stack
);
e.setDefaultPickupDelay();
e.setMotion((world.rand.nextFloat()*0.1-0.05), (world.rand.nextFloat()*0.1-0.03), (world.rand.nextFloat()*0.1-0.05));
world.addEntity(e);
}
private boolean breakBlock(BlockState state, BlockPos pos, World world) private boolean breakBlock(BlockState state, BlockPos pos, World world)
{ {
if(world.isRemote || (!(world instanceof ServerWorld)) || world.restoringBlockSnapshots) return false; // retry next cycle if(world.isRemote || (!(world instanceof ServerWorld)) || world.restoringBlockSnapshots) return false; // retry next cycle
@ -276,7 +291,7 @@ public class EdBreaker
final Block block = state.getBlock(); final Block block = state.getBlock();
drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos)); drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos));
world.removeBlock(pos, false); world.removeBlock(pos, false);
for(ItemStack drop:drops) Block.spawnAsEntity(world, pos, drop); for(ItemStack drop:drops) spawnBlockAsEntity(world, pos, drop);
SoundType stype = state.getBlock().getSoundType(state, world, pos, null); 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()); if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true; return true;
@ -287,15 +302,16 @@ public class EdBreaker
public void tick() public void tick()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BreakerBlock)) return;
if(world.isRemote) { if(world.isRemote) {
BlockState state = world.getBlockState(pos); if(!device_state.get(BreakerBlock.ACTIVE)) {
if(!state.get(BreakerBlock.ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
// not sure if is so cool to do this each tick ... may be simplified/removed again. // not sure if is so cool to do this each tick ... may be simplified/removed again.
SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT; SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT;
BlockState target_state = world.getBlockState(pos.offset(state.get(BreakerBlock.HORIZONTAL_FACING))); BlockState target_state = world.getBlockState(pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING)));
SoundType stype = target_state.getBlock().getSoundType(target_state); SoundType stype = target_state.getBlock().getSoundType(target_state);
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) { if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_WOOL_HIT; sound = SoundEvents.BLOCK_WOOL_HIT;
@ -306,7 +322,6 @@ public class EdBreaker
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING)); final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING));
final BlockState target_state = world.getBlockState(target_pos); final BlockState target_state = world.getBlockState(target_pos);
if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) { if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) {

View file

@ -589,6 +589,7 @@ public class EdDropper
if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty(); if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof DropperBlock)) return;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0; final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode))); boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode)));

View file

@ -475,6 +475,7 @@ public class EdElectricalFurnace
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof ElectricalFurnaceBlock)) return;
final boolean was_burning = burning(); final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0; if(burntime_left_ < 0) burntime_left_ = 0;

View file

@ -212,10 +212,10 @@ public class EdFluidAccumulator
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = tick_idle_interval; tick_timer_ = tick_idle_interval;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof FluidAccumulatorBlock)) return;
if(!initialized_) { if(!initialized_) {
initialized_ = true; initialized_ = true;
BlockState state = world.getBlockState(pos);
if((state==null) || (!(state.getBlock() instanceof FluidAccumulatorBlock))) return;
block_facing_ = state.get(FluidAccumulatorBlock.FACING); block_facing_ = state.get(FluidAccumulatorBlock.FACING);
} }
int n_requested = last_drain_request_amount_; int n_requested = last_drain_request_amount_;

View file

@ -415,6 +415,8 @@ public class EdFluidFunnel
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL; collection_timer_ += TICK_INTERVAL;
final BlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof FluidFunnelBlock)) return;
boolean dirty = false; boolean dirty = false;
// Collection // Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) { if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) {
@ -454,7 +456,6 @@ public class EdFluidFunnel
} }
// Block state // Block state
int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX)); int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX));
final BlockState funnel_state = world.getBlockState(pos);
if(funnel_state.get(FluidFunnelBlock.FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.with(FluidFunnelBlock.FILL_LEVEL, fill_level), 2|16); if(funnel_state.get(FluidFunnelBlock.FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.with(FluidFunnelBlock.FILL_LEVEL, fill_level), 2|16);
if(dirty) markDirty(); if(dirty) markDirty();
} }

View file

@ -542,6 +542,8 @@ public class EdFurnace
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof FurnaceBlock)) return;
final boolean was_burning = burning(); final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL; if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0; if(burntime_left_ < 0) burntime_left_ = 0;
@ -598,10 +600,7 @@ public class EdFurnace
} }
if(was_burning != burning()) { if(was_burning != burning()) {
dirty = true; dirty = true;
final BlockState state = world.getBlockState(pos); world.setBlockState(pos, state.with(FurnaceBlock.LIT, burning()));
if(state.getBlock() instanceof FurnaceBlock) {
world.setBlockState(pos, state.with(FurnaceBlock.LIT, burning()));
}
} }
if(dirty) { if(dirty) {
markDirty(); markDirty();

View file

@ -623,7 +623,7 @@ public class EdHopper
final boolean pulse_mode = ((logic_ & LOGIC_CONTINUOUS)==0); final boolean pulse_mode = ((logic_ & LOGIC_CONTINUOUS)==0);
boolean trigger = (rssignal && ((block_power_updated_) || (!pulse_mode))); boolean trigger = (rssignal && ((block_power_updated_) || (!pulse_mode)));
final BlockState state = world.getBlockState(pos); final BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; } if(!(state.getBlock() instanceof HopperBlock)) { block_power_signal_= false; return; }
final Direction hopper_facing = state.get(HopperBlock.FACING); final Direction hopper_facing = state.get(HopperBlock.FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -11,6 +11,7 @@ package wile.engineersdecor.blocks;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Fluidics;
import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.ModContent; import wile.engineersdecor.ModContent;
@ -291,20 +292,7 @@ public class EdMilker
// IFluidHandler --------------------------------------------------------------------------------------- // IFluidHandler ---------------------------------------------------------------------------------------
private LazyOptional<IFluidHandler> fluid_handler_ = LazyOptional.of(() -> (IFluidHandler)new BFluidHandler(this)); private LazyOptional<IFluidHandler> fluid_handler_ = LazyOptional.of(() -> (IFluidHandler)new Fluidics.SingleTankFluidHandler(this));
private static class BFluidHandler implements IFluidHandler
{
private final MilkerTileEntity te;
BFluidHandler(MilkerTileEntity te) { this.te = te; }
@Override public int getTanks() { return 1; }
@Override public FluidStack getFluidInTank(int tank) { return te.getFluid(); }
@Override public int getTankCapacity(int tank) { return te.getCapacity(); }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return te.isFluidValid(stack); }
@Override public int fill(FluidStack resource, FluidAction action) { return 0; }
@Override public FluidStack drain(FluidStack resource, FluidAction action) { return te.drain(resource, action); }
@Override public FluidStack drain(int maxDrain, FluidAction action) { return te.drain(maxDrain, action); }
}
// IFluidTank ------------------------------------------------------------------------------------------ // IFluidTank ------------------------------------------------------------------------------------------
@ -368,13 +356,14 @@ public class EdMilker
private static ItemStack milk_filled_container_item(ItemStack stack) private static ItemStack milk_filled_container_item(ItemStack stack)
{ return milk_containers_.entrySet().stream().filter(e->Inventories.areItemStacksIdentical(e.getKey(), stack)).map(Map.Entry::getValue).findFirst().orElse(ItemStack.EMPTY); } { return milk_containers_.entrySet().stream().filter(e->Inventories.areItemStacksIdentical(e.getKey(), stack)).map(Map.Entry::getValue).findFirst().orElse(ItemStack.EMPTY); }
private void fill_adjacent_inventory_item_containers(Direction block_facing) private boolean fill_adjacent_inventory_item_containers(Direction block_facing)
{ {
// Check inventory existence, back to down is preferred, otherwise sort back into same inventory. // Check inventory existence, back to down is preferred, otherwise sort back into same inventory.
IItemHandler src = Inventories.itemhandler(world, pos.offset(block_facing), block_facing.getOpposite()); IItemHandler src = Inventories.itemhandler(world, pos.offset(block_facing), block_facing.getOpposite());
IItemHandler dst = Inventories.itemhandler(world, pos.down(), Direction.UP); IItemHandler dst = Inventories.itemhandler(world, pos.down(), Direction.UP);
if(src==null) { src = dst; } else if(dst==null) { dst = src; } if(src==null) { src = dst; } else if(dst==null) { dst = src; }
if((src==null) || (dst==null)) return; if((src==null) || (dst==null)) return false;
boolean dirty = false;
while((tank_level_ >= BUCKET_SIZE)) { while((tank_level_ >= BUCKET_SIZE)) {
boolean inserted = false; boolean inserted = false;
for(Entry<ItemStack,ItemStack> e:milk_containers_.entrySet()) { for(Entry<ItemStack,ItemStack> e:milk_containers_.entrySet()) {
@ -383,10 +372,12 @@ public class EdMilker
Inventories.extract(src, e.getKey(), 1, false); Inventories.extract(src, e.getKey(), 1, false);
tank_level_ -= BUCKET_SIZE; tank_level_ -= BUCKET_SIZE;
inserted = true; inserted = true;
dirty = true;
break; break;
} }
if(!inserted) break; if(!inserted) break;
} }
return dirty;
} }
private void release_cow(CowEntity cow) private void release_cow(CowEntity cow)
@ -546,6 +537,7 @@ public class EdMilker
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
boolean dirty = false; boolean dirty = false;
final BlockState block_state = world.getBlockState(pos); final BlockState block_state = world.getBlockState(pos);
if(!(block_state.getBlock() instanceof MilkerBlock)) return;
if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) { if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) {
if(energy_consumption > 0) { if(energy_consumption > 0) {
if(energy_stored_ <= 0) return; if(energy_stored_ <= 0) return;
@ -570,9 +562,9 @@ public class EdMilker
} }
} }
// Adjacent inventory update, only done just after milking to prevent waste of server cpu. // Adjacent inventory update, only done just after milking to prevent waste of server cpu.
if(dirty && (fluid_level() >= BUCKET_SIZE)) { if((!dirty) && (fluid_level() >= BUCKET_SIZE)) {
log("Try item transfer"); log("Try item transfer");
fill_adjacent_inventory_item_containers(block_state.get(MilkerBlock.HORIZONTAL_FACING)); if(fill_adjacent_inventory_item_containers(block_state.get(MilkerBlock.HORIZONTAL_FACING))) dirty = true;
} }
} }
// State update // State update

View file

@ -560,6 +560,8 @@ public class EdMineralSmelter
if(world.isRemote) return; if(world.isRemote) return;
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof MineralSmelterBlock)) return;
boolean dirty = false; boolean dirty = false;
final int last_phase = phase(); final int last_phase = phase();
final ItemStack istack = stacks_.get(0); final ItemStack istack = stacks_.get(0);
@ -649,8 +651,7 @@ public class EdMineralSmelter
} }
} }
// Block state // Block state
BlockState state = world.getBlockState(pos); if((force_block_update_ || (state.get(MineralSmelterBlock.PHASE) != new_phase))) {
if((state.getBlock() instanceof MineralSmelterBlock) && (force_block_update_ || (state.get(MineralSmelterBlock.PHASE) != new_phase))) {
state = state.with(MineralSmelterBlock.PHASE, new_phase); state = state.with(MineralSmelterBlock.PHASE, new_phase);
world.setBlockState(pos, state,3|16); world.setBlockState(pos, state,3|16);
world.notifyNeighborsOfStateChange(getPos(), state.getBlock()); world.notifyNeighborsOfStateChange(getPos(), state.getBlock());

View file

@ -81,14 +81,13 @@ public class EdPipeValve
{ {
if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state; if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state;
Direction.Axis bfa = state.get(FACING).getAxis(); Direction.Axis bfa = state.get(FACING).getAxis();
int bfi = state.get(FACING).getIndex();
for(Direction f:Direction.values()) { for(Direction f:Direction.values()) {
boolean cn = (f.getAxis() != bfa); boolean cn = (f.getAxis() != bfa);
if(cn) { if(cn) {
BlockPos nbp = pos.offset(f); BlockPos nbp = pos.offset(f);
if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos. if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos.
BlockState nbs = world.getBlockState(nbp); BlockState nbs = world.getBlockState(nbp);
if(!nbs.canProvidePower()) cn = false; // @todo check if there is a direction selective canProvidePower(). if((!nbs.canProvidePower()) && (!nbs.canConnectRedstone(world, nbp, f.getOpposite()))) cn = false;
} }
switch(f) { switch(f) {
case NORTH: state = state.with(RS_CN_N, cn); break; case NORTH: state = state.with(RS_CN_N, cn); break;
@ -236,7 +235,7 @@ public class EdPipeValve
{ {
private PipeValveTileEntity te; private PipeValveTileEntity te;
public MainFlowHandler(PipeValveTileEntity te) { this.te = te; } public MainFlowHandler(PipeValveTileEntity te) { this.te = te; }
@Override public int getTanks() { return 0; } @Override public int getTanks() { return 1; }
@Override public FluidStack getFluidInTank(int tank) { return FluidStack.EMPTY; } @Override public FluidStack getFluidInTank(int tank) { return FluidStack.EMPTY; }
@Override public int getTankCapacity(int tank) { return fluid_maxflow_mb; } @Override public int getTankCapacity(int tank) { return fluid_maxflow_mb; }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; }
@ -266,7 +265,7 @@ public class EdPipeValve
private static class BackFlowHandler implements IFluidHandler private static class BackFlowHandler implements IFluidHandler
{ {
@Override public int getTanks() { return 0; } @Override public int getTanks() { return 1; }
@Override public FluidStack getFluidInTank(int tank) { return FluidStack.EMPTY; } @Override public FluidStack getFluidInTank(int tank) { return FluidStack.EMPTY; }
@Override public int getTankCapacity(int tank) { return 0; } @Override public int getTankCapacity(int tank) { return 0; }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return false; } @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return false; }

View file

@ -8,7 +8,6 @@
*/ */
package wile.engineersdecor.blocks; package wile.engineersdecor.blocks;
import net.minecraft.util.text.TranslationTextComponent;
import wile.engineersdecor.ModContent; import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.Networking;
@ -19,6 +18,7 @@ import net.minecraft.world.server.ServerWorld;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
@ -34,6 +34,7 @@ import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
@ -489,7 +490,10 @@ public class EdPlacer
placement_pos = placement_pos.up(); placement_pos = placement_pos.up();
} }
} }
} else if(!world.getBlockState(placement_pos).getMaterial().isReplaceable()) { } else if(
(!world.getBlockState(placement_pos).getMaterial().isReplaceable()) ||
(!world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(placement_pos), Entity::canBeCollidedWith).isEmpty())
) {
block = Blocks.AIR; block = Blocks.AIR;
no_space = true; no_space = true;
} }
@ -559,11 +563,11 @@ public class EdPlacer
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
// Cycle init // Cycle init
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof PlacerBlock)) { block_power_signal_= false; return; }
boolean dirty = block_power_updated_; boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0))); boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0)));
final BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final Direction placer_facing = state.get(PlacerBlock.FACING); final Direction placer_facing = state.get(PlacerBlock.FACING);
// Trigger edge detection for next cycle // Trigger edge detection for next cycle
{ {

View file

@ -185,6 +185,8 @@ public class EdSolarPanel
{ {
if((world.isRemote) || (--tick_timer_ > 0)) return; if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof SolarPanelBlock)) return;
current_feedin_ = 0; current_feedin_ = 0;
if(output_enabled_) { if(output_enabled_) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) { for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
@ -203,13 +205,11 @@ public class EdSolarPanel
if(!world.canBlockSeeSky(pos)) { if(!world.canBlockSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5; tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0; current_production_ = 0;
BlockState state = world.getBlockState(pos);
if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2)); if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2));
return; return;
} }
if(--recalc_timer_ > 0) return; if(--recalc_timer_ > 0) return;
recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5)); recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5));
BlockState state = world.getBlockState(pos);
int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360); int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360);
int e = 2; int e = 2;
if(theta > 340) e = 2; if(theta > 340) e = 2;

View file

@ -212,8 +212,10 @@ public class EdTreeCutter
public void tick() public void tick()
{ {
if(--tick_timer_ > 0) return; if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof TreeCutterBlock)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) { if(world.isRemote) {
if(!world.getBlockState(pos).get(TreeCutterBlock.ACTIVE)) { if(!device_state.get(TreeCutterBlock.ACTIVE)) {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
} else { } else {
tick_timer_ = 1; tick_timer_ = 1;
@ -221,7 +223,6 @@ public class EdTreeCutter
} }
} else { } else {
tick_timer_ = TICK_INTERVAL; tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos tree_pos = pos.offset(device_state.get(TreeCutterBlock.HORIZONTAL_FACING)); final BlockPos tree_pos = pos.offset(device_state.get(TreeCutterBlock.HORIZONTAL_FACING));
final BlockState tree_state = world.getBlockState(tree_pos); final BlockState tree_state = world.getBlockState(tree_pos);
if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) { if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) {

View file

@ -70,12 +70,12 @@ public class StandardFenceBlock extends WallBlock implements StandardBlocks.ISta
VoxelShapes.or(vp, vs3), VoxelShapes.or(vp, vs3),
VoxelShapes.or(vp, vs6), VoxelShapes.or(vp, vs6),
VoxelShapes.or(vp, vs1), VoxelShapes.or(vp, vs1),
VoxelShapes.or(vs2, vs1), VoxelShapes.or(vs2, vs1),
VoxelShapes.or(vp, VoxelShapes.or(vs3, vs1)), VoxelShapes.or(vp, VoxelShapes.or(vs3, vs1)),
VoxelShapes.or(vp, VoxelShapes.or(vs6, vs1)), VoxelShapes.or(vp, VoxelShapes.or(vs6, vs1)),
VoxelShapes.or(vp, vs4), VoxelShapes.or(vp, vs4),
VoxelShapes.or(vp, VoxelShapes.or(vs2, vs4)), VoxelShapes.or(vp, VoxelShapes.or(vs2, vs4)),
VoxelShapes.or(vs3, vs4), VoxelShapes.or(vs3, vs4),
VoxelShapes.or(vp, VoxelShapes.or(vs6, vs4)), VoxelShapes.or(vp, VoxelShapes.or(vs6, vs4)),
VoxelShapes.or(vp, vs5), VoxelShapes.or(vp, vs5),
VoxelShapes.or(vp, VoxelShapes.or(vs2, vs5)), VoxelShapes.or(vp, VoxelShapes.or(vs2, vs5)),

View file

@ -0,0 +1,35 @@
/*
* @file Fluidics.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* General fluid handling functionality.
*/
package wile.engineersdecor.libmc.detail;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import javax.annotation.Nonnull;
public class Fluidics
{
public static class SingleTankFluidHandler implements IFluidHandler
{
private final IFluidTank tank_;
public SingleTankFluidHandler(IFluidTank tank) { tank_ = tank; }
@Override public int getTanks() { return 1; }
@Override public FluidStack getFluidInTank(int tank) { return tank_.getFluid(); }
@Override public int getTankCapacity(int tank) { return tank_.getCapacity(); }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return tank_.isFluidValid(stack); }
@Override public int fill(FluidStack resource, FluidAction action) { return 0; }
@Override public FluidStack drain(FluidStack resource, FluidAction action) { return tank_.drain(resource, action); }
@Override public FluidStack drain(int maxDrain, FluidAction action) { return tank_.drain(maxDrain, action); }
}
}

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 837 B

After

Width:  |  Height:  |  Size: 880 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

After

Width:  |  Height:  |  Size: 866 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 B

After

Width:  |  Height:  |  Size: 850 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 809 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 758 B

After

Width:  |  Height:  |  Size: 819 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 B

After

Width:  |  Height:  |  Size: 868 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 857 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 784 B

After

Width:  |  Height:  |  Size: 862 B

Before After
Before After

View file

@ -397,6 +397,7 @@
const dst = fs.realpath("src/main/resources/data/" + constants.modid); const dst = fs.realpath("src/main/resources/data/" + constants.modid);
const src = fs.realpath("src/generated/resources/data/" + constants.modid); const src = fs.realpath("src/generated/resources/data/" + constants.modid);
if(!dst || !src) throw "Source or destination directory not found."; if(!dst || !src) throw "Source or destination directory not found.";
if(!fs.isdir(src)) return;
const src_files = fs.find(src, "*.json"); const src_files = fs.find(src, "*.json");
const upath = function(s) { return s.replace(/[\\]/g,"/").replace(/^[\/]/,""); } // for correct display on win32 const upath = function(s) { return s.replace(/[\\]/g,"/").replace(/^[\/]/,""); } // for correct display on win32
if(src_files===undefined) return 1; if(src_files===undefined) return 1;

View file

@ -2,13 +2,14 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"promos": { "promos": {
"1.12.2-recommended": "1.0.20", "1.12.2-recommended": "1.0.20",
"1.12.2-latest": "1.1.0-b1", "1.12.2-latest": "1.1.0-b2",
"1.14.4-recommended": "", "1.14.4-recommended": "",
"1.14.4-latest": "1.1.0-b2", "1.14.4-latest": "1.1.0-b3",
"1.15.2-recommended": "", "1.15.2-recommended": "",
"1.15.2-latest": "1.1.0-b2" "1.15.2-latest": "1.1.0-b3"
}, },
"1.12.2": { "1.12.2": {
"1.1.0-b2": "[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[M] Changed Labeled Crate Nesting to circumvent server crashing in combination with the Sponge mod.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[M] Changed Labeled Crate Nesting to circumvent server crashing in combination with the Sponge mod.",
"1.0.20": "[R] Release based on v1.0.20-b6. Release-to-release changes: * Manual back ported. * Steel Mesh Fence Gate back ported. * E-Furnace speed selection switch back ported. * Labeled Crate back ported. * Minor bug fixes, compatibility changes.", "1.0.20": "[R] Release based on v1.0.20-b6. Release-to-release changes: * Manual back ported. * Steel Mesh Fence Gate back ported. * E-Furnace speed selection switch back ported. * Labeled Crate back ported. * Minor bug fixes, compatibility changes.",
"1.0.20-b6": "[F] Implemented compat related to issue #91.", "1.0.20-b6": "[F] Implemented compat related to issue #91.",
@ -97,6 +98,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.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.14.4": {
"1.1.0-b3": "[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).\n[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).", "1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.",
"1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.", "1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.",
@ -153,6 +155,7 @@
"1.0.7-b3": "[A] Initial 1.14.2 port of decorative blocks." "1.0.7-b3": "[A] Initial 1.14.2 port of decorative blocks."
}, },
"1.15.2": { "1.15.2": {
"1.1.0-b3": "[!] Forge update, requires Forge 1.15.2-31.2.20.\n[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[M] Block Breaker item drop trajectories have lower speed (fall slightly straighter down).\n[M] Pipe Valves redstone connector also shown if the adjacent block can connect redstone in general.\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).\n[U] Updated Forge/Mappings.", "1.1.0-b2": "[A] Added tooltips for buttons/settings in device GUIs (1.5s display delay).\n[U] Updated Forge/Mappings.",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] IE Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] GUI models updated to circumvent too dark representations.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.", "1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[A] IE Sheet Metal Slab Slices added (only available if IE is installed).\n[M] Config options extended/updated.\n[M] GUI models updated to circumvent too dark representations.\n[M] Dense Grit Sand textures altered to get slightly more visible structure from distance.",
"1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.", "1.0.20-b7": "[A] Dense Grit Sand added.\n[!] Variant Slab compatibility fix. *This may alter placed slabs of this mod, data fixers don't work yet unfortunately*.",