diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index dde544d1..a8328d55 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -36,21 +36,23 @@ 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 void getTileEntitiesInArea(World world, BlockPos pos, int radius, Consumer consumer) { + public static boolean getTileEntitiesInArea(World world, BlockPos pos, int radius, Function 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++) { if (isChunkLoaded(world, x, z)) { for (TileEntity tile : world.getChunk(x, z).getTileEntityMap().values()) { if (tile.getPos().distanceSq(pos) <= radius * radius) - consumer.accept(tile); + if (consumer.apply(tile)) + return true; } } } } + return false; } public static List getAttachedItemFrames(World world, BlockPos pos) { diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index 16046997..065b4c24 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -10,7 +10,6 @@ import de.ellpeck.naturesaura.chunk.effect.DrainSpotEffects; import de.ellpeck.naturesaura.commands.CommandAura; import de.ellpeck.naturesaura.compat.Compat; import de.ellpeck.naturesaura.events.CommonEvents; -import de.ellpeck.naturesaura.events.TerrainGenEvents; import de.ellpeck.naturesaura.items.ModItems; import de.ellpeck.naturesaura.packet.PacketHandler; import de.ellpeck.naturesaura.proxy.IProxy; @@ -66,7 +65,6 @@ public final class NaturesAura { ModRegistry.preInit(event); new Multiblocks(); - MinecraftForge.TERRAIN_GEN_BUS.register(new TerrainGenEvents()); MinecraftForge.EVENT_BUS.register(new CommonEvents()); proxy.preInit(event); diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockOakGenerator.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockOakGenerator.java new file mode 100644 index 00000000..610cbca0 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockOakGenerator.java @@ -0,0 +1,53 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityOakGenerator; +import net.minecraft.block.BlockSapling; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.terraingen.SaplingGrowTreeEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.Random; + +public class BlockOakGenerator extends BlockContainerImpl { + + public BlockOakGenerator() { + super(Material.WOOD, "oak_generator", TileEntityOakGenerator.class, "oak_generator"); + this.setHardness(2F); + this.setSoundType(SoundType.WOOD); + + MinecraftForge.TERRAIN_GEN_BUS.register(this); + } + + @SubscribeEvent + public void onTreeGrow(SaplingGrowTreeEvent event) { + World world = event.getWorld(); + BlockPos pos = event.getPos(); + if (!world.isRemote && NaturesAuraAPI.TYPE_OVERWORLD.isPresentInWorld(world) + && world.getBlockState(pos).getBlock() instanceof BlockSapling) { + Helper.getTileEntitiesInArea(world, pos, 10, tile -> { + if (!(tile instanceof TileEntityOakGenerator)) + return false; + + Random rand = event.getRand(); + if (rand.nextInt(10) == 0) + ((TileEntityOakGenerator) tile).scheduledBigTrees.add(pos); + + long seed; + do { + seed = rand.nextLong(); + rand.setSeed(seed); + } + while (rand.nextInt(10) == 0); + rand.setSeed(seed); + + return true; + }); + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java index 07eec446..0b6d0477 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java @@ -1,18 +1,31 @@ package de.ellpeck.naturesaura.blocks; import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.recipes.TreeRitualRecipe; +import de.ellpeck.naturesaura.blocks.multi.Multiblocks; import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.terraingen.SaplingGrowTreeEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.mutable.MutableObject; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class BlockWoodStand extends BlockContainerImpl { @@ -23,6 +36,54 @@ public class BlockWoodStand extends BlockContainerImpl { this.setHardness(1.5F); this.setSoundType(SoundType.WOOD); this.setHarvestLevel("axe", 0); + + MinecraftForge.TERRAIN_GEN_BUS.register(this); + } + + @SubscribeEvent + public void onTreeGrow(SaplingGrowTreeEvent event) { + World world = event.getWorld(); + BlockPos pos = event.getPos(); + if (!world.isRemote) { + if (Multiblocks.TREE_RITUAL.isComplete(world, pos)) { + IBlockState sapling = world.getBlockState(pos); + ItemStack saplingStack = sapling.getBlock().getItem(world, pos, sapling); + if (!saplingStack.isEmpty()) { + for (TreeRitualRecipe recipe : NaturesAuraAPI.TREE_RITUAL_RECIPES.values()) { + if (Helper.areItemsEqual(saplingStack, recipe.saplingType, true)) { + List required = new ArrayList<>(Arrays.asList(recipe.items)); + MutableObject toPick = new MutableObject<>(); + + boolean fine = Multiblocks.TREE_RITUAL.forEach(pos, 'W', (tilePos, matcher) -> { + TileEntity tile = world.getTileEntity(tilePos); + if (tile instanceof TileEntityWoodStand) { + TileEntityWoodStand stand = (TileEntityWoodStand) tile; + ItemStack stack = stand.items.getStackInSlot(0); + if (!stack.isEmpty()) { + int index = Helper.getItemIndex(required, stack, true); + if (index >= 0) { + required.remove(index); + + if (toPick.getValue() == null) { + toPick.setValue(stand); + } + } else { + return false; + } + } + } + return true; + }); + + if (fine && required.isEmpty()) { + toPick.getValue().setRitual(pos, recipe); + break; + } + } + } + } + } + } } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index 894a38e6..13ebaf65 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -32,4 +32,5 @@ public final class ModBlocks { public static final Block PLACER = new BlockPlacer(); public static final Block HOPPER_UPGRADE = new BlockHopperUpgrade(); public static final Block FIELD_CREATOR = new BlockFieldCreator(); + public static final Block OAK_GENERATOR = new BlockOakGenerator(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityOakGenerator.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityOakGenerator.java new file mode 100644 index 00000000..662f78d6 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityOakGenerator.java @@ -0,0 +1,32 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; +import de.ellpeck.naturesaura.packet.PacketHandler; +import de.ellpeck.naturesaura.packet.PacketParticles; +import net.minecraft.block.BlockLog; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class TileEntityOakGenerator extends TileEntityImpl implements ITickable { + + public Queue scheduledBigTrees = new ArrayDeque<>(); + + @Override + public void update() { + if (!this.world.isRemote) + while (!this.scheduledBigTrees.isEmpty()) { + BlockPos pos = this.scheduledBigTrees.remove(); + if (this.world.getBlockState(pos).getBlock() instanceof BlockLog) { + BlockPos spot = IAuraChunk.getLowestSpot(this.world, this.pos, 25, this.pos); + IAuraChunk.getAuraChunk(this.world, spot).storeAura(spot, 500); + + PacketHandler.sendToAllAround(this.world, this.pos, 32, new PacketParticles( + this.pos.getX(), this.pos.getY(), this.pos.getZ(), 12, + pos.getX(), pos.getY(), pos.getZ())); + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/effect/ReplenishingEffect.java b/src/main/java/de/ellpeck/naturesaura/chunk/effect/ReplenishingEffect.java index 5e60ce98..7b25fc77 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/effect/ReplenishingEffect.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/effect/ReplenishingEffect.java @@ -33,6 +33,7 @@ public class ReplenishingEffect implements IDrainSpotEffect { tiles.add((ISpotDrainable) container); } } + return false; }); if (!tiles.isEmpty()) { IAuraType type = IAuraType.forWorld(world); diff --git a/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java b/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java deleted file mode 100644 index 9192cadb..00000000 --- a/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java +++ /dev/null @@ -1,68 +0,0 @@ -package de.ellpeck.naturesaura.events; - -import de.ellpeck.naturesaura.Helper; -import de.ellpeck.naturesaura.api.NaturesAuraAPI; -import de.ellpeck.naturesaura.blocks.multi.Multiblocks; -import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; -import de.ellpeck.naturesaura.api.recipes.TreeRitualRecipe; -import net.minecraft.block.state.IBlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.event.terraingen.SaplingGrowTreeEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.apache.commons.lang3.mutable.MutableObject; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class TerrainGenEvents { - - @SubscribeEvent - public void onTreeGrow(SaplingGrowTreeEvent event) { - World world = event.getWorld(); - BlockPos pos = event.getPos(); - if (!world.isRemote) { - if (Multiblocks.TREE_RITUAL.isComplete(world, pos)) { - IBlockState sapling = world.getBlockState(pos); - ItemStack saplingStack = sapling.getBlock().getItem(world, pos, sapling); - if (!saplingStack.isEmpty()) { - for (TreeRitualRecipe recipe : NaturesAuraAPI.TREE_RITUAL_RECIPES.values()) { - if (Helper.areItemsEqual(saplingStack, recipe.saplingType, true)) { - List required = new ArrayList<>(Arrays.asList(recipe.items)); - MutableObject toPick = new MutableObject<>(); - - boolean fine = Multiblocks.TREE_RITUAL.forEach(pos, 'W', (tilePos, matcher) -> { - TileEntity tile = world.getTileEntity(tilePos); - if (tile instanceof TileEntityWoodStand) { - TileEntityWoodStand stand = (TileEntityWoodStand) tile; - ItemStack stack = stand.items.getStackInSlot(0); - if (!stack.isEmpty()) { - int index = Helper.getItemIndex(required, stack, true); - if (index >= 0) { - required.remove(index); - - if (toPick.getValue() == null) { - toPick.setValue(stand); - } - } else { - return false; - } - } - } - return true; - }); - - if (fine && required.isEmpty()) { - toPick.getValue().setRitual(pos, recipe); - break; - } - } - } - } - } - } - } -} diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index a2e5b2ea..14b84f20 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeColorHelper; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; @@ -209,6 +210,28 @@ public class PacketParticles implements IMessage { 0x911b07, 3F, 10, 0F, false, true); } break; + case 12: // Oak generator + int sapX = message.data[0]; + int sapY = message.data[1]; + int sapZ = message.data[2]; + for (int i = world.rand.nextInt(20) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnParticleStream( + sapX + 0.5F + (float) world.rand.nextGaussian() * 3F, + sapY + 0.5F + world.rand.nextFloat() * 4F, + sapZ + 0.5F + (float) world.rand.nextGaussian() * 3F, + message.posX + 0.5F, + message.posY + 0.5F, + message.posZ + 0.5F, + 0.6F, BiomeColorHelper.getFoliageColorAtPos(world, new BlockPos(sapX, sapY, sapZ)), 1.5F); + for (int i = world.rand.nextInt(10) + 10; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + 0.25F + world.rand.nextFloat() * 0.5F, + message.posY + 1.01F, + message.posZ + 0.25F + world.rand.nextFloat() * 0.5F, + world.rand.nextGaussian() * 0.03F, + world.rand.nextFloat() * 0.04F + 0.04F, + world.rand.nextGaussian() * 0.03F, + 0x5ccc30, 1F + world.rand.nextFloat() * 1.5F, 60, 0F, false, true); } } }); diff --git a/src/main/resources/assets/naturesaura/blockstates/oak_generator.json b/src/main/resources/assets/naturesaura/blockstates/oak_generator.json new file mode 100644 index 00000000..458ee94b --- /dev/null +++ b/src/main/resources/assets/naturesaura/blockstates/oak_generator.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube", + "textures": { + "particle": "naturesaura:blocks/oak_generator", + "up": "naturesaura:blocks/oak_generator_top", + "down": "naturesaura:blocks/oak_generator_bottom", + "north": "#particle", + "east": "#particle", + "south": "#particle", + "west": "#particle" + }, + "transform": "forge:default-block" + }, + "variants": { + "normal": [{}], + "inventory": [{}] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/lang/en_US.lang b/src/main/resources/assets/naturesaura/lang/en_US.lang index 83cf5d6c..ff6d26ac 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -29,6 +29,7 @@ tile.naturesaura.flower_generator.name=Herbivorous Absorber tile.naturesaura.placer.name=Imperceptible Builder tile.naturesaura.hopper_upgrade.name=Hopper Enhancement tile.naturesaura.field_creator.name=Aura Field Creator +tile.naturesaura.oak_generator.name=Canopy Diminisher item.naturesaura.eye.name=Environmental Eye item.naturesaura.gold_fiber.name=Brilliant Fiber diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/oak_generator.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/oak_generator.json new file mode 100644 index 00000000..77ef9af3 --- /dev/null +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/oak_generator.json @@ -0,0 +1,21 @@ +{ + "name": "Canopy Diminisher", + "icon": "naturesaura:oak_generator", + "category": "creating", + "advancement": "naturesaura:infused_materials", + "pages": [ + { + "type": "text", + "text": "Surely, at one point in their lives, any person dealing with trees was faced with this well-known issue: An $(item)Oak Sapling$() grows into a $(thing)big tree$() which is hard to look at, to manage and to chop down.$(br)The $(item)Canopy Diminisher$() is a block that serves two purposes in and of itself:$(br)Placing it close to an area that oak trees are growing in, at most about 10 blocks away from them, will cause only" + }, + { + "type": "text", + "text": "normal-sized oaks to grow.$(br)In the process, the additional natural energy of any saplings that were growing into big trees gets turned into a quite substantial amount of $(aura) that will be fed into the environment.$(p)Quite obviously, a great way to make use of this is for an automatic $(thing)tree farm$()." + }, + { + "type": "crafting", + "recipe": "naturesaura:oak_generator", + "text": "Creating the $(item)Canopy Diminisher$()" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/recipes/oak_generator.json b/src/main/resources/assets/naturesaura/recipes/oak_generator.json new file mode 100644 index 00000000..ed2beb09 --- /dev/null +++ b/src/main/resources/assets/naturesaura/recipes/oak_generator.json @@ -0,0 +1,35 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + "MBI", + "SOS", + "IBM" + ], + "key": { + "O": { + "type": "forge:ore_dict", + "ore": "logWood" + }, + "S": { + "type": "forge:ore_dict", + "ore": "treeSapling" + }, + "B": { + "type": "minecraft:item_nbt", + "item": "naturesaura:aura_bottle", + "nbt": { + "stored_type": "naturesaura:overworld" + } + }, + "M": { + "item": "minecraft:dye", + "data": 15 + }, + "I": { + "item": "naturesaura:infused_iron" + } + }, + "result": { + "item": "naturesaura:oak_generator" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/textures/blocks/oak_generator.png b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator.png new file mode 100644 index 00000000..916cc4cc Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator.png differ diff --git a/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_bottom.png b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_bottom.png new file mode 100644 index 00000000..16b0f133 Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_bottom.png differ diff --git a/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_top.png b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_top.png new file mode 100644 index 00000000..02229f71 Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/oak_generator_top.png differ