From f2eca230e81e1923331a9e561b651a7527b6a3aa Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Tue, 16 Oct 2018 01:36:30 +0200 Subject: [PATCH] some ritual work, needs finishing --- .../java/de/ellpeck/naturesaura/Helper.java | 30 +++ .../de/ellpeck/naturesaura/NaturesAura.java | 18 +- .../naturesaura/blocks/BlockGoldPowder.java | 223 ++++++++++++++++++ .../ellpeck/naturesaura/blocks/ModBlocks.java | 1 + .../blocks/tiles/TileEntityNatureAltar.java | 12 +- .../naturesaura/events/TreeRitualHandler.java | 178 ++++++++++++++ .../naturesaura/packet/PacketHandler.java | 7 +- .../packet/PacketParticleStream.java | 91 +++++++ .../naturesaura/packet/PacketParticles.java | 91 +++---- .../naturesaura/recipes/ModRecipes.java | 12 + .../naturesaura/recipes/TreeRitualRecipe.java | 41 ++++ .../naturesaura/blockstates/gold_powder.json | 144 +++++++++++ .../assets/naturesaura/lang/en_US.lang | 2 + .../naturesaura/models/item/gold_powder.json | 6 + .../textures/items/gold_powder.png | Bin 0 -> 256 bytes 15 files changed, 797 insertions(+), 59 deletions(-) create mode 100644 src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java create mode 100644 src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java create mode 100644 src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java create mode 100644 src/main/java/de/ellpeck/naturesaura/recipes/ModRecipes.java create mode 100644 src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java create mode 100644 src/main/resources/assets/naturesaura/blockstates/gold_powder.json create mode 100644 src/main/resources/assets/naturesaura/models/item/gold_powder.json create mode 100644 src/main/resources/assets/naturesaura/textures/items/gold_powder.png diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index e54abab5..d5903bcb 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -1,5 +1,7 @@ package de.ellpeck.naturesaura; +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; @@ -25,6 +27,16 @@ public final class Helper { return tiles; } + public static boolean checkMultiblock(World world, BlockPos pos, BlockPos[] positions, IBlockState state, boolean blockOnly) { + for (BlockPos offset : positions) { + IBlockState current = world.getBlockState(pos.add(offset)); + if (blockOnly ? current.getBlock() != state.getBlock() : current != state) { + return false; + } + } + return true; + } + @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)); @@ -33,4 +45,22 @@ public final class Helper { int b = (int) ((c1 & 0xFF) * ratio + (c2 & 0xFF) * (1 - ratio)); 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; + } + } + return false; + } + + public static boolean containsItem(ItemStack[] array, ItemStack item) { + for (ItemStack stack : array) { + if (stack.isItemEqual(item)) { + return true; + } + } + return false; + } } diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index 8d111a63..bd3d9648 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -1,19 +1,18 @@ package de.ellpeck.naturesaura; import de.ellpeck.naturesaura.blocks.ModBlocks; +import de.ellpeck.naturesaura.events.TreeRitualHandler; import de.ellpeck.naturesaura.items.ModItems; import de.ellpeck.naturesaura.packet.PacketHandler; import de.ellpeck.naturesaura.proxy.IProxy; +import de.ellpeck.naturesaura.recipes.ModRecipes; import de.ellpeck.naturesaura.reg.ModRegistry; import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.SidedProxy; -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.event.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -41,14 +40,20 @@ public final class NaturesAura { public void preInit(FMLPreInitializationEvent event) { new ModBlocks(); new ModItems(); + PacketHandler.init(); ModRegistry.preInit(event); + + new TreeRitualHandler(); + proxy.preInit(event); } @EventHandler public void init(FMLInitializationEvent event) { + ModRecipes.init(); ModRegistry.init(event); + proxy.init(event); } @@ -57,4 +62,9 @@ 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 new file mode 100644 index 00000000..54e662de --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockGoldPowder.java @@ -0,0 +1,223 @@ +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.reg.IColorProvidingBlock; +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyEnum; +import net.minecraft.block.state.BlockFaceShape; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.color.IBlockColor; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.IStringSerializable; +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.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.Random; + +public class BlockGoldPowder extends BlockImpl implements IColorProvidingBlock { + + public static final PropertyEnum NORTH = PropertyEnum.create("north", AttachPos.class); + public static final PropertyEnum EAST = PropertyEnum.create("east", AttachPos.class); + public static final PropertyEnum SOUTH = PropertyEnum.create("south", AttachPos.class); + public static final PropertyEnum WEST = PropertyEnum.create("west", AttachPos.class); + protected static final AxisAlignedBB[] AABBS = new AxisAlignedBB[]{ + new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), + new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 0.8125D, 0.0625D, 1.0D), + new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), + new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.8125D, 0.0625D, 1.0D), + new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.1875D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), + new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.0D, 0.0D, 0.1875D, 1.0D, 0.0625D, 1.0D), + new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.1875D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D), + new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 0.8125D), + new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.0625D, 1.0D) + }; + + public BlockGoldPowder() { + super("gold_powder", Material.CIRCUITS); + this.setSoundType(SoundType.STONE); + this.setHardness(0F); + } + + @Override + public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { + if (rand.nextFloat() >= 0.8F) { + for (BlockPos offsetToOrigin : TreeRitualHandler.GOLD_POWDER_POSITIONS) { + BlockPos origin = pos.subtract(offsetToOrigin); + if (Helper.checkMultiblock(worldIn, origin, TreeRitualHandler.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, + 0xf4cb42, 1F, 50, 0F, false, true); + break; + } + } + } + } + + @Override + protected BlockStateContainer createBlockState() { + return new BlockStateContainer(this, NORTH, EAST, SOUTH, WEST); + } + + @Override + public int getMetaFromState(IBlockState state) { + return 0; + } + + @Override + public IBlockColor getBlockColor() { + return (state, worldIn, pos, tintIndex) -> 0xf4cb42; + } + + @Override + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { + return AABBS[getAABBIndex(state.getActualState(source, pos))]; + } + + private static int getAABBIndex(IBlockState state) { + int i = 0; + boolean n = state.getValue(NORTH) != AttachPos.NONE; + boolean e = state.getValue(EAST) != AttachPos.NONE; + boolean s = state.getValue(SOUTH) != AttachPos.NONE; + boolean w = state.getValue(WEST) != AttachPos.NONE; + + if (n || s && !n && !e && !w) { + i |= 1 << EnumFacing.NORTH.getHorizontalIndex(); + } + if (e || w && !n && !e && !s) { + i |= 1 << EnumFacing.EAST.getHorizontalIndex(); + } + if (s || n && !e && !s && !w) { + i |= 1 << EnumFacing.SOUTH.getHorizontalIndex(); + } + if (w || e && !n && !s && !w) { + i |= 1 << EnumFacing.WEST.getHorizontalIndex(); + } + return i; + } + + @Override + public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) { + state = state.withProperty(WEST, this.getAttachPosition(worldIn, pos, EnumFacing.WEST)); + state = state.withProperty(EAST, this.getAttachPosition(worldIn, pos, EnumFacing.EAST)); + state = state.withProperty(NORTH, this.getAttachPosition(worldIn, pos, EnumFacing.NORTH)); + state = state.withProperty(SOUTH, this.getAttachPosition(worldIn, pos, EnumFacing.SOUTH)); + return state; + } + + private AttachPos getAttachPosition(IBlockAccess worldIn, BlockPos pos, EnumFacing direction) { + BlockPos dirPos = pos.offset(direction); + IBlockState state = worldIn.getBlockState(pos.offset(direction)); + + if (!this.canConnectTo(worldIn.getBlockState(dirPos), direction, worldIn, dirPos) + && (state.isNormalCube() || !this.canConnectUpwardsTo(worldIn, dirPos.down()))) { + IBlockState iblockstate1 = worldIn.getBlockState(pos.up()); + if (!iblockstate1.isNormalCube()) { + boolean flag = worldIn.getBlockState(dirPos).isSideSolid(worldIn, dirPos, EnumFacing.UP) + || worldIn.getBlockState(dirPos).getBlock() == Blocks.GLOWSTONE; + if (flag && this.canConnectUpwardsTo(worldIn, dirPos.up())) { + if (state.isBlockNormalCube()) { + return AttachPos.UP; + } + return AttachPos.SIDE; + } + } + return AttachPos.NONE; + } else { + return AttachPos.SIDE; + } + } + + @Override + public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) { + return NULL_AABB; + } + + @Override + public boolean isOpaqueCube(IBlockState state) { + return false; + } + + @Override + public boolean isFullCube(IBlockState state) { + return false; + } + + @Override + public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { + IBlockState downState = worldIn.getBlockState(pos.down()); + return downState.isTopSolid() + || downState.getBlockFaceShape(worldIn, pos.down(), EnumFacing.UP) == BlockFaceShape.SOLID + || worldIn.getBlockState(pos.down()).getBlock() == Blocks.GLOWSTONE; + } + + @Override + public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { + if (!worldIn.isRemote) { + if (!this.canPlaceBlockAt(worldIn, pos)) { + this.dropBlockAsItem(worldIn, pos, state, 0); + worldIn.setBlockToAir(pos); + } + } + } + + private boolean canConnectUpwardsTo(IBlockAccess worldIn, BlockPos pos) { + return this.canConnectTo(worldIn.getBlockState(pos), null, worldIn, pos); + } + + private boolean canConnectTo(IBlockState blockState, @Nullable EnumFacing side, IBlockAccess world, BlockPos pos) { + Block block = blockState.getBlock(); + return block == this; + } + + @Override + @SideOnly(Side.CLIENT) + public BlockRenderLayer getRenderLayer() { + return BlockRenderLayer.CUTOUT; + } + + @Override + public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) { + return BlockFaceShape.UNDEFINED; + } + + private enum AttachPos implements IStringSerializable { + UP("up"), + SIDE("side"), + NONE("none"); + + private final String name; + + AttachPos(String name) { + this.name = name; + } + + public String toString() { + return this.getName(); + } + + @Override + public String getName() { + return this.name; + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index 636ea6da..9addd5cc 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -13,4 +13,5 @@ public final class ModBlocks { public static final Block NATURE_ALTAR = new BlockNatureAltar(); public static final Block DECAYED_LEAVES = new BlockDecayedLeaves(); public static final Block GOLDEN_LEAVES = new BlockGoldenLeaves(); + public static final Block GOLD_POWDER = new BlockGoldPowder(); } 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 f24f4159..d8e4c60f 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityNatureAltar.java @@ -6,7 +6,7 @@ import de.ellpeck.naturesaura.aura.BasicAuraContainer; import de.ellpeck.naturesaura.aura.IAuraContainer; import de.ellpeck.naturesaura.aura.IAuraContainerProvider; import de.ellpeck.naturesaura.packet.PacketHandler; -import de.ellpeck.naturesaura.packet.PacketParticles; +import de.ellpeck.naturesaura.packet.PacketParticleStream; import net.minecraft.block.BlockStoneBrick; import net.minecraft.block.BlockStoneBrick.EnumType; import net.minecraft.block.state.IBlockState; @@ -129,7 +129,7 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable, if (stored > 0) { provider.container().drainAura(stored, false); - PacketHandler.sendToAllLoaded(this.world, this.pos, new PacketParticles( + 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, rand.nextFloat() * 0.05F + 0.05F, provider.container().getAuraColor(), rand.nextFloat() * 1F + 1F @@ -176,13 +176,7 @@ public class TileEntityNatureAltar extends TileEntityImpl implements ITickable, } private boolean check(BlockPos[] positions, IBlockState state, boolean blockOnly) { - for (BlockPos offset : positions) { - IBlockState world = this.world.getBlockState(this.pos.add(offset)); - if (blockOnly ? world.getBlock() != state.getBlock() : world != state) { - return false; - } - } - return true; + return Helper.checkMultiblock(this.world, this.pos, positions, state, blockOnly); } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java b/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java new file mode 100644 index 00000000..2921c8c1 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/events/TreeRitualHandler.java @@ -0,0 +1,178 @@ +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/packet/PacketHandler.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketHandler.java index b4d69cbf..8b1153d4 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketHandler.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketHandler.java @@ -14,11 +14,16 @@ public final class PacketHandler { public static void init() { network = new SimpleNetworkWrapper(NaturesAura.MOD_ID); - network.registerMessage(PacketParticles.Handler.class, PacketParticles.class, 0, Side.CLIENT); + network.registerMessage(PacketParticleStream.Handler.class, PacketParticleStream.class, 0, Side.CLIENT); + network.registerMessage(PacketParticles.Handler.class, PacketParticles.class, 1, Side.CLIENT); } public static void sendToAllLoaded(World world, BlockPos pos, IMessage message) { network.sendToAllTracking(message, new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), pos.getY(), pos.getZ(), 0)); } + public static void sendToAllAround(World world, BlockPos pos, int range, IMessage message) { + network.sendToAllAround(message, new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), pos.getY(), pos.getZ(), range)); + } + } diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java new file mode 100644 index 00000000..daf15047 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticleStream.java @@ -0,0 +1,91 @@ +package de.ellpeck.naturesaura.packet; + +import de.ellpeck.naturesaura.NaturesAura; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.util.vector.Vector3f; + +public class PacketParticleStream implements IMessage { + + private float startX; + private float startY; + private float startZ; + + private float endX; + private float endY; + private float endZ; + + private float speed; + private int color; + private float scale; + + public PacketParticleStream(float startX, float startY, float startZ, float endX, float endY, float endZ, float speed, int color, float scale) { + this.startX = startX; + this.startY = startY; + this.startZ = startZ; + this.endX = endX; + this.endY = endY; + this.endZ = endZ; + this.speed = speed; + this.color = color; + this.scale = scale; + } + + public PacketParticleStream() { + + } + + @Override + public void fromBytes(ByteBuf buf) { + this.startX = buf.readFloat(); + this.startY = buf.readFloat(); + this.startZ = buf.readFloat(); + this.endX = buf.readFloat(); + this.endY = buf.readFloat(); + this.endZ = buf.readFloat(); + this.speed = buf.readFloat(); + this.color = buf.readInt(); + this.scale = buf.readFloat(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeFloat(this.startX); + buf.writeFloat(this.startY); + buf.writeFloat(this.startZ); + buf.writeFloat(this.endX); + buf.writeFloat(this.endY); + buf.writeFloat(this.endZ); + buf.writeFloat(this.speed); + buf.writeInt(this.color); + buf.writeFloat(this.scale); + } + + public static class Handler implements IMessageHandler { + + @Override + @SideOnly(Side.CLIENT) + public IMessage onMessage(PacketParticleStream message, MessageContext ctx) { + NaturesAura.proxy.scheduleTask(() -> { + Vector3f dir = new Vector3f( + message.endX - message.startX, + message.endY - message.startY, + message.endZ - message.startZ); + int maxAge = (int) (dir.length() / message.speed); + dir.normalise(); + + NaturesAura.proxy.spawnMagicParticle(Minecraft.getMinecraft().world, + message.startX, message.startY, message.startZ, + dir.x * message.speed, dir.y * message.speed, dir.z * message.speed, + message.color, message.scale, maxAge, 0F, false, false); + }); + + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index 25c1025d..48d0500e 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -8,32 +8,35 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.lwjgl.util.vector.Vector3f; public class PacketParticles implements IMessage { - private float startX; - private float startY; - private float startZ; - - private float endX; - private float endY; - private float endZ; - - private float speed; + private float posX; + private float posY; + private float posZ; + private float motionX; + private float motionY; + private float motionZ; private int color; private float scale; + private int maxAge; + private float gravity; + private boolean collision; + private boolean fade; - public PacketParticles(float startX, float startY, float startZ, float endX, float endY, float endZ, float speed, int color, float scale) { - this.startX = startX; - this.startY = startY; - this.startZ = startZ; - this.endX = endX; - this.endY = endY; - this.endZ = endZ; - this.speed = speed; + public PacketParticles(float posX, float posY, float posZ, float motionX, float motionY, float motionZ, int color, float scale, int maxAge, float gravity, boolean collision, boolean fade) { + this.posX = posX; + this.posY = posY; + this.posZ = posZ; + this.motionX = motionX; + this.motionY = motionY; + this.motionZ = motionZ; this.color = color; this.scale = scale; + this.maxAge = maxAge; + this.gravity = gravity; + this.collision = collision; + this.fade = fade; } public PacketParticles() { @@ -42,28 +45,34 @@ public class PacketParticles implements IMessage { @Override public void fromBytes(ByteBuf buf) { - this.startX = buf.readFloat(); - this.startY = buf.readFloat(); - this.startZ = buf.readFloat(); - this.endX = buf.readFloat(); - this.endY = buf.readFloat(); - this.endZ = buf.readFloat(); - this.speed = buf.readFloat(); + this.posX = buf.readFloat(); + this.posY = buf.readFloat(); + this.posZ = buf.readFloat(); + this.motionX = buf.readFloat(); + this.motionY = buf.readFloat(); + this.motionZ = buf.readFloat(); this.color = buf.readInt(); this.scale = buf.readFloat(); + this.maxAge = buf.readInt(); + this.gravity = buf.readFloat(); + this.collision = buf.readBoolean(); + this.fade = buf.readBoolean(); } @Override public void toBytes(ByteBuf buf) { - buf.writeFloat(this.startX); - buf.writeFloat(this.startY); - buf.writeFloat(this.startZ); - buf.writeFloat(this.endX); - buf.writeFloat(this.endY); - buf.writeFloat(this.endZ); - buf.writeFloat(this.speed); + buf.writeFloat(this.posX); + buf.writeFloat(this.posY); + buf.writeFloat(this.posZ); + buf.writeFloat(this.motionX); + buf.writeFloat(this.motionY); + buf.writeFloat(this.motionZ); buf.writeInt(this.color); buf.writeFloat(this.scale); + buf.writeInt(this.maxAge); + buf.writeFloat(this.gravity); + buf.writeBoolean(this.collision); + buf.writeBoolean(this.fade); } public static class Handler implements IMessageHandler { @@ -71,19 +80,11 @@ public class PacketParticles implements IMessage { @Override @SideOnly(Side.CLIENT) public IMessage onMessage(PacketParticles message, MessageContext ctx) { - NaturesAura.proxy.scheduleTask(() -> { - Vector3f dir = new Vector3f( - message.endX - message.startX, - message.endY - message.startY, - message.endZ - message.startZ); - int maxAge = (int) (dir.length() / message.speed); - dir.normalise(); - - NaturesAura.proxy.spawnMagicParticle(Minecraft.getMinecraft().world, - message.startX, message.startY, message.startZ, - dir.x * message.speed, dir.y * message.speed, dir.z * message.speed, - message.color, message.scale, maxAge, 0F, false, false); - }); + NaturesAura.proxy.scheduleTask(() -> + NaturesAura.proxy.spawnMagicParticle(Minecraft.getMinecraft().world, + message.posX, message.posY, message.posZ, + message.motionX, message.motionY, message.motionZ, + message.color, message.scale, message.maxAge, message.gravity, message.collision, message.fade)); return null; } diff --git a/src/main/java/de/ellpeck/naturesaura/recipes/ModRecipes.java b/src/main/java/de/ellpeck/naturesaura/recipes/ModRecipes.java new file mode 100644 index 00000000..cc27432f --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/recipes/ModRecipes.java @@ -0,0 +1,12 @@ +package de.ellpeck.naturesaura.recipes; + +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +public final class ModRecipes { + + public static void init() { + new TreeRitualRecipe(new ItemStack(Blocks.SAPLING), new ItemStack(Items.APPLE, 16), 300, new ItemStack(Items.BEETROOT), new ItemStack(Items.ITEM_FRAME), new ItemStack(Items.COMMAND_BLOCK_MINECART)).add(); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java b/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java new file mode 100644 index 00000000..cb95f9d0 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/recipes/TreeRitualRecipe.java @@ -0,0 +1,41 @@ +package de.ellpeck.naturesaura.recipes; + +import de.ellpeck.naturesaura.Helper; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +public class TreeRitualRecipe { + + public static final List RECIPES = new ArrayList<>(); + + public final ItemStack saplingType; + public final ItemStack[] items; + public final ItemStack result; + public final int time; + + public TreeRitualRecipe(ItemStack saplingType, ItemStack result, int time, ItemStack... items) { + this.saplingType = saplingType; + this.items = items; + this.result = result; + this.time = time; + } + + public boolean matchesItems(ItemStack sapling, List items) { + if (this.saplingType.isItemEqual(sapling)) { + for (ItemStack ingredient : this.items) { + if (!Helper.containsItem(items, ingredient)) { + return false; + } + } + return true; + } else { + return false; + } + } + + public void add() { + RECIPES.add(this); + } +} diff --git a/src/main/resources/assets/naturesaura/blockstates/gold_powder.json b/src/main/resources/assets/naturesaura/blockstates/gold_powder.json new file mode 100644 index 00000000..77562806 --- /dev/null +++ b/src/main/resources/assets/naturesaura/blockstates/gold_powder.json @@ -0,0 +1,144 @@ +{ + "multipart": [ + { + "when": { + "OR": [ + { + "north": "none", + "east": "none", + "south": "none", + "west": "none" + }, + { + "north": "side|up", + "east": "side|up" + }, + { + "east": "side|up", + "south": "side|up" + }, + { + "south": "side|up", + "west": "side|up" + }, + { + "west": "side|up", + "north": "side|up" + } + ] + }, + "apply": { + "model": "redstone_dot" + } + }, + { + "when": { + "OR": [ + { + "north": "side|up" + }, + { + "north": "none", + "east": "none", + "south": "side|up", + "west": "none" + } + ] + }, + "apply": { + "model": "redstone_side0" + } + }, + { + "when": { + "OR": [ + { + "south": "side|up" + }, + { + "north": "side|up", + "east": "none", + "south": "none", + "west": "none" + } + ] + }, + "apply": { + "model": "redstone_side_alt0" + } + }, + { + "when": { + "OR": [ + { + "east": "side|up" + }, + { + "north": "none", + "east": "none", + "south": "none", + "west": "side|up" + } + ] + }, + "apply": { + "model": "redstone_side_alt1", + "y": 270 + } + }, + { + "when": { + "OR": [ + { + "west": "side|up" + }, + { + "north": "none", + "east": "side|up", + "south": "none", + "west": "none" + } + ] + }, + "apply": { + "model": "redstone_side1", + "y": 270 + } + }, + { + "when": { + "north": "up" + }, + "apply": { + "model": "redstone_up" + } + }, + { + "when": { + "east": "up" + }, + "apply": { + "model": "redstone_up", + "y": 90 + } + }, + { + "when": { + "south": "up" + }, + "apply": { + "model": "redstone_up", + "y": 180 + } + }, + { + "when": { + "west": "up" + }, + "apply": { + "model": "redstone_up", + "y": 270 + } + } + ] +} \ 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 f5674071..b376f2db 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -7,6 +7,8 @@ tile.naturesaura.ancient_sapling.name=Ancient Sapling 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 item.naturesaura.eye.name=Environmental Eye item.naturesaura.gold_fiber.name=Brilliant Fiber diff --git a/src/main/resources/assets/naturesaura/models/item/gold_powder.json b/src/main/resources/assets/naturesaura/models/item/gold_powder.json new file mode 100644 index 00000000..3d2711b4 --- /dev/null +++ b/src/main/resources/assets/naturesaura/models/item/gold_powder.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "naturesaura:items/gold_powder" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/textures/items/gold_powder.png b/src/main/resources/assets/naturesaura/textures/items/gold_powder.png new file mode 100644 index 0000000000000000000000000000000000000000..71e7f0ba90da952d9fdb6fbea4789d4f8bd28e5e GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjGK$vmro+3}6phSslL`iUdT1k0gQ7S`0VrE{6US4X6f{C7?o?)`q9B-hSI!_nJ z5DWji6Abwp40xD7N4d!zK6Z%1+Ws-C5Wk*^YnDSaz&G z`ci}bre7D3dkU99S+Tck*^!kDl xV+Ku?sOZA)yefKInoQPTpQoz8Tc@*G*t+OIW)6GTZ=g#UJYD@<);T3K0RVlXR!jf@ literal 0 HcmV?d00001