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();
}

View file

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

View file

@ -5,4 +5,4 @@ version_minecraft=1.14.4
version_forge_minecraft=1.14.4-28.2.3
version_fml_mappings=20190719-1.14.3
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/",
"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-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*.",
@ -58,6 +59,6 @@
},
"promos": {
"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
- 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-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(
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"));
public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock(
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"));
// -------------------------------------------------------------------------------------------------------------------

View file

@ -13,8 +13,9 @@ import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.blocks.StandardBlocks;
import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Overlay;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.GameRules;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer;
@ -26,6 +27,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes;
@ -272,6 +274,19 @@ public class EdBreaker
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)
{
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();
drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos));
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);
if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true;
@ -290,15 +305,16 @@ public class EdBreaker
public void tick()
{
if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BreakerBlock)) return;
if(world.isRemote) {
BlockState state = world.getBlockState(pos);
if(!state.get(BreakerBlock.ACTIVE)) {
if(!device_state.get(BreakerBlock.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;
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);
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_WOOL_HIT;
@ -309,7 +325,6 @@ public class EdBreaker
}
} else {
tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING));
final BlockState target_state = world.getBlockState(target_pos);
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(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof DropperBlock)) return;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean dirty = block_power_updated_;
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;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof ElectricalFurnaceBlock)) return;
final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0;

View file

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

View file

@ -406,6 +406,8 @@ public class EdFluidFunnel
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL;
final BlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof FluidFunnelBlock)) return;
boolean dirty = false;
// Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) {
@ -427,7 +429,6 @@ public class EdFluidFunnel
}
// Block state
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(dirty) markDirty();
}

View file

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

View file

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

View file

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

View file

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

View file

@ -77,14 +77,13 @@ public class EdPipeValve
{
if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state;
Direction.Axis bfa = state.get(FACING).getAxis();
int bfi = state.get(FACING).getIndex();
for(Direction f:Direction.values()) {
boolean cn = (f.getAxis() != bfa);
if(cn) {
BlockPos nbp = pos.offset(f);
if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos.
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) {
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.TileEntityType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.LivingEntity;
@ -490,7 +491,10 @@ public class EdPlacer
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;
no_space = true;
}
@ -559,12 +563,12 @@ public class EdPlacer
if(world.isRemote) return;
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof PlacerBlock)) { 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 BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final Direction placer_facing = state.get(PlacerBlock.FACING);
// Trigger edge detection for next cycle
{

View file

@ -193,6 +193,8 @@ public class EdSolarPanel
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof SolarPanelBlock)) return;
current_feedin_ = 0;
if(output_enabled_) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
@ -211,13 +213,11 @@ public class EdSolarPanel
if(!world.canBlockSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0;
BlockState state = world.getBlockState(pos);
if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2));
return;
}
if(--recalc_timer_ > 0) return;
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 e = 2;
if(theta > 340) e = 2;

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G
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_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/",
"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-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*.",
@ -23,6 +24,6 @@
},
"promos": {
"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
- 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).
[U] Updated Forge/Mappings.

View file

@ -202,12 +202,12 @@ public class ModContent
public static final EdGlassBlock PANZERGLASS_BLOCK = (EdGlassBlock)(new EdGlassBlock(
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"));
public static final EdSlabBlock PANZERGLASS_SLAB = (EdSlabBlock)(new EdSlabBlock(
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"));
// -------------------------------------------------------------------------------------------------------------------

View file

@ -12,8 +12,9 @@ import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Overlay;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.GameRules;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer;
@ -25,6 +26,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes;
@ -269,6 +271,19 @@ public class EdBreaker
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)
{
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();
drops = Block.getDrops(state, (ServerWorld)world, pos, world.getTileEntity(pos));
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);
if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true;
@ -287,15 +302,16 @@ public class EdBreaker
public void tick()
{
if(--tick_timer_ > 0) return;
final BlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BreakerBlock)) return;
if(world.isRemote) {
BlockState state = world.getBlockState(pos);
if(!state.get(BreakerBlock.ACTIVE)) {
if(!device_state.get(BreakerBlock.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;
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);
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_WOOL_HIT;
@ -306,7 +322,6 @@ public class EdBreaker
}
} else {
tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos target_pos = pos.offset(device_state.get(BreakerBlock.HORIZONTAL_FACING));
final BlockState target_state = world.getBlockState(target_pos);
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(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof DropperBlock)) return;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean dirty = block_power_updated_;
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;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof ElectricalFurnaceBlock)) return;
final boolean was_burning = burning();
if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0;

View file

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

View file

@ -415,6 +415,8 @@ public class EdFluidFunnel
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL;
final BlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof FluidFunnelBlock)) return;
boolean dirty = false;
// Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) {
@ -454,7 +456,6 @@ public class EdFluidFunnel
}
// Block state
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(dirty) markDirty();
}

View file

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

View file

@ -623,7 +623,7 @@ public class EdHopper
final boolean pulse_mode = ((logic_ & LOGIC_CONTINUOUS)==0);
boolean trigger = (rssignal && ((block_power_updated_) || (!pulse_mode)));
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);
// 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.StringTextComponent;
import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Fluidics;
import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.ModContent;
@ -291,20 +292,7 @@ public class EdMilker
// IFluidHandler ---------------------------------------------------------------------------------------
private LazyOptional<IFluidHandler> fluid_handler_ = LazyOptional.of(() -> (IFluidHandler)new BFluidHandler(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); }
}
private LazyOptional<IFluidHandler> fluid_handler_ = LazyOptional.of(() -> (IFluidHandler)new Fluidics.SingleTankFluidHandler(this));
// IFluidTank ------------------------------------------------------------------------------------------
@ -368,13 +356,14 @@ public class EdMilker
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); }
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.
IItemHandler src = Inventories.itemhandler(world, pos.offset(block_facing), block_facing.getOpposite());
IItemHandler dst = Inventories.itemhandler(world, pos.down(), Direction.UP);
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)) {
boolean inserted = false;
for(Entry<ItemStack,ItemStack> e:milk_containers_.entrySet()) {
@ -383,10 +372,12 @@ public class EdMilker
Inventories.extract(src, e.getKey(), 1, false);
tank_level_ -= BUCKET_SIZE;
inserted = true;
dirty = true;
break;
}
if(!inserted) break;
}
return dirty;
}
private void release_cow(CowEntity cow)
@ -546,6 +537,7 @@ public class EdMilker
tick_timer_ = TICK_INTERVAL;
boolean dirty = false;
final BlockState block_state = world.getBlockState(pos);
if(!(block_state.getBlock() instanceof MilkerBlock)) return;
if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) {
if(energy_consumption > 0) {
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.
if(dirty && (fluid_level() >= BUCKET_SIZE)) {
if((!dirty) && (fluid_level() >= BUCKET_SIZE)) {
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

View file

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

View file

@ -81,14 +81,13 @@ public class EdPipeValve
{
if((valve_config & (CFG_REDSTONE_CONTROLLED_VALVE))==0) return state;
Direction.Axis bfa = state.get(FACING).getAxis();
int bfi = state.get(FACING).getIndex();
for(Direction f:Direction.values()) {
boolean cn = (f.getAxis() != bfa);
if(cn) {
BlockPos nbp = pos.offset(f);
if((fromPos != null) && (!nbp.equals(fromPos))) continue; // do not change connectors except form the frompos.
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) {
case NORTH: state = state.with(RS_CN_N, cn); break;
@ -236,7 +235,7 @@ public class EdPipeValve
{
private PipeValveTileEntity 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 int getTankCapacity(int tank) { return fluid_maxflow_mb; }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; }
@ -266,7 +265,7 @@ public class EdPipeValve
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 int getTankCapacity(int tank) { return 0; }
@Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return false; }

View file

@ -8,7 +8,6 @@
*/
package wile.engineersdecor.blocks;
import net.minecraft.util.text.TranslationTextComponent;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
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.TileEntityType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.entity.item.ItemEntity;
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.math.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
@ -489,7 +490,10 @@ public class EdPlacer
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;
no_space = true;
}
@ -559,11 +563,11 @@ public class EdPlacer
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
// Cycle init
final BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof PlacerBlock)) { block_power_signal_= false; return; }
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 BlockState state = world.getBlockState(pos);
if(state == null) { block_power_signal_= false; return; }
final Direction placer_facing = state.get(PlacerBlock.FACING);
// Trigger edge detection for next cycle
{

View file

@ -185,6 +185,8 @@ public class EdSolarPanel
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
BlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof SolarPanelBlock)) return;
current_feedin_ = 0;
if(output_enabled_) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
@ -203,13 +205,11 @@ public class EdSolarPanel
if(!world.canBlockSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0;
BlockState state = world.getBlockState(pos);
if(state.get((SolarPanelBlock.EXPOSITION))!=2) world.setBlockState(pos, state.with(SolarPanelBlock.EXPOSITION, 2));
return;
}
if(--recalc_timer_ > 0) return;
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 e = 2;
if(theta > 340) e = 2;

View file

@ -212,8 +212,10 @@ public class EdTreeCutter
public void tick()
{
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.getBlockState(pos).get(TreeCutterBlock.ACTIVE)) {
if(!device_state.get(TreeCutterBlock.ACTIVE)) {
tick_timer_ = TICK_INTERVAL;
} else {
tick_timer_ = 1;
@ -221,7 +223,6 @@ public class EdTreeCutter
}
} else {
tick_timer_ = TICK_INTERVAL;
final BlockState device_state = world.getBlockState(pos);
final BlockPos tree_pos = pos.offset(device_state.get(TreeCutterBlock.HORIZONTAL_FACING));
final BlockState tree_state = world.getBlockState(tree_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, vs6),
VoxelShapes.or(vp, vs1),
VoxelShapes.or(vs2, vs1),
VoxelShapes.or(vs2, vs1),
VoxelShapes.or(vp, VoxelShapes.or(vs3, vs1)),
VoxelShapes.or(vp, VoxelShapes.or(vs6, vs1)),
VoxelShapes.or(vp, 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, 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]]
modId="forge"
mandatory=true
versionRange="[31.1.0,)"
versionRange="[31.2.20,)"
ordering="NONE"
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 src = fs.realpath("src/generated/resources/data/" + constants.modid);
if(!dst || !src) throw "Source or destination directory not found.";
if(!fs.isdir(src)) return;
const src_files = fs.find(src, "*.json");
const upath = function(s) { return s.replace(/[\\]/g,"/").replace(/^[\/]/,""); } // for correct display on win32
if(src_files===undefined) return 1;

View file

@ -2,13 +2,14 @@
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"promos": {
"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-latest": "1.1.0-b2",
"1.14.4-latest": "1.1.0-b3",
"1.15.2-recommended": "",
"1.15.2-latest": "1.1.0-b2"
"1.15.2-latest": "1.1.0-b3"
},
"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.",
@ -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.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-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*.",
@ -153,6 +155,7 @@
"1.0.7-b3": "[A] Initial 1.14.2 port of decorative blocks."
},
"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-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*.",