diff --git a/src/api/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java b/src/api/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java index 3817725d..93e13c45 100644 --- a/src/api/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java +++ b/src/api/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java @@ -11,7 +11,8 @@ import javax.annotation.Nullable; /** * Allows recipe addition and removal. */ -public interface IBloodMagicRecipeRegistrar { +public interface IBloodMagicRecipeRegistrar +{ /** * Adds a new recipe to the Blood Altar. @@ -54,7 +55,7 @@ public interface IBloodMagicRecipeRegistrar { /** * Adds a new recipe to the Soul/Tartaric Forge. - * + * * @param output An output {@link ItemStack}. * @param minimumSouls The minimum number of souls that must be contained in the Soul Gem. * @param soulDrain The number of souls to drain from the Soul Gem. @@ -65,8 +66,8 @@ public interface IBloodMagicRecipeRegistrar { /** * Removes a Soul/Tartaric Forge recipe based on an input {@link ItemStack} array. * - * @param input The input items to remove the recipe of. - * @return Whether or not a recipe was removed. + * @param input The input items to remove the recipe of. + * @return Whether or not a recipe was removed. */ boolean removeTartaricForge(@Nonnull ItemStack... input); @@ -88,4 +89,8 @@ public interface IBloodMagicRecipeRegistrar { * @return Whether or not a recipe was removed. */ boolean removeAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst); + + void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Ingredient... input); + + boolean removeSacrificeCraft(@Nonnull ItemStack... input); } diff --git a/src/main/java/WayofTime/bloodmagic/alchemyArray/AlchemyArrayEffectMobSacrifice.java b/src/main/java/WayofTime/bloodmagic/alchemyArray/AlchemyArrayEffectMobSacrifice.java new file mode 100644 index 00000000..e0ad6ae9 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/alchemyArray/AlchemyArrayEffectMobSacrifice.java @@ -0,0 +1,184 @@ +package WayofTime.bloodmagic.alchemyArray; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.passive.EntityAnimal; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.registry.EntityEntry; +import net.minecraftforge.fml.common.registry.EntityRegistry; +import WayofTime.bloodmagic.api.impl.BloodMagicAPI; +import WayofTime.bloodmagic.api.impl.recipe.RecipeSacrificeCraft; +import WayofTime.bloodmagic.ritual.AreaDescriptor; +import WayofTime.bloodmagic.util.DamageSourceBloodMagic; +import WayofTime.bloodmagic.util.helper.PurificationHelper; + +public class AlchemyArrayEffectMobSacrifice extends AlchemyArrayEffect +{ + public static final AreaDescriptor itemDescriptor = new AreaDescriptor.Rectangle(new BlockPos(-5, -5, -5), 11); + public static final AreaDescriptor mobDescriptor = new AreaDescriptor.Rectangle(new BlockPos(-5, -5, -5), 11); + + public AlchemyArrayEffectMobSacrifice(String key) + { + super(key); + } + + @Override + public boolean update(TileEntity tile, int ticksActive) + { + World world = tile.getWorld(); + if (world.isRemote && ticksActive < 200 && ticksActive > 40) + { + BlockPos pos = tile.getPos(); + Random rand = world.rand; + + for (int i = 0; i < 2; i++) + { + double d0 = (double) pos.getX() + 0.5D + (rand.nextDouble() - 0.5D) * 2.5D; + double d1 = (double) pos.getY() + 0.2D + (rand.nextDouble() - 0.5D) * 0.2D; + double d2 = (double) pos.getZ() + 0.5D + (rand.nextDouble() - 0.5D) * 2.5D; + world.spawnParticle(EnumParticleTypes.SPELL_MOB, d0, d1, d2, 1D, 0.0D, 0.0D); + } + } + + if (!world.isRemote) + { + if (ticksActive >= 200) + { + BlockPos pos = tile.getPos(); + + List itemList = world.getEntitiesWithinAABB(EntityItem.class, itemDescriptor.getAABB(pos)); + + List inputList = new ArrayList(); + + for (EntityItem entityItem : itemList) + { + if (entityItem.isDead || entityItem.getItem().isEmpty()) + { + continue; + } + + inputList.add(entityItem.getItem().copy()); + } + + if (inputList.isEmpty()) + { + return false; + } + + if (inputList.size() == 1) //TODO: Test if it is a something that can be filled with Soul Breath + { + + } + + RecipeSacrificeCraft recipe = BloodMagicAPI.INSTANCE.getRecipeRegistrar().getSacrificeCraft(inputList); + if (recipe != null) + { + double healthRequired = recipe.getHealthRequired(); + double healthAvailable = 0; + + List livingEntities = world.getEntitiesWithinAABB(EntityLivingBase.class, mobDescriptor.getAABB(pos)); + for (EntityLivingBase living : livingEntities) + { + double health = getEffectiveHealth(living); + if (health > 0) + { + healthAvailable += health; + } + } + + if (healthAvailable < healthRequired) + { + return false; + } + + for (EntityLivingBase living : livingEntities) + { + double health = getEffectiveHealth(living); + if (health > 0) + { + healthAvailable -= health; + living.getEntityWorld().playSound(null, living.posX, living.posY, living.posZ, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (living.getEntityWorld().rand.nextFloat() - living.getEntityWorld().rand.nextFloat()) * 0.8F); + living.setHealth(-1); + living.onDeath(DamageSourceBloodMagic.INSTANCE); + } + + if (healthAvailable <= 0) + { + break; + } + } + + for (EntityItem itemEntity : itemList) + { + itemEntity.getItem().setCount(itemEntity.getItem().getCount() - 1); + if (itemEntity.getItem().isEmpty()) //TODO: Check container + { + itemEntity.setDead(); + } + } + + world.spawnEntity(new EntityItem(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, recipe.getOutput())); + } + } + } + + return false; + } + + //Future-proofing in case I want to make different mobs give different effective health + public double getEffectiveHealth(EntityLivingBase living) + { + if (living == null) + return 0; + + if (!living.isNonBoss()) + return 0; + + if (living instanceof EntityPlayer) + return 0; + + if (living.isChild() && !(living instanceof IMob)) + return 0; + + if (living.isDead || living.getHealth() < 0.5F) + return 0; + + EntityEntry entityEntry = EntityRegistry.getEntry(living.getClass()); + if (entityEntry == null) + return 0; + + return living.getHealth(); + } + + @Override + public void writeToNBT(NBTTagCompound tag) + { + + } + + @Override + public void readFromNBT(NBTTagCompound tag) + { + + } + + @Override + public AlchemyArrayEffect getNewCopy() + { + return new AlchemyArrayEffectMobSacrifice(key); + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java index 8448277e..633e2a40 100644 --- a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java +++ b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java @@ -25,10 +25,12 @@ import net.minecraftforge.fml.common.registry.EntityEntry; import net.minecraftforge.fml.common.registry.ForgeRegistries; @BloodMagicPlugin -public class BloodMagicCorePlugin implements IBloodMagicPlugin { +public class BloodMagicCorePlugin implements IBloodMagicPlugin +{ @Override - public void register(IBloodMagicAPI apiInterface) { + public void register(IBloodMagicAPI apiInterface) + { BloodMagicAPI api = (BloodMagicAPI) apiInterface; // Add forced blacklistings api.getBlacklist().addTeleposer(RegistrarBloodMagicBlocks.INPUT_ROUTING_NODE); @@ -82,15 +84,19 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { } @Override - public void registerRecipes(IBloodMagicRecipeRegistrar recipeRegistrar) { + public void registerRecipes(IBloodMagicRecipeRegistrar recipeRegistrar) + { RegistrarBloodMagicRecipes.registerAltarRecipes((BloodMagicRecipeRegistrar) recipeRegistrar); RegistrarBloodMagicRecipes.registerAlchemyTableRecipes((BloodMagicRecipeRegistrar) recipeRegistrar); RegistrarBloodMagicRecipes.registerTartaricForgeRecipes((BloodMagicRecipeRegistrar) recipeRegistrar); RegistrarBloodMagicRecipes.registerAlchemyArrayRecipes((BloodMagicRecipeRegistrar) recipeRegistrar); + RegistrarBloodMagicRecipes.registerSacrificeCraftRecipes((BloodMagicRecipeRegistrar) recipeRegistrar); } - private static void handleConfigValues(BloodMagicAPI api) { - for (String value : ConfigHandler.values.sacrificialValues) { + private static void handleConfigValues(BloodMagicAPI api) + { + for (String value : ConfigHandler.values.sacrificialValues) + { String[] split = value.split(";"); if (split.length != 2) // Not valid format continue; @@ -98,15 +104,18 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { api.getValueManager().setSacrificialValue(new ResourceLocation(split[0]), Integer.parseInt(split[1])); } - for (String value : ConfigHandler.blacklist.teleposer) { + for (String value : ConfigHandler.blacklist.teleposer) + { EntityEntry entityEntry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(value)); - if (entityEntry == null) { // It's not an entity (or at least not a valid one), so let's try a block. + if (entityEntry == null) + { // It's not an entity (or at least not a valid one), so let's try a block. String[] blockData = value.split("\\["); Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(blockData[0])); if (block == Blocks.AIR || block == null) // Not a valid block either continue; - if (blockData.length > 1) { // We have properties listed, so let's build a state. + if (blockData.length > 1) + { // We have properties listed, so let's build a state. api.getBlacklist().addTeleposer(parseState(value)); continue; } @@ -118,13 +127,15 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { api.getBlacklist().addTeleposer(entityEntry.getRegistryName()); } - for (String value : ConfigHandler.blacklist.transposer) { + for (String value : ConfigHandler.blacklist.transposer) + { String[] blockData = value.split("\\["); Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(blockData[0])); if (block == Blocks.AIR || block == null) // Not a valid block continue; - if (blockData.length > 1) { // We have properties listed, so let's build a state. + if (blockData.length > 1) + { // We have properties listed, so let's build a state. api.getBlacklist().addTeleposer(parseState(value)); continue; } @@ -132,7 +143,8 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { api.getBlacklist().addTeleposer(block); } - for (String value : ConfigHandler.blacklist.wellOfSuffering) { + for (String value : ConfigHandler.blacklist.wellOfSuffering) + { EntityEntry entityEntry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(value)); if (entityEntry == null) // Not a valid entity continue; @@ -141,7 +153,8 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { } } - private static IBlockState parseState(String blockInfo) { + private static IBlockState parseState(String blockInfo) + { String[] split = blockInfo.split("\\["); split[1] = split[1].substring(0, split[1].lastIndexOf("]")); // Make sure brackets are removed from state @@ -154,7 +167,8 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { // Force our values into the state String[] stateValues = split[1].split(","); // Splits up each value - for (String value : stateValues) { + for (String value : stateValues) + { String[] valueSplit = value.split("="); // Separates property and value IProperty property = blockState.getProperty(valueSplit[0]); if (property != null) diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java index 59fb5dba..776d762d 100644 --- a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java +++ b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java @@ -1,31 +1,31 @@ package WayofTime.bloodmagic.api.impl; -import WayofTime.bloodmagic.api.IBloodMagicRecipeRegistrar; -import WayofTime.bloodmagic.api.impl.recipe.RecipeAlchemyArray; -import WayofTime.bloodmagic.api.impl.recipe.RecipeAlchemyTable; -import WayofTime.bloodmagic.api.impl.recipe.RecipeBloodAltar; -import WayofTime.bloodmagic.api.impl.recipe.RecipeTartaricForge; -import WayofTime.bloodmagic.orb.IBloodOrb; -import WayofTime.bloodmagic.core.recipe.IngredientBloodOrb; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.Ingredient; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.crafting.CraftingHelper; +import WayofTime.bloodmagic.api.IBloodMagicRecipeRegistrar; +import WayofTime.bloodmagic.api.impl.recipe.RecipeAlchemyArray; +import WayofTime.bloodmagic.api.impl.recipe.RecipeAlchemyTable; +import WayofTime.bloodmagic.api.impl.recipe.RecipeBloodAltar; +import WayofTime.bloodmagic.api.impl.recipe.RecipeSacrificeCraft; +import WayofTime.bloodmagic.api.impl.recipe.RecipeTartaricForge; +import WayofTime.bloodmagic.core.recipe.IngredientBloodOrb; +import WayofTime.bloodmagic.orb.IBloodOrb; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar { @@ -34,6 +34,7 @@ public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar private final Set alchemyRecipes; private final Set tartaricForgeRecipes; private final Set alchemyArrayRecipes; + private final Set sacrificeCraftRecipes; public BloodMagicRecipeRegistrar() { @@ -41,6 +42,7 @@ public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar this.alchemyRecipes = Sets.newHashSet(); this.tartaricForgeRecipes = Sets.newHashSet(); this.alchemyArrayRecipes = Sets.newHashSet(); + this.sacrificeCraftRecipes = Sets.newHashSet(); } @Override @@ -189,6 +191,49 @@ public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar addAlchemyArray(Ingredient.fromStacks(input), Ingredient.fromStacks(catalyst), output, circleTexture); } + public void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Object... input) + { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + List ingredients = Lists.newArrayList(); + for (Object object : input) + { + if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) + { + ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object))); + continue; + } + + ingredients.add(CraftingHelper.getIngredient(object)); + } + + addSacrificeCraft(output, healthRequired, ingredients.toArray(new Ingredient[0])); + } + + @Override + public boolean removeSacrificeCraft(@Nonnull ItemStack... input) + { + Preconditions.checkNotNull(input, "inputs cannot be null."); + + for (ItemStack stack : input) + Preconditions.checkNotNull(stack, "input cannot be null."); + + return sacrificeCraftRecipes.remove(getSacrificeCraft(Lists.newArrayList(input))); + } + + @Override + public void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Ingredient... input) + { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + NonNullList inputs = NonNullList.from(Ingredient.EMPTY, input); + sacrificeCraftRecipes.add(new RecipeSacrificeCraft(inputs, output, healthRequired)); + } + @Nullable public RecipeBloodAltar getBloodAltar(@Nonnull ItemStack input) { @@ -279,6 +324,44 @@ public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar return null; } + @Nullable + public RecipeSacrificeCraft getSacrificeCraft(@Nonnull List input) + { + Preconditions.checkNotNull(input, "input cannot be null."); + if (input.isEmpty()) + return null; + + mainLoop: for (RecipeSacrificeCraft recipe : sacrificeCraftRecipes) + { + if (recipe.getInput().size() != input.size()) + continue; + + List recipeInput = new ArrayList<>(recipe.getInput()); + + for (int i = 0; i < input.size(); i++) + { + boolean matched = false; + for (int j = 0; j < recipeInput.size(); j++) + { + Ingredient ingredient = recipeInput.get(j); + if (ingredient.apply(input.get(i))) + { + matched = true; + recipeInput.remove(j); + break; + } + } + + if (!matched) + continue mainLoop; + } + + return recipe; + } + + return null; + } + @Nullable public RecipeAlchemyArray getAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst) { diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeSacrificeCraft.java b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeSacrificeCraft.java new file mode 100644 index 00000000..95bf3354 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeSacrificeCraft.java @@ -0,0 +1,48 @@ +package WayofTime.bloodmagic.api.impl.recipe; + +import com.google.common.base.Preconditions; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +public class RecipeSacrificeCraft +{ + @Nonnull + private final NonNullList input; + @Nonnull + private final ItemStack output; + @Nonnegative + private final double healthRequired; + + public RecipeSacrificeCraft(@Nonnull NonNullList input, @Nonnull ItemStack output, @Nonnegative double healthRequired) + { + Preconditions.checkNotNull(input, "input cannot be null."); + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(healthRequired >= 0, "healthRequired cannot be negative."); + + this.input = input; + this.output = output; + this.healthRequired = healthRequired; + } + + @Nonnull + public final NonNullList getInput() + { + return input; + } + + @Nonnull + public final ItemStack getOutput() + { + return output; + } + + @Nonnegative + public final double getHealthRequired() + { + return healthRequired; + } +} diff --git a/src/main/java/WayofTime/bloodmagic/client/render/alchemyArray/MobSacrificeAlchemyCircleRenderer.java b/src/main/java/WayofTime/bloodmagic/client/render/alchemyArray/MobSacrificeAlchemyCircleRenderer.java new file mode 100644 index 00000000..d4590a5d --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/client/render/alchemyArray/MobSacrificeAlchemyCircleRenderer.java @@ -0,0 +1,267 @@ +package WayofTime.bloodmagic.client.render.alchemyArray; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import WayofTime.bloodmagic.alchemyArray.AlchemyCircleRenderer; +import WayofTime.bloodmagic.tile.TileAlchemyArray; + +public class MobSacrificeAlchemyCircleRenderer extends AlchemyCircleRenderer +{ + private ResourceLocation bottomArrayResource = new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/MovementArray.png"); + + private ResourceLocation mobSacrificeSwirlResource = new ResourceLocation("bloodmagic", "textures/models/mobsacrificeswirl.png"); + + public MobSacrificeAlchemyCircleRenderer(ResourceLocation location) + { + super(location); + } + + public MobSacrificeAlchemyCircleRenderer() + { + this(new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/mobsacrifice.png")); + } + + @Override + public float getSizeModifier(float craftTime) + { + if (craftTime < 40) + { + return 0; + } else if (craftTime > 40 && craftTime < 100) + { + return (craftTime - 40) / 60f; + } + return 1; + } + + @Override + public float getRotation(float craftTime) + { + float offset = 50; + if (craftTime >= offset) + { + float modifier = (craftTime - offset) * 5f; + return modifier * 1f; + } + return 0; + } + + @Override + public float getSecondaryRotation(float craftTime) + { + return 0; + } + + @Override + public void renderAt(TileEntity tile, double x, double y, double z, float craftTime) + { + if (!(tile instanceof TileAlchemyArray)) + { + return; + } + + TileAlchemyArray tileArray = (TileAlchemyArray) tile; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder wr = tessellator.getBuffer(); + + GlStateManager.pushMatrix(); + + float rot = getRotation(craftTime); + + float size = 1.0F * getSizeModifier(craftTime); + + // Bind the texture to the circle + Minecraft.getMinecraft().renderEngine.bindTexture(arrayResource); + + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(770, 1); + + GlStateManager.translate(x, y, z); + + // Specify which face this "circle" is located on + EnumFacing sideHit = EnumFacing.UP; + EnumFacing rotation = tileArray.getRotation(); + + GlStateManager.translate(sideHit.getFrontOffsetX() * offsetFromFace, sideHit.getFrontOffsetY() * offsetFromFace, sideHit.getFrontOffsetZ() * offsetFromFace); + + switch (sideHit) + { + case DOWN: + GlStateManager.translate(0, 0, 1); + GlStateManager.rotate(-90.0f, 1, 0, 0); + break; + case EAST: + GlStateManager.rotate(-90.0f, 0, 1, 0); + GlStateManager.translate(0, 0, -1); + break; + case NORTH: + break; + case SOUTH: + GlStateManager.rotate(180.0f, 0, 1, 0); + GlStateManager.translate(-1, 0, -1); + break; + case UP: + GlStateManager.translate(0, 1, 0); + GlStateManager.rotate(90.0f, 1, 0, 0); + break; + case WEST: + GlStateManager.translate(0, 0, 1); + GlStateManager.rotate(90.0f, 0, 1, 0); + break; + } + + GlStateManager.pushMatrix(); + GlStateManager.translate(0.5f, 0.5f, getVerticalOffset(craftTime)); +// GlStateManager.rotate(rotation.getHorizontalAngle() + 180, 0, 0, 1); + + GlStateManager.pushMatrix(); + + double topHeightOffset = 0; + double middleHeightOffset = 0; + double bottomHeightOffset = 0; + + BlockPos pos = tileArray.getPos(); + World world = tileArray.getWorld(); + +// GlStateManager.rotate((float) (yaw + 360 * getStartupPitchYawRatio(craftTime)), 0, 0, 1); +// GlStateManager.rotate((float) ((pitch + 90) * getStartupPitchYawRatio(craftTime)), 1, 0, 0); + + for (int i = 1; i <= 3; i++) + { + GlStateManager.pushMatrix(); + Minecraft.getMinecraft().renderEngine.bindTexture(bottomArrayResource); + translateAndRotateFloatingArray(tessellator, wr, size, rot, craftTime, i); + GlStateManager.popMatrix(); + } + + //Render the main array. + GlStateManager.pushMatrix(); + Minecraft.getMinecraft().renderEngine.bindTexture(arrayResource); +// GlStateManager.rotate(rot, 0, 0, 1); + renderStandardCircle(tessellator, wr, 3); + GlStateManager.popMatrix(); + + //Render the swirlz + float swirlSize = 3; + if (craftTime <= 40) + { + swirlSize = 0; + } else if (craftTime <= 100) + { + swirlSize = 3 * (craftTime - 40) / 60; + } + GlStateManager.pushMatrix(); + Minecraft.getMinecraft().renderEngine.bindTexture(mobSacrificeSwirlResource); + GlStateManager.translate(0, 0, 0.1); + GlStateManager.rotate(rot / 3, 0, 0, 1); + renderStandardCircle(tessellator, wr, swirlSize); + GlStateManager.popMatrix(); + +// GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + + // GlStateManager.depthMask(true); + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + // GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + } + + public float getStartupPitchYawRatio(float craftTime) + { + if (craftTime <= 80) + { + return 0; + } else if (craftTime > 80 && craftTime < 140) + { + return (craftTime - 80) / 60f; + } + + return 1; + } + + private void translateAndRotateFloatingArray(Tessellator tessellator, BufferBuilder builder, double size, float rotation, float craftTime, int circle) + { + double verticalOffset = 2; + + float primaryRotation = 0; + float secondaryRotation = 0; + if (craftTime >= 40) + { + primaryRotation = (craftTime - 40) * 4f; + secondaryRotation = (craftTime - 40) * 2f; + } + + float translationOffset = 1; + if (craftTime < 80) + { + translationOffset = 0; + } else if (craftTime < 140) + { + translationOffset = (craftTime - 80) / 60; + } + + switch (circle) + { + case 1: + GlStateManager.translate(0, 0, -verticalOffset); + GlStateManager.rotate(rotation / 200, 1, 0, 0); + GlStateManager.rotate(rotation / 10, 0, 0, 1); + GlStateManager.translate(1.7 * translationOffset, 0, 0); + break; + case 2: + GlStateManager.translate(0, 0, -verticalOffset); +// GlStateManager.rotate(254, 0, 0, 1); + GlStateManager.rotate((float) (rotation / 150 + 120), 1, 0, 0); + GlStateManager.rotate(120, 0, 1, 0); + GlStateManager.rotate(-rotation / 10, 0, 0, 1); + GlStateManager.translate(1.2 * translationOffset, 0, 0); + break; + case 3: + GlStateManager.translate(0, 0, -verticalOffset); +// GlStateManager.rotate(130, 0, 0, 1); + GlStateManager.rotate((float) (rotation / 100 + 284), 1, 0, 0); + GlStateManager.rotate(240, 0, 1, 0); + GlStateManager.rotate(-rotation / 7 + 180, 0, 0, 1); + GlStateManager.translate(2 * translationOffset, 0, 0); + break; + default: + //What are you doing, Way??? + } + + GlStateManager.rotate(primaryRotation, 0, 1, 0); + GlStateManager.rotate(secondaryRotation, 1, 0, 0); + GlStateManager.rotate(secondaryRotation * 0.41831f, 0, 0, 1); + + renderStandardCircle(tessellator, builder, size); + } + + private void renderStandardCircle(Tessellator tessellator, BufferBuilder builder, double size) + { + double var31 = 0.0D; + double var33 = 1.0D; + double var35 = 0; + double var37 = 1; + GlStateManager.color(1f, 1f, 1f, 1f); + builder.begin(7, DefaultVertexFormats.POSITION_TEX); + // wr.setBrightness(200); + builder.pos(size / 2f, size / 2f, 0).tex(var33, var37).endVertex(); + builder.pos(size / 2f, -size / 2f, 0).tex(var33, var35).endVertex(); + builder.pos(-size / 2f, -size / 2f, 0).tex(var31, var35).endVertex(); + builder.pos(-size / 2f, size / 2f, 0).tex(var31, var37).endVertex(); + tessellator.draw(); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/core/RegistrarBloodMagicRecipes.java b/src/main/java/WayofTime/bloodmagic/core/RegistrarBloodMagicRecipes.java index 62f6d717..caa7f823 100644 --- a/src/main/java/WayofTime/bloodmagic/core/RegistrarBloodMagicRecipes.java +++ b/src/main/java/WayofTime/bloodmagic/core/RegistrarBloodMagicRecipes.java @@ -237,4 +237,9 @@ public class RegistrarBloodMagicRecipes registrar.addAlchemyArray(ComponentTypes.REAGENT_FROST.getStack(), ItemSlate.SlateType.REINFORCED.getStack(), new ItemStack(RegistrarBloodMagicItems.SIGIL_FROST), null); } + + public static void registerSacrificeCraftRecipes(BloodMagicRecipeRegistrar registrar) + { + registrar.addSacrificeCraft(new ItemStack(RegistrarBloodMagicBlocks.TELEPOSER), 10, Items.REDSTONE); + } } diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java b/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java index cbec17ec..25d54dd2 100644 --- a/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java +++ b/src/main/java/WayofTime/bloodmagic/registry/ModRecipes.java @@ -25,6 +25,7 @@ import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectBinding; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectBounce; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectFurnaceFuel; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectLaputa; +import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectMobSacrifice; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectMovement; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectSigil; import WayofTime.bloodmagic.alchemyArray.AlchemyArrayEffectSkeletonTurret; @@ -36,6 +37,7 @@ import WayofTime.bloodmagic.client.render.alchemyArray.BindingAlchemyCircleRende import WayofTime.bloodmagic.client.render.alchemyArray.DualAlchemyCircleRenderer; import WayofTime.bloodmagic.client.render.alchemyArray.LowAlchemyCircleRenderer; import WayofTime.bloodmagic.client.render.alchemyArray.LowStaticAlchemyCircleRenderer; +import WayofTime.bloodmagic.client.render.alchemyArray.MobSacrificeAlchemyCircleRenderer; import WayofTime.bloodmagic.client.render.alchemyArray.SingleAlchemyCircleRenderer; import WayofTime.bloodmagic.client.render.alchemyArray.StaticAlchemyCircleRenderer; import WayofTime.bloodmagic.client.render.alchemyArray.TurretAlchemyCircleRenderer; @@ -128,6 +130,7 @@ public class ModRecipes AlchemyArrayRecipeRegistry.registerRecipe(new ItemStack(Items.BOW), new ItemStack(Items.ARROW), new AlchemyArrayEffectArrowTurret("turret"), new TurretAlchemyCircleRenderer(new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/SkeletonTurret1.png"))); AlchemyArrayRecipeRegistry.registerRecipe(new ItemStack(Items.REDSTONE), new ItemStack(Blocks.LAPIS_BLOCK), new AlchemyArrayEffectLaputa("laputa"), new AttractorAlchemyCircleRenderer(new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/shardoflaputa.png"))); AlchemyArrayRecipeRegistry.registerRecipe(new ItemStack(Blocks.COBBLESTONE), new ItemStack(Items.IRON_INGOT), new AlchemyArrayEffectSpike("spike"), new LowStaticAlchemyCircleRenderer(new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/spikearray.png"))); + AlchemyArrayRecipeRegistry.registerRecipe(new ItemStack(Blocks.REDSTONE_BLOCK), new ItemStack(Items.REDSTONE), new AlchemyArrayEffectMobSacrifice("mobSacrifice"), new MobSacrificeAlchemyCircleRenderer()); AlchemyArrayRecipeRegistry.registerRecipe(ComponentTypes.REAGENT_FAST_MINER.getStack(), new ItemStack(Items.IRON_PICKAXE), new AlchemyArrayEffectSigil("fastMiner", (ISigil) RegistrarBloodMagicItems.SIGIL_FAST_MINER), new SingleAlchemyCircleRenderer(new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/FastMinerSigil.png"))); diff --git a/src/main/resources/assets/bloodmagic/textures/models/alchemyarrays/mobsacrifice.png b/src/main/resources/assets/bloodmagic/textures/models/alchemyarrays/mobsacrifice.png new file mode 100644 index 00000000..409c9eeb Binary files /dev/null and b/src/main/resources/assets/bloodmagic/textures/models/alchemyarrays/mobsacrifice.png differ diff --git a/src/main/resources/assets/bloodmagic/textures/models/mobsacrificeswirl.png b/src/main/resources/assets/bloodmagic/textures/models/mobsacrificeswirl.png new file mode 100644 index 00000000..023cf956 Binary files /dev/null and b/src/main/resources/assets/bloodmagic/textures/models/mobsacrificeswirl.png differ