From dd5bf7a72e11de50cff3de9f4eed173281c144c1 Mon Sep 17 00:00:00 2001 From: "Michael J. Evans" Date: Thu, 26 Dec 2019 18:59:22 -0800 Subject: [PATCH 1/2] src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java Fix bugs #22 #25 (do not work on source hive) Fix bugs #23 #37 (use canHandleBlock guard) (and my issue) https://github.com/DarkPacks/Crackpack-3/issues/113 src/main/java/com/rwtema/careerbees/effects/EffectPower.java Fix #17 (work on any valid side, including 'internal' / null) and refactored to de-duplicate code Also include the logger to annotate the 'sent too much' corner case covered by the code this replaces (in case other mods are glitchy about storing too much energy). --- .../careerbees/effects/EffectAssassin.java | 37 +++++---- .../careerbees/effects/EffectPower.java | 82 ++++++++++++++----- 2 files changed, 85 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java b/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java index a778a9e..5ccea7a 100644 --- a/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java +++ b/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java @@ -31,11 +31,15 @@ public EffectAssassin(String name, boolean isDominant, boolean isCombinable, flo @Override public boolean canHandleBlock(World world, BlockPos pos, @Nonnull IBeeGenome genome, @Nullable EnumFacing sideHit) { TileEntity tileEntity = world.getTileEntity(pos); + if ( tileEntity == null ) + return false; if (tileEntity instanceof IBeeHousing) { ItemStack queen = ((IBeeHousing) tileEntity).getBeeInventory().getQueen(); - if (queen.isEmpty() || BeeManager.beeRoot.getType(queen) != EnumBeeType.QUEEN) return false; + if (queen.isEmpty() || BeeManager.beeRoot.getType(queen) != EnumBeeType.QUEEN) + return false; IBee member = BeeManager.beeRoot.getMember(queen); - if (member == null) return false; + if (member == null) + return false; IBeeGenome memberGenome = member.getGenome(); return memberGenome.getPrimary() != genome.getPrimary(); } @@ -44,17 +48,22 @@ public boolean canHandleBlock(World world, BlockPos pos, @Nonnull IBeeGenome gen @Override protected boolean performPosEffect(World world, BlockPos blockPos, IBlockState state, IBeeGenome genome, IBeeHousing housing) { - IBeeHousing house = (IBeeHousing) world.getTileEntity(blockPos); - if(house == null) return false; - ItemStack queenStack = house.getBeeInventory().getQueen(); - IBee queen = BeeManager.beeRoot.getMember(queenStack); - if(queen == null || queenStack.isEmpty() || !queenStack.hasTagCompound()) return false; - queen.setHealth(0); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - queen.writeToNBT(nbttagcompound); - queenStack.setTagCompound(nbttagcompound); - housing.getBeeInventory().setQueen(queenStack); - house.getBeekeepingLogic().canWork(); - return true; + if ( housing.getCoordinates() == blockPos ) + return false; + if ( canHandleBlock(world, blockPos, genome, null) ) { + IBeeHousing house = (IBeeHousing) world.getTileEntity(blockPos); + ItemStack queenStack = house.getBeeInventory().getQueen(); + IBee queen = BeeManager.beeRoot.getMember(queenStack); + if (queen == null || queenStack.isEmpty() || !queenStack.hasTagCompound()) + return false; + queen.setHealth(0); + NBTTagCompound nbttagcompound = new NBTTagCompound(); + queen.writeToNBT(nbttagcompound); + queenStack.setTagCompound(nbttagcompound); + house.getBeeInventory().setQueen(queenStack); + house.getBeekeepingLogic().canWork(); + return true; + } + return false; } } diff --git a/src/main/java/com/rwtema/careerbees/effects/EffectPower.java b/src/main/java/com/rwtema/careerbees/effects/EffectPower.java index f4fdebf..f8dff7c 100644 --- a/src/main/java/com/rwtema/careerbees/effects/EffectPower.java +++ b/src/main/java/com/rwtema/careerbees/effects/EffectPower.java @@ -1,5 +1,6 @@ package com.rwtema.careerbees.effects; +import com.rwtema.careerbees.BeeMod; // get BeeMod.logger to record erroring import com.rwtema.careerbees.effects.settings.IEffectSettingsHolder; import forestry.api.apiculture.IBeeGenome; import forestry.api.apiculture.IBeeHousing; @@ -14,6 +15,7 @@ import javax.annotation.Nonnull; import java.util.Random; +import java.util.ArrayList; public class EffectPower extends EffectBase implements ISpecialBeeEffect.SpecialEffectBlock { public static final EffectPower INSTANCE = new EffectPower("rf"); @@ -29,7 +31,7 @@ public EffectPower(String rawname, boolean isDominant, boolean isCombinable) { @Nonnull @Override public IEffectData doEffectBase(@Nonnull IBeeGenome genome, @Nonnull IEffectData storedData, @Nonnull IBeeHousing housing, IEffectSettingsHolder settings) { - int rfrate = getRFRate(genome, housing); + int rfRate = getRFRate(genome, housing); TileEntity entity = housing.getWorldObj().getTileEntity(housing.getCoordinates()); if (!(entity instanceof IBeeHousing)) { @@ -41,18 +43,15 @@ public IEffectData doEffectBase(@Nonnull IBeeGenome genome, @Nonnull IEffectData return storedData; } - int energyleft = rfrate; + int energyleft = rfRate; + World world = housing.getWorldObj(); for (BlockPos pos : getAdjacentTiles(housing)) { - World world = housing.getWorldObj(); - TileEntity tileEntity = world.getTileEntity(pos); - if (tileEntity != null) { - IEnergyStorage energyStorage = tileEntity.getCapability(CapabilityEnergy.ENERGY, null); - if (energyStorage != null) { - energyleft -= energyStorage.receiveEnergy(energyleft, false); - if (energyleft <= 0) break; - } - } + ArrayList faces = getEnergyStorageFaces(world, pos, true); + int energysent = storeRFTEFaces(world, pos, faces, rfRate); + energyleft -= energysent; + if ( 0 == energyleft ) + break; } return storedData; } @@ -63,10 +62,57 @@ public int getRFRate(@Nonnull IBeeGenome genome, @Nonnull IBeeHousing housing) { return MathHelper.ceil(400 * speed * speed); } + private ArrayList getEnergyStorageFaces(World world, BlockPos pos, boolean scanAll) { + ArrayList faces = new ArrayList(); + TileEntity te = world.getTileEntity(pos); + if ( null == te ) + return faces; + if ( te.hasCapability(CapabilityEnergy.ENERGY, null) && + te.getCapability(CapabilityEnergy.ENERGY, null).canReceive() ) { + faces.add(null); + if ( ! scanAll ) + return faces; + } + for (EnumFacing face : EnumFacing.VALUES) { + if ( te.hasCapability(CapabilityEnergy.ENERGY, face) && + te.getCapability(CapabilityEnergy.ENERGY, face).canReceive() ) + faces.add(face); + if ( ! scanAll ) + return faces; + } + return faces; + } + + private int storeRFTEFaces(World world, BlockPos pos, ArrayList faces, int maxRF) { + int energyLeft = maxRF; + TileEntity te = world.getTileEntity(pos); + if ( null == te ) + return 0; // no energy sent + for (EnumFacing face : faces) { + IEnergyStorage storage = te.getCapability(CapabilityEnergy.ENERGY, face); + if (storage != null) { + // max rate, simulate (is false; actually do it) + int energyStored = storage.receiveEnergy(energyLeft, false); + if ( energyStored > energyLeft ) { + BeeMod.logger.trace("The block at " + pos + " on face " + face + + " consumed (" + energyStored + + ") more energy than was sent (" + energyLeft + + "); this should never happen. " + + "Please report it to the author of the TileEntity: " + te); + energyLeft = 0; + } else { + energyLeft -= energyStored; + } + } + if ( 0 == energyLeft ) + break; + } + return maxRF - energyLeft; // return used/sent + } + @Override public boolean canHandleBlock(World world, BlockPos pos, @Nonnull IBeeGenome genome, EnumFacing sideHit) { - TileEntity tile = world.getTileEntity(pos); - return tile != null && tile.hasCapability(CapabilityEnergy.ENERGY, null); + return ! getEnergyStorageFaces(world, pos, false).isEmpty(); } @Override @@ -76,13 +122,9 @@ public float getCooldown(IBeeGenome genome, Random random) { @Override public void processingTick(World world, BlockPos pos, @Nonnull IBeeGenome genome, @Nonnull IBeeHousing housing, EnumFacing facing) { - TileEntity tile = world.getTileEntity(pos); - if (tile == null || !tile.hasCapability(CapabilityEnergy.ENERGY, null)) return; - IEnergyStorage storage = tile.getCapability(CapabilityEnergy.ENERGY, null); - if (storage != null) { - int rfRate = getRFRate(genome, housing); - storage.receiveEnergy(rfRate, false); - } + ArrayList faces = getEnergyStorageFaces(world, pos, true); + int rfRate = getRFRate(genome, housing); + storeRFTEFaces(world, pos, faces, rfRate); } @Override From 5607782103fb8eee04933743ec8fc8f519d71c7c Mon Sep 17 00:00:00 2001 From: "Michael J. Evans" Date: Sun, 29 Dec 2019 02:29:10 -0800 Subject: [PATCH 2/2] Fix bee gun (Assassin); it passes in a fake housing for the target block pos, which broke the seemingly non-issue guard. The bug in question is still resolved by calling canHandleBlock, since that checks the target genome against the calling genome as it's only possible true result. --- src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java b/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java index 5ccea7a..d8c0635 100644 --- a/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java +++ b/src/main/java/com/rwtema/careerbees/effects/EffectAssassin.java @@ -48,8 +48,6 @@ public boolean canHandleBlock(World world, BlockPos pos, @Nonnull IBeeGenome gen @Override protected boolean performPosEffect(World world, BlockPos blockPos, IBlockState state, IBeeGenome genome, IBeeHousing housing) { - if ( housing.getCoordinates() == blockPos ) - return false; if ( canHandleBlock(world, blockPos, genome, null) ) { IBeeHousing house = (IBeeHousing) world.getTileEntity(blockPos); ItemStack queenStack = house.getBeeInventory().getQueen();