diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index 9ef7393d..ba6199d2 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -5,7 +5,6 @@ import de.ellpeck.naturesaura.aura.Capabilities; import de.ellpeck.naturesaura.aura.item.IAuraRecharge; import de.ellpeck.naturesaura.blocks.tiles.TileEntityImpl; import de.ellpeck.naturesaura.compat.Compat; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; @@ -19,6 +18,8 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderServer; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fml.relauncher.Side; @@ -37,15 +38,26 @@ public final class Helper { public static void getTileEntitiesInArea(World world, BlockPos pos, int radius, Consumer consumer) { 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 (TileEntity tile : world.getChunk(x, z).getTileEntityMap().values()) { - if (tile.getPos().distanceSq(pos) <= radius * radius) { - consumer.accept(tile); + if (isChunkLoaded(world, x, z)) { + for (TileEntity tile : world.getChunk(x, z).getTileEntityMap().values()) { + if (tile.getPos().distanceSq(pos) <= radius * radius) + consumer.accept(tile); } } } } } + // For some reason this method isn't public in World, but I also don't want to have to make a new BlockPos + // or use the messy MutableBlockPos system just to see if a chunk is loaded, so this will have to do I guess + public static boolean isChunkLoaded(World world, int x, int z) { + IChunkProvider provider = world.getChunkProvider(); + if (provider instanceof ChunkProviderServer) + return ((ChunkProviderServer) provider).chunkExists(x, z); + else + return !provider.provideChunk(x, z).isEmpty(); + } + @SideOnly(Side.CLIENT) public static int blendColors(int c1, int c2, float ratio) { int a = (int) ((c1 >> 24 & 0xFF) * ratio + (c2 >> 24 & 0xFF) * (1 - ratio)); diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java index 1b7b9789..c1d83bb6 100644 --- a/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java @@ -1,9 +1,11 @@ package de.ellpeck.naturesaura.aura.chunk; +import de.ellpeck.naturesaura.Helper; import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.aura.Capabilities; import de.ellpeck.naturesaura.aura.chunk.effect.GrassDieEffect; import de.ellpeck.naturesaura.aura.chunk.effect.IDrainSpotEffect; +import de.ellpeck.naturesaura.aura.chunk.effect.PlantBoostEffect; import de.ellpeck.naturesaura.aura.chunk.effect.ReplenishingEffect; import de.ellpeck.naturesaura.packet.PacketAuraChunk; import de.ellpeck.naturesaura.packet.PacketHandler; @@ -43,16 +45,19 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable 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++) { - Chunk chunk = world.getChunk(x, z); - if (chunk.hasCapability(Capabilities.auraChunk, null)) { - AuraChunk auraChunk = chunk.getCapability(Capabilities.auraChunk, null); - auraChunk.getSpotsInArea(pos, radius, consumer); + if (Helper.isChunkLoaded(world, x, z)) { + Chunk chunk = world.getChunk(x, z); + if (chunk.hasCapability(Capabilities.auraChunk, null)) { + AuraChunk auraChunk = chunk.getCapability(Capabilities.auraChunk, null); + auraChunk.getSpotsInArea(pos, radius, consumer); + } } } } diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/PlantBoostEffect.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/PlantBoostEffect.java new file mode 100644 index 00000000..d6e66b8e --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/PlantBoostEffect.java @@ -0,0 +1,56 @@ +package de.ellpeck.naturesaura.aura.chunk.effect; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.aura.chunk.AuraChunk; +import de.ellpeck.naturesaura.packet.PacketHandler; +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.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import org.apache.commons.lang3.mutable.MutableInt; + +public class PlantBoostEffect implements IDrainSpotEffect { + @Override + public void update(World world, Chunk chunk, AuraChunk auraChunk, BlockPos pos, MutableInt spot) { + world.profiler.func_194340_a(() -> NaturesAura.MOD_ID + ":PlantBoostEffect"); + if (spot.intValue() <= 0) + return; + int aura = AuraChunk.getAuraInArea(world, pos, 25); + if (aura <= 0) + return; + int amount = Math.min(45, Math.abs(aura) / 1000); + if (amount <= 0) + return; + int dist = MathHelper.clamp(Math.abs(aura) / 1500, 5, 35); + if (dist <= 0) + return; + + 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); + BlockPos plantPos = new BlockPos(x, world.getHeight(x, z), z); + if (plantPos.distanceSq(pos) <= dist * dist && world.isBlockLoaded(plantPos)) { + IBlockState state = world.getBlockState(plantPos); + Block block = state.getBlock(); + if (block instanceof IGrowable && block != Blocks.TALLGRASS && block != Blocks.GRASS) { + IGrowable growable = (IGrowable) block; + if (growable.canGrow(world, plantPos, state, false)) { + growable.grow(world, world.rand, plantPos, state); + + BlockPos closestSpot = AuraChunk.getClosestSpot(world, plantPos, 25, pos); + AuraChunk.getAuraChunk(world, closestSpot).drainAura(closestSpot, 25); + + PacketHandler.sendToAllAround(world, plantPos, 32, + new PacketParticles(plantPos.getX(), plantPos.getY(), plantPos.getZ(), 6)); + } + } + } + } + world.profiler.endSection(); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index 2040eed4..df2aae0c 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -144,6 +144,16 @@ public class PacketParticles implements IMessage { } } break; + case 6: // Plant boost effect + for (int i = world.rand.nextInt(20) + 15; i >= 0; i--) + NaturesAura.proxy.spawnMagicParticle(world, + message.posX + world.rand.nextFloat(), + message.posY + 0.25F + world.rand.nextFloat() * 0.5F, + message.posZ + world.rand.nextFloat(), + 0F, world.rand.nextFloat() * 0.01F, 0F, + 0x5ccc30, 1F + world.rand.nextFloat() * 2F, 100, 0F, false, true); + + break; } } }); diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/effects/plant_boost.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/effects/plant_boost.json new file mode 100644 index 00000000..bd671659 --- /dev/null +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/effects/plant_boost.json @@ -0,0 +1,16 @@ +{ + "name": "Vegetational Increase", + "icon": "minecraft:wheat_seeds", + "category": "effects", + "advancement": "naturesaura:potion_generator", + "pages": [ + { + "type": "text", + "text": "When the amount of $(aura) in an area is high enough for it to become unstable, it starts to migrate into parts of vegetation that is close by, specifically plants like $(item)Wheat$(), $(item)Potatoes$() and so on. This will cause them to have $(thing)growth spurts$(), while, at the same time, causing the $(aura) in the area to slightly decrease as a result." + }, + { + "type":"text", + "text":"Effects like these become apparent around the time that the meter of the $(l:items/eye)Environmental Eye$() fills up fully." + } + ] +} \ No newline at end of file