diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index d5903bcb..eb1df604 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -1,6 +1,10 @@ package de.ellpeck.naturesaura; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -46,21 +50,27 @@ public final class Helper { return ((a & 255) << 24) | ((r & 255) << 16) | ((g & 255) << 8) | (b & 255); } - public static boolean containsItem(List list, ItemStack item) { - for (ItemStack stack : list) { - if (stack.isItemEqual(item)) { - return true; + public static int getItemIndex(List list, ItemStack item) { + for (int i = 0; i < list.size(); i++) { + if (list.get(i).isItemEqual(item)) { + return i; } } - return false; + return -1; } - public static boolean containsItem(ItemStack[] array, ItemStack item) { - for (ItemStack stack : array) { - if (stack.isItemEqual(item)) { - return true; - } + @SideOnly(Side.CLIENT) + public static void renderItemInWorld(ItemStack stack) { + if (!stack.isEmpty()) { + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + GlStateManager.pushAttrib(); + RenderHelper.enableStandardItemLighting(); + Minecraft.getMinecraft().getRenderItem().renderItem(stack, ItemCameraTransforms.TransformType.FIXED); + RenderHelper.disableStandardItemLighting(); + GlStateManager.popAttrib(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); } - return false; } } diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index bd3d9648..ebca484f 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -1,7 +1,7 @@ package de.ellpeck.naturesaura; import de.ellpeck.naturesaura.blocks.ModBlocks; -import de.ellpeck.naturesaura.events.TreeRitualHandler; +import de.ellpeck.naturesaura.events.TerrainGenEvents; import de.ellpeck.naturesaura.items.ModItems; import de.ellpeck.naturesaura.packet.PacketHandler; import de.ellpeck.naturesaura.proxy.IProxy; @@ -9,6 +9,7 @@ import de.ellpeck.naturesaura.recipes.ModRecipes; import de.ellpeck.naturesaura.reg.ModRegistry; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.SidedProxy; @@ -44,7 +45,7 @@ public final class NaturesAura { PacketHandler.init(); ModRegistry.preInit(event); - new TreeRitualHandler(); + MinecraftForge.TERRAIN_GEN_BUS.register(new TerrainGenEvents()); proxy.preInit(event); } @@ -62,9 +63,4 @@ public final class NaturesAura { ModRegistry.postInit(event); proxy.postInit(event); } - - @EventHandler - public void serverStopped(FMLServerStoppedEvent event){ - TreeRitualHandler.clear(); - } } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java index 54e662de..60d1d51a 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java @@ -2,7 +2,7 @@ package de.ellpeck.naturesaura.blocks; import de.ellpeck.naturesaura.Helper; import de.ellpeck.naturesaura.NaturesAura; -import de.ellpeck.naturesaura.events.TreeRitualHandler; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; import de.ellpeck.naturesaura.reg.IColorProvidingBlock; import net.minecraft.block.Block; import net.minecraft.block.SoundType; @@ -60,9 +60,9 @@ public class BlockGoldPowder extends BlockImpl implements IColorProvidingBlock { @Override public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { if (rand.nextFloat() >= 0.8F) { - for (BlockPos offsetToOrigin : TreeRitualHandler.GOLD_POWDER_POSITIONS) { + for (BlockPos offsetToOrigin : TileEntityWoodStand.GOLD_POWDER_POSITIONS) { BlockPos origin = pos.subtract(offsetToOrigin); - if (Helper.checkMultiblock(worldIn, origin, TreeRitualHandler.GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true)) { + if (Helper.checkMultiblock(worldIn, origin, TileEntityWoodStand.GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true)) { NaturesAura.proxy.spawnMagicParticle(worldIn, pos.getX() + 0.375 + rand.nextFloat() * 0.25, pos.getY() + 0.1, pos.getZ() + 0.375 + rand.nextFloat() * 0.25, rand.nextGaussian() * 0.001, rand.nextFloat() * 0.001 + 0.005, rand.nextGaussian() * 0.001, diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockNatureAltar.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockNatureAltar.java index afc0f924..04edf46b 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockNatureAltar.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockNatureAltar.java @@ -31,4 +31,9 @@ public class BlockNatureAltar extends BlockContainerImpl { public boolean isOpaqueCube(IBlockState state) { return false; } + + @Override + public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) { + return false; + } } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java new file mode 100644 index 00000000..f417a2e8 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockWoodStand.java @@ -0,0 +1,92 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItem; +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; + +public class BlockWoodStand extends BlockContainerImpl { + + private static final AxisAlignedBB BOUND_BOX = new AxisAlignedBB(3 / 16F, 0F, 3 / 16F, 13 / 16F, 13 / 16F, 13 / 16F); + + public BlockWoodStand() { + super(Material.WOOD, "wood_stand", TileEntityWoodStand.class, "wood_stand"); + this.setHardness(1.5F); + this.setSoundType(SoundType.WOOD); + this.setHarvestLevel("axe", 0); + } + + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + TileEntity tile = worldIn.getTileEntity(pos); + if (tile instanceof TileEntityWoodStand) { + TileEntityWoodStand stand = (TileEntityWoodStand) tile; + if (stand.stack.isEmpty()) { + ItemStack handStack = playerIn.getHeldItem(hand); + if (!handStack.isEmpty()) { + if (!worldIn.isRemote) { + ItemStack copy = handStack.copy(); + copy.setCount(1); + stand.stack = copy; + handStack.shrink(1); + stand.sendToClients(); + } + return true; + } + } else { + if (!worldIn.isRemote) { + playerIn.addItemStackToInventory(stand.stack); + stand.stack = ItemStack.EMPTY; + stand.sendToClients(); + } + return true; + } + } + return false; + } + + @Override + public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { + if (!worldIn.isRemote) { + TileEntity tile = worldIn.getTileEntity(pos); + if (tile instanceof TileEntityWoodStand) { + TileEntityWoodStand stand = (TileEntityWoodStand) tile; + if (!stand.stack.isEmpty()) { + EntityItem item = new EntityItem(worldIn, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, stand.stack); + worldIn.spawnEntity(item); + } + } + } + super.breakBlock(worldIn, pos, state); + } + + @Override + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { + return BOUND_BOX; + } + + @Override + public boolean isFullCube(IBlockState state) { + return false; + } + + @Override + public boolean isOpaqueCube(IBlockState state) { + return false; + } + + @Override + public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) { + return false; + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index 9addd5cc..71445834 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -14,4 +14,5 @@ public final class ModBlocks { public static final Block DECAYED_LEAVES = new BlockDecayedLeaves(); public static final Block GOLDEN_LEAVES = new BlockGoldenLeaves(); public static final Block GOLD_POWDER = new BlockGoldPowder(); + public static final Block WOOD_STAND = new BlockWoodStand(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java index d8e4c60f..9e64a0b0 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java @@ -123,12 +123,12 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable, if (!this.cachedProviders.isEmpty()) { int index = rand.nextInt(this.cachedProviders.size()); IAuraContainerProvider provider = this.cachedProviders.get(index); - BlockPos pos = ((TileEntity) provider).getPos(); - if (this.world.getTileEntity(pos) == provider) { + if (((TileEntity) provider).isInvalid()) { int stored = this.container.storeAura(provider.container().drainAura(5, true), false); if (stored > 0) { provider.container().drainAura(stored, false); + BlockPos pos = ((TileEntity) provider).getPos(); PacketHandler.sendToAllAround(this.world, this.pos, 32, new PacketParticleStream( pos.getX() + 0.5F, pos.getY() + 0.5F, pos.getZ() + 0.5F, this.pos.getX() + 0.5F, this.pos.getY() + 0.5F, this.pos.getZ() + 0.5F, diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java new file mode 100644 index 00000000..b2090cd6 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityWoodStand.java @@ -0,0 +1,158 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.blocks.ModBlocks; +import de.ellpeck.naturesaura.packet.PacketHandler; +import de.ellpeck.naturesaura.packet.PacketParticleStream; +import de.ellpeck.naturesaura.packet.PacketParticles; +import de.ellpeck.naturesaura.recipes.TreeRitualRecipe; +import net.minecraft.block.BlockLeaves; +import net.minecraft.block.BlockLog; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Map; + +public class TileEntityWoodStand extends TileEntityImpl implements ITickable { + + public static final BlockPos[] GOLD_POWDER_POSITIONS = new BlockPos[]{ + new BlockPos(-2, 0, 0), + new BlockPos(2, 0, 0), + new BlockPos(0, 0, -2), + new BlockPos(0, 0, 2), + new BlockPos(-1, 0, -1), + new BlockPos(-1, 0, 1), + new BlockPos(1, 0, 1), + new BlockPos(1, 0, -1), + new BlockPos(2, 0, -1), + new BlockPos(2, 0, 1), + new BlockPos(-2, 0, -1), + new BlockPos(-2, 0, 1), + new BlockPos(1, 0, 2), + new BlockPos(-1, 0, 2), + new BlockPos(1, 0, -2), + new BlockPos(-1, 0, -2) + }; + public ItemStack stack = ItemStack.EMPTY; + + private BlockPos ritualPos; + private Map involvedStands; + private TreeRitualRecipe recipe; + private int timer; + + public void setRitual(BlockPos pos, TreeRitualRecipe recipe, Map involvedStands) { + this.ritualPos = pos; + this.recipe = recipe; + this.involvedStands = involvedStands; + } + + @Override + public void update() { + if (!this.world.isRemote) { + if (this.ritualPos != null && this.involvedStands != null && this.recipe != null) { + if (this.isRitualOkay(this.world)) { + this.timer++; + + if (this.timer % 3 == 0) { + for (TileEntityWoodStand stand : this.involvedStands.keySet()) { + PacketHandler.sendToAllAround(this.world, this.pos, 32, new PacketParticleStream( + (float) stand.pos.getX() + 0.5F, (float) stand.pos.getY() + 1.25F, (float) stand.pos.getZ() + 0.5F, + this.ritualPos.getX() + 0.5F, this.ritualPos.getY() + 2.5F, this.ritualPos.getZ() + 0.5F, + this.world.rand.nextFloat() * 0.02F + 0.02F, 0xFF00FF, this.world.rand.nextFloat() * 1F + 1F + )); + } + } + if (this.timer % 5 == 0) { + for (BlockPos offset : TileEntityWoodStand.GOLD_POWDER_POSITIONS) { + BlockPos dustPos = this.ritualPos.add(offset); + PacketHandler.sendToAllAround(this.world, this.ritualPos, 32, + new PacketParticles( + (float) dustPos.getX() + 0.375F + this.world.rand.nextFloat() * 0.25F, + (float) dustPos.getY() + 0.1F, + (float) dustPos.getZ() + 0.375F + this.world.rand.nextFloat() * 0.25F, + (float) this.world.rand.nextGaussian() * 0.01F, + this.world.rand.nextFloat() * 0.005F + 0.01F, + (float) this.world.rand.nextGaussian() * 0.01F, + 0xf4cb42, 2F, 100, 0F, false, true + )); + } + } + + if (this.timer >= this.recipe.time) { + this.recurseTreeDestruction(this.ritualPos, this.ritualPos); + //TODO Spawn item and stuff here, make some more nice particles probably + + this.ritualPos = null; + this.involvedStands = null; + this.recipe = null; + this.timer = 0; + } else if (this.timer >= this.recipe.time / 2) { + for (TileEntityWoodStand stand : this.involvedStands.keySet()) { + //TODO Turn this into a single packet that just randomly spawns a certain amount of particles + for (int j = this.world.rand.nextInt(20) + 10; j >= 0; j--) { + PacketHandler.sendToAllAround(this.world, this.ritualPos, 32, new PacketParticles( + (float) stand.pos.getX() + 0.5F, (float) stand.pos.getY() + 1.25F, (float) stand.pos.getZ() + 0.5F, + (float) this.world.rand.nextGaussian() * 0.05F, this.world.rand.nextFloat() * 0.05F, (float) this.world.rand.nextGaussian() * 0.05F, + 0xFF00FF, 1.5F, 50, 0F, false, true)); + } + stand.stack = ItemStack.EMPTY; + stand.sendToClients(); + } + this.involvedStands.clear(); + } + + } else { + this.ritualPos = null; + this.involvedStands = null; + this.recipe = null; + this.timer = 0; + } + } + } + } + + private void recurseTreeDestruction(BlockPos pos, BlockPos start) { + if (pos.distanceSq(start) >= 15 * 15) { + return; + } + + for (EnumFacing facing : EnumFacing.VALUES) { + BlockPos offset = pos.offset(facing); + IBlockState state = this.world.getBlockState(offset); + if (state.getBlock() instanceof BlockLog || state.getBlock() instanceof BlockLeaves) { + this.world.setBlockToAir(offset); + //TODO Spawn particles around the block outline here, probably with the same packet as above + + this.recurseTreeDestruction(offset, start); + } + } + } + + private boolean isRitualOkay(World world) { + for (Map.Entry entry : this.involvedStands.entrySet()) { + TileEntityWoodStand stand = entry.getKey(); + if (stand.isInvalid() || !stand.stack.isItemEqual(entry.getValue())) { + return false; + } + } + return Helper.checkMultiblock(world, this.ritualPos, TileEntityWoodStand.GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true); + } + + @Override + public void writeNBT(NBTTagCompound compound, boolean syncing) { + super.writeNBT(compound, syncing); + compound.setTag("item", this.stack.writeToNBT(new NBTTagCompound())); + //TODO Save info about the current ritual somehow + } + + @Override + public void readNBT(NBTTagCompound compound, boolean syncing) { + super.readNBT(compound, syncing); + this.stack = new ItemStack(compound.getCompoundTag("item")); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/render/RenderWoodStand.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/render/RenderWoodStand.java new file mode 100644 index 00000000..0e638439 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/render/RenderWoodStand.java @@ -0,0 +1,30 @@ +package de.ellpeck.naturesaura.blocks.tiles.render; + +import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; + +public class RenderWoodStand extends TileEntitySpecialRenderer { + @Override + public void render(TileEntityWoodStand tile, double x, double y, double z, float par5, int par6, float f) { + ItemStack stack = tile.stack; + if (!stack.isEmpty()) { + GlStateManager.pushMatrix(); + GlStateManager.translate((float) x + 0.5F, (float) y + 1.125F, (float) z + 0.5F); + + double boop = Minecraft.getSystemTime() / 800D; + GlStateManager.translate(0D, Math.sin(boop % (2 * Math.PI)) * 0.04, 0D); + GlStateManager.rotate((float) (((boop * 40D) % 360)), 0, 1, 0); + + float scale = stack.getItem() instanceof ItemBlock ? 0.45F : 0.35F; + GlStateManager.scale(scale, scale, scale); + Helper.renderItemInWorld(stack); + + GlStateManager.popMatrix(); + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java b/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java new file mode 100644 index 00000000..c4f05150 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/events/TerrainGenEvents.java @@ -0,0 +1,68 @@ +package de.ellpeck.naturesaura.events; + +import de.ellpeck.naturesaura.Helper; +import de.ellpeck.naturesaura.blocks.ModBlocks; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; +import de.ellpeck.naturesaura.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 java.util.*; + +public class TerrainGenEvents { + + @SubscribeEvent + public void onTreeGrow(SaplingGrowTreeEvent event) { + World world = event.getWorld(); + BlockPos pos = event.getPos(); + if (!world.isRemote) { + if (Helper.checkMultiblock(world, pos, TileEntityWoodStand.GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true)) { + List tileEntities = Helper.getTileEntitiesInArea(world, pos, 5); + List stands = new ArrayList<>(); + List usableItems = new ArrayList<>(); + + for (TileEntity tile : tileEntities) { + if (tile instanceof TileEntityWoodStand) { + TileEntityWoodStand stand = (TileEntityWoodStand) tile; + if (!stand.stack.isEmpty()) { + usableItems.add(stand.stack); + stands.add(stand); + } + } + } + + IBlockState sapling = world.getBlockState(pos); + ItemStack saplingStack = sapling.getBlock().getItem(world, pos, sapling); + if (!saplingStack.isEmpty()) { + for (TreeRitualRecipe recipe : TreeRitualRecipe.RECIPES) { + if (recipe.matchesItems(saplingStack, usableItems)) { + Map actuallyInvolved = new HashMap<>(); + List stillRequired = new ArrayList<>(Arrays.asList(recipe.items)); + TileEntityWoodStand toPick = null; + + for (TileEntityWoodStand stand : stands) { + int index = Helper.getItemIndex(stillRequired, stand.stack); + if (index >= 0) { + actuallyInvolved.put(stand, stand.stack); + stillRequired.remove(index); + + if (toPick == null) { + toPick = stand; + } + } + } + + toPick.setRitual(pos, recipe, actuallyInvolved); + break; + } + } + } + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java b/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java deleted file mode 100644 index 2921c8c1..00000000 --- a/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java +++ /dev/null @@ -1,178 +0,0 @@ -package de.ellpeck.naturesaura.events; - -import de.ellpeck.naturesaura.Helper; -import de.ellpeck.naturesaura.blocks.ModBlocks; -import de.ellpeck.naturesaura.packet.PacketHandler; -import de.ellpeck.naturesaura.packet.PacketParticleStream; -import de.ellpeck.naturesaura.packet.PacketParticles; -import de.ellpeck.naturesaura.recipes.TreeRitualRecipe; -import net.minecraft.block.BlockLog; -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.AxisAlignedBB; -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 net.minecraftforge.fml.common.gameevent.TickEvent; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class TreeRitualHandler { - - public static final BlockPos[] GOLD_POWDER_POSITIONS = new BlockPos[]{ - new BlockPos(-2, 0, 0), - new BlockPos(2, 0, 0), - new BlockPos(0, 0, -2), - new BlockPos(0, 0, 2), - new BlockPos(-1, 0, -1), - new BlockPos(-1, 0, 1), - new BlockPos(1, 0, 1), - new BlockPos(1, 0, -1), - new BlockPos(2, 0, -1), - new BlockPos(2, 0, 1), - new BlockPos(-2, 0, -1), - new BlockPos(-2, 0, 1), - new BlockPos(1, 0, 2), - new BlockPos(-1, 0, 2), - new BlockPos(1, 0, -2), - new BlockPos(-1, 0, -2) - }; - private static final List ACTIVE_RITUALS = new ArrayList<>(); - - public TreeRitualHandler() { - MinecraftForge.TERRAIN_GEN_BUS.register(this); - MinecraftForge.EVENT_BUS.register(this); - } - - @SubscribeEvent - public void onTreeGrow(SaplingGrowTreeEvent event) { - World world = event.getWorld(); - BlockPos pos = event.getPos(); - if (!world.isRemote) { - if (Helper.checkMultiblock(world, pos, GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true)) { - List items = world.getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(pos).grow(4, 0, 4)); - List usableItems = new ArrayList<>(); - Set usedLogs = new HashSet<>(); - - for (EntityItem item : items) { - BlockPos itemPos = item.getPosition(); - ItemStack stack = item.getItem(); - if (stack.getCount() == 1) { - if (!usedLogs.contains(itemPos) && world.getBlockState(itemPos.down()).getBlock() instanceof BlockLog) { - usedLogs.add(itemPos); - usableItems.add(stack); - } - } - } - - IBlockState sapling = world.getBlockState(pos); - ItemStack saplingStack = sapling.getBlock().getItem(world, pos, sapling); - if (!saplingStack.isEmpty()) { - for (TreeRitualRecipe recipe : TreeRitualRecipe.RECIPES) { - if (recipe.matchesItems(saplingStack, usableItems)) { - ActiveRitual ritual = new ActiveRitual(pos, items, recipe); - ACTIVE_RITUALS.add(ritual); - break; - } - } - } - } - } - } - - @SubscribeEvent - public void onWorldTick(TickEvent.WorldTickEvent event) { - World world = event.world; - if (!world.isRemote) { - for (int i = ACTIVE_RITUALS.size() - 1; i >= 0; i--) { - ActiveRitual ritual = ACTIVE_RITUALS.get(i); - if (ritual.isOkay(world)) { - ritual.timer++; - - if (ritual.timer % 3 == 0) { - for (EntityItem item : ritual.involvedItems) { - PacketHandler.sendToAllAround(world, ritual.pos, 32, new PacketParticleStream( - (float) item.posX, (float) item.posY + 0.5F, (float) item.posZ, - ritual.pos.getX() + 0.5F, ritual.pos.getY() + 1.5F, ritual.pos.getZ() + 0.5F, - world.rand.nextFloat() * 0.05F + 0.05F, 0xFF00FF, world.rand.nextFloat() * 1F + 1F - )); - } - } - if (ritual.timer % 5 == 0) { - for (BlockPos offset : GOLD_POWDER_POSITIONS) { - BlockPos dustPos = ritual.pos.add(offset); - PacketHandler.sendToAllAround(world, ritual.pos, 32, - new PacketParticles( - (float) dustPos.getX() + 0.375F + world.rand.nextFloat() * 0.25F, - (float) dustPos.getY() + 0.1F, - (float) dustPos.getZ() + 0.375F + world.rand.nextFloat() * 0.25F, - (float) world.rand.nextGaussian() * 0.01F, - world.rand.nextFloat() * 0.005F + 0.01F, - (float) world.rand.nextGaussian() * 0.01F, - 0xf4cb42, 2F, 100, 0F, false, true - )); - } - } - - if (ritual.timer >= ritual.recipe.time) { - ACTIVE_RITUALS.remove(i); - } else if (ritual.timer >= ritual.recipe.time / 2) { - for (EntityItem item : ritual.involvedItems) { - for (int j = world.rand.nextInt(20) + 10; j >= 0; j--) { - PacketHandler.sendToAllAround(world, ritual.pos, 32, new PacketParticles( - (float) item.posX, (float) item.posY + 0.5F, (float) item.posZ, - (float) world.rand.nextGaussian() * 0.05F, world.rand.nextFloat() * 0.05F, (float) world.rand.nextGaussian() * 0.05F, - 0xFF00FF, 1.5F, 50, 0F, false, true)); - } - item.setDead(); - } - ritual.involvedItems.clear(); - } - - } else { - ACTIVE_RITUALS.remove(i); - } - } - } - } - - public static void clear() { - ACTIVE_RITUALS.clear(); - } - - private static class ActiveRitual { - - private final BlockPos pos; - private final List involvedItems; - private final TreeRitualRecipe recipe; - - private int timer; - - public ActiveRitual(BlockPos pos, List involvedItems, TreeRitualRecipe recipe) { - this.pos = pos; - this.recipe = recipe; - - this.involvedItems = new ArrayList<>(); - for (EntityItem item : involvedItems) { - if (Helper.containsItem(this.recipe.items, item.getItem())) { - this.involvedItems.add(item); - } - } - } - - private boolean isOkay(World world) { - for (EntityItem item : this.involvedItems) { - if (item.isDead || item.prevPosX != item.posX || item.prevPosY != item.posY || item.prevPosZ != item.posZ) { - return false; - } - } - return Helper.checkMultiblock(world, this.pos, GOLD_POWDER_POSITIONS, ModBlocks.GOLD_POWDER.getDefaultState(), true); - } - } -} diff --git a/src/main/java/de/ellpeck/naturesaura/proxy/ClientProxy.java b/src/main/java/de/ellpeck/naturesaura/proxy/ClientProxy.java index 047c16dd..c2d5ff6b 100644 --- a/src/main/java/de/ellpeck/naturesaura/proxy/ClientProxy.java +++ b/src/main/java/de/ellpeck/naturesaura/proxy/ClientProxy.java @@ -1,5 +1,7 @@ package de.ellpeck.naturesaura.proxy; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityWoodStand; +import de.ellpeck.naturesaura.blocks.tiles.render.RenderWoodStand; import de.ellpeck.naturesaura.events.ClientEvents; import de.ellpeck.naturesaura.particles.ParticleHandler; import de.ellpeck.naturesaura.particles.ParticleMagic; @@ -16,6 +18,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -29,7 +32,7 @@ public class ClientProxy implements IProxy { @Override public void init(FMLInitializationEvent event) { - + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityWoodStand.class, new RenderWoodStand()); } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java b/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java index cb95f9d0..2cdc0b99 100644 --- a/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java +++ b/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java @@ -25,7 +25,7 @@ public class TreeRitualRecipe { public boolean matchesItems(ItemStack sapling, List items) { if (this.saplingType.isItemEqual(sapling)) { for (ItemStack ingredient : this.items) { - if (!Helper.containsItem(items, ingredient)) { + if (Helper.getItemIndex(items, ingredient) < 0) { return false; } } diff --git a/src/main/resources/assets/naturesaura/blockstates/wood_stand.json b/src/main/resources/assets/naturesaura/blockstates/wood_stand.json new file mode 100644 index 00000000..15479107 --- /dev/null +++ b/src/main/resources/assets/naturesaura/blockstates/wood_stand.json @@ -0,0 +1,16 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "naturesaura:wood_stand", + "textures": { + "texture": "minecraft:blocks/log_oak", + "top": "minecraft:blocks/log_oak_top", + "particle": "#texture" + }, + "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 b376f2db..d1c9a726 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -8,7 +8,7 @@ tile.naturesaura.nature_altar.name=Natural Altar tile.naturesaura.decayed_leaves.name=Decayed Leaves tile.naturesaura.golden_leaves.name=Golden Leaves tile.naturesaura.gold_powder.name=Gold Powder -tile.naturesaura.tree_ritual.name=Drained Dirt +tile.naturesaura.wood_stand.name=Wooden Stand item.naturesaura.eye.name=Environmental Eye item.naturesaura.gold_fiber.name=Brilliant Fiber diff --git a/src/main/resources/assets/naturesaura/models/block/wood_stand.json b/src/main/resources/assets/naturesaura/models/block/wood_stand.json new file mode 100644 index 00000000..3b757650 --- /dev/null +++ b/src/main/resources/assets/naturesaura/models/block/wood_stand.json @@ -0,0 +1,39 @@ +{ + "elements": [ + { + "from": [3, 0, 3], + "to": [13, 13, 13], + "faces": { + "down": { + "uv": [3, 3, 13, 13], + "texture": "#top", + "cullface": "down" + }, + "up": { + "uv": [3, 3, 13, 13], + "texture": "#top" + }, + "north": { + "uv": [3, 3, 13, 13], + "texture": "#texture", + "cullface": "north" + }, + "south": { + "uv": [3, 3, 13, 13], + "texture": "#texture", + "cullface": "south" + }, + "west": { + "uv": [3, 3, 13, 13], + "texture": "#texture", + "cullface": "west" + }, + "east": { + "uv": [3, 3, 13, 13], + "texture": "#texture", + "cullface": "east" + } + } + } + ] +}