Add imbuement altar
- Adds imbuement altar block and associated tile entity - Adds basic functionality for imbuing wizard armour (other stuff to be decided) - Incorporates imbuement altar into glowing overlay model event (this could do with being tidied up and generalised) - Adds a TESR for the ray effect (based on some of the oldest code in the entire mod, which definitely needs improving!) - Adds a simple sound effect for the imbuement process, needs upgrading to a ticked sound later
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
|
||||
+138
@@ -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<TileEntityImbuementAltar> {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Block> 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"));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user