made an API change to enforce the right aura methods, also add over- and underflow protection

This commit is contained in:
Ellpeck 2018-12-02 01:36:41 +01:00
parent 5abeeba757
commit 08fd796fe2
13 changed files with 50 additions and 54 deletions

View file

@ -73,7 +73,7 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
} }
@Override @Override
public void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) { public void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer) {
world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getSpotsInArea"); world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getSpotsInArea");
for (int x = (pos.getX() - radius) >> 4; x <= (pos.getX() + radius) >> 4; x++) { for (int x = (pos.getX() - radius) >> 4; x <= (pos.getX() + radius) >> 4; x++) {
for (int z = (pos.getZ() - radius) >> 4; z <= (pos.getZ() + radius) >> 4; z++) { for (int z = (pos.getZ() - radius) >> 4; z <= (pos.getZ() + radius) >> 4; z++) {
@ -92,7 +92,7 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
@Override @Override
public int getAuraInArea(World world, BlockPos pos, int radius) { public int getAuraInArea(World world, BlockPos pos, int radius) {
MutableInt result = new MutableInt(IAuraChunk.DEFAULT_AURA); MutableInt result = new MutableInt(IAuraChunk.DEFAULT_AURA);
this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> result.add(drainSpot.intValue())); this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> result.add(drainSpot));
return result.intValue(); return result.intValue();
} }
@ -101,9 +101,8 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
MutableInt lowestAmount = new MutableInt(Integer.MAX_VALUE); MutableInt lowestAmount = new MutableInt(Integer.MAX_VALUE);
MutableObject<BlockPos> lowestSpot = new MutableObject<>(); MutableObject<BlockPos> lowestSpot = new MutableObject<>();
this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> { this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> {
int amount = drainSpot.intValue(); if (drainSpot < lowestAmount.intValue()) {
if (amount < lowestAmount.intValue()) { lowestAmount.setValue(drainSpot);
lowestAmount.setValue(amount);
lowestSpot.setValue(blockPos); lowestSpot.setValue(blockPos);
} }
}); });
@ -118,9 +117,8 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks {
MutableInt highestAmount = new MutableInt(Integer.MIN_VALUE); MutableInt highestAmount = new MutableInt(Integer.MIN_VALUE);
MutableObject<BlockPos> highestSpot = new MutableObject<>(); MutableObject<BlockPos> highestSpot = new MutableObject<>();
this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> { this.getAuraSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> {
int amount = drainSpot.intValue(); if (drainSpot > highestAmount.intValue()) {
if (amount > highestAmount.intValue()) { highestAmount.setValue(drainSpot);
highestAmount.setValue(amount);
highestSpot.setValue(blockPos); highestSpot.setValue(blockPos);
} }
}); });

View file

@ -21,7 +21,6 @@ import net.minecraft.world.DimensionType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityInject;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -40,7 +39,7 @@ public final class NaturesAuraAPI {
public static final String MOD_ID = "naturesaura"; public static final String MOD_ID = "naturesaura";
public static final String API_ID = MOD_ID + "api"; public static final String API_ID = MOD_ID + "api";
public static final String VERSION = "4"; public static final String VERSION = "5";
/** /**
* The list of all {@link AltarRecipe} instances which are the recipes used * The list of all {@link AltarRecipe} instances which are the recipes used
@ -226,7 +225,7 @@ public final class NaturesAuraAPI {
/** /**
* @see IAuraChunk#getSpotsInArea(World, BlockPos, int, BiConsumer) * @see IAuraChunk#getSpotsInArea(World, BlockPos, int, BiConsumer)
*/ */
void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer); void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer);
/** /**
* @see IAuraChunk#getAuraInArea(World, BlockPos, int) * @see IAuraChunk#getAuraInArea(World, BlockPos, int)

View file

@ -8,7 +8,6 @@ import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.INBTSerializable;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -59,7 +58,7 @@ public interface IAuraChunk extends ICapabilityProvider, INBTSerializable<NBTTag
* @param consumer A consumer that gets given the position and amount of * @param consumer A consumer that gets given the position and amount of
* aura in each drain spot found * aura in each drain spot found
*/ */
static void getSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) { static void getSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer) {
NaturesAuraAPI.instance().getAuraSpotsInArea(world, pos, radius, consumer); NaturesAuraAPI.instance().getAuraSpotsInArea(world, pos, radius, consumer);
} }
@ -117,7 +116,7 @@ public interface IAuraChunk extends ICapabilityProvider, INBTSerializable<NBTTag
/** /**
* @see #getSpotsInArea(World, BlockPos, int, BiConsumer) * @see #getSpotsInArea(World, BlockPos, int, BiConsumer)
*/ */
void getSpotsInArea(BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer); void getSpotsInArea(BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer);
/** /**
* Drains the given amount of Aura from the given position. Returns the * Drains the given amount of Aura from the given position. Returns the
@ -165,7 +164,7 @@ public interface IAuraChunk extends ICapabilityProvider, INBTSerializable<NBTTag
*/ */
int storeAura(BlockPos pos, int amount); int storeAura(BlockPos pos, int amount);
MutableInt getDrainSpot(BlockPos pos); int getDrainSpot(BlockPos pos);
IAuraType getType(); IAuraType getType();

View file

@ -5,11 +5,10 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public interface IDrainSpotEffect { public interface IDrainSpotEffect {
void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot); void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot);
boolean appliesHere(Chunk chunk, IAuraChunk auraChunk, IAuraType type); boolean appliesHere(Chunk chunk, IAuraChunk auraChunk, IAuraType type);

View file

@ -6,7 +6,6 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -32,7 +31,7 @@ public class StubHooks implements NaturesAuraAPI.IInternalHooks {
} }
@Override @Override
public void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) { public void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer) {
} }

View file

@ -43,11 +43,11 @@ public class AuraChunk implements IAuraChunk {
} }
@Override @Override
public void getSpotsInArea(BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) { public void getSpotsInArea(BlockPos pos, int radius, BiConsumer<BlockPos, Integer> consumer) {
for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) { for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) {
BlockPos drainPos = entry.getKey(); BlockPos drainPos = entry.getKey();
if (drainPos.distanceSq(pos) <= radius * radius) { if (drainPos.distanceSq(pos) <= radius * radius) {
consumer.accept(drainPos, entry.getValue()); consumer.accept(drainPos, entry.getValue().intValue());
} }
} }
} }
@ -56,9 +56,11 @@ public class AuraChunk implements IAuraChunk {
public int drainAura(BlockPos pos, int amount, boolean aimForZero, boolean simulate) { public int drainAura(BlockPos pos, int amount, boolean aimForZero, boolean simulate) {
if (amount <= 0) if (amount <= 0)
return 0; return 0;
MutableInt spot = this.getDrainSpot(pos); MutableInt spot = this.getActualDrainSpot(pos, true);
if (aimForZero) {
int curr = spot.intValue(); int curr = spot.intValue();
if (curr < 0 && curr - amount > 0) // Underflow protection
return 0;
if (aimForZero) {
if (curr > 0 && curr - amount < 0) if (curr > 0 && curr - amount < 0)
amount = curr; amount = curr;
} }
@ -78,9 +80,11 @@ public class AuraChunk implements IAuraChunk {
public int storeAura(BlockPos pos, int amount, boolean aimForZero, boolean simulate) { public int storeAura(BlockPos pos, int amount, boolean aimForZero, boolean simulate) {
if (amount <= 0) if (amount <= 0)
return 0; return 0;
MutableInt spot = this.getDrainSpot(pos); MutableInt spot = this.getActualDrainSpot(pos, true);
if (aimForZero) {
int curr = spot.intValue(); int curr = spot.intValue();
if (curr > 0 && curr + amount < 0) // Overflow protection
return 0;
if (aimForZero) {
if (curr < 0 && curr + amount > 0) { if (curr < 0 && curr + amount > 0) {
amount = -curr; amount = -curr;
} }
@ -97,16 +101,21 @@ public class AuraChunk implements IAuraChunk {
return this.storeAura(pos, amount, true, false); return this.storeAura(pos, amount, true, false);
} }
@Override private MutableInt getActualDrainSpot(BlockPos pos, boolean make) {
public MutableInt getDrainSpot(BlockPos pos) {
MutableInt spot = this.drainSpots.get(pos); MutableInt spot = this.drainSpots.get(pos);
if (spot == null) { if (spot == null && make) {
spot = new MutableInt(); spot = new MutableInt();
this.addDrainSpot(pos, spot); this.addDrainSpot(pos, spot);
} }
return spot; return spot;
} }
@Override
public int getDrainSpot(BlockPos pos) {
MutableInt spot = this.getActualDrainSpot(pos, false);
return spot == null ? 0 : spot.intValue();
}
private void addDrainSpot(BlockPos pos, MutableInt spot) { private void addDrainSpot(BlockPos pos, MutableInt spot) {
int expX = pos.getX() >> 4; int expX = pos.getX() >> 4;
int expZ = pos.getZ() >> 4; int expZ = pos.getZ() >> 4;
@ -141,7 +150,7 @@ public class AuraChunk implements IAuraChunk {
MutableInt amount = entry.getValue(); MutableInt amount = entry.getValue();
for (IDrainSpotEffect effect : this.effects) { for (IDrainSpotEffect effect : this.effects) {
world.profiler.func_194340_a(() -> effect.getName().toString()); world.profiler.func_194340_a(() -> effect.getName().toString());
effect.update(world, this.chunk, this, pos, amount); effect.update(world, this.chunk, this, pos, amount.intValue());
world.profiler.endSection(); world.profiler.endSection();
} }
if (amount.intValue() == 0) { if (amount.intValue() == 0) {

View file

@ -8,15 +8,14 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public class BalanceEffect implements IDrainSpotEffect { public class BalanceEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "balance"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "balance");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (spot.intValue() >= 0) if (spot >= 0)
return; return;
int aura = IAuraChunk.getAuraInArea(world, pos, 25); int aura = IAuraChunk.getAuraInArea(world, pos, 25);
if (aura >= 0) if (aura >= 0)
@ -28,7 +27,7 @@ public class BalanceEffect implements IDrainSpotEffect {
if (highestPos == null) if (highestPos == null)
return; return;
IAuraChunk highestChunk = IAuraChunk.getAuraChunk(world, highestPos); IAuraChunk highestChunk = IAuraChunk.getAuraChunk(world, highestPos);
int toTransfer = Math.min(25, highestChunk.getDrainSpot(highestPos).intValue()); int toTransfer = Math.min(25, highestChunk.getDrainSpot(highestPos));
int stored = auraChunk.storeAura(pos, toTransfer); int stored = auraChunk.storeAura(pos, toTransfer);
highestChunk.drainAura(highestPos, stored); highestChunk.drainAura(highestPos, stored);
} }

View file

@ -14,7 +14,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.List; import java.util.List;
@ -23,8 +22,8 @@ public class BreathlessEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "breathless"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "breathless");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (spot.intValue() >= 0 || world.getTotalWorldTime() % 100 != 0) if (spot >= 0 || world.getTotalWorldTime() % 100 != 0)
return; return;
int aura = IAuraChunk.getAuraInArea(world, pos, 50); int aura = IAuraChunk.getAuraInArea(world, pos, 50);
if (aura > 0) if (aura > 0)

View file

@ -10,15 +10,14 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public class ExplosionEffect implements IDrainSpotEffect { public class ExplosionEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "explosions"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "explosions");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (spot.intValue() >= 0 || world.getTotalWorldTime() % 40 != 0) if (spot >= 0 || world.getTotalWorldTime() % 40 != 0)
return; return;
int aura = IAuraChunk.getAuraInArea(world, pos, 85); int aura = IAuraChunk.getAuraInArea(world, pos, 85);
if (aura > -50000) if (aura > -50000)

View file

@ -15,15 +15,14 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public class GrassDieEffect implements IDrainSpotEffect { public class GrassDieEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "grass_die"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "grass_die");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (spot.intValue() < 0) { if (spot < 0) {
int aura = IAuraChunk.getAuraInArea(world, pos, 50); int aura = IAuraChunk.getAuraInArea(world, pos, 50);
if (aura < 0) { if (aura < 0) {
int amount = Math.min(300, Math.abs(aura) / 1000); int amount = Math.min(300, Math.abs(aura) / 1000);

View file

@ -17,15 +17,14 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public class PlantBoostEffect implements IDrainSpotEffect { public class PlantBoostEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "plant_boost"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "plant_boost");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (spot.intValue() <= 0) if (spot <= 0)
return; return;
int aura = IAuraChunk.getAuraInArea(world, pos, 30); int aura = IAuraChunk.getAuraInArea(world, pos, 30);
if (aura < 15000) if (aura < 15000)

View file

@ -12,7 +12,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -22,9 +21,8 @@ public class ReplenishingEffect implements IDrainSpotEffect {
public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "replenishing"); public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "replenishing");
@Override @Override
public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, MutableInt spot) { public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
int amount = spot.intValue(); if (spot < 0) {
if (amount < 0) {
List<ISpotDrainable> tiles = new ArrayList<>(); List<ISpotDrainable> tiles = new ArrayList<>();
Helper.getTileEntitiesInArea(world, pos, 25, tile -> { Helper.getTileEntitiesInArea(world, pos, 25, tile -> {
if (tile.hasCapability(NaturesAuraAPI.capAuraContainer, null)) { if (tile.hasCapability(NaturesAuraAPI.capAuraContainer, null)) {
@ -41,12 +39,12 @@ public class ReplenishingEffect implements IDrainSpotEffect {
ISpotDrainable tile = tiles.get(world.rand.nextInt(tiles.size())); ISpotDrainable tile = tiles.get(world.rand.nextInt(tiles.size()));
if (!tile.isAcceptableType(type)) if (!tile.isAcceptableType(type))
continue; continue;
int drained = tile.drainAuraPassively(-amount, false); int drained = tile.drainAuraPassively(-spot, false);
if (drained <= 0) if (drained <= 0)
continue; continue;
auraChunk.storeAura(pos, drained); auraChunk.storeAura(pos, drained);
amount += drained; spot += drained;
if (amount >= drained) { if (spot >= drained) {
break; break;
} }
} }

View file

@ -57,9 +57,9 @@ public class ClientEvents {
MutableInt spots = new MutableInt(); MutableInt spots = new MutableInt();
IAuraChunk.getSpotsInArea(mc.world, mc.player.getPosition(), 15, ((blockPos, drainSpot) -> { IAuraChunk.getSpotsInArea(mc.world, mc.player.getPosition(), 15, ((blockPos, drainSpot) -> {
spots.increment(); spots.increment();
amount.add(drainSpot.intValue()); amount.add(drainSpot);
if (mc.player.isSneaking()) if (mc.player.isSneaking())
left.add(prefix + drainSpot.intValue() + " @ " + blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ()); left.add(prefix + drainSpot + " @ " + blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ());
})); }));
left.add(prefix + "Total: " + amount.intValue() + " in " + spots.intValue() + " spots"); left.add(prefix + "Total: " + amount.intValue() + " in " + spots.intValue() + " spots");
left.add(prefix + "Type: " + IAuraType.forWorld(mc.world).getName()); left.add(prefix + "Type: " + IAuraType.forWorld(mc.world).getName());