From bf2097734680dc7e10b9f49c4ac65d2c1ec079ca Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Sat, 19 Nov 2022 22:58:21 +0100 Subject: [PATCH] feat: implement crystal stuff --- .../anvilcraft/classiccasting/CCBlocks.java | 5 + .../classiccasting/ClientProxy.java | 16 + .../classiccasting/CommonProxy.java | 4 + .../anvilcraft/classiccasting/GuiTicker.java | 51 +++ .../net/anvilcraft/classiccasting/Utils.java | 5 +- .../classiccasting/WandManager.java | 60 +++- .../classiccasting/blocks/BlockCrystal.java | 219 ++++++++++++ .../items/ItemBlockCrystal.java | 72 ++++ .../items/wands/ItemWandCasting.java | 15 +- .../items/wands/ItemWandExcavation.java | 2 +- .../items/wands/ItemWandLightning.java | 2 +- .../render/BlockCrystalRenderer.java | 162 +++++++++ .../render/TileCrystalCapacitorRenderer.java | 105 ++++++ .../render/TileCrystalCoreRenderer.java | 172 ++++++++++ .../render/models/ModelCrystal.java | 30 ++ .../tiles/TileCrystalCapacitor.java | 128 +++++++ .../classiccasting/tiles/TileCrystalCore.java | 316 ++++++++++++++++++ .../assets/classiccasting/lang/en_US.lang | 2 + .../textures/blocks/crystal.png | Bin 0 -> 340 bytes .../textures/blocks/crystalframe.png | Bin 0 -> 457 bytes .../textures/models/crystal.png | Bin 0 -> 1567 bytes .../textures/models/crystalcapacitor.png | Bin 0 -> 8393 bytes 22 files changed, 1353 insertions(+), 13 deletions(-) create mode 100644 src/main/java/net/anvilcraft/classiccasting/blocks/BlockCrystal.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/items/ItemBlockCrystal.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/render/BlockCrystalRenderer.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCapacitorRenderer.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCoreRenderer.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/render/models/ModelCrystal.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCapacitor.java create mode 100644 src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCore.java create mode 100644 src/main/resources/assets/classiccasting/textures/blocks/crystal.png create mode 100644 src/main/resources/assets/classiccasting/textures/blocks/crystalframe.png create mode 100644 src/main/resources/assets/classiccasting/textures/models/crystal.png create mode 100644 src/main/resources/assets/classiccasting/textures/models/crystalcapacitor.png diff --git a/src/main/java/net/anvilcraft/classiccasting/CCBlocks.java b/src/main/java/net/anvilcraft/classiccasting/CCBlocks.java index 5fbf340..a9b5a4f 100644 --- a/src/main/java/net/anvilcraft/classiccasting/CCBlocks.java +++ b/src/main/java/net/anvilcraft/classiccasting/CCBlocks.java @@ -2,19 +2,24 @@ package net.anvilcraft.classiccasting; import cpw.mods.fml.common.registry.GameRegistry; import net.anvilcraft.classiccasting.blocks.BlockAlembic; +import net.anvilcraft.classiccasting.blocks.BlockCrystal; import net.anvilcraft.classiccasting.blocks.BlockInfusionWorkbench; import net.anvilcraft.classiccasting.items.ItemBlockAlembic; +import net.anvilcraft.classiccasting.items.ItemBlockCrystal; import net.minecraft.block.Block; public class CCBlocks { public static Block alembic; + public static Block crystal; public static Block infusionWorkbench; public static void init() { alembic = new BlockAlembic(); + crystal = new BlockCrystal(); infusionWorkbench = new BlockInfusionWorkbench(); GameRegistry.registerBlock(alembic, ItemBlockAlembic.class, "alembic"); + GameRegistry.registerBlock(crystal, ItemBlockCrystal.class, "crystal"); GameRegistry.registerBlock(infusionWorkbench, "infusionWorkbench"); } } diff --git a/src/main/java/net/anvilcraft/classiccasting/ClientProxy.java b/src/main/java/net/anvilcraft/classiccasting/ClientProxy.java index 1afdec1..c961101 100644 --- a/src/main/java/net/anvilcraft/classiccasting/ClientProxy.java +++ b/src/main/java/net/anvilcraft/classiccasting/ClientProxy.java @@ -5,11 +5,16 @@ import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.FMLCommonHandler; import net.anvilcraft.classiccasting.gui.GuiInfusionWorkbench; import net.anvilcraft.classiccasting.render.BlockAlembicRenderer; +import net.anvilcraft.classiccasting.render.BlockCrystalRenderer; import net.anvilcraft.classiccasting.render.BlockInfusionWorkbenchRenderer; import net.anvilcraft.classiccasting.render.ItemAuraCompassRenderer; import net.anvilcraft.classiccasting.render.TileAlembicRenderer; +import net.anvilcraft.classiccasting.render.TileCrystalCapacitorRenderer; +import net.anvilcraft.classiccasting.render.TileCrystalCoreRenderer; import net.anvilcraft.classiccasting.render.TileInfusionWorkbenchRenderer; import net.anvilcraft.classiccasting.tiles.TileAlembic; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; import net.anvilcraft.classiccasting.tiles.TileInfusionWorkbench; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; @@ -25,6 +30,9 @@ public class ClientProxy extends CommonProxy { BlockAlembicRenderer.RI = RenderingRegistry.getNextAvailableRenderId(); RenderingRegistry.registerBlockHandler(new BlockAlembicRenderer()); + BlockCrystalRenderer.RI = RenderingRegistry.getNextAvailableRenderId(); + RenderingRegistry.registerBlockHandler(new BlockCrystalRenderer()); + BlockInfusionWorkbenchRenderer.RI = RenderingRegistry.getNextAvailableRenderId(); RenderingRegistry.registerBlockHandler(new BlockInfusionWorkbenchRenderer()); } @@ -43,6 +51,14 @@ public class ClientProxy extends CommonProxy { ClientRegistry.registerTileEntity( TileAlembic.class, "alembic", new TileAlembicRenderer() ); + ClientRegistry.registerTileEntity( + TileCrystalCapacitor.class, + "crystalCapacitor", + new TileCrystalCapacitorRenderer() + ); + ClientRegistry.registerTileEntity( + TileCrystalCore.class, "crystalCore", new TileCrystalCoreRenderer() + ); ClientRegistry.registerTileEntity( TileInfusionWorkbench.class, "infusionWorkbench", diff --git a/src/main/java/net/anvilcraft/classiccasting/CommonProxy.java b/src/main/java/net/anvilcraft/classiccasting/CommonProxy.java index c294617..ef3340b 100644 --- a/src/main/java/net/anvilcraft/classiccasting/CommonProxy.java +++ b/src/main/java/net/anvilcraft/classiccasting/CommonProxy.java @@ -5,6 +5,8 @@ import cpw.mods.fml.common.network.IGuiHandler; import cpw.mods.fml.common.registry.GameRegistry; import net.anvilcraft.classiccasting.container.ContainerInfusionWorkbench; import net.anvilcraft.classiccasting.tiles.TileAlembic; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; import net.anvilcraft.classiccasting.tiles.TileInfusionWorkbench; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; @@ -22,6 +24,8 @@ public class CommonProxy implements IGuiHandler { public void registerTileEntities() { GameRegistry.registerTileEntity(TileAlembic.class, "alembic"); + GameRegistry.registerTileEntity(TileCrystalCapacitor.class, "crystalCapacitor"); + GameRegistry.registerTileEntity(TileCrystalCore.class, "crystalCore"); GameRegistry.registerTileEntity(TileInfusionWorkbench.class, "infusionWorkbench"); } diff --git a/src/main/java/net/anvilcraft/classiccasting/GuiTicker.java b/src/main/java/net/anvilcraft/classiccasting/GuiTicker.java index ffa9389..fa9e8fd 100644 --- a/src/main/java/net/anvilcraft/classiccasting/GuiTicker.java +++ b/src/main/java/net/anvilcraft/classiccasting/GuiTicker.java @@ -3,9 +3,12 @@ package net.anvilcraft.classiccasting; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.gameevent.TickEvent.RenderTickEvent; +import dev.tilera.auracore.AuraCore; +import dev.tilera.auracore.api.CrystalColors; import net.anvilcraft.classiccasting.items.wands.ItemHellrod; import net.anvilcraft.classiccasting.items.wands.ItemWandCasting; import net.anvilcraft.classiccasting.items.wands.ItemWandTrade; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; @@ -13,7 +16,9 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; +import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import thaumcraft.client.lib.UtilsFX; @@ -35,6 +40,7 @@ public class GuiTicker { = (EntityPlayer) Minecraft.getMinecraft().renderViewEntity; final long time = System.currentTimeMillis(); if (player != null && mc.inGameHasFocus && Minecraft.isGuiEnabled()) { + this.renderCrystalCapacitorChargeHud(player); if (player.inventory.getCurrentItem() != null) { if (player.inventory.getCurrentItem().getItem() instanceof ItemWandTrade) { @@ -224,6 +230,51 @@ public class GuiTicker { GL11.glPopMatrix(); } + private void renderCrystalCapacitorChargeHud(EntityPlayer pl) { + Minecraft mc = Minecraft.getMinecraft(); + if (!dev.tilera.auracore.helper.Utils.hasGoggles(pl)) + return; + + MovingObjectPosition mop = Utils.getTargetBlock(pl.worldObj, pl, false, 3.0f); + if (mop == null || mop.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) + return; + + TileEntity te = pl.worldObj.getTileEntity(mop.blockX, mop.blockY, mop.blockZ); + if (!(te instanceof TileCrystalCapacitor)) + return; + + int storedVis = ((TileCrystalCapacitor) te).storedVis; + int maxVis = ((TileCrystalCapacitor) te).maxVis; + + String top_s = storedVis + " Vis"; + String bot_s = Math.round(maxVis == 0 ? 0 : ((float)storedVis / (float)maxVis) * 100.0) + "%"; + + int textwidth = Math.max( + mc.fontRenderer.getStringWidth(top_s), mc.fontRenderer.getStringWidth(bot_s) + ); + + final ScaledResolution res + = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + final int width = res.getScaledWidth(); + final int height = res.getScaledHeight(); + + GL11.glTranslatef((width / 2), (height / 2) + 16, 0.0f); + mc.renderEngine.bindTexture( + new ResourceLocation("auracore", "textures/misc/particles.png") + ); + final int px = 32 * (mc.thePlayer.ticksExisted % 16); + final int py = 32 * (mc.thePlayer.ticksExisted % 32 / 16); + GL11.glScalef(2.0f, 2.0f, 1.0f); + UtilsFX.drawTexturedQuad( + -16, -16 + (mc.fontRenderer.FONT_HEIGHT / 2), px, 96 + py, 32, 32, -90.0 + ); + GL11.glScalef(0.5f, 0.5f, 1.0f); + mc.fontRenderer.drawString(top_s, -(textwidth / 2), 0, CrystalColors.colors[7]); + mc.fontRenderer.drawString( + bot_s, -(textwidth / 2), mc.fontRenderer.FONT_HEIGHT, CrystalColors.colors[7] + ); + } + private void renderCastingWandHud( final Float partialTicks, final EntityPlayer player, diff --git a/src/main/java/net/anvilcraft/classiccasting/Utils.java b/src/main/java/net/anvilcraft/classiccasting/Utils.java index 713df57..a50a521 100644 --- a/src/main/java/net/anvilcraft/classiccasting/Utils.java +++ b/src/main/java/net/anvilcraft/classiccasting/Utils.java @@ -151,7 +151,7 @@ public class Utils { } public static MovingObjectPosition - getTargetBlock(final World world, final EntityPlayer player, final boolean par3) { + getTargetBlock(final World world, final EntityPlayer player, final boolean par3, float range) { final float var4 = 1.0f; final float var5 = ((Entity) player).prevRotationPitch + (((Entity) player).rotationPitch - ((Entity) player).prevRotationPitch) @@ -172,8 +172,7 @@ public class Utils { final float var14 = MathHelper.sin(-var5 * 0.017453292f); final float var15 = var12 * var13; final float var16 = var11 * var13; - final double var17 = 10.0; - final Vec3 var18 = var10.addVector(var15 * var17, var14 * var17, var16 * var17); + final Vec3 var18 = var10.addVector(var15 * range, var14 * range, var16 * range); return world.rayTraceBlocks(var10, var18, par3); } diff --git a/src/main/java/net/anvilcraft/classiccasting/WandManager.java b/src/main/java/net/anvilcraft/classiccasting/WandManager.java index edfa701..512c624 100644 --- a/src/main/java/net/anvilcraft/classiccasting/WandManager.java +++ b/src/main/java/net/anvilcraft/classiccasting/WandManager.java @@ -3,12 +3,13 @@ package net.anvilcraft.classiccasting; import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; import cpw.mods.fml.common.registry.LanguageRegistry; import dev.tilera.auracore.api.IWand; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagShort; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentText; import net.minecraft.world.World; import thaumcraft.api.IVisDiscountGear; @@ -267,4 +268,61 @@ public class WandManager { && world.getBlock(x + 1, y, z + 1) == CCBlocks.infusionWorkbench && world.getBlockMetadata(x + 1, y, z + 1) == 0; } + + public static boolean createNodeMagnet( + final ItemStack itemstack, + final EntityPlayer player, + final World world, + final int x, + final int y, + final int z + ) { + for (int xx = x - 2; xx <= x; ++xx) { + for (int yy = y - 2; yy <= y; ++yy) { + int zz = z - 2; + while (zz <= z) { + final TileEntity te = world.getTileEntity(xx + 1, yy + 2, zz + 1); + if (fitNodeMagnet(world, xx, yy, zz) && te != null + && te instanceof TileCrystalCore && !((TileCrystalCore) te).active + && spendCharge(world, itemstack, player, 300)) { + if (!world.isRemote) { + ((TileCrystalCore) te).activate(); + return true; + } + return false; + } else { + ++zz; + } + } + } + } + return false; + } + + public static boolean + fitNodeMagnet(final World world, final int x, final int y, final int z) { + final Block bo = ConfigBlocks.blockCosmeticSolid; + final Block bc = CCBlocks.crystal; + final Block ba = Blocks.air; + final Block[][][] blueprintBI + = { { { ba, ba, ba }, { ba, bc, ba }, { ba, ba, ba } }, + { { bo, ba, bo }, { ba, ba, ba }, { bo, ba, bo } }, + { { bo, ba, bo }, { ba, ba, ba }, { bo, ba, bo } } }; + final int[][][] blueprintMD = { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }, + { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }, + { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } }; + for (int yy = 0; yy < 3; ++yy) { + for (int xx = 0; xx < 3; ++xx) { + for (int zz = 0; zz < 3; ++zz) { + final Block block = world.getBlock(x + xx, y - yy + 2, z + zz); + final int meta = world.getBlockMetadata(x + xx, y - yy + 2, z + zz); + if (block != blueprintBI[yy][xx][zz] + || meta != blueprintMD[yy][xx][zz]) { + return false; + } + } + } + } + return true; + } } diff --git a/src/main/java/net/anvilcraft/classiccasting/blocks/BlockCrystal.java b/src/main/java/net/anvilcraft/classiccasting/blocks/BlockCrystal.java new file mode 100644 index 0000000..401237f --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/blocks/BlockCrystal.java @@ -0,0 +1,219 @@ +package net.anvilcraft.classiccasting.blocks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import dev.tilera.auracore.client.FXSparkle; +import net.anvilcraft.classiccasting.ClassicCastingTab; +import net.anvilcraft.classiccasting.render.BlockCrystalRenderer; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import thaumcraft.common.blocks.JarStepSound; +import thaumcraft.common.config.ConfigItems; + +public class BlockCrystal extends BlockContainer { + public IIcon icon; + public IIcon iconFrame; + + public BlockCrystal() { + super(Material.glass); + this.setHardness(0.7f); + this.setResistance(1.0f); + this.setLightLevel(0.4f); + this.setStepSound(new JarStepSound("crystal", 1.0f, 1.0f)); + this.setBlockName("classiccasting:crystal"); + this.setCreativeTab(ClassicCastingTab.INSTANCE); + } + + @Override + @SideOnly(Side.CLIENT) + public void getSubBlocks( + final Item par1, final CreativeTabs par2CreativeTabs, final List par3List + ) { + // crystal core + par3List.add(new ItemStack(par1, 1, 0)); + + // crystal capacitor + par3List.add(new ItemStack(par1, 1, 1)); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerBlockIcons(final IIconRegister ir) { + this.icon = ir.registerIcon("classiccasting:crystal"); + this.iconFrame = ir.registerIcon("classiccasting:crystalframe"); + } + + @Override + public IIcon getIcon(final int par1, final int meta) { + if (meta == 1) { + return this.iconFrame; + } + return null; + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick( + final World world, final int i, final int j, final int k, final Random random + ) { + final int md = world.getBlockMetadata(i, j, k); + if (md == 1 || random.nextInt(4) != 0) { + return; + } + float mod = 0.2f; + final TileEntity te = world.getTileEntity(i, j, k); + if (te != null && te instanceof TileCrystalCore) { + mod += ((TileCrystalCore) te).speed; + } + final int c = random.nextInt(5); + final FXSparkle ef2 = new FXSparkle( + world, + i + 0.2f + world.rand.nextFloat() * 0.6f, + j + mod + world.rand.nextFloat() * 0.6f, + k + 0.2f + world.rand.nextFloat() * 0.6f, + 1.0f, + c, + 3 + ); + ((Entity) ef2).noClip = true; + Minecraft.getMinecraft().effectRenderer.addEffect((EntityFX) ef2); + } + + @Override + public int colorMultiplier( + final IBlockAccess par1iBlockAccess, + final int par2, + final int par3, + final int par4 + ) { + final int md = par1iBlockAccess.getBlockMetadata(par2, par3, par4); + if (md < 1) { + return 0; + } + return super.colorMultiplier(par1iBlockAccess, par2, par3, par4); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public int getRenderType() { + return BlockCrystalRenderer.RI; + } + + @Override + public TileEntity createTileEntity(final World world, final int metadata) { + if (metadata == 0) { + return new TileCrystalCore(); + } + if (metadata == 1) { + return new TileCrystalCapacitor(); + } + return super.createTileEntity(world, metadata); + } + + @Override + public TileEntity createNewTileEntity(final World var1, int meta) { + return this.createTileEntity(var1, meta); + } + + @Override + public ArrayList getDrops( + final World world, + final int x, + final int y, + final int z, + final int md, + final int fortune + ) { + final ArrayList ret = new ArrayList<>(); + if (md == 0) { + ret.add(new ItemStack(Items.nether_star)); + int total = 0; + for (int t = 0; t < 5; ++t) { + final int q = 2 + world.rand.nextInt(3); + total += q; + for (int a = 0; a < q; ++a) { + ret.add(new ItemStack(ConfigItems.itemShard, 1, t)); + } + } + if (20 - total > 0) { + ret.add(new ItemStack(ConfigItems.itemShard, 20 - total, 5)); + } + return ret; + } + if (md == 1) { + return new ArrayList<>(); + } + return super.getDrops(world, x, y, z, md, fortune); + } + + // TODO: WTF + //@Override + //public int idDropped(final int par1, final Random par2Random, final int par3) { + // if (par1 == 6) { + // return Item.netherStar.field_77779_bT; + // } + // return super.idDropped(par1, par2Random, par3); + //} + + @Override + public int damageDropped(int meta) { + return meta; + } + + @Override + public void breakBlock( + final World par1World, + final int par2, + final int par3, + final int par4, + final Block par5, + final int par6 + ) { + if (par6 == 1) { + final TileEntity te = par1World.getTileEntity(par2, par3, par4); + if (te != null && te instanceof TileCrystalCapacitor) { + if (((TileCrystalCapacitor) te).storedVis > 0) { + final ItemStack drop = new ItemStack((Block) this, 1, 1); + drop.setTagInfo( + "amount", new NBTTagShort(((TileCrystalCapacitor) te).storedVis) + ); + this.dropBlockAsItem(par1World, par2, par3, par4, drop); + } else { + this.dropBlockAsItem( + par1World, par2, par3, par4, new ItemStack((Block) this, 1, 1) + ); + } + } + } + super.breakBlock(par1World, par2, par3, par4, par5, par6); + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/items/ItemBlockCrystal.java b/src/main/java/net/anvilcraft/classiccasting/items/ItemBlockCrystal.java new file mode 100644 index 0000000..1a8241f --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/items/ItemBlockCrystal.java @@ -0,0 +1,72 @@ +package net.anvilcraft.classiccasting.items; + +import java.util.List; + +import net.anvilcraft.classiccasting.ClassicCastingTab; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public class ItemBlockCrystal extends ItemBlock { + public ItemBlockCrystal(final Block par1) { + super(par1); + this.setMaxDamage(0); + this.setHasSubtypes(true); + this.setCreativeTab(ClassicCastingTab.INSTANCE); + this.setUnlocalizedName("classiccasting:crystal"); + } + + @Override + public int getMetadata(final int par1) { + return par1; + } + + @Override + public String getUnlocalizedName(final ItemStack par1ItemStack) { + return super.getUnlocalizedName() + "." + par1ItemStack.getItemDamage(); + } + + @Override + public boolean placeBlockAt( + final ItemStack stack, + final EntityPlayer player, + final World world, + final int x, + final int y, + final int z, + final int side, + final float hitX, + final float hitY, + final float hitZ, + final int metadata + ) { + final boolean placed = super.placeBlockAt( + stack, player, world, x, y, z, side, hitX, hitY, hitZ, metadata + ); + if (placed && metadata == 1 && stack.hasTagCompound()) { + final int amount = stack.stackTagCompound.getShort("amount"); + final TileCrystalCapacitor tcc + = (TileCrystalCapacitor) world.getTileEntity(x, y, z); + if (tcc != null) { + tcc.storedVis = (short) amount; + } + } + return placed; + } + + @Override + public void addInformation( + final ItemStack item, + final EntityPlayer par2EntityPlayer, + final List list, + final boolean par4 + ) { + if (item.hasTagCompound()) { + final int amount = item.stackTagCompound.getShort("amount"); + list.add("Holds " + amount + " vis"); + } + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandCasting.java b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandCasting.java index 9d80361..c95d785 100644 --- a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandCasting.java +++ b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandCasting.java @@ -303,13 +303,14 @@ public abstract class ItemWandCasting extends Item implements IWand { )) { result = WandManager.createArcaneFurnace(itemstack, player, world, x, y, z); } - // TODO: WTF - //if ((bi == ConfigBlocks.blockCosmeticSolid || bi == ConfigBlocks.blockCrystal) - // && ResearchManager.isResearchComplete( - // player.getDisplayName(), "CRYSTALCORE" - // )) { - // result = WandManager.createNodeMagnet(itemstack, player, world, x, y, z); - //} + if ((bi == ConfigBlocks.blockCosmeticSolid || bi == CCBlocks.crystal) + // TODO: research + //&& ResearchManager.isResearchComplete( + // player.getDisplayName(), "CRYSTALCORE" + //) + ) { + result = WandManager.createNodeMagnet(itemstack, player, world, x, y, z); + } if (bi == CCBlocks.infusionWorkbench /*&& ResearchManager.isResearchComplete(player.getDisplayName(), "MAGBLOCK")*/) { diff --git a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandExcavation.java b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandExcavation.java index 61ef48c..10aea84 100644 --- a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandExcavation.java +++ b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandExcavation.java @@ -127,7 +127,7 @@ public class ItemWandExcavation extends ItemWandBasic { ItemWandExcavation.lastZ.put(pp, 0); } final MovingObjectPosition mop - = Utils.getTargetBlock(((Entity) p).worldObj, p, false); + = Utils.getTargetBlock(((Entity) p).worldObj, p, false, 10.0f); final Vec3 v = p.getLookVec(); double tx = ((Entity) p).posX + v.xCoord * 10.0; double ty = ((Entity) p).posY + v.yCoord * 10.0; diff --git a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandLightning.java b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandLightning.java index b12d52a..f94e657 100644 --- a/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandLightning.java +++ b/src/main/java/net/anvilcraft/classiccasting/items/wands/ItemWandLightning.java @@ -147,7 +147,7 @@ public class ItemWandLightning extends ItemWandBasic { if (((Entity) p).worldObj.isRemote) { if (zapped) { final MovingObjectPosition mop - = Utils.getTargetBlock(((Entity) p).worldObj, p, false); + = Utils.getTargetBlock(((Entity) p).worldObj, p, false, 10.0f); final Vec3 v = p.getLook(2.0f); double px = ((Entity) p).posX + v.xCoord * 10.0; double py = ((Entity) p).posY + v.yCoord * 10.0; diff --git a/src/main/java/net/anvilcraft/classiccasting/render/BlockCrystalRenderer.java b/src/main/java/net/anvilcraft/classiccasting/render/BlockCrystalRenderer.java new file mode 100644 index 0000000..5b6e74c --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/render/BlockCrystalRenderer.java @@ -0,0 +1,162 @@ +package net.anvilcraft.classiccasting.render; + +import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; +import net.anvilcraft.classiccasting.blocks.BlockCrystal; +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IIcon; +import net.minecraft.world.IBlockAccess; +import org.lwjgl.opengl.GL11; +import thaumcraft.client.renderers.block.BlockRenderer; + +public class BlockCrystalRenderer + extends BlockRenderer implements ISimpleBlockRenderingHandler { + public static int RI; + + @Override + public void renderInventoryBlock( + final Block block, + final int metadata, + final int modelID, + final RenderBlocks renderer + ) { + if (metadata == 0) { + GL11.glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + GL11.glTranslatef(-0.5f, -0.5f, -0.5f); + final TileCrystalCore tc2 = new TileCrystalCore(); + tc2.blockMetadata = 0; + TileEntityRendererDispatcher.instance.renderTileEntityAt( + (TileEntity) tc2, 0.0, 0.0, 0.0, 0.0f + ); + GL11.glEnable(32826); + } else if (metadata == 1) { + block.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); + renderer.setRenderBoundsFromBlock(block); + BlockRenderer.drawFaces( + renderer, block, ((BlockCrystal) block).iconFrame, false + ); + this.drawFacesInside(renderer, block, ((BlockCrystal) block).iconFrame); + GL11.glTranslatef(-0.5f, -0.5f, -0.5f); + final TileCrystalCapacitor tc3 = new TileCrystalCapacitor(); + tc3.blockMetadata = 0; + tc3.storedVis = 50; + TileEntityRendererDispatcher.instance.renderTileEntityAt( + (TileEntity) tc3, 0.0, 0.0, 0.0, 0.0f + ); + GL11.glEnable(32826); + } + } + + @Override + public boolean renderWorldBlock( + final IBlockAccess world, + final int x, + final int y, + final int z, + final Block block, + final int modelId, + final RenderBlocks renderer + ) { + final int md = world.getBlockMetadata(x, y, z); + if (md == 1) { + final IIcon icon = ((BlockCrystal) block).iconFrame; + BlockRenderer.setBrightness(world, x, y, z, block); + block.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); + renderer.setRenderBoundsFromBlock(block); + renderer.renderStandardBlock(block, x, y, z); + renderer.renderFaceXPos( + block, + (double) (x - 1.0f + BlockRenderer.W2 - 0.01f), + (double) y, + (double) z, + icon + ); + renderer.renderFaceXNeg( + block, + (double) (x + 1.0f - BlockRenderer.W2 + 0.01f), + (double) y, + (double) z, + icon + ); + renderer.renderFaceZPos( + block, + (double) x, + (double) y, + (double) (z - 1.0f + BlockRenderer.W2 - 0.01f), + icon + ); + renderer.renderFaceZNeg( + block, + (double) x, + (double) y, + (double) (z + 1.0f - BlockRenderer.W2 + 0.01f), + icon + ); + renderer.renderFaceYPos( + block, + (double) x, + (double) (y - 1.0f + BlockRenderer.W2 - 0.01f), + (double) z, + icon + ); + renderer.renderFaceYNeg( + block, + (double) x, + (double) (y + 1.0f - BlockRenderer.W2 + 0.01f), + (double) z, + icon + ); + renderer.clearOverrideBlockTexture(); + block.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); + renderer.setRenderBoundsFromBlock(block); + return true; + } + return false; + } + + void + drawFacesInside(final RenderBlocks renderblocks, final Block block, final IIcon i1) { + final Tessellator tessellator = Tessellator.instance; + GL11.glTranslatef(-0.5f, -0.5f, -0.5f); + tessellator.startDrawingQuads(); + tessellator.setNormal(0.0f, -1.0f, 0.0f); + renderblocks.renderFaceYNeg(block, 0.0, 1.0 - BlockRenderer.W2, 0.0, i1); + tessellator.draw(); + tessellator.startDrawingQuads(); + tessellator.setNormal(0.0f, 1.0f, 0.0f); + renderblocks.renderFaceYPos(block, 0.0, -1.0 + BlockRenderer.W2, 0.0, i1); + tessellator.draw(); + tessellator.startDrawingQuads(); + tessellator.setNormal(0.0f, 0.0f, 1.0f); + renderblocks.renderFaceXNeg(block, 1.0 - BlockRenderer.W2, 0.0, 0.0, i1); + tessellator.draw(); + tessellator.startDrawingQuads(); + tessellator.setNormal(0.0f, 0.0f, -1.0f); + renderblocks.renderFaceXPos(block, -1.0 + BlockRenderer.W2, 0.0, 0.0, i1); + tessellator.draw(); + tessellator.startDrawingQuads(); + tessellator.setNormal(1.0f, 0.0f, 0.0f); + renderblocks.renderFaceZNeg(block, 0.0, 0.0, 1.0 - BlockRenderer.W2, i1); + tessellator.draw(); + tessellator.startDrawingQuads(); + tessellator.setNormal(-1.0f, 0.0f, 0.0f); + renderblocks.renderFaceZPos(block, 0.0, 0.0, -1.0 + BlockRenderer.W2, i1); + tessellator.draw(); + GL11.glTranslatef(0.5f, 0.5f, 0.5f); + } + + @Override + public boolean shouldRender3DInInventory(int meta) { + return true; + } + + @Override + public int getRenderId() { + return RI; + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCapacitorRenderer.java b/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCapacitorRenderer.java new file mode 100644 index 0000000..7273740 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCapacitorRenderer.java @@ -0,0 +1,105 @@ +package net.anvilcraft.classiccasting.render; + +import java.awt.Color; +import java.util.Random; + +import net.anvilcraft.classiccasting.tiles.TileCrystalCapacitor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import thaumcraft.client.renderers.models.ModelCube; + +public class TileCrystalCapacitorRenderer extends TileEntitySpecialRenderer { + private ModelCube model; + + public TileCrystalCapacitorRenderer() { + this.model = new ModelCube(); + } + + private void drawCrystal( + final float x, + final float y, + final float z, + final Random rand, + final int color, + final float size + ) { + final EntityPlayer p = (EntityPlayer) Minecraft.getMinecraft().thePlayer; + final float shade + = MathHelper.sin( + (((Entity) p).ticksExisted + rand.nextInt(10)) + / (10.0f + rand.nextFloat()) + ) * 0.05f + + 0.95f; + final Color c = new Color(color); + final float r = c.getRed() / 220.0f; + final float g = c.getGreen() / 220.0f; + final float b = c.getBlue() / 220.0f; + GL11.glPushMatrix(); + GL11.glEnable(2977); + GL11.glEnable(3042); + GL11.glEnable(32826); + GL11.glBlendFunc(770, 771); + GL11.glTranslatef( + x + (1.0f - size) / 2.0f, y + (1.0f - size) / 2.0f, z + (1.0f - size) / 2.0f + ); + GL11.glScalef(size, size, size); + final int var19 = (int) (210.0f * shade); + final int var20 = var19 % 65536; + final int var21 = var19 / 65536; + OpenGlHelper.setLightmapTextureCoords( + OpenGlHelper.lightmapTexUnit, var20 / 1.0f, var21 / 1.0f + ); + GL11.glColor4f(r, g, b, 1.0f); + this.model.render(); + GL11.glScalef(1.0f, 1.0f, 1.0f); + GL11.glDisable(32826); + GL11.glDisable(3042); + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GL11.glPopMatrix(); + } + + @Override + public void renderTileEntityAt( + final TileEntity te, final double x, final double y, final double z, final float f + ) { + GL11.glPushMatrix(); + final EntityPlayer p = (EntityPlayer) Minecraft.getMinecraft().thePlayer; + final TileCrystalCapacitor tco = (TileCrystalCapacitor) te; + final Color col + = new Color(1.0f, 1.0f - tco.storedVis / (float) tco.maxVis * 0.8f, 1.0f); + this.bindTexture( + new ResourceLocation("classiccasting", "textures/models/crystalcapacitor.png") + ); + final Random rand = new Random(tco.xCoord + tco.yCoord * tco.zCoord); + for (int xx = 0; xx < 2; ++xx) { + for (int zz = 0; zz < 2; ++zz) { + for (int yy = 0; yy < 2; ++yy) { + final int t = ((Entity) p).ticksExisted; + final float bob + = MathHelper.sin(t / (10 + xx * yy + te.xCoord % 8.0f)) * 0.02f; + final float weave + = MathHelper.sin(t / (10 + yy * zz + te.yCoord % 6.0f)) * 0.02f; + final float wobble + = MathHelper.sin(t / (10 + zz * xx + te.zCoord % 4.0f)) * 0.02f; + this.drawCrystal( + (float) x + bob + xx * 0.4f - 0.2f, + (float) y + wobble + yy * 0.4f - 0.2f, + (float) z + weave + zz * 0.4f - 0.2f, + rand, + col.getRGB(), + 0.3f + ); + } + } + } + GL11.glPopMatrix(); + GL11.glDisable(3042); + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCoreRenderer.java b/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCoreRenderer.java new file mode 100644 index 0000000..af13346 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/render/TileCrystalCoreRenderer.java @@ -0,0 +1,172 @@ +package net.anvilcraft.classiccasting.render; + +import java.awt.Color; +import java.util.Random; + +import net.anvilcraft.classiccasting.render.models.ModelCrystal; +import net.anvilcraft.classiccasting.tiles.TileCrystalCore; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import dev.tilera.auracore.api.CrystalColors; +import thaumcraft.common.blocks.BlockCustomOreItem; + +public class TileCrystalCoreRenderer extends TileEntitySpecialRenderer { + private ModelCrystal model; + + public TileCrystalCoreRenderer() { + this.model = new ModelCrystal(); + } + + private void drawCrystal( + final float x, + final float y, + final float z, + final float a1, + final float a2, + final float a3, + final Random rand, + final int color, + final float size, + final float speed + ) { + final EntityPlayer p = (EntityPlayer) Minecraft.getMinecraft().thePlayer; + final float shade + = MathHelper.sin( + (((Entity) p).ticksExisted + rand.nextInt(10)) + / (5.0f + rand.nextFloat()) + ) * 0.075f + + 0.925f; + final Color c = new Color(color); + final float r = c.getRed() / 220.0f; + final float g = c.getGreen() / 220.0f; + final float b = c.getBlue() / 220.0f; + GL11.glPushMatrix(); + GL11.glEnable(2977); + GL11.glEnable(3042); + GL11.glEnable(32826); + GL11.glBlendFunc(770, 771); + GL11.glTranslatef(x + 0.5f, y + 0.5f, z + 0.5f); + GL11.glRotatef(a3, 0.0f, 0.0f, 1.0f); + GL11.glRotatef(a1, 0.0f, 1.0f, 0.0f); + GL11.glRotatef(a2, 1.0f, 0.0f, 0.0f); + GL11.glTranslatef(0.0f, -0.1f + speed / 4.0f, 0.0f); + GL11.glScalef( + (0.15f + rand.nextFloat() * 0.075f) * size, + (0.5f + rand.nextFloat() * 0.1f) * size, + (0.15f + rand.nextFloat() * 0.05f) * size + ); + final int var19 = (int) (210.0f * shade); + final int var20 = var19 % 65536; + final int var21 = var19 / 65536; + OpenGlHelper.setLightmapTextureCoords( + OpenGlHelper.lightmapTexUnit, var20 / 1.0f, var21 / 1.0f + ); + GL11.glColor4f(r, g, b, 1.0f); + this.model.render(); + GL11.glScalef(1.0f, 1.0f, 1.0f); + GL11.glDisable(32826); + GL11.glDisable(3042); + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GL11.glPopMatrix(); + } + + @Override + public void renderTileEntityAt( + final TileEntity te, final double x, final double y, final double z, final float f + ) { + final TileCrystalCore tco = (TileCrystalCore) te; + GL11.glPushMatrix(); + this.bindTexture(new ResourceLocation("classiccasting", "textures/models/crystal.png") + ); + final Random rand = new Random(tco.xCoord + tco.yCoord * tco.zCoord); + int col = 0; + GL11.glPushMatrix(); + for (int a = 0; a < 20; ++a) { + ++col; + if (a % 5 == 0) { + ++col; + } + if (col > 5) { + col = 1; + } + final int color = CrystalColors.colors[col]; + final float angle1 + = (tco.active ? (f * tco.speed) : 0.0f) + tco.rotation + 18 * a; + final float angle2 = (float) (30 * (1 + a % 5)); + this.drawCrystal( + (float) x, + (float) y + tco.speed, + (float) z, + angle1, + angle2, + ((tco.active ? (f * tco.speed) : 0.0f) + tco.rotation) * 2.0f, + rand, + color, + 0.7f, + tco.speed + ); + } + GL11.glPopMatrix(); + final int age = ((Entity) Minecraft.getMinecraft().renderViewEntity).ticksExisted; + GL11.glPushMatrix(); + GL11.glTranslated(x + 0.5, y + 0.5 + tco.speed, z + 0.5); + final int q = Minecraft.getMinecraft().gameSettings.fancyGraphics ? 20 : 10; + final Tessellator tessellator = Tessellator.instance; + RenderHelper.disableStandardItemLighting(); + final float f2 = age / 500.0f; + final float f4 = 0.0f; + final Random random = new Random(245L); + GL11.glDisable(3553); + GL11.glShadeModel(7425); + GL11.glEnable(3042); + GL11.glBlendFunc(770, 1); + GL11.glDisable(3008); + GL11.glEnable(2884); + GL11.glDepthMask(false); + GL11.glPushMatrix(); + for (int i = 0; i < q; ++i) { + GL11.glRotatef(random.nextFloat() * 360.0f, 1.0f, 0.0f, 0.0f); + GL11.glRotatef(random.nextFloat() * 360.0f, 0.0f, 1.0f, 0.0f); + GL11.glRotatef(random.nextFloat() * 360.0f, 0.0f, 0.0f, 1.0f); + GL11.glRotatef(random.nextFloat() * 360.0f, 1.0f, 0.0f, 0.0f); + GL11.glRotatef(random.nextFloat() * 360.0f, 0.0f, 1.0f, 0.0f); + GL11.glRotatef(random.nextFloat() * 360.0f + f2 * 360.0f, 0.0f, 0.0f, 1.0f); + tessellator.startDrawing(6); + float fa = random.nextFloat() * 20.0f + 5.0f + f4 * 10.0f; + float f5 = random.nextFloat() * 2.0f + 1.0f + f4 * 2.0f; + fa /= 30.0f / (Math.min(age, 10) / 10.0f); + f5 /= 30.0f / (Math.min(age, 10) / 10.0f); + tessellator.setColorRGBA_I(16777215, (int) (255.0f * (1.0f - f4))); + tessellator.addVertex(0.0, 0.0, 0.0); + tessellator.setColorRGBA_I(16764159, 0); + tessellator.addVertex(-0.866 * f5, (double) fa, (double) (-0.5f * f5)); + tessellator.addVertex(0.866 * f5, (double) fa, (double) (-0.5f * f5)); + tessellator.addVertex(0.0, (double) fa, (double) (1.0f * f5)); + tessellator.addVertex(-0.866 * f5, (double) fa, (double) (-0.5f * f5)); + tessellator.draw(); + } + GL11.glPopMatrix(); + GL11.glDepthMask(true); + GL11.glDisable(2884); + GL11.glDisable(3042); + GL11.glShadeModel(7424); + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GL11.glEnable(3553); + GL11.glEnable(3008); + RenderHelper.enableStandardItemLighting(); + GL11.glBlendFunc(770, 771); + GL11.glPopMatrix(); + GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GL11.glPopMatrix(); + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/render/models/ModelCrystal.java b/src/main/java/net/anvilcraft/classiccasting/render/models/ModelCrystal.java new file mode 100644 index 0000000..11acec8 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/render/models/ModelCrystal.java @@ -0,0 +1,30 @@ +package net.anvilcraft.classiccasting.render.models; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; + +public class ModelCrystal extends ModelBase { + ModelRenderer Crystal; + + public ModelCrystal() { + super.textureWidth = 64; + super.textureHeight = 32; + (this.Crystal = new ModelRenderer((ModelBase) this, 0, 0)) + .addBox(-16.0f, -16.0f, 0.0f, 16, 16, 16); + this.Crystal.setRotationPoint(0.0f, 32.0f, 0.0f); + this.Crystal.setTextureSize(64, 32); + this.Crystal.mirror = true; + this.setRotation(this.Crystal, 0.7071f, 0.0f, 0.7071f); + } + + public void render() { + this.Crystal.render(0.0625f); + } + + public void + setRotation(final ModelRenderer model, final float x, final float y, final float z) { + model.rotateAngleX = x; + model.rotateAngleY = y; + model.rotateAngleZ = z; + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCapacitor.java b/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCapacitor.java new file mode 100644 index 0000000..cd32022 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCapacitor.java @@ -0,0 +1,128 @@ +package net.anvilcraft.classiccasting.tiles; + +import java.util.ArrayList; +import java.util.Random; + +import dev.tilera.auracore.api.AuraNode; +import dev.tilera.auracore.aura.AuraManager; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; + +public class TileCrystalCapacitor extends TileEntity { + public short storedVis; + public short maxVis; + short interval; + private long count; + + public TileCrystalCapacitor() { + this.maxVis = 100; + this.interval = 5000; + this.count = System.currentTimeMillis() + new Random().nextInt(this.interval); + } + + @Override + public boolean canUpdate() { + return true; + } + + @Override + public void updateEntity() { + super.updateEntity(); + if (this.worldObj.isRemote) { + return; + } + if (this.count <= System.currentTimeMillis()) { + try { + this.count = System.currentTimeMillis() + this.interval; + final ArrayList nodes = AuraManager.getAurasWithin( + this.worldObj, + this.xCoord + 0.5f, + this.yCoord + 0.5f, + this.zCoord + 0.5f + ); + if (nodes.size() == 0) { + return; + } + for (final Integer key : nodes) { + final AuraNode nd = AuraManager.getNode(key); + if (nd == null) { + continue; + } + if (nd.level > nd.baseLevel && this.storedVis < this.maxVis) { + AuraManager.queueNodeChanges( + nd.key, -1, 0, false, null, 0.0f, 0.0f, 0.0f + ); + ++this.storedVis; + this.worldObj.markBlockForUpdate( + this.xCoord, this.yCoord, this.zCoord + ); + break; + } + if (nd.level < nd.baseLevel && this.storedVis> 0) { + AuraManager.queueNodeChanges( + nd.key, 1, 0, false, null, 0.0f, 0.0f, 0.0f + ); + --this.storedVis; + this.worldObj.markBlockForUpdate( + this.xCoord, this.yCoord, this.zCoord + ); + break; + } + } + } catch (final Exception ex) {} + } + } + + @Override + public void readFromNBT(final NBTTagCompound nbttagcompound) { + super.readFromNBT(nbttagcompound); + this.storedVis = nbttagcompound.getShort("storedVis"); + } + + @Override + public void writeToNBT(final NBTTagCompound nbttagcompound) { + super.writeToNBT(nbttagcompound); + nbttagcompound.setShort("storedVis", this.storedVis); + } + + @Override + public Packet getDescriptionPacket() { + NBTTagCompound nbt = new NBTTagCompound(); + + nbt.setShort("storedVis", this.storedVis); + + return new S35PacketUpdateTileEntity( + this.xCoord, this.yCoord, this.zCoord, this.getBlockMetadata(), nbt + ); + } + + @Override + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + NBTTagCompound nbt = pkt.func_148857_g(); + + this.storedVis = nbt.getShort("storedVis"); + } + + // TODO: WTF + //public static void handlePacket(final ByteArrayDataInput dat) { + // final int x = dat.readInt(); + // final int y = dat.readInt(); + // final int z = dat.readInt(); + // final short storedVis = dat.readShort(); + // final World world = Thaumcraft.proxy.getClientWorld(); + // TileEntity te = world.getTileEntity(x, y, z); + // if (te instanceof TileCrystalCapacitor) { + // ((TileCrystalCapacitor) te).storedVis = storedVis; + // } else if (te == null) { + // final TileHole ts = new TileHole(); + // world.func_72837_a(x, y, z, (TileEntity) ts); + // te = world.func_72796_p(x, y, z); + // if (te instanceof TileCrystalCapacitor) { + // ((TileCrystalCapacitor) te).storedVis = storedVis; + // } + // } + //} +} diff --git a/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCore.java b/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCore.java new file mode 100644 index 0000000..6ff3f8e --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/tiles/TileCrystalCore.java @@ -0,0 +1,316 @@ +package net.anvilcraft.classiccasting.tiles; + +import dev.tilera.auracore.api.AuraNode; +import dev.tilera.auracore.aura.AuraManager; +import dev.tilera.auracore.client.AuraManagerClient; +import dev.tilera.auracore.client.AuraManagerClient.NodeStats; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import thaumcraft.common.Thaumcraft; +import thaumcraft.common.config.ConfigBlocks; +import thaumcraft.common.lib.utils.Utils; + +public class TileCrystalCore extends TileEntity { + public boolean active; + public int nodeKey; + public float speed; + public float rotation; + private int count; + + public TileCrystalCore() { + this.active = false; + this.nodeKey = -1; + this.speed = 0.0f; + this.rotation = 0.0f; + this.count = -1; + } + + @Override + public boolean canUpdate() { + return true; + } + + public void activate() { + this.active = true; + this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); + } + + private boolean isValidStructure() { + return this.worldObj.getBlock(this.xCoord - 1, this.yCoord - 1, this.zCoord - 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord + 1, this.yCoord - 1, this.zCoord + 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord - 1, this.yCoord - 1, this.zCoord + 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord + 1, this.yCoord - 1, this.zCoord - 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord - 1, this.yCoord - 2, this.zCoord - 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord + 1, this.yCoord - 2, this.zCoord + 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord - 1, this.yCoord - 2, this.zCoord + 1) + == ConfigBlocks.blockCosmeticSolid + && this.worldObj.getBlock(this.xCoord + 1, this.yCoord - 2, this.zCoord - 1) + == ConfigBlocks.blockCosmeticSolid; + } + + @Override + public void updateEntity() { + super.updateEntity(); + ++this.count; + this.rotation += this.speed; + if (this.active) { + if (this.speed < 1.0f) { + this.speed += 0.001f + this.speed / 100.0f; + } else { + this.speed = 1.0f; + } + } else if (this.speed > 0.0f) { + this.speed -= 0.01f; + } else { + this.speed = 0.0f; + } + if (this.worldObj.isRemote) { + if (this.active && this.speed > 0.9 && this.nodeKey > -1 + && this.count % 2 == 0) { + switch (this.count % 8 / 2) { + case 0: { + Thaumcraft.proxy.blockRunes( + this.worldObj, + this.xCoord - 1, + this.yCoord - 1, + this.zCoord - 1, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 0.0f, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 20, + 0.0f + ); + break; + } + case 1: { + Thaumcraft.proxy.blockRunes( + this.worldObj, + this.xCoord + 1, + this.yCoord - 1, + this.zCoord + 1, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 0.0f, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 20, + 0.0f + ); + break; + } + case 2: { + Thaumcraft.proxy.blockRunes( + this.worldObj, + this.xCoord - 1, + this.yCoord - 1, + this.zCoord + 1, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 0.0f, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 20, + 0.0f + ); + break; + } + case 3: { + Thaumcraft.proxy.blockRunes( + this.worldObj, + this.xCoord + 1, + this.yCoord - 1, + this.zCoord - 1, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 0.0f, + 0.3f + this.worldObj.rand.nextFloat() * 0.7f, + 20, + 0.0f + ); + break; + } + } + } + if (this.active && this.nodeKey > -1 && this.speed > 0.9 + && AuraManagerClient.auraClientMovementList.get(this.nodeKey) != null + && this.count % 20 == 0) { + final AuraManagerClient.NodeRenderInfo nri + = AuraManagerClient.auraClientMovementList.get(this.nodeKey); + float size = 3.0f; + final NodeStats l = AuraManagerClient.auraClientList.get(this.nodeKey); + if (l != null) { + size = l.level / 100.0f; + } + Thaumcraft.proxy.beam( + this.worldObj, + this.xCoord + 0.5, + this.yCoord + 0.5 + this.speed, + this.zCoord + 0.5, + nri.x, + nri.y, + nri.z, + 0, + 16777215, + true, + size, + 20 + ); + Thaumcraft.proxy.beam( + this.worldObj, + this.xCoord + 0.5, + this.yCoord + 0.5 + this.speed, + this.zCoord + 0.5, + nri.x, + nri.y, + nri.z, + 1, + 16777215, + true, + size / 2.0f, + 20 + ); + } + return; + } + if (this.active && this.speed > 0.9f && this.count % 20 == 0) { + if (this.count % 100 == 0 && this.nodeKey > -1 + && AuraManager.copyNode(AuraManager.getNode(this.nodeKey)) == null) { + this.nodeKey = -1; + } + if (!this.isValidStructure()) { + this.active = false; + this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); + } + if (this.nodeKey < 0) { + this.nodeKey = AuraManager.getClosestAuraWithinRange( + this.worldObj, + this.xCoord + 0.5, + this.yCoord + 0.5, + this.zCoord + 0.5, + 24.0 + ); + if (this.nodeKey < 0) { + this.active = false; + } + this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); + } + if (!this.active) { + return; + } + AuraNode node = null; + if (node == null && this.nodeKey > -1) { + node = AuraManager.copyNode(AuraManager.getNode(this.nodeKey)); + if (this.count % 80 == 0) { + AuraManager.decreaseClosestAura( + this.worldObj, + this.xCoord + 0.5, + this.yCoord + 0.5, + this.zCoord + 0.5, + 1 + ); + } + } + if (node != null) { + double dist + = Math.sqrt(this.getDistanceFrom2(node.xPos, node.yPos, node.zPos)); + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + if (dist < 0.2) { + this.active = false; + this.worldObj.markBlockForUpdate( + this.xCoord, this.yCoord, this.zCoord + ); + x = (float) (this.xCoord + 0.5f - node.xPos); + y = (float) (this.yCoord + 0.5f - node.yPos); + z = (float) (this.zCoord + 0.5f - node.zPos); + } else { + dist *= 20.0; + x = (float) ((this.xCoord + 0.5f - node.xPos) / dist); + y = (float) ((this.yCoord + 0.5f - node.yPos) / dist); + z = (float) ((this.zCoord + 0.5f - node.zPos) / dist); + } + x = Utils.clamp_float(x, -0.25f, 0.25f); + y = Utils.clamp_float(y, -0.25f, 0.25f); + z = Utils.clamp_float(z, -0.25f, 0.25f); + AuraManager.queueNodeChanges(this.nodeKey, 0, 0, false, null, x, y, z); + } + } + } + + @Override + public void readFromNBT(final NBTTagCompound nbttagcompound) { + super.readFromNBT(nbttagcompound); + this.active = nbttagcompound.getBoolean("active"); + this.speed = nbttagcompound.getFloat("speed"); + this.nodeKey = nbttagcompound.getInteger("node"); + } + + @Override + public void writeToNBT(final NBTTagCompound nbttagcompound) { + super.writeToNBT(nbttagcompound); + nbttagcompound.setBoolean("active", this.active); + nbttagcompound.setFloat("speed", this.speed); + nbttagcompound.setInteger("node", this.nodeKey); + } + + public double + getDistanceFrom2(final double par1, final double par3, final double par5) { + final double var7 = this.xCoord + 0.5 - par1; + final double var8 = this.yCoord + 0.5 - par3; + final double var9 = this.zCoord + 0.5 - par5; + return var7 * var7 + var8 * var8 + var9 * var9; + } + + @Override + public Packet getDescriptionPacket() { + NBTTagCompound nbt = new NBTTagCompound(); + + nbt.setBoolean("active", this.active); + nbt.setFloat("speed", this.speed); + nbt.setInteger("node", this.nodeKey); + + return new S35PacketUpdateTileEntity( + this.xCoord, this.yCoord, this.zCoord, this.getBlockMetadata(), nbt + ); + } + + @Override + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + NBTTagCompound nbt = pkt.func_148857_g(); + + this.active = nbt.getBoolean("active"); + this.speed = nbt.getFloat("speed"); + this.nodeKey = nbt.getInteger("node"); + } + + // TODO: WTF + //public static void handlePacket(final ByteArrayDataInput dat) { + // final int x = dat.readInt(); + // final int y = dat.readInt(); + // final int z = dat.readInt(); + // final boolean active = dat.readBoolean(); + // final float speed = dat.readFloat(); + // final int node = dat.readInt(); + // final World world = Thaumcraft.proxy.getClientWorld(); + // TileEntity te = world.getTileEntity(x, y, z); + // if (te instanceof TileCrystalCore) { + // ((TileCrystalCore) te).active = active; + // ((TileCrystalCore) te).speed = speed; + // ((TileCrystalCore) te).nodeKey = node; + // } else if (te == null) { + // final TileHole ts = new TileHole(); + // world.setTileEntity(x, y, z, (TileEntity) ts); + // te = world.getTileEntity(x, y, z); + // if (te instanceof TileCrystalCore) { + // ((TileCrystalCore) te).active = active; + // ((TileCrystalCore) te).speed = speed; + // ((TileCrystalCore) te).nodeKey = node; + // } + // } + //} +} diff --git a/src/main/resources/assets/classiccasting/lang/en_US.lang b/src/main/resources/assets/classiccasting/lang/en_US.lang index 0100a9f..d8009a8 100644 --- a/src/main/resources/assets/classiccasting/lang/en_US.lang +++ b/src/main/resources/assets/classiccasting/lang/en_US.lang @@ -19,4 +19,6 @@ item.classiccasting:wandTrade.name=Wand of Equal Trade # ---- BLOCKS ---- tile.classiccasting:alembic.name=Arcane Alembic +tile.classiccasting:crystal.0.name=Crystal Core +tile.classiccasting:crystal.1.name=Crystal Capacitor tile.classiccasting:infusionWorkbench.name=Arcane Stone diff --git a/src/main/resources/assets/classiccasting/textures/blocks/crystal.png b/src/main/resources/assets/classiccasting/textures/blocks/crystal.png new file mode 100644 index 0000000000000000000000000000000000000000..724852a6b3a04464d1820b9a71e8e900508ddb2d GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`>?NMQuIzW21vxbJb-v0J0);pW zJR*x37~~FuFyrCOkYJ!7OS+@4BLl<6e(pbstU&%_PZ!6Kid&_V8~IucIGoLowo;?jOFY#-|ww^9aZhJMpfSW{AR(~Gjnfmo5povVVUfS zFKZJT{_tGh&-%ok^P2fgRxg9}Psb(7S&L5eSWZ|qdHoKqCAI}~^be+pbC_7No6M`Q z4P`#7mDTjCjPq#V{mHrv&)>gQd7#;NnS0^niIxr1x{s;qWxf4f7hDk6P{3Kg^^LjB zy;hgl9l>R9`J7!tk1XwWuDo!-U7bB$HECx@o?k21+`Jzxp-b;a{bqlq|DJb+ozZpO jz3}#>@Z{5(}lZ6UR1ZOWiTIByn`-_wL=R zUY?&~s~7nA{KDvFR28u9J1j)tW)B}cTCMZD^B%^Iu;YY>n@c2~jFW@skHg6T5g2w` z_!zKV^(4)heZYwXsZ|!BKKib~nOEIk4Y6-EUfJNh+0!#R5uI6cNa(Z#e5vEMUhO zAmbB{brqcDs9z~{j8UL zHs)kT#nOO000SaNLh0L01mhVxCH!+5T|&u{h_b94KB zxt0Fk0N~tymUf*&90Wr&l8p4iECA)X%^&hzz-x0Sz{h8#AqM8>d0v?wHs0@JBB-_*2AJ#tV0q4b zY(9IybhG{b-sf!!0EC3#{F?YMZrcqrVE~B_`@fJlpm5LnsuB2#%>l^3ZXpUFDieSZ z4KaXx2XI^f%RPJKU4~6*GXNkaj36o7x{1znG$4QhmK_`#;SlIBXp`|Cn*xAsLL`pR z8i8~p`2cV&&Lib$h&2dcGw<~VZc_jp_I%a(5FQ3_b`F*P&dw2lk$9XaQNw3!4nPJ( z+kP`hj*yuBK~$c^24-u*^Yrwzo|QR5E)iyP00>>EImF`&LNJUgfw@@kOs{GLeguG+ zbI!3T02PRgn$vS1AR=`J5_c%X{+(as7Y*Xu-$;Uf4FG3>Fq#1qAwH%6P+n)|e~R_l z4*)Frea;2!pAv?!Ua#9VQ<~8xm_;oA} zt(e=Im%+fX%`Xmv0A4SmO{1^(0|u~bKLH^U{7#EJj*L&{A|b zYu8~A-TMJ(hqJkWLU?3erb0d6&!>1Yvo@n4xmC*T8_cHn6C6V69OWEqGW!o+4-<$& zuwyv3OC!Unr;!fIcyZV6xsS?W%Yf)`2FTTSpfwi6wNg0GKA-jWIdxzTJ-YA$9gl18sjHh-Z2MFhn}bv%NpRfM)@qK^Bsu1_0Kki!~45a?y~f5~uuRRP|xL z`UT(D5EcT0cm~=~L3E$s!b>ZP#5dt*oD)DlT3o|# z-+)1G;^@NJt`F2Yzi_5Cx$1d>k*%Fw1Hs`=b6Hn=_paV*;}a)TTj$m3Iff(Yl*WWq z{|Dg;)Az1U^F5&1FH9f^($3l(4eX)u3B+5kt?FvP92sgCiLeE6Fj!+b`(l>073WaQ zJHWI<&xlidrl;nsu>(?Gzxc z_3~`P&c5t7+|0ma>Yphl%KKJlhF18S8j*hLEmjBHX-rL>!p3c@y15BPV$|aU;n@e6 z=-Stpf0;)wq4xuvVG=fpGz`ukxx{)t{RnG9b--xZs9rnGDaivsB0;am9r~=|Mpy{; zdVZ+mTF?96A={rL&5%f5P6N1$^|i6;_0qn6{_ymDy`zc!nd=n&3l+gne*w~YToCZ! R4v_!=002ovPDHLkV1fu)_38is literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/classiccasting/textures/models/crystalcapacitor.png b/src/main/resources/assets/classiccasting/textures/models/crystalcapacitor.png new file mode 100644 index 0000000000000000000000000000000000000000..7e286e300352eb7d6cdd46d9651d7b265b779a14 GIT binary patch literal 8393 zcmV;)AU5BLP))goF{!{DfQK4!#l07(o~iV1z@XjWq7=?#}-_ zE4(NByMj%^PAXNkYcKn`tyNnsX1=bw?z+u?|NZx3yY04H?7#p1i> z?6Ac*-+Z&!YOAdlpMCb(;+J238Sj7m@yB>(`|Y=1eEs#;i*2^qW^vR}M~(L1efQns z*I$1f?_Rs?vdie}#~*)OY`g8YizAOba`EY>pDv8&zL$QyYk$x|2aW#TefQnP-h1yo z`akf%0~b5&u)`Spop;_@{Q2jfV@}!`++6d%y3t+in9vC!c)s7#HG>Ip&zf z@4x@P*l)l6#>;&~28pk{^2%tBAbmHMe%7vCyLkQe*B76E{`r_MqS5ZFuf7_ejf^k`1gU55);A#km zOdN^h<4FAixV|9Oy&rz~VSLsW;y(D`gMl>2i3oSvX{W^(UwpB6|NZwzTb~h!asBSI z`-dNX_~MX54jFUM56Pu(Phz;PyVeBOEI4Nj+T-2-HR-*LwsM;{-4 z_~H0n{}ALJalU^2`o&XEJvCH-z7dD^+Cee`y8r(Bhjc+`RLpV59XHzJVq@TZ{X(FZ z&q*d~z<2hBdAis(+8f6@5wmvsoBNub0B*kd<^k+8&NyQL4v-)U7r*w}Ym3dBHxDj_ zO!puf!2lu=i>nX;af(|38sTI^cm^kC___4)*kg|^Hf`Fp*m>uj2ZBB88Jz61HaK5@ zK0`Y7Kq~o+aI`mfdLA+p^PWe*t%L2+T#fhAOD`?ne*5k5eeP>^0&wAMK*W6r08jyv zk>oerLPbEpsi&U0Di!E*$jFkMd09*kO07L=+IB^dV^tF5Ra|H6_lTR+5fByNwaS;lsfh)B` z6zOV2;_?h6{@ ztCn|w*o;x12!fSwEYBpBi2vL{{UQpI!JMa3fdnE&^m)Jm2aGYy$vXl@NONDa6F}n9 zJKz8^0OAf@$5>joZruPl4x~Q;KJG#cfDN$-NIz5xPK3}@L-!E`z~{^7`W40V8R84x z)HdSLz9=HqLSncOfbqQ}ifN=#Kh}om*dp$wLgv1f=AOWcQMa7P#2FBWb07gia1T)q zco}p6tqo4h%I`a3;3Y&PxD)cUb+4$P{*xGfcOfRaJZ~go$cRG}Mg3gvopsh(!_9La zQr~>@&G8#U)jScK`{t!j?-2&V+OlQK|IG>i*^NNR_KG`l2?IKd9UzHP5`Y_qbA0!X zBl+B(hadqR1OxdYJIR7Gvk~-Nm^VAXb6(jT`beE1Mu_$s$q|9EM~Vs>!|$F=yzAE( zzPs-k$VUv++uYaeDgeMruw>omW_gEL{yl(G2Y?Pa#5oa+`ypCCf<=A{_?`iLNO1WK zQN*@q5S(^C>j!bTm&ivXJ{w!VqKPCFBJsVTP+kF5hVwl~a+$xEwLy3iEaW5Rxv$wJ z06^hvzy}z?7w%Tv0{HYkU}bdSd;k}xhs?L$dTSs>8{8;i6E{P?dys^9NDKr+Qiv9k zE`Ea~gobFu_l1%XLr5#U%e6CJDhY!1BYKGd*#N@5=0$p$10q3Ch{^cu8PbHhnfsbu z0^mHrB90*+vJ&my5eB`PJLd8{WZ^UjfeggApmQEbY4w%L`2FXkZUmaxv$v?fCwfw0Ss3{2u@*; zd1qWf=G2gbeD_HX&)`u*&Ji?0&0dAZuJZ#xQP4m2%df9kw*rR6_+nigu9IonFW{-oxaTJ{PWKrl7wj2 zH^Qs{rFcT#gR3}4YbjMd_cc2KK!%t*(O>mWd42#)7pD%g?DNCB2T1^{KQBm0M{AEb zO2i~hd}cpXg+zQqQWZjZ2M90jhj8QZG>Cd>W&J>A>EiMY1$^|4pb#VC$Y?D9^`9ny zknJj;570&8e9zDK9RL9|AG`cNq|ng-3o#Iz`xmizFCOnIRcj8cch4~35RK2cUw`IP zu*y3zZysDf?Rz0Qb0rCSjUPyn)J%a#GesSAd4>16tz zUIyTdw8U(+gNaw%={ffS-i2uNm-UUnAcN6od{U!gR5pgobNWdCn+p|E;41Z$HIKLo z{T4N>%Gvm}^W49I`^TK;o&ezDT!6w=ke}WJ@QOMrvyNkX2BO{PLh`Hot^7Qx!hIuU zvIh`dIv&CqYK4a(2?8U;+EnyW9HIJw0#=Bi%4P&xskzVE$PtwALIl$s#GKdc1WVHSrA*rv6p8f00cquXoq0f0NVNN%4^UMLiC%tR9G^tCom2bMFJQ@C>sGF zQ2kRcsS#XH8dZ!s_cc2K2m)1j5n@CBG@#>xXhvN|A*9f?1&X+3j5s3SeMpGoglzK? zD#q}xFG(eKL(k-C#HHzZ#8fcKoKjr{qu3I>0M9{uhM{#K0CO)JhzPA=?rU}efCSu> z+XUbcU0ff)0(?eZUO;}eD>sljfCz-3KkXpPXC-C`BV-hYb|DA^Wc(6Shyx+wSaU41 zIL#3hLol{EL=-NF&saoU>=FG@2NCVu*X#r!ir0QW?{qGpR_WuyEf9{I01gm~yB8`h zM^H{4!VvlHb949?IE9Z$!PQ) zGAq}Hu)@tg7aWSy+x$_@KZG||{kFx-+&oj-U02A|V!7A07h%Q;F~zl1#fxYdc7CIt zNEPad;cA{P$Thw>`OPz_llCFz*;IIuL&OE}kVbSDO3pi|_(NOBCt0|D5LWEI7(f+Fg>(yB8^2^wDebC<@+1(_ zz4zYxuTTM7-EhMVn@zqd79x&F(h3a-ebLkfUHqBa)S&K>~QpM|%R zx8#cFv$o9vmq3oWl*cbgM3)Cl*3op~7M({5#Rv3|ceIUB_K+752)7=(l|W-jS8vKS7`(ONqI zW4hH$Ce>W3a`q~tI)#7b?CpCnhv7+Gdg-OZ2S!~Uf?Sl>e)>+fV1%I_m(B~Uv`w0{ z$cW1_Hi4>n+H$2|h%pHZyyTKg7B9T;!sr)~=>xJYv>i7-3#FQ0MVA2pup(T@?{Emf z)ZTlgVWoLf8=iGA#Iw&nyJ|odxdUv$A?*;r9e3O@+Jg_G!!T|2@{BPMjCOH;=K>g~ z`UG_cO3AGs!>E9kQEZEQoLNWjww+?s1`VM2Ofdyj;A6sItvwFb~fqHLCM}=9y>I2CT#_ zN-$;Lw5L%U5|28st`hN)bmp7nTe{|&YnA~FbxMk~mDyk@#$o}S=*-nZ{gpLCfLBG4 zCQ)g1_CO`qiAkJ9yys5o&qNVPb@(_QAp#l|g9t3FZDECkI}*mis^TrBtp7sE1!>a# z7hG_`0C<~CD;}-L)Y{FhT17-_jOzKUDbJ;S3+4-{E-*2ds*S)S1JR)t3Sl4%ae%ub zQ4#=Qrrydb7SqsQUX6Y$ZPQOj;Nl3NI$(tyiB2p?M-eFwdYP?MSMJ9(rgnPJ0(yw{en4#W~XZ*#_2G{$t73 zEDHi?4K22Vk4nN2MHb{Y;;YRRvR;7LuG{Pai!-sfp^22ZsVdh6uqLFB{PKVpW#f`K zO*|l7-Yy`&mGvWX1BO21%=Y5B4~S(7t2PE?XAdMrvSp|PFUWzcqz(czw(m*4Qoq?J zU`Op~pEaKhr3a@=e0vb zqyZo*7>Q`6N5i?yBX7Zd#L_WtZ7p{Jq_wo2-24!dHCDB29k|nPNx13(IxVC_DVk3a zL@xwR>a;6J-{ziL@x8ROIeNZwbA6IXs+GI%DrMeY2}sW^@35@Akq*>|5!^FQ_7Mio z##vf%W0o^)rtXD@i6#`BOQBA*km(4?tP&u8KsHVCGxSKd(od3QOYFR1=ObPS9LBMWhH~ zVdK0Uu<8J*5=K=CmsEn(xLtpw(P^ihw(2oe2os(X^Ci$ak1%_SLJLoiV8TV;wiE1w|32%P&xbQA&rSieH9Zhmreq~g(M0< z(S-pwab9k}3&0T7(@#IWx*s5-N;)8}vUDK|LOcuD2q#@>PSjyWS-?-Sbnp~WTtdkj zsw0e8It#I!1u5GuVXw{=XqPnjnum(z0$LHcd9b5W&t*hYw|QNDr-~7Dxrx+UL_O*w zSFHKvcHmeH!@{7QV&!wkote16h3}A~!zyjOSi6aJM3muza7@4=N{V;^iphJ1a(NG-ykrZ*%2@#gmEhx4LNbW#S*`Ce`B>*Amb=$RXJHFmnQnP2cJBleDUTM zXOWoJX^a9+#;H2F@vXl|UK>>}zx?t6*L?X@P}|b`oKae4)O;~a3}t==qI@q4Y7JnK zDj5fFty{NlIqTViEi!`(655Da8Z({ODVPjF6G$X=ylcm`8C1IrtBN2hyV9>PrAQn7 zkMjLi(S=JN#91X{)4hX$jc7X@N*nhwe5$@hcol6FT8>l9NkE3}fpDi1r85GnMv9Bm z@8vDbFG5SyCfN$$G^fraN&;9f#zLU_>mRrI0ct9ml9n8?tsklgV zj7w;&EZqpeLJ+2jC)%^Zjb9LNqtVZ(d9GNv>hL zfb?6y3j#9=-Oq5YdZ`E}WEQkBkFuQ|d8@xX9P0qD4y|a5IwP@j3d=}FbnThw?8T%R zMl1YVjAzs>tRQ^3!w?GlqAuS}wh3#T5dz75FPqn)%uU)Lxs16U76$2sW2qEGM$|L* z^jQg3hGF`*#7Kb5?SUjObMnk|!)2V8s>lMyv2EjOZ=bP*rOVVAtHfA_p7~j0CyvoB>Lxhb1agYbS#w}=Xd;Fa41rkA>6ZwsN6#;I~O$@ zN4x_Zxu#1iqGuV>S+XW((H2@hdzy|d;#X`s0}3&CwlHj#wfmmWNSmIOgLvd1DyuGZ zseMTlpQp#SBwk4oueMv~R+SA*7bl)8%FtgN2=R31^n8MVnJd{m+Im(bu{ow^iyUU@ zd&c;cx#cc*CIN|s&;)&qV@|lSxgzMQr1KC`d0wPPgjMx&Q9x}y!!}EOwilse^^Aoe zsoXUX5=Bf8XihB@u`1u3uUZMW!2(v1wOpDGd5TL+&NK8~XY3lETVsrlaPKsaVg!Y0 zE8%WGU+4PehUODDR<2nwhiVF@CzC-UuIbc{&LB#}7tXE_wd6|@#(2281EV{+jGn&w z>Z=#`-FM%r4vw?+*Y>dN2jdq;&rnTTRw-T43wUDys-pS_aOkx4B(5>^OEPtm8aNbs z9;x!1Zn|lCZ+?ozmVAG z4Fp(VYnla|7Q+~u+APr1zQ2rL{b!vgeZYg1EhyyPwbx!d2rxB(0A(#ZgrbC5sp1M) zio2Lsg*0GTMK$TtarQ-2!)pgzj^dh9wj~wHw6!Ix$(jH|$-;`$v)p~APqk?yhs#8! zn2L^_6tb9%x3*g6d3e#=oxYiWjA#?xac^914Y{DkO)|t`1#cjeIw7t* zlPHzftLkL>+gdwGv`QUouxr}*p(;gF5qJ{xG7ja|*B{?**prULQMwaKMr^;v*5`_$umUuNtdMxRI0waPX z07}nVC5|i{^|lvKKZR`Lgj4}zs~x`~G$RopA=G>;iOOG}ZpfTk#>6B4-?O*he*2I> z*&a!+f+^FaQ?dBs7S;>k0e4#L+E%xYi|=o6Ds}~T{~-Vtj;gPcDUYTz336?#Pbk9~ zfu=eN2(?YU1FZ8LI&*0lvn!Op%!P@f0l%zkws)$e{r>mdbI+Wl z=#wJ3hlO&hm&{5pom@)1EL2IQ7@+- zh$ZDwbb9Vzlg6QOXHmiQRF%4bLX?(tDFs{!na_o16Vrf^VTS7wR^qAS+EYb&BDp-B z^HbYgua1{5Ctj+x5O%Q!7mllDKlgWfDw*~9J$+yCX^76x?oi4Iv3Px3)N<*H(^uXO zp^5IozA;`dXHv7QV2QBeFVo^rzcXktbwNAhXZz&hb}g+uyqs7leL4kD`Rf3ZCE1?+ zEbjnPRWEgr`;!aQS^E8xR^drhnyN^jd!@V5!^I-XG&aX9{{Hz3@JW@#=2RV|TXU^) zJ+suOvHGc$2$%&`rg}avrM!n{5e(acjS#`Mmg)IH#`kRZ%TXk@vtbIrh4j3Nl48>n zO&NqmNGn&bhOs2m>S-zJ0ZLm!LK8^5ghU*MicHu9+-h^Z;7&sWFIB#L@mjDy3Y8_JEynS4JG4zrM;ROgGZ#m*h1kYnRW-Q19%- z)KNJZL^}#yRwlcg&Mn`cUg=*t@|)wRYUc{?=I=+1H{N*TY8Efoak>GtqJ^y7PU+0w zMMNcB;sz7$h_&hsi{}@NN;=>=9*P&h0%m!HX$5mG?sUg*g%bV0K!;V84a`kTuNDcd zu+-7^`luYcfEj5v-2#`G@2_a4g{kH3i~dEJZEP)oRVFj$N^12#1qg*}ofN3=w#g3( zuyNzYMf{ee@dT@%bO>)gNm`BX>g(rGQ8fKu^&_D83I6bWmi zh=`fgas84QW%jZgGJdKnh^RbEH|8=G%H@7$BTSP3Hjz((nMA#b~O1iaOvgj2gH`ahX9K^ z6p0KGMG!k%P~Qj*0SF^&kLcQ#mD?3(bi8|FGwIg8h30Q9)!?_i3rt9zto1}~Niuz9 zAN3ET`k3bbW2Own>M1fh+l^dKKSMK#Q>9kV7o)K@>H$1DseEZ=QOlinm5~O>?qv-J zq>39l;iA&(sJAv%_?8OoB<;$f1H5)NMU?7P$~8TjEw|1b+7ez!GXrS)hf%4EfYC{! zA=lcdg$y};2>i4Ys(vG|j+3n-dK#q4{wa3iz5GI(Pp4H${UK$lwnHMUxnNF2kSCQL zQe|~Me|V{UE?2Z|X&I0e`c#NR+K~X(*H*JN89^4%A0>qFD8I?I<+{R<#9}*R(@*-a z2>M#P^!v0pG?&ID_Ao6Vt!kx;7Hvs}^m)=KH?_q~|NqC>2*7+Hm^e;MnnNdtSDK|y zC23XFREb-L|biLLVB9mz40+LJuJe8A~Q?6+Nn@%vvNQJ!9*WzXZM>vrhiIR*x4G|TvLHf_DC@f9!m3`?ze2WaYy1BzjUsCxx0uLVzWz< zlx1!!mTmpjFO)?E8&Yabg@uVzBG$x(NK08x|6;9^J2OPmwG|wco{Y0PzrR0V=mbxI z%jfSf$Gi+W3itLu!S0tl$+|AJT8ttNs^${?@K#dU1pH#?mDDP4HqvF-pUe!?l z0-B`EEe^ohNU6P=$7g?yQ8o fh>XCFv+@2v%qBm%BGk<~00000NkvXXu0mjfE(zlE literal 0 HcmV?d00001