diff --git a/src/main/java/electroblob/wizardry/block/BlockImbuementAltar.java b/src/main/java/electroblob/wizardry/block/BlockImbuementAltar.java new file mode 100644 index 00000000..4777d38a --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockImbuementAltar.java @@ -0,0 +1,168 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.registry.WizardryBlocks; +import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; +import electroblob.wizardry.tileentity.TileEntityImbuementAltar; +import net.minecraft.block.Block; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.PropertyBool; +import net.minecraft.block.state.BlockFaceShape; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.InventoryHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import java.util.Arrays; + +public class BlockImbuementAltar extends Block implements ITileEntityProvider { + + public static final PropertyBool ACTIVE = PropertyBool.create("active"); + + private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.75, 1.0); + + public BlockImbuementAltar(){ + super(Material.ROCK); + this.setBlockUnbreakable(); + this.setResistance(6000000); + this.setLightLevel(0.4f); + this.setCreativeTab(WizardryTabs.WIZARDRY); + this.setDefaultState(this.blockState.getBaseState().withProperty(ACTIVE, false)); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer(this, ACTIVE); + } + + @Override + public IBlockState getStateFromMeta(int meta){ + return this.getDefaultState().withProperty(ACTIVE, meta == 1); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(ACTIVE) ? 1 : 0; + } + + @Override + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){ + return AABB; + } + + @Override + public TileEntity createNewTileEntity(World world, int metadata){ + return new TileEntityImbuementAltar(); + } + + @Override + public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){ + return false; + } + + @Override + public EnumBlockRenderType getRenderType(IBlockState state){ + return EnumBlockRenderType.MODEL; + } + + @Override + public BlockRenderLayer getRenderLayer(){ + return BlockRenderLayer.CUTOUT; // Required to shade parts of the block faces differently to others + } + + @Override + public boolean isOpaqueCube(IBlockState state){ + return false; + } + + @Override + public boolean isFullCube(IBlockState state){ + return false; + } + + @Override + public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face){ + // TODO: Change this back to how it should be and give receptacles a special case for attaching to the altar + return face == EnumFacing.UP ? BlockFaceShape.UNDEFINED : BlockFaceShape.SOLID; + } + + @Override + public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos){ + return state.getValue(ACTIVE) ? super.getLightValue(state, world, pos) : 0; + } + + @Override + public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighbour){ + + boolean shouldBeActive = Arrays.stream(EnumFacing.HORIZONTALS) + .allMatch(s -> world.getBlockState(pos.offset(s)).getBlock() == WizardryBlocks.receptacle + && world.getBlockState(pos.offset(s)).getValue(BlockReceptacle.FACING) == s); + + if(world.getBlockState(pos).getValue(ACTIVE) != shouldBeActive){ // Only set when it actually needs changing + world.setBlockState(pos, world.getBlockState(pos).withProperty(ACTIVE, shouldBeActive)); + world.checkLight(pos); + } + + TileEntity tileEntity = world.getTileEntity(pos); + if(tileEntity instanceof TileEntityImbuementAltar){ + ((TileEntityImbuementAltar)tileEntity).checkRecipe(); + } + } + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState block, EntityPlayer player, EnumHand hand, + EnumFacing side, float hitX, float hitY, float hitZ){ + + TileEntity tileEntity = world.getTileEntity(pos); + + if(!(tileEntity instanceof TileEntityImbuementAltar) || player.isSneaking()){ + return false; + } + + ItemStack currentStack = ((TileEntityImbuementAltar)tileEntity).getStack(); + ItemStack toInsert = player.getHeldItem(hand); + + if(currentStack.isEmpty()){ + ItemStack stack = toInsert.copy(); + stack.setCount(1); + ((TileEntityImbuementAltar)tileEntity).setStack(stack); + if(!player.isCreative()) toInsert.shrink(1); + + }else{ + + if(toInsert.isEmpty()){ + player.setHeldItem(hand, currentStack); + }else if(!player.addItemStackToInventory(currentStack)){ + player.dropItem(currentStack, false); + } + + ((TileEntityImbuementAltar)tileEntity).setStack(ItemStack.EMPTY); + } + + return true; + } + + @Override + public void breakBlock(World world, BlockPos pos, IBlockState block){ + + TileEntity tileentity = world.getTileEntity(pos); + + if(tileentity instanceof TileEntityArcaneWorkbench){ + InventoryHelper.dropInventoryItems(world, pos, (TileEntityArcaneWorkbench)tileentity); + } + + super.breakBlock(world, pos, block); + } + +} diff --git a/src/main/java/electroblob/wizardry/block/BlockReceptacle.java b/src/main/java/electroblob/wizardry/block/BlockReceptacle.java index d57faa5d..25ee0585 100644 --- a/src/main/java/electroblob/wizardry/block/BlockReceptacle.java +++ b/src/main/java/electroblob/wizardry/block/BlockReceptacle.java @@ -141,7 +141,6 @@ public class BlockReceptacle extends BlockTorch implements ITileEntityProvider { if(!player.capabilities.isCreativeMode) stack.shrink(1); world.playSound(pos.getX(), pos.getY(), pos.getZ(), WizardrySounds.BLOCK_RECEPTACLE_IGNITE, SoundCategory.BLOCKS, 0.7f, 0.7f, false); - world.checkLight(pos); return true; } @@ -157,7 +156,6 @@ public class BlockReceptacle extends BlockTorch implements ITileEntityProvider { player.dropItem(dust, false); } - world.checkLight(pos); return true; } } diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index 903d25ed..2aaf2a01 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -20,10 +20,7 @@ import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFa import electroblob.wizardry.client.renderer.entity.*; import electroblob.wizardry.client.renderer.entity.layers.*; import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect; -import electroblob.wizardry.client.renderer.tileentity.RenderArcaneWorkbench; -import electroblob.wizardry.client.renderer.tileentity.RenderLectern; -import electroblob.wizardry.client.renderer.tileentity.RenderMagicLight; -import electroblob.wizardry.client.renderer.tileentity.RenderStatue; +import electroblob.wizardry.client.renderer.tileentity.*; import electroblob.wizardry.command.SpellEmitter; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.data.DispenserCastingData; @@ -848,6 +845,7 @@ public class ClientProxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStatue.class, renderStatue = new RenderStatue()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMagicLight.class, new RenderMagicLight()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityLectern.class, new RenderLectern()); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityImbuementAltar.class, new RenderImbuementAltar()); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/model/WizardryModels.java b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java index 4b6c1991..cb776c61 100644 --- a/src/main/java/electroblob/wizardry/client/model/WizardryModels.java +++ b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java @@ -89,6 +89,7 @@ public final class WizardryModels { registerItemModel(Item.getItemFromBlock(WizardryBlocks.dark_oak_lectern)); registerItemModel(Item.getItemFromBlock(WizardryBlocks.receptacle)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.imbuement_altar)); // Items @@ -314,7 +315,8 @@ public final class WizardryModels { IBakedModel original = event.getModelRegistry().getObject(location); - if(location.getPath().contains("runestone") || location.getPath().contains("runestone_pedestal")){ + if(location.getPath().contains("runestone") || location.getPath().contains("runestone_pedestal") + || location.getPath().endsWith("imbuement_altar")){ // Ends with to exclude inactive version event.getModelRegistry().putObject(location, new BakedModelGlowingOverlay(original, "overlay")); }else if(location.getPath().contains("spectral_block")){ event.getModelRegistry().putObject(location, new BakedModelGlowingOverlay(original, "spectral_block")); diff --git a/src/main/java/electroblob/wizardry/client/renderer/tileentity/RenderImbuementAltar.java b/src/main/java/electroblob/wizardry/client/renderer/tileentity/RenderImbuementAltar.java new file mode 100644 index 00000000..aba26a17 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/tileentity/RenderImbuementAltar.java @@ -0,0 +1,138 @@ +package electroblob.wizardry.client.renderer.tileentity; + +import electroblob.wizardry.block.BlockReceptacle; +import electroblob.wizardry.tileentity.TileEntityImbuementAltar; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; + +import java.util.Random; + +public class RenderImbuementAltar extends TileEntitySpecialRenderer { + + public RenderImbuementAltar(){} + + @Override + public void render(TileEntityImbuementAltar tileentity, double x, double y, double z, float partialTicks, int destroyStage, float alpha){ + + GlStateManager.pushMatrix(); + + GlStateManager.translate((float)x + 0.5F, (float)y + 1.4F, (float)z + 0.5F); + GlStateManager.rotate(180, 0F, 0F, 1F); + + float t = (getWorld().getTotalWorldTime() + partialTicks); + GlStateManager.translate(0, 0.05f * MathHelper.sin(t/15), 0); + + this.renderItem(tileentity, t); + this.renderRays(tileentity, partialTicks); + + GlStateManager.popMatrix(); + } + + private void renderItem(TileEntityImbuementAltar tileentity, float t){ + + ItemStack stack = tileentity.getStack(); + + if(!stack.isEmpty()){ + + GlStateManager.pushMatrix(); + + GlStateManager.rotate(180, 1, 0, 0); + GlStateManager.rotate(t, 0, 1, 0); + GlStateManager.scale(0.85F, 0.85F, 0.85F); + + Minecraft.getMinecraft().getRenderItem().renderItem(stack, TransformType.FIXED); + + GlStateManager.popMatrix(); + } + } + + private void renderRays(TileEntityImbuementAltar tileentity, float partialTicks){ + + float t = (getWorld().getTotalWorldTime() + partialTicks); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + Random random = new Random(tileentity.getPos().toLong()); // Use position to get a constant seed + + int[] colours = BlockReceptacle.PARTICLE_COLOURS.get(tileentity.getDisplayElement()); + + if(colours == null) return; // Shouldn't happen + + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); + RenderHelper.disableStandardItemLighting(); + + int r1 = colours[1] >> 16 & 255; + int g1 = colours[1] >> 8 & 255; + int b1 = colours[1] & 255; + + int r2 = colours[2] >> 16 & 255; + int g2 = colours[2] >> 8 & 255; + int b2 = colours[2] & 255; + + for(int j = 0; j < 30; j++){ + + int m = random.nextInt(10); + int n = random.nextInt(10); + + int sliceAngle = 20 + m; + float scale = 0.5f; + + GlStateManager.pushMatrix(); + + float progress = Math.min(tileentity.getImbuementProgress() + partialTicks/141, 1); + float s = 1 - progress; + s = 1 - s*s; + GlStateManager.scale(s, s, s); + + // TODO: This needs optimising! We should easily be able to do this with a single draw() call + // Same for magic light and black hole, which don't need ray textures either! + GlStateManager.rotate(31 * m, 1, 0, 0); + GlStateManager.rotate(31 * n, 0, 0, 1); + + buffer.begin(5, DefaultVertexFormats.POSITION_COLOR); + + float fade = (Math.min(1, 1.9f - progress) - 0.9f) * 10; + + buffer.pos(0, 0, 0).color(r1, g1, b1, (int)(255 * fade)).endVertex(); + buffer.pos(0, 0, 0).color(r1, g1, b1, (int)(255 * fade)).endVertex(); + + double x1 = scale * MathHelper.sin((t + 40 * j) * ((float)Math.PI / 180)); + double z1 = scale * MathHelper.cos((t + 40 * j) * ((float)Math.PI / 180)); + + double x2 = scale * MathHelper.sin((t + 40 * j - sliceAngle) * ((float)Math.PI / 180)); + double z2 = scale * MathHelper.cos((t + 40 * j - sliceAngle) * ((float)Math.PI / 180)); + + buffer.pos(x1, 0, z1).color(r2, g2, b2, 0).endVertex(); + buffer.pos(x2, 0, z2).color(r2, g2, b2, 0).endVertex(); + + tessellator.draw(); + + GlStateManager.popMatrix(); + } + + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableCull(); + GlStateManager.disableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableLighting(); + RenderHelper.enableStandardItemLighting(); + } + +} diff --git a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java index d1fdc412..c5ae30a5 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java @@ -77,6 +77,7 @@ public final class WizardryBlocks { public static final Block dark_oak_lectern = placeholder(); public static final Block receptacle = placeholder(); + public static final Block imbuement_altar = placeholder(); /** * Sets both the registry and unlocalised names of the given block, then registers it with the given registry. Use @@ -101,6 +102,7 @@ public final class WizardryBlocks { IForgeRegistry registry = event.getRegistry(); + // TODO: Put everything in block classes wherever possible registerBlock(registry, "arcane_workbench", new BlockArcaneWorkbench().setHardness(1.0F).setCreativeTab(WizardryTabs.WIZARDRY)); registerBlock(registry, "crystal_ore", new BlockCrystalOre(Material.ROCK).setHardness(3.0F).setCreativeTab(WizardryTabs.WIZARDRY)); registerBlock(registry, "crystal_flower", new BlockCrystalFlower(Material.PLANTS).setHardness(0.0F).setCreativeTab(WizardryTabs.WIZARDRY)); @@ -139,6 +141,7 @@ public final class WizardryBlocks { registerBlock(registry, "dark_oak_lectern", new BlockLectern()); registerBlock(registry, "receptacle", new BlockReceptacle()); + registerBlock(registry, "imbuement_altar", new BlockImbuementAltar()); } @@ -155,5 +158,6 @@ public final class WizardryBlocks { GameRegistry.registerTileEntity(TileEntityBookshelf.class, new ResourceLocation(Wizardry.MODID, "bookshelf")); GameRegistry.registerTileEntity(TileEntityLectern.class, new ResourceLocation(Wizardry.MODID, "lectern")); GameRegistry.registerTileEntity(TileEntityReceptacle.class, new ResourceLocation(Wizardry.MODID, "receptacle")); + GameRegistry.registerTileEntity(TileEntityImbuementAltar.class, new ResourceLocation(Wizardry.MODID, "imbuement_altar")); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryItems.java b/src/main/java/electroblob/wizardry/registry/WizardryItems.java index b17f7ceb..a490b27c 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryItems.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryItems.java @@ -436,6 +436,7 @@ public final class WizardryItems { registerItemBlock(registry, WizardryBlocks.dark_oak_lectern); registerItemBlock(registry, WizardryBlocks.receptacle); + registerItemBlock(registry, WizardryBlocks.imbuement_altar); // Items @@ -708,6 +709,7 @@ public final class WizardryItems { ((TileEntityReceptacle)tileEntity).setElement(Element.values()[stack.getMetadata()]); stack.shrink(1); world.checkLight(pos); + // TESTME: Do we need this? world.notifyBlockUpdate(pos, source.getBlockState(), source.getBlockState(), 3); return stack; } diff --git a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java index afd32d60..67b87788 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardrySounds.java +++ b/src/main/java/electroblob/wizardry/registry/WizardrySounds.java @@ -33,6 +33,7 @@ public final class WizardrySounds { public static final SoundEvent BLOCK_PEDESTAL_CONQUER = createSound("block.pedestal.conquer"); public static final SoundEvent BLOCK_LECTERN_LOCATE_SPELL = createSound("block.lectern.locate_spell"); public static final SoundEvent BLOCK_RECEPTACLE_IGNITE = createSound("block.receptacle.ignite"); + public static final SoundEvent BLOCK_IMBUEMENT_ALTAR_IMBUE = createSound("block.imbuement_altar.imbue"); public static final SoundEvent ITEM_WAND_SWITCH_SPELL = createSound("item.wand.switch_spell"); public static final SoundEvent ITEM_WAND_LEVELUP = createSound("item.wand.levelup"); diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityImbuementAltar.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityImbuementAltar.java new file mode 100644 index 00000000..c323ad9e --- /dev/null +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityImbuementAltar.java @@ -0,0 +1,204 @@ +package electroblob.wizardry.tileentity; + +import electroblob.wizardry.block.BlockReceptacle; +import electroblob.wizardry.constants.Element; +import electroblob.wizardry.item.IManaStoringItem; +import electroblob.wizardry.item.ItemWizardArmour; +import electroblob.wizardry.registry.WizardryItems; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.util.GeometryUtils; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.Vec3d; + +import javax.annotation.Nullable; +import java.util.Arrays; + +public class TileEntityImbuementAltar extends TileEntity implements ITickable { + + private static final int IMBUEMENT_DURATION = 140; + + private ItemStack stack; + private int imbuementTimer; + private Element displayElement; + + public TileEntityImbuementAltar(){ + stack = ItemStack.EMPTY; + } + + public void setStack(ItemStack stack){ + this.stack = stack; + checkRecipe(); + } + + public void checkRecipe(){ + + if(getResult().isEmpty()){ + imbuementTimer = 0; + }else if(imbuementTimer == 0){ + imbuementTimer = 1; + }else{ + return; // Don't sync if nothing changed + } + + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); // Sync + } + + public ItemStack getStack(){ + return stack; + } + + @Override + public void update(){ + + if(imbuementTimer > 0){ + + if(imbuementTimer == 1){ // Has to be done here because of syncing + world.playSound(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, + WizardrySounds.BLOCK_IMBUEMENT_ALTAR_IMBUE, SoundCategory.BLOCKS, 1, 1, false); + } + + ItemStack result = getResult(); + + if(result.isEmpty()){ + imbuementTimer = 0; + + }else{ + + if(imbuementTimer++ >= IMBUEMENT_DURATION){ + this.stack = result; + consumeReceptacleContents(); + imbuementTimer = 0; + displayElement = null; + } + + if(world.isRemote && world.rand.nextInt(2) == 0){ + + Element[] elements = getReceptacleElements(); + + Vec3d centre = GeometryUtils.getCentre(this.pos.up()); + + for(int i = 0; i < elements.length; i++){ + + if(elements[i] == null) continue; + + Vec3d offset = new Vec3d(EnumFacing.byHorizontalIndex(i).getDirectionVec()); + Vec3d vec = GeometryUtils.getCentre(this.pos).add(0, 0.3, 0).add(offset.scale(0.7)); + + int[] colours = BlockReceptacle.PARTICLE_COLOURS.get(elements[i]); + + ParticleBuilder.create(Type.DUST, world.rand, vec.x, vec.y, vec.z, 0.1, false) + .vel(centre.subtract(vec).scale(0.02)).clr(colours[1]).fade(colours[2]).time(50).spawn(world); + } + } + } + } + } + + /** Returns the element to use for the visual ray effect colours, or null if they should not be displayed. */ + public Element getDisplayElement(){ + return displayElement; + } + + /** Returns how complete the current action is (from 0 to 1), or 0 if no action is being performed. */ + public float getImbuementProgress(){ + return (float)imbuementTimer / IMBUEMENT_DURATION; + } + + private ItemStack getResult(){ + + if(stack.getItem() instanceof ItemWizardArmour && ((ItemWizardArmour)stack.getItem()).element == null){ + + Element[] elements = getReceptacleElements(); + + if(Arrays.stream(elements).distinct().count() == 1 && elements[0] != null){ // All the same element + + ItemStack result = new ItemStack(WizardryItems.getArmour(elements[0], ((ItemWizardArmour)stack.getItem()).armorType)); + displayElement = elements[0]; + + result.setTagCompound(stack.getTagCompound()); + ((IManaStoringItem)result.getItem()).setMana(result, ((ItemWizardArmour)stack.getItem()).getMana(stack)); + + return result; + } + } + + displayElement = null; + return ItemStack.EMPTY; + } + + /** Returns the elements of the 4 adjacent receptacles, in SWNE order. Null means an empty or missing receptacle. */ + private Element[] getReceptacleElements(){ + + Element[] elements = new Element[4]; + + for(EnumFacing side : EnumFacing.HORIZONTALS){ + + TileEntity tileEntity = world.getTileEntity(pos.offset(side)); + + if(tileEntity instanceof TileEntityReceptacle){ + elements[side.getHorizontalIndex()] = ((TileEntityReceptacle)tileEntity).getElement(); + }else{ + elements[side.getHorizontalIndex()] = null; + } + } + + return elements; + } + + /** Empties the 4 adjacent receptacles. */ + private void consumeReceptacleContents(){ + + for(EnumFacing side : EnumFacing.HORIZONTALS){ + + TileEntity tileEntity = world.getTileEntity(pos.offset(side)); + + if(tileEntity instanceof TileEntityReceptacle){ + ((TileEntityReceptacle)tileEntity).setElement(null); + } + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt){ + super.writeToNBT(nbt); + NBTTagCompound itemTag = new NBTTagCompound(); + stack.writeToNBT(itemTag); + nbt.setTag("item", itemTag); + nbt.setInteger("imbuementTimer", imbuementTimer); + return nbt; + } + + @Override + public void readFromNBT(NBTTagCompound nbt){ + super.readFromNBT(nbt); + NBTTagCompound itemTag = nbt.getCompoundTag("item"); + this.stack = new ItemStack(itemTag); + this.imbuementTimer = nbt.getInteger("imbuementTimer"); + } + + @Override + public NBTTagCompound getUpdateTag(){ + return this.writeToNBT(new NBTTagCompound()); + } + + @Nullable + @Override + public SPacketUpdateTileEntity getUpdatePacket(){ + return new SPacketUpdateTileEntity(pos, 0, this.getUpdateTag()); + } + + @Override + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt){ + readFromNBT(pkt.getNbtCompound()); + } + +} diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityReceptacle.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityReceptacle.java index eefb1c61..7f322774 100644 --- a/src/main/java/electroblob/wizardry/tileentity/TileEntityReceptacle.java +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityReceptacle.java @@ -26,6 +26,8 @@ public class TileEntityReceptacle extends TileEntity { public void setElement(Element element){ this.element = element; + world.notifyNeighborsRespectDebug(pos, blockType, true); // Update altar if connected + world.checkLight(pos); } @Override diff --git a/src/main/resources/assets/ebwizardry/blockstates/imbuement_altar.json b/src/main/resources/assets/ebwizardry/blockstates/imbuement_altar.json new file mode 100644 index 00000000..ac08f939 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/imbuement_altar.json @@ -0,0 +1,7 @@ +{ + "forge_marker": 1, + "variants": { + "active=false": { "model": "ebwizardry:imbuement_altar_inactive" }, + "active=true": { "model": "ebwizardry:imbuement_altar" } + } +} diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index 47d1dc23..6e8d87d6 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -49,6 +49,7 @@ tile.ebwizardry\:acacia_lectern.name=Acacia Lectern tile.ebwizardry\:dark_oak_lectern.name=Dark Oak Lectern tile.ebwizardry\:receptacle.name=Receptacle +tile.ebwizardry\:imbuement_altar.name=Imbuement Altar item.ebwizardry\:crystal_magic.name=Magic Crystal item.ebwizardry\:crystal_magic.desc=The iridescent colours of this crystal seem to slowly shift and swirl, hinting at a magical energy within. Perhaps this magic could be harnessed in some way? diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index 080042b8..f34add33 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -49,6 +49,7 @@ tile.ebwizardry\:acacia_lectern.name=Acacia Lectern tile.ebwizardry\:dark_oak_lectern.name=Dark Oak Lectern tile.ebwizardry\:receptacle.name=Receptacle +tile.ebwizardry\:imbuement_altar.name=Imbuement Altar item.ebwizardry\:crystal_magic.name=Magic Crystal item.ebwizardry\:crystal_magic.desc=The iridescent colors of this crystal seem to slowly shift and swirl, hinting at a magical energy within. Perhaps this magic could be harnessed, somehow... diff --git a/src/main/resources/assets/ebwizardry/models/block/imbuement_altar.json b/src/main/resources/assets/ebwizardry/models/block/imbuement_altar.json new file mode 100644 index 00000000..e5bb2841 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/imbuement_altar.json @@ -0,0 +1,36 @@ +{ + "parent": "block/block", + "textures": { + "particle": "ebwizardry:blocks/imbuement_altar_bottom", + "bottom": "ebwizardry:blocks/imbuement_altar_bottom", + "top": "ebwizardry:blocks/imbuement_altar_top", + "side": "ebwizardry:blocks/imbuement_altar_side", + "top_overlay": "ebwizardry:blocks/imbuement_altar_top_overlay", + "side_overlay": "ebwizardry:blocks/imbuement_altar_side_overlay" + }, + "elements": [ + { + "from": [ 0, 0, 0 ], + "to": [ 16, 12, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, + "north": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "north" }, + "south": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "east" } + } + }, + { + "from": [ 0, 0, 0 ], + "to": [ 16, 12, 16 ], + "faces": { + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top_overlay" }, + "north": { "uv": [ 0, 4, 16, 16 ], "texture": "#side_overlay", "cullface": "north" }, + "south": { "uv": [ 0, 4, 16, 16 ], "texture": "#side_overlay", "cullface": "south" }, + "west": { "uv": [ 0, 4, 16, 16 ], "texture": "#side_overlay", "cullface": "west" }, + "east": { "uv": [ 0, 4, 16, 16 ], "texture": "#side_overlay", "cullface": "east" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/block/imbuement_altar_inactive.json b/src/main/resources/assets/ebwizardry/models/block/imbuement_altar_inactive.json new file mode 100644 index 00000000..85009bfa --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/imbuement_altar_inactive.json @@ -0,0 +1,22 @@ +{ + "parent": "block/block", + "textures": { + "particle": "ebwizardry:blocks/imbuement_altar_bottom", + "bottom": "ebwizardry:blocks/imbuement_altar_bottom", + "top": "ebwizardry:blocks/imbuement_altar_top", + "side": "ebwizardry:blocks/imbuement_altar_side" + }, + "elements": [ + { "from": [ 0, 0, 0 ], + "to": [ 16, 12, 16 ], + "faces": { + "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" }, + "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, + "north": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "north" }, + "south": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "south" }, + "west": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "west" }, + "east": { "uv": [ 0, 4, 16, 16 ], "texture": "#side", "cullface": "east" } + } + } + ] +} diff --git a/src/main/resources/assets/ebwizardry/models/item/imbuement_altar.json b/src/main/resources/assets/ebwizardry/models/item/imbuement_altar.json new file mode 100644 index 00000000..d82d1f0b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/imbuement_altar.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/imbuement_altar_inactive" +} diff --git a/src/main/resources/assets/ebwizardry/sounds.json b/src/main/resources/assets/ebwizardry/sounds.json index ac252dbf..5ca316eb 100644 --- a/src/main/resources/assets/ebwizardry/sounds.json +++ b/src/main/resources/assets/ebwizardry/sounds.json @@ -4,6 +4,7 @@ "block.pedestal.conquer": {"category": "blocks", "sounds": ["ui/toast/challenge_complete"]}, "block.lectern.locate_spell": {"category": "blocks", "sounds": ["ebwizardry:conjure"]}, "block.receptacle.ignite": {"category": "blocks", "sounds": ["mob/evocation_illager/cast1", "mob/evocation_illager/cast2"]}, + "block.imbuement_altar.imbue": {"category": "blocks", "sounds": ["ebwizardry:imbue"]}, "item.wand.switch_spell": {"category": "player", "sounds": ["ebwizardry:select"]}, "item.wand.levelup": {"category": "player", "sounds": ["random/levelup"]}, diff --git a/src/main/resources/assets/ebwizardry/sounds/imbue.ogg b/src/main/resources/assets/ebwizardry/sounds/imbue.ogg new file mode 100644 index 00000000..fd2183cb Binary files /dev/null and b/src/main/resources/assets/ebwizardry/sounds/imbue.ogg differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_bottom.png b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_bottom.png new file mode 100644 index 00000000..49884613 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_bottom.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side.png new file mode 100644 index 00000000..9982b86d Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png new file mode 100644 index 00000000..8eaeba9a Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png.mcmeta new file mode 100644 index 00000000..0719b1bb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_side_overlay.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 40, + + "interpolate": true, + + "frames": [0, 1, 2, 3] + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top.png new file mode 100644 index 00000000..1d75ed0c Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png new file mode 100644 index 00000000..3adc9e9c Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png.mcmeta b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png.mcmeta new file mode 100644 index 00000000..0719b1bb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/textures/blocks/imbuement_altar_top_overlay.png.mcmeta @@ -0,0 +1,12 @@ +{ + "animation": { + + "frametime": 40, + + "interpolate": true, + + "frames": [0, 1, 2, 3] + + } + +} \ No newline at end of file