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
sanitize:
@echo "[1.12] Running sanatising tasks ..."
@echo "[1.12] Running sanitising tasks ..."
@$(TASK) sanitize
@$(TASK) sync-languages
@$(TASK) version-check

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.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/",
"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.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.",
@ -90,6 +91,6 @@
},
"promos": {
"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
~ 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).
[M] Changed Labeled Crate Nesting to circumvent server crashing

View file

@ -266,15 +266,16 @@ public class BlockDecorBreaker extends BlockDecorDirectedHorizontal
public void update()
{
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) {
IBlockState state = world.getBlockState(pos);
if(!state.getValue(ACTIVE)) {
if(!device_state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL;
} else {
tick_timer_ = 1;
// not sure if is so cool to do this each tick ... may be simplified/removed again.
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)) {
sound = SoundEvents.BLOCK_CLOTH_HIT;
} else if((stype == SoundType.GROUND) || (stype == SoundType.SAND)) {
@ -284,7 +285,6 @@ public class BlockDecorBreaker extends BlockDecorDirectedHorizontal
}
} else {
tick_timer_ = TICK_INTERVAL;
final IBlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.getValue(FACING));
final IBlockState target_state = world.getBlockState(target_pos);
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(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof BlockDecorDropper)) return;
boolean dirty = block_power_updated_;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
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;
tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL;
final IBlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof BlockDecorFluidFunnel)) return;
boolean dirty = false;
// Collection
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(last_pick_pos_==null) last_pick_pos_ = pos.up();
if(try_collect(pos.up())) dirty = true;
@ -378,7 +380,6 @@ public class BlockDecorFluidFunnel extends BlockDecor
}
// Block state
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(dirty) markDirty();
}

View file

@ -809,6 +809,8 @@ public class BlockDecorFurnace extends BlockDecorDirected
{
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorFurnace)) return;
final boolean was_burning = isBurning();
if(was_burning) burntime_left_ -= TICK_INTERVAL;
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()) {
dirty = true;
final IBlockState state = world.getBlockState(pos);
if(state.getBlock() instanceof BlockDecorFurnace) {
world.setBlockState(pos, state.withProperty(LIT, isBurning()));
}
world.setBlockState(pos, state.withProperty(LIT, isBurning()));
}
if(dirty) markDirty();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -167,6 +167,8 @@ public class BlockDecorSolarPanel extends BlockDecor
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorSolarPanel)) return;
current_feedin_ = 0;
if(accumulated_power_ > 0) {
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)) {
tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0;
IBlockState state = world.getBlockState(pos);
if(state.getValue((EXPOSITION))!=2) world.setBlockState(pos, state.withProperty(EXPOSITION, 2));
return;
}
if(--recalc_timer_ > 0) return;
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 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 < 135) e = 3;
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);
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));

View file

@ -215,8 +215,10 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
public void update()
{
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.getBlockState(pos).getValue(ACTIVE)) {
if(!device_state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL;
} else {
tick_timer_ = 1;
@ -224,7 +226,6 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
}
} else {
tick_timer_ = TICK_INTERVAL;
final IBlockState device_state = world.getBlockState(pos);
final BlockPos tree_pos = pos.offset(device_state.getValue(FACING));
final IBlockState tree_state = world.getBlockState(tree_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;
tick_timer_ = TICK_INTERVAL;
if(world.isRemote) return;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorWasteIncinerator)) return;
boolean dirty = false;
ItemStack processing_stack = stacks_.get(BURN_SLOT_NO);
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(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f);
final IBlockState state = world.getBlockState(pos);
if(state.getBlock() instanceof BlockDecorWasteIncinerator) {
world.setBlockState(pos, state.withProperty(LIT, is_processing), 2|16);
}
world.setBlockState(pos, state.withProperty(LIT, is_processing), 2|16);
}
if(dirty) markDirty();
}