diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockEndFlower.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockEndFlower.java new file mode 100644 index 00000000..83df6bed --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockEndFlower.java @@ -0,0 +1,132 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityEndFlower; +import de.ellpeck.naturesaura.reg.ICreativeItem; +import de.ellpeck.naturesaura.reg.IModItem; +import de.ellpeck.naturesaura.reg.IModelProvider; +import de.ellpeck.naturesaura.reg.ModRegistry; +import net.minecraft.block.BlockBush; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.boss.EntityDragon; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +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.entity.living.LivingEvent.LivingUpdateEvent; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; + +import javax.annotation.Nullable; + +public class BlockEndFlower extends BlockBush implements IModItem, ICreativeItem, IModelProvider, ITileEntityProvider { + + public BlockEndFlower() { + this.setHardness(0.5F); + this.setSoundType(SoundType.PLANT); + MinecraftForge.EVENT_BUS.register(this); + + ModRegistry.add(this); + + } + + @SubscribeEvent + public void onDraonTick(LivingUpdateEvent event) { + EntityLivingBase living = event.getEntityLiving(); + if (living.world.isRemote || !(living instanceof EntityDragon)) + return; + EntityDragon dragon = (EntityDragon) living; + if (dragon.deathTicks < 150 || dragon.deathTicks % 10 != 0) + return; + + for (int i = 0; i < 6; i++) { + int x = dragon.world.rand.nextInt(256) - 128; + int z = dragon.world.rand.nextInt(256) - 128; + BlockPos pos = new BlockPos(x, dragon.world.getHeight(x, z), z); + if (!dragon.world.isBlockLoaded(pos)) + continue; + if (dragon.world.getBlockState(pos.down()).getBlock() != Blocks.END_STONE) + continue; + dragon.world.setBlockState(pos, this.getDefaultState()); + } + } + + @Override + protected boolean canSustainBush(IBlockState state) { + return state.getBlock() == Blocks.END_STONE; + } + + @Override + public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { + return this.canSustainBush(worldIn.getBlockState(pos.down())); + } + + @Override + public boolean canBlockStay(World worldIn, BlockPos pos, IBlockState state) { + return this.canSustainBush(worldIn.getBlockState(pos.down())); + } + + @Override + public String getBaseName() { + return "end_flower"; + } + + @Override + public void onPreInit(FMLPreInitializationEvent event) { + + } + + @Override + public void onInit(FMLInitializationEvent event) { + GameRegistry.registerTileEntity(TileEntityEndFlower.class, new ResourceLocation(NaturesAura.MOD_ID, "end_flower")); + } + + @Override + public void onPostInit(FMLPostInitializationEvent event) { + + } + + @Nullable + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + return new TileEntityEndFlower(); + } + + @Override + public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { + super.breakBlock(worldIn, pos, state); + worldIn.removeTileEntity(pos); + } + + @Override + public void getDrops(NonNullList drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof TileEntityEndFlower && ((TileEntityEndFlower) tile).isDrainMode) + return; + + super.getDrops(drops, world, pos, state, fortune); + } + + @Override + public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) { + return willHarvest || super.removedByPlayer(state, world, pos, player, false); + } + + @Override + public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack) { + super.harvestBlock(worldIn, player, pos, state, te, stack); + worldIn.setBlockToAir(pos); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index efaa16fd..1d0e1de5 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -38,4 +38,5 @@ public final class ModBlocks { public static final Block PICKUP_STOPPER = new BlockPickupStopper(); public static final Block SPAWN_LAMP = new BlockSpawnLamp(); public static final Block ANIMAL_GENERATOR = new BlockAnimalGenerator(); + public static final Block END_FLOWER = new BlockEndFlower(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEndFlower.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEndFlower.java new file mode 100644 index 00000000..39a95c8e --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEndFlower.java @@ -0,0 +1,103 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; +import de.ellpeck.naturesaura.api.aura.container.BasicAuraContainer; +import de.ellpeck.naturesaura.api.aura.container.IAuraContainer; +import de.ellpeck.naturesaura.packet.PacketHandler; +import de.ellpeck.naturesaura.packet.PacketParticles; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; + +public class TileEntityEndFlower extends TileEntityImpl implements ITickable { + + private final BasicAuraContainer container = new BasicAuraContainer(null, 5000) { + { + this.aura = this.maxAura; + } + + @Override + public int storeAura(int amountToStore, boolean simulate) { + return 0; + } + + @Override + public int drainAura(int amountToDrain, boolean simulate) { + int amount = super.drainAura(amountToDrain, simulate); + if (amount > 0 && !simulate) + TileEntityEndFlower.this.sendToClients(); + return amount; + } + + @Override + public int getAuraColor() { + return 0x6a25dd; + } + }; + + public boolean isDrainMode; + + @Override + public void update() { + if (!this.world.isRemote) { + if (this.world.getTotalWorldTime() % 10 != 0) + return; + + if (!this.isDrainMode) { + int amount = IAuraChunk.getAuraInArea(this.world, this.pos, 30); + if (amount < IAuraChunk.DEFAULT_AURA) + this.isDrainMode = true; + } else { + int toDrain = Math.min(50, this.container.getStoredAura()); + this.container.drainAura(toDrain, false); + + while (toDrain > 0) { + BlockPos spot = IAuraChunk.getLowestSpot(this.world, this.pos, 30, this.pos); + toDrain -= IAuraChunk.getAuraChunk(this.world, spot).storeAura(spot, toDrain); + } + + if (this.container.getStoredAura() <= 0) { + this.world.setBlockState(this.pos, Blocks.DEADBUSH.getDefaultState()); + PacketHandler.sendToAllAround(this.world, this.pos, 32, + new PacketParticles(this.pos.getX(), this.pos.getY(), this.pos.getZ(), 18, this.container.getAuraColor())); + } + } + } else { + if (this.isDrainMode && this.world.getTotalWorldTime() % 5 == 0) + NaturesAuraAPI.instance().spawnMagicParticle( + this.pos.getX() + 0.25F + this.world.rand.nextFloat() * 0.5F, + this.pos.getY() + 0.25F + this.world.rand.nextFloat() * 0.5F, + this.pos.getZ() + 0.25F + this.world.rand.nextFloat() * 0.5F, + this.world.rand.nextGaussian() * 0.05F, + this.world.rand.nextFloat() * 0.1F, + this.world.rand.nextGaussian() * 0.05F, + this.container.getAuraColor(), this.world.rand.nextFloat() * 2F + 1F, 50, 0F, false, true); + } + } + + @Override + public IAuraContainer getAuraContainer(EnumFacing facing) { + return this.container; + } + + @Override + public void writeNBT(NBTTagCompound compound, SaveType type) { + super.writeNBT(compound, type); + if (type != SaveType.BLOCK) { + this.container.writeNBT(compound); + compound.setBoolean("drain_mode", this.isDrainMode); + } + } + + @Override + public void readNBT(NBTTagCompound compound, SaveType type) { + super.readNBT(compound, type); + if (type != SaveType.BLOCK) { + this.container.readNBT(compound); + this.isDrainMode = compound.getBoolean("drain_mode"); + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index 5b8dc08f..a4f6a71c 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -300,6 +300,18 @@ public class PacketParticles implements IMessage { genX + 0.5F, genY + 0.5F, genZ + 0.5F, 0.15F, 0x41c4f4, child ? 1.5F : 3F); break; + case 18: // End flower decay + color = message.data[0]; + for (int i = world.rand.nextInt(10) + 20; i >= 0; i--) + NaturesAuraAPI.instance().spawnMagicParticle( + message.posX + world.rand.nextFloat(), + message.posY + world.rand.nextFloat(), + message.posZ + world.rand.nextFloat(), + world.rand.nextGaussian() * 0.01F, + world.rand.nextFloat() * 0.01F, + world.rand.nextGaussian() * 0.01F, + color, 1.5F, 80, 0F, true, true); + break; } } }); diff --git a/src/main/resources/assets/naturesaura/advancements/aura_bottle_end.json b/src/main/resources/assets/naturesaura/advancements/aura_bottle_end.json index f6770ef4..0a3d2eb5 100644 --- a/src/main/resources/assets/naturesaura/advancements/aura_bottle_end.json +++ b/src/main/resources/assets/naturesaura/advancements/aura_bottle_end.json @@ -11,7 +11,7 @@ "translate": "advancement.naturesaura.aura_bottle_end.desc" } }, - "parent": "naturesaura:wood_stand", + "parent": "naturesaura:end_flower", "criteria": { "bottle": { "trigger": "minecraft:inventory_changed", diff --git a/src/main/resources/assets/naturesaura/advancements/end_flower.json b/src/main/resources/assets/naturesaura/advancements/end_flower.json new file mode 100644 index 00000000..331c29a8 --- /dev/null +++ b/src/main/resources/assets/naturesaura/advancements/end_flower.json @@ -0,0 +1,24 @@ +{ + "display": { + "icon": { + "item": "naturesaura:end_flower" + }, + "title": { + "translate": "advancement.naturesaura.end_flower" + }, + "description": { + "translate": "advancement.naturesaura.end_flower.desc" + } + }, + "parent": "naturesaura:wood_stand", + "criteria": { + "killed_dragon": { + "trigger": "minecraft:player_killed_entity", + "conditions": { + "entity": { + "type": "ender_dragon" + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/blockstates/end_flower.json b/src/main/resources/assets/naturesaura/blockstates/end_flower.json new file mode 100644 index 00000000..37b5fe5e --- /dev/null +++ b/src/main/resources/assets/naturesaura/blockstates/end_flower.json @@ -0,0 +1,22 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cross", + "textures": { + "cross": "naturesaura:blocks/end_flower" + }, + "transform": "forge:default-block" + }, + "variants": { + "normal": [{}], + "inventory": [ + { + "model": "builtin/generated", + "textures": { + "layer0": "naturesaura:blocks/end_flower" + }, + "transform": "forge:default-item" + } + ] + } +} \ 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 09fcde03..5988000f 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -35,6 +35,7 @@ tile.naturesaura.offering_table.name=Offering Table tile.naturesaura.pickup_stopper.name=Item Grounder tile.naturesaura.spawn_lamp.name=Lamp of Sanctuary tile.naturesaura.animal_generator.name=Disentangler of Mortals +tile.naturesaura.end_flower.name=Rose of Oblivion item.naturesaura.eye.name=Environmental Eye item.naturesaura.gold_fiber.name=Brilliant Fiber @@ -120,6 +121,8 @@ advancement.naturesaura.positive_imbalance=Luscious Surroundings advancement.naturesaura.positive_imbalance.desc=Create enough Aura to cause positive imbalance effects advancement.naturesaura.negative_imbalance=Deadly Day advancement.naturesaura.negative_imbalance.desc=Drain enough Aura to cause negative imbalance effects +advancement.naturesaura.end_flower=Blue Lotus +advancement.naturesaura.end_flower.desc=Kill the Ender Dragon to make a Rose of Oblivion grow command.naturesaura.aura.usage=/naaura diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/end_flower.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/end_flower.json new file mode 100644 index 00000000..e1f61621 --- /dev/null +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/creating/end_flower.json @@ -0,0 +1,17 @@ +{ + "name": "Rose of Oblivion", + "icon": "naturesaura:end_flower", + "category": "creating", + "advancement": "naturesaura:end_flower", + "pages": [ + { + "type": "text", + "text": "The $(thing)Ender Dragon$() is known to be quite a beast to behold. It guards $(thing)The End$() better than anybody else, but it can be defeated. This not only bears a token of its offspring and a lot of pride, it also bears the $(item)Rose of Oblivion$(). Upon the dragon's death, they will start sprouting out of the ground on the end island, ready to be collected by any botanist and placed in any dimension." + }, + { + "type": "spotlight", + "item": "naturesaura:end_flower", + "text": "These flowers bear very large amounts of $(aura) that they $(thing)disperse$() in an interesting way: Initially, they will do nothing; however, if there is even the slightest bit of $(aura) missing from the area, they will start slowly feeding their $(aura) into the environment, dying after all of it is drained. During this process, they can neither be stopped, nor harvested." + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/textures/blocks/end_flower.png b/src/main/resources/assets/naturesaura/textures/blocks/end_flower.png new file mode 100644 index 00000000..7732a7b6 Binary files /dev/null and b/src/main/resources/assets/naturesaura/textures/blocks/end_flower.png differ