diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index ecc8eb22..6ace1ef8 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -3,6 +3,7 @@ package de.ellpeck.naturesaura; import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.item.IAuraRecharge; import de.ellpeck.naturesaura.blocks.tiles.TileEntityImpl; +import de.ellpeck.naturesaura.chunk.AuraChunk; import net.minecraft.advancements.Advancement; import net.minecraft.block.Block; import net.minecraft.block.properties.IProperty; @@ -28,6 +29,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderServer; import net.minecraftforge.common.capabilities.Capability; @@ -41,25 +43,46 @@ import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; +import java.util.function.Consumer; import java.util.function.Function; public final class Helper { public static boolean getTileEntitiesInArea(World world, BlockPos pos, int radius, Function consumer) { + world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getAuraChunksInArea"); 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++) { if (isChunkLoaded(world, x, z)) { for (TileEntity tile : world.getChunk(x, z).getTileEntityMap().values()) { if (tile.getPos().distanceSq(pos) <= radius * radius) - if (consumer.apply(tile)) + if (consumer.apply(tile)) { + world.profiler.endSection(); return true; + } } } } } + world.profiler.endSection(); return false; } + public static void getAuraChunksInArea(World world, BlockPos pos, int radius, Consumer consumer) { + world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getAuraChunksInArea"); + 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++) { + if (Helper.isChunkLoaded(world, x, z)) { + Chunk chunk = world.getChunk(x, z); + if (chunk.hasCapability(NaturesAuraAPI.capAuraChunk, null)) { + AuraChunk auraChunk = (AuraChunk) chunk.getCapability(NaturesAuraAPI.capAuraChunk, null); + consumer.accept(auraChunk); + } + } + } + } + world.profiler.endSection(); + } + public static List getAttachedItemFrames(World world, BlockPos pos) { List frames = world.getEntitiesWithinAABB(EntityItemFrame.class, new AxisAlignedBB(pos).grow(0.25)); for (int i = frames.size() - 1; i >= 0; i--) { diff --git a/src/main/java/de/ellpeck/naturesaura/InternalHooks.java b/src/main/java/de/ellpeck/naturesaura/InternalHooks.java index 013545db..fef298fb 100644 --- a/src/main/java/de/ellpeck/naturesaura/InternalHooks.java +++ b/src/main/java/de/ellpeck/naturesaura/InternalHooks.java @@ -15,7 +15,6 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; import net.minecraftforge.items.IItemHandler; import org.apache.commons.lang3.mutable.MutableFloat; import org.apache.commons.lang3.mutable.MutableInt; @@ -114,17 +113,7 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks { @Override public void getAuraSpotsInArea(World world, BlockPos pos, int radius, BiConsumer consumer) { world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":getSpotsInArea"); - 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++) { - if (Helper.isChunkLoaded(world, x, z)) { - Chunk chunk = world.getChunk(x, z); - if (chunk.hasCapability(NaturesAuraAPI.capAuraChunk, null)) { - IAuraChunk auraChunk = chunk.getCapability(NaturesAuraAPI.capAuraChunk, null); - auraChunk.getSpotsInArea(pos, radius, consumer); - } - } - } - } + Helper.getAuraChunksInArea(world, pos, radius, chunk -> chunk.getSpotsInArea(pos, radius, consumer)); world.profiler.endSection(); } diff --git a/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IAuraChunk.java b/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IAuraChunk.java index ce28066e..40146df1 100644 --- a/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IAuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IAuraChunk.java @@ -46,11 +46,6 @@ public interface IAuraChunk extends ICapabilityProvider, INBTSerializable - * Notice that this is different from {@link #getSpotsInArea(BlockPos, int, - * BiConsumer)} because this method iterates over several chunks while the - * former only uses the current aura chunk instance. Most of the time, you - * will want to use this method. * * @param world The world * @param pos The center position @@ -133,11 +128,6 @@ public interface IAuraChunk extends ICapabilityProvider, INBTSerializable consumer); - /** * Drains the given amount of Aura from the given position. Returns the * amount of Aura that was drained. diff --git a/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IDrainSpotEffect.java b/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IDrainSpotEffect.java index 7066ef5d..7262e5e6 100644 --- a/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IDrainSpotEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/api/aura/chunk/IDrainSpotEffect.java @@ -1,6 +1,8 @@ package de.ellpeck.naturesaura.api.aura.chunk; import de.ellpeck.naturesaura.api.aura.type.IAuraType; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -13,4 +15,12 @@ public interface IDrainSpotEffect { boolean appliesHere(Chunk chunk, IAuraChunk auraChunk, IAuraType type); ResourceLocation getName(); + + default int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + return -1; + } + + default ItemStack getDisplayIcon() { + return ItemStack.EMPTY; + } } diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java b/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java index 8c8574ed..79c28e01 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java @@ -6,10 +6,14 @@ import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect; import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.packet.PacketAuraChunk; import de.ellpeck.naturesaura.packet.PacketHandler; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -45,16 +49,6 @@ public class AuraChunk implements IAuraChunk { } } - @Override - public void getSpotsInArea(BlockPos pos, int radius, BiConsumer consumer) { - for (Map.Entry entry : this.drainSpots.entrySet()) { - BlockPos drainPos = entry.getKey(); - if (drainPos.distanceSq(pos) <= radius * radius) { - consumer.accept(drainPos, entry.getValue().intValue()); - } - } - } - @Override public int drainAura(BlockPos pos, int amount, boolean aimForZero, boolean simulate) { if (amount <= 0) @@ -174,6 +168,34 @@ public class AuraChunk implements IAuraChunk { return new PacketAuraChunk(this.chunk.x, this.chunk.z, this.drainSpots); } + public void getSpotsInArea(BlockPos pos, int radius, BiConsumer consumer) { + for (Map.Entry entry : this.drainSpots.entrySet()) { + BlockPos drainPos = entry.getKey(); + if (drainPos.distanceSq(pos) <= radius * radius) { + consumer.accept(drainPos, entry.getValue().intValue()); + } + } + } + + public void getActiveEffectIcons(EntityPlayer player, Map> icons) { + for (IDrainSpotEffect effect : this.effects) { + Tuple alreadyThere = icons.get(effect.getName()); + if (alreadyThere != null && alreadyThere.getSecond()) + continue; + for (Map.Entry entry : this.drainSpots.entrySet()) { + BlockPos pos = entry.getKey(); + MutableInt amount = entry.getValue(); + int state = effect.isActiveHere(player, this.chunk, this, pos, amount.intValue()); + if (state < 0) + continue; + ItemStack stack = effect.getDisplayIcon(); + if (stack.isEmpty()) + continue; + icons.put(effect.getName(), new Tuple<>(stack, state == 0)); + } + } + } + @Override public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { return capability == NaturesAuraAPI.capAuraChunk; diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/AnimalEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/AnimalEffect.java index 5bdce071..a284ba50 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/AnimalEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/AnimalEffect.java @@ -9,6 +9,8 @@ import de.ellpeck.naturesaura.api.aura.type.IAuraType; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityChicken; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; import net.minecraft.item.ItemEgg; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumParticleTypes; @@ -28,25 +30,50 @@ public class AnimalEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "animal"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + private int chance; + private AxisAlignedBB bb; + + private boolean calcValues(World world, BlockPos pos, Integer spot) { if (spot <= 0) - return; + return false; int aura = IAuraChunk.getAuraInArea(world, pos, 30); if (aura < 1500000) - return; - int chance = Math.min(50, Math.abs(aura) / 500000); - if (chance <= 0) - return; + return false; + this.chance = Math.min(50, Math.abs(aura) / 500000); + if (this.chance <= 0) + return false; int dist = MathHelper.clamp(Math.abs(aura) / 150000, 5, 35); - AxisAlignedBB bb = new AxisAlignedBB(pos).grow(dist); + this.bb = new AxisAlignedBB(pos).grow(dist); + return true; + } - List animals = world.getEntitiesWithinAABB(EntityAnimal.class, bb); + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (!this.bb.contains(player.getPositionVector())) + return -1; + if (NaturesAuraAPI.instance().isEffectPowderActive(player.world, player.getPosition(), NAME)) + return 0; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(Items.EGG); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(world, pos, spot)) + return; + + List animals = world.getEntitiesWithinAABB(EntityAnimal.class, this.bb); if (animals.size() >= 200) return; if (world.getTotalWorldTime() % 200 == 0) { - List items = world.getEntitiesWithinAABB(EntityItem.class, bb); + List items = world.getEntitiesWithinAABB(EntityItem.class, this.bb); for (EntityItem item : items) { if (item.isDead) continue; @@ -78,7 +105,7 @@ public class AnimalEffect implements IDrainSpotEffect { } } - if (world.rand.nextInt(200) <= chance) { + if (world.rand.nextInt(200) <= this.chance) { if (animals.size() < 2) return; EntityAnimal first = animals.get(world.rand.nextInt(animals.size())); diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/BreathlessEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/BreathlessEffect.java index 8a0badeb..0236b4ec 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/BreathlessEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/BreathlessEffect.java @@ -2,11 +2,15 @@ package de.ellpeck.naturesaura.chunk.effect; import de.ellpeck.naturesaura.ModConfig; import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect; import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.potion.ModPotions; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; @@ -21,22 +25,46 @@ public class BreathlessEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "breathless"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { - if (spot >= 0 || world.getTotalWorldTime() % 100 != 0) - return; + private int amp; + private AxisAlignedBB bb; + + private boolean calcValues(World world, BlockPos pos, Integer spot) { + if (spot >= 0) + return false; int aura = IAuraChunk.getAuraInArea(world, pos, 50); if (aura > 0) - return; + return false; int dist = Math.min(Math.abs(aura) / 50000, 75); if (dist < 10) - return; - int amp = Math.min(MathHelper.floor(Math.abs(aura) / 2500000F), 3); + return false; + this.amp = Math.min(MathHelper.floor(Math.abs(aura) / 2500000F), 3); + this.bb = new AxisAlignedBB(pos).grow(dist); + return true; + } - List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(pos).grow(dist)); + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (!this.bb.contains(player.getPositionVector())) + return -1; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(Blocks.WOOL); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (world.getTotalWorldTime() % 100 != 0) + return; + if (!this.calcValues(world, pos, spot)) + return; + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, this.bb); for (EntityLivingBase entity : entities) - entity.addPotionEffect(new PotionEffect(ModPotions.BREATHLESS, 300, amp)); + entity.addPotionEffect(new PotionEffect(ModPotions.BREATHLESS, 300, this.amp)); } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/CacheRechargeEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/CacheRechargeEffect.java index 11035321..e48e02dd 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/CacheRechargeEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/CacheRechargeEffect.java @@ -6,7 +6,9 @@ import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect; import de.ellpeck.naturesaura.api.aura.type.IAuraType; +import de.ellpeck.naturesaura.items.ModItems; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -20,23 +22,48 @@ public class CacheRechargeEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "cache_recharge"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + private int amount; + private AxisAlignedBB bb; + + private boolean calcValues(World world, BlockPos pos, Integer spot) { if (spot < 100000) - return; + return false; int aura = IAuraChunk.getAuraInArea(world, pos, 20); if (aura < 1500000) - return; - if (NaturesAuraAPI.instance().isEffectPowderActive(world, pos, NAME)) - return; + return false; int dist = MathHelper.clamp(aura / 3500, 3, 15); - int amount = aura / 250000 - 2; + this.bb = new AxisAlignedBB(pos).grow(dist); + this.amount = aura / 250000 - 2; + return true; + } - List players = world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(pos).grow(dist)); + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (!this.bb.contains(player.getPositionVector())) + return -1; + if (NaturesAuraAPI.instance().isEffectPowderActive(player.world, player.getPosition(), NAME)) + return 0; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(ModItems.AURA_CACHE); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(world, pos, spot)) + return; + List players = world.getEntitiesWithinAABB(EntityPlayer.class, this.bb); for (EntityPlayer player : players) { - if (NaturesAuraAPI.instance().insertAuraIntoPlayer(player, amount, true)) { - NaturesAuraAPI.instance().insertAuraIntoPlayer(player, amount, false); - auraChunk.drainAura(pos, amount); + if (NaturesAuraAPI.instance().isEffectPowderActive(world, player.getPosition(), NAME)) + continue; + if (NaturesAuraAPI.instance().insertAuraIntoPlayer(player, this.amount, true)) { + NaturesAuraAPI.instance().insertAuraIntoPlayer(player, this.amount, false); + auraChunk.drainAura(pos, this.amount); } } } diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/ExplosionEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/ExplosionEffect.java index 9be3c096..76f0b948 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/ExplosionEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/ExplosionEffect.java @@ -5,6 +5,9 @@ import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect; import de.ellpeck.naturesaura.api.aura.type.IAuraType; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -15,28 +18,54 @@ public class ExplosionEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "explosions"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { - if (spot >= 0 || world.getTotalWorldTime() % 40 != 0) - return; + private int chance; + private float strength; + private int dist; + + private boolean calcValues(World world, BlockPos pos, Integer spot){ + if (spot >= 0) + return false; int aura = IAuraChunk.getAuraInArea(world, pos, 85); if (aura > -5000000) - return; - int chance = 140 - Math.abs(aura) / 200000; - if (chance > 1 && world.rand.nextInt(chance) != 0) - return; - float strength = Math.min(Math.abs(aura) / 5000000F, 5F); - if (strength <= 0) - return; - int dist = MathHelper.clamp(Math.abs(aura) / 200000, 25, 100); + return false; + this.chance = 140 - Math.abs(aura) / 200000; + if (this.chance > 1 && world.rand.nextInt(this.chance) != 0) + return false; + this.strength = Math.min(Math.abs(aura) / 5000000F, 5F); + if (this.strength <= 0) + return false; + this.dist = MathHelper.clamp(Math.abs(aura) / 200000, 25, 100); + return true; + } - int x = MathHelper.floor(pos.getX() + world.rand.nextGaussian() * dist); - int z = MathHelper.floor(pos.getZ() + world.rand.nextGaussian() * dist); + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (player.getDistanceSq(pos) > this.dist * this.dist) + return -1; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(Blocks.TNT); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if(world.getTotalWorldTime() % 40 != 0) + return; + if(!this.calcValues(world, pos, spot)) + return; + + int x = MathHelper.floor(pos.getX() + world.rand.nextGaussian() * this.dist); + int z = MathHelper.floor(pos.getZ() + world.rand.nextGaussian() * this.dist); BlockPos chosenPos = new BlockPos(x, world.getHeight(x, z), z); - if (chosenPos.distanceSq(pos) <= dist * dist && world.isBlockLoaded(chosenPos)) { + if (chosenPos.distanceSq(pos) <= this.dist * this.dist && world.isBlockLoaded(chosenPos)) { world.newExplosion(null, chosenPos.getX() + 0.5, chosenPos.getY() + 0.5, chosenPos.getZ() + 0.5, - strength, false, true); + this.strength, false, true); } } diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/GrassDieEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/GrassDieEffect.java index bfef5b5b..7a5f4191 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/GrassDieEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/GrassDieEffect.java @@ -9,7 +9,9 @@ import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.blocks.ModBlocks; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -20,39 +22,63 @@ public class GrassDieEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "grass_die"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + private int amount; + private int dist; + + private boolean calcValues(World world, BlockPos pos, Integer spot) { if (spot < 0) { int aura = IAuraChunk.getAuraInArea(world, pos, 50); if (aura < 0) { - int amount = Math.min(300, Math.abs(aura) / 100000); - if (amount > 1) { - int dist = MathHelper.clamp(Math.abs(aura) / 75000, 5, 75); - for (int i = amount / 2 + world.rand.nextInt(amount / 2); i >= 0; i--) { - BlockPos grassPos = new BlockPos( - pos.getX() + world.rand.nextGaussian() * dist, - pos.getY() + world.rand.nextGaussian() * dist, - pos.getZ() + world.rand.nextGaussian() * dist - ); - if (grassPos.distanceSq(pos) <= dist * dist && world.isBlockLoaded(grassPos)) { - IBlockState state = world.getBlockState(grassPos); - Block block = state.getBlock(); - - IBlockState newState = null; - if (block instanceof BlockLeaves) { - newState = ModBlocks.DECAYED_LEAVES.getDefaultState(); - } else if (block instanceof BlockGrass) { - newState = Blocks.DIRT.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.COARSE_DIRT); - } else if (block instanceof BlockBush) { - newState = Blocks.AIR.getDefaultState(); - } - if (newState != null) - world.setBlockState(grassPos, newState); - } - } + this.amount = Math.min(300, Math.abs(aura) / 100000); + if (this.amount > 1) { + this.dist = MathHelper.clamp(Math.abs(aura) / 75000, 5, 75); + return true; } } } + return false; + } + + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (player.getDistanceSq(pos) > this.dist * this.dist) + return -1; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(ModBlocks.DECAYED_LEAVES); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(world, pos, spot)) + return; + for (int i = this.amount / 2 + world.rand.nextInt(this.amount / 2); i >= 0; i--) { + BlockPos grassPos = new BlockPos( + pos.getX() + world.rand.nextGaussian() * this.dist, + pos.getY() + world.rand.nextGaussian() * this.dist, + pos.getZ() + world.rand.nextGaussian() * this.dist + ); + if (grassPos.distanceSq(pos) <= this.dist * this.dist && world.isBlockLoaded(grassPos)) { + IBlockState state = world.getBlockState(grassPos); + Block block = state.getBlock(); + + IBlockState newState = null; + if (block instanceof BlockLeaves) { + newState = ModBlocks.DECAYED_LEAVES.getDefaultState(); + } else if (block instanceof BlockGrass) { + newState = Blocks.DIRT.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.COARSE_DIRT); + } else if (block instanceof BlockBush) { + newState = Blocks.AIR.getDefaultState(); + } + if (newState != null) + world.setBlockState(grassPos, newState); + } + } } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/PlantBoostEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/PlantBoostEffect.java index 3900d6c0..c3a30b78 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/PlantBoostEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/PlantBoostEffect.java @@ -11,7 +11,10 @@ import de.ellpeck.naturesaura.packet.PacketParticles; import net.minecraft.block.Block; import net.minecraft.block.IGrowable; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -22,23 +25,47 @@ public class PlantBoostEffect implements IDrainSpotEffect { public static final ResourceLocation NAME = new ResourceLocation(NaturesAura.MOD_ID, "plant_boost"); - @Override - public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + private int amount; + private int dist; + + private boolean calcValues(World world, BlockPos pos, Integer spot) { if (spot <= 0) - return; + return false; int aura = IAuraChunk.getAuraInArea(world, pos, 30); if (aura < 1500000) - return; - int amount = Math.min(45, Math.abs(aura) / 100000); - if (amount <= 1) - return; - int dist = MathHelper.clamp(Math.abs(aura) / 150000, 5, 35); + return false; + this.amount = Math.min(45, Math.abs(aura) / 100000); + if (this.amount <= 1) + return false; + this.dist = MathHelper.clamp(Math.abs(aura) / 150000, 5, 35); + return true; + } - for (int i = amount / 2 + world.rand.nextInt(amount / 2); i >= 0; i--) { - int x = MathHelper.floor(pos.getX() + world.rand.nextGaussian() * dist); - int z = MathHelper.floor(pos.getZ() + world.rand.nextGaussian() * dist); + @Override + public int isActiveHere(EntityPlayer player, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(player.world, pos, spot)) + return -1; + if (player.getDistanceSq(pos) > this.dist * this.dist) + return -1; + if (NaturesAuraAPI.instance().isEffectPowderActive(player.world, player.getPosition(), NAME)) + return 0; + return 1; + } + + @Override + public ItemStack getDisplayIcon() { + return new ItemStack(Items.WHEAT_SEEDS); + } + + @Override + public void update(World world, Chunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) { + if (!this.calcValues(world, pos, spot)) + return; + for (int i = this.amount / 2 + world.rand.nextInt(this.amount / 2); i >= 0; i--) { + int x = MathHelper.floor(pos.getX() + world.rand.nextGaussian() * this.dist); + int z = MathHelper.floor(pos.getZ() + world.rand.nextGaussian() * this.dist); BlockPos plantPos = new BlockPos(x, world.getHeight(x, z), z); - if (plantPos.distanceSq(pos) <= dist * dist && world.isBlockLoaded(plantPos)) { + if (plantPos.distanceSq(pos) <= this.dist * this.dist && world.isBlockLoaded(plantPos)) { if (NaturesAuraAPI.instance().isEffectPowderActive(world, plantPos, NAME)) continue; diff --git a/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java b/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java index 3d28facc..0f268092 100644 --- a/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java +++ b/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java @@ -29,6 +29,7 @@ import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Tuple; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -58,6 +59,10 @@ import java.util.Map; public class ClientEvents { public static final ResourceLocation OVERLAYS = new ResourceLocation(NaturesAura.MOD_ID, "textures/gui/overlays.png"); + private static final Map> SHOWING_EFFECTS = new HashMap<>(); + private static ItemStack heldCache = ItemStack.EMPTY; + private static ItemStack heldEye = ItemStack.EMPTY; + private static ItemStack heldOcular = ItemStack.EMPTY; @SubscribeEvent public void onDebugRender(RenderGameOverlayEvent.Text event) { @@ -95,6 +100,10 @@ public class ClientEvents { @SubscribeEvent public void onClientTick(ClientTickEvent event) { if (event.phase == Phase.END) { + heldCache = ItemStack.EMPTY; + heldEye = ItemStack.EMPTY; + heldOcular = ItemStack.EMPTY; + Minecraft mc = Minecraft.getMinecraft(); if (mc.world == null) { ParticleHandler.clearParticles(); @@ -138,6 +147,41 @@ public class ClientEvents { if (!mc.isGamePaused()) ParticleHandler.updateParticles(); mc.profiler.endSection(); + + if (mc.player != null) { + if (Compat.baubles) { + IItemHandler baubles = BaublesApi.getBaublesHandler(mc.player); + for (int i = 0; i < baubles.getSlots(); i++) { + ItemStack slot = baubles.getStackInSlot(i); + if (!slot.isEmpty()) { + if (slot.getItem() == ModItems.AURA_CACHE) + heldCache = slot; + else if (slot.getItem() == ModItems.EYE) + heldEye = slot; + else if (slot.getItem() == ModItems.EYE_IMPROVED) + heldOcular = slot; + } + } + } + + for (int i = 0; i < mc.player.inventory.getSizeInventory(); i++) { + ItemStack slot = mc.player.inventory.getStackInSlot(i); + if (!slot.isEmpty()) { + if (slot.getItem() == ModItems.AURA_CACHE) + heldCache = slot; + else if (slot.getItem() == ModItems.EYE && i <= 8) + heldEye = slot; + else if (slot.getItem() == ModItems.EYE_IMPROVED) + heldOcular = slot; + } + } + + if (!heldOcular.isEmpty() && mc.world.getTotalWorldTime() % 20 == 0) { + SHOWING_EFFECTS.clear(); + Helper.getAuraChunksInArea(mc.world, mc.player.getPosition(), 100, + chunk -> chunk.getActiveEffectIcons(mc.player, SHOWING_EFFECTS)); + } + } } } } @@ -237,39 +281,8 @@ public class ClientEvents { if (event.getType() == ElementType.ALL) { ScaledResolution res = event.getResolution(); if (mc.player != null) { - ItemStack cache = ItemStack.EMPTY; - ItemStack eye = ItemStack.EMPTY; - ItemStack eyeImproved = ItemStack.EMPTY; - - if (Compat.baubles) { - IItemHandler baubles = BaublesApi.getBaublesHandler(mc.player); - for (int i = 0; i < baubles.getSlots(); i++) { - ItemStack slot = baubles.getStackInSlot(i); - if (!slot.isEmpty()) { - if (slot.getItem() == ModItems.AURA_CACHE) - cache = slot; - else if (slot.getItem() == ModItems.EYE) - eye = slot; - else if (slot.getItem() == ModItems.EYE_IMPROVED) - eyeImproved = slot; - } - } - } - - for (int i = 0; i < mc.player.inventory.getSizeInventory(); i++) { - ItemStack slot = mc.player.inventory.getStackInSlot(i); - if (!slot.isEmpty()) { - if (slot.getItem() == ModItems.AURA_CACHE) - cache = slot; - else if (slot.getItem() == ModItems.EYE && i <= 8) - eye = slot; - else if (slot.getItem() == ModItems.EYE_IMPROVED) - eyeImproved = slot; - } - } - - if (!cache.isEmpty()) { - IAuraContainer container = cache.getCapability(NaturesAuraAPI.capAuraContainer, null); + if (!heldCache.isEmpty()) { + IAuraContainer container = heldCache.getCapability(NaturesAuraAPI.capAuraContainer, null); int width = MathHelper.ceil(container.getStoredAura() / (float) container.getMaxAura() * 80); int x = res.getScaledWidth() / 2 - 173 - (mc.player.getHeldItemOffhand().isEmpty() ? 0 : 29); int y = res.getScaledHeight() - 8; @@ -286,14 +299,14 @@ public class ClientEvents { float scale = 0.75F; GlStateManager.scale(scale, scale, scale); - String s = cache.getDisplayName(); + String s = heldCache.getDisplayName(); mc.fontRenderer.drawString(s, (x + 80) / scale - mc.fontRenderer.getStringWidth(s), (y - 7) / scale, color, true); GlStateManager.color(1F, 1F, 1F); GlStateManager.popMatrix(); } - if (!eye.isEmpty() || !eyeImproved.isEmpty()) { + if (!heldEye.isEmpty() || !heldOcular.isEmpty()) { GlStateManager.pushMatrix(); mc.getTextureManager().bindTexture(OVERLAYS); @@ -307,19 +320,19 @@ public class ClientEvents { float textScale = 0.75F; int startX = conf % 2 == 0 ? 3 : res.getScaledWidth() - 3 - 6; - int startY = conf < 2 ? 10 : (!eyeImproved.isEmpty() && (totalPercentage > 1F || totalPercentage < 0) ? -26 : 0) + res.getScaledHeight() - 60; + int startY = conf < 2 ? 10 : (!heldOcular.isEmpty() && (totalPercentage > 1F || totalPercentage < 0) ? -26 : 0) + res.getScaledHeight() - 60; float plusOffX = conf % 2 == 0 ? 7 : -1 - 6; float textX = conf % 2 == 0 ? 3 : res.getScaledWidth() - 3 - mc.fontRenderer.getStringWidth(text) * textScale; float textY = conf < 2 ? 3 : res.getScaledHeight() - 3 - 6; int tHeight = MathHelper.ceil(MathHelper.clamp(totalPercentage, 0F, 1F) * 50); - int y = !eyeImproved.isEmpty() && totalPercentage > 1F ? startY + 26 : startY; + int y = !heldOcular.isEmpty() && totalPercentage > 1F ? startY + 26 : startY; if (tHeight < 50) Gui.drawModalRectWithCustomSizedTexture(startX, y, 6, 12, 6, 50 - tHeight, 256, 256); if (tHeight > 0) Gui.drawModalRectWithCustomSizedTexture(startX, y + 50 - tHeight, 0, 12 + 50 - tHeight, 6, tHeight, 256, 256); - if (!eyeImproved.isEmpty()) { + if (!heldOcular.isEmpty()) { GlStateManager.color(160 / 255F, 83 / 255F, 8 / 255F); int topHeight = MathHelper.ceil(MathHelper.clamp((totalPercentage - 1F) * 2F, 0F, 1F) * 25); @@ -336,16 +349,37 @@ public class ClientEvents { } } - int color = eyeImproved.isEmpty() ? 0x53a008 : 0xa05308; - if (totalPercentage > (eyeImproved.isEmpty() ? 1F : 1.5F)) + int color = heldOcular.isEmpty() ? 0x53a008 : 0xa05308; + if (totalPercentage > (heldOcular.isEmpty() ? 1F : 1.5F)) mc.fontRenderer.drawString("+", startX + plusOffX, startY - 0.5F, color, true); - if (totalPercentage < (eyeImproved.isEmpty() ? 0F : -0.5F)) - mc.fontRenderer.drawString("-", startX + plusOffX, startY - 0.5F + (eyeImproved.isEmpty() ? 44 : 70), color, true); + if (totalPercentage < (heldOcular.isEmpty() ? 0F : -0.5F)) + mc.fontRenderer.drawString("-", startX + plusOffX, startY - 0.5F + (heldOcular.isEmpty() ? 44 : 70), color, true); GlStateManager.pushMatrix(); GlStateManager.scale(textScale, textScale, textScale); mc.fontRenderer.drawString(text, textX / textScale, textY / textScale, 0x53a008, true); GlStateManager.popMatrix(); + + if (!heldOcular.isEmpty()) { + float scale = 0.75F; + GlStateManager.pushMatrix(); + GlStateManager.scale(scale, scale, scale); + int stackY = 15; + for (Tuple effect : SHOWING_EFFECTS.values()) { + int theX = (int) (10 / scale); + int theY = (int) (stackY / scale); + ItemStack stack = effect.getFirst(); + Helper.renderItemInGui(stack, theX, theY, 1F); + if (effect.getSecond()) { + GlStateManager.disableDepth(); + mc.getTextureManager().bindTexture(OVERLAYS); + Gui.drawModalRectWithCustomSizedTexture(theX, theY, 240, 0, 16, 16, 256, 256); + GlStateManager.enableDepth(); + } + stackY += 8; + } + GlStateManager.popMatrix(); + } } if (mc.objectMouseOver != null) { diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/eye_improved.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/eye_improved.json index b154c64e..934a9868 100644 --- a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/eye_improved.json +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/eye_improved.json @@ -10,7 +10,10 @@ }, { "type": "text", - "text": "It needs be noted that the extended bar only shows if $(aura) levels are high or low enough.$(br)An additional perk is that, while the $(item)Environmental Eye$() needs to be held in the hotbar, the $(item)Environmental Ocular$() can be anywhere in the user's inventory to work.$(p)All other properties of the $(item)Environmental Eye$() carry over to the $(item)Environmental Ocular$() as expected." + "text": "It needs be noted that the extended bar only shows if $(aura) levels are high or low enough.$(p)Secondly, the $(item)Environmental Ocular$() has the ability to display all $(thing)Aura Imbalance$() effects that are currently occuring in the place the user is standing. The icons it displays are the same as the ones depicted for each effect in the $(thing)Aura Imbalance$() section of this book." + },{ + "type": "text", + "text": "An additional perk is that, while the $(item)Environmental Eye$() needs to be held in the hotbar, the $(item)Environmental Ocular$() can be anywhere in the user's inventory to work.$(p)All other properties of the $(item)Environmental Eye$() carry over to the $(item)Environmental Ocular$() as expected." }, { "type": "naturesaura:tree_ritual", diff --git a/src/main/resources/assets/naturesaura/textures/gui/overlays.png b/src/main/resources/assets/naturesaura/textures/gui/overlays.png index a93eac7c..7b497e26 100644 Binary files a/src/main/resources/assets/naturesaura/textures/gui/overlays.png and b/src/main/resources/assets/naturesaura/textures/gui/overlays.png differ