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

@ -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