2016-06-23 03:49:47 +00:00
|
|
|
/*
|
|
|
|
* Minecraft Forge
|
|
|
|
* Copyright (c) 2016.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation version 2.1
|
|
|
|
* of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
2012-08-06 22:07:53 +00:00
|
|
|
/**
|
|
|
|
* This software is provided under the terms of the Minecraft Forge Public
|
|
|
|
* License v1.0.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package net.minecraftforge.common;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
2012-12-13 05:58:35 +00:00
|
|
|
import net.minecraft.util.DamageSource;
|
2013-06-30 12:50:11 +00:00
|
|
|
import net.minecraft.entity.EntityLivingBase;
|
2012-12-13 05:58:35 +00:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
|
|
import net.minecraft.item.ItemArmor;
|
|
|
|
import net.minecraft.item.ItemStack;
|
2012-08-06 22:07:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This interface is to be implemented by ItemArmor classes. It will allow to
|
|
|
|
* modify computation of damage and health loss. Computation will be called
|
|
|
|
* before the actual armor computation, which can then be cancelled.
|
|
|
|
*
|
|
|
|
* @see ItemArmor
|
|
|
|
*/
|
|
|
|
public interface ISpecialArmor
|
|
|
|
{
|
2016-03-30 21:05:27 +00:00
|
|
|
//TODO: Change 'int slot' to EnumArmorType
|
2012-08-06 22:07:53 +00:00
|
|
|
/**
|
|
|
|
* Retrieves the modifiers to be used when calculating armor damage.
|
|
|
|
*
|
|
|
|
* Armor will higher priority will have damage applied to them before
|
|
|
|
* lower priority ones. If there are multiple pieces of armor with the
|
|
|
|
* same priority, damage will be distributed between them based on there
|
|
|
|
* absorption ratio.
|
|
|
|
*
|
2012-09-11 20:11:17 +00:00
|
|
|
* @param player The entity wearing the armor.
|
2012-08-06 22:07:53 +00:00
|
|
|
* @param armor The ItemStack of the armor item itself.
|
|
|
|
* @param source The source of the damage, which can be used to alter armor
|
|
|
|
* properties based on the type or source of damage.
|
|
|
|
* @param damage The total damage being applied to the entity
|
|
|
|
* @param slot The armor slot the item is in.
|
|
|
|
* @return A ArmorProperties instance holding information about how the armor effects damage.
|
|
|
|
*/
|
2013-06-30 12:50:11 +00:00
|
|
|
public ArmorProperties getProperties(EntityLivingBase player, ItemStack armor, DamageSource source, double damage, int slot);
|
2012-08-06 22:07:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the displayed effective armor.
|
|
|
|
*
|
|
|
|
* @param player The player wearing the armor.
|
|
|
|
* @param armor The ItemStack of the armor item itself.
|
|
|
|
* @param slot The armor slot the item is in.
|
|
|
|
* @return The number of armor points for display, 2 per shield.
|
|
|
|
*/
|
|
|
|
public abstract int getArmorDisplay(EntityPlayer player, ItemStack armor, int slot);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Applies damage to the ItemStack. The mod is responsible for reducing the
|
|
|
|
* item durability and stack size. If the stack is depleted it will be cleaned
|
|
|
|
* up automatically.
|
|
|
|
*
|
|
|
|
* @param entity The entity wearing the armor
|
2012-09-11 20:11:17 +00:00
|
|
|
* @param stack The ItemStack of the armor item itself.
|
2012-08-06 22:07:53 +00:00
|
|
|
* @param source The source of the damage, which can be used to alter armor
|
|
|
|
* properties based on the type or source of damage.
|
|
|
|
* @param damage The amount of damage being applied to the armor
|
|
|
|
* @param slot The armor slot the item is in.
|
|
|
|
*/
|
2013-06-30 12:50:11 +00:00
|
|
|
public abstract void damageArmor(EntityLivingBase entity, ItemStack stack, DamageSource source, int damage, int slot);
|
Initial update to 1.8, Super beta. Most rendering related hooks are out due to major changes in 1.8.
Some notes:
Almost all int x, int y, int z parameters have been changed to BlockPos class
ForgeDirection has been removed, replaced by net.minecraft.util.EnumFacing.
All FML classes have moved from packet cpw.mods.fml to net.minecraftforge.fml
Fluid Rendering has been disabled for the time being, to be re-evaulated and a test mod created for it.
Minecraft now uses a Model based system for rendering blocks and Items. The intention is to expand the model format to better suit modder's needed once it is evaulated.
As such, The model loaders from Forge have been removed, to be replaced by expanding vanilla's model format.
Metadata has been extracted out in Minecraft to IBlockState, which holds a list of properties instead of magic number metadata. DO NOT listen to the fearmongering, you can do EVERYTHING with block states you could previously with metadata.
Stencil Bits are disabled entirely by for the main Display, Modders must enable and recreate the FrameBuffer if they wish to use Stencil Bits.
2014-11-26 03:56:35 +00:00
|
|
|
|
2012-08-06 22:07:53 +00:00
|
|
|
public static class ArmorProperties implements Comparable<ArmorProperties>
|
|
|
|
{
|
|
|
|
public int Priority = 0;
|
|
|
|
public int AbsorbMax = Integer.MAX_VALUE;
|
|
|
|
public double AbsorbRatio = 0;
|
|
|
|
public int Slot = 0;
|
2016-03-23 14:34:48 +00:00
|
|
|
private static final boolean DEBUG = false; //Only enable this if you wish to be spammed with debugging information.
|
2012-08-06 22:07:53 +00:00
|
|
|
//Left it in because I figured it'd be useful for modders developing custom armor.
|
|
|
|
|
|
|
|
public ArmorProperties(int priority, double ratio, int max)
|
|
|
|
{
|
|
|
|
Priority = priority;
|
|
|
|
AbsorbRatio = ratio;
|
|
|
|
AbsorbMax = max;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gathers and applies armor reduction to damage being dealt to a entity.
|
|
|
|
*
|
|
|
|
* @param entity The Entity being damage
|
|
|
|
* @param inventory An array of armor items
|
|
|
|
* @param source The damage source type
|
|
|
|
* @param damage The total damage being done
|
|
|
|
* @return The left over damage that has not been absorbed by the armor
|
|
|
|
*/
|
Initial update to 1.8, Super beta. Most rendering related hooks are out due to major changes in 1.8.
Some notes:
Almost all int x, int y, int z parameters have been changed to BlockPos class
ForgeDirection has been removed, replaced by net.minecraft.util.EnumFacing.
All FML classes have moved from packet cpw.mods.fml to net.minecraftforge.fml
Fluid Rendering has been disabled for the time being, to be re-evaulated and a test mod created for it.
Minecraft now uses a Model based system for rendering blocks and Items. The intention is to expand the model format to better suit modder's needed once it is evaulated.
As such, The model loaders from Forge have been removed, to be replaced by expanding vanilla's model format.
Metadata has been extracted out in Minecraft to IBlockState, which holds a list of properties instead of magic number metadata. DO NOT listen to the fearmongering, you can do EVERYTHING with block states you could previously with metadata.
Stencil Bits are disabled entirely by for the main Display, Modders must enable and recreate the FrameBuffer if they wish to use Stencil Bits.
2014-11-26 03:56:35 +00:00
|
|
|
public static float applyArmor(EntityLivingBase entity, ItemStack[] inventory, DamageSource source, double damage)
|
2012-08-06 22:07:53 +00:00
|
|
|
{
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
|
|
|
System.out.println("Start: " + damage + " " + (damage * 25));
|
|
|
|
}
|
|
|
|
damage *= 25;
|
|
|
|
ArrayList<ArmorProperties> dmgVals = new ArrayList<ArmorProperties>();
|
|
|
|
for (int x = 0; x < inventory.length; x++)
|
|
|
|
{
|
|
|
|
ItemStack stack = inventory[x];
|
|
|
|
if (stack == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ArmorProperties prop = null;
|
|
|
|
if (stack.getItem() instanceof ISpecialArmor)
|
|
|
|
{
|
|
|
|
ISpecialArmor armor = (ISpecialArmor)stack.getItem();
|
|
|
|
prop = armor.getProperties(entity, stack, source, damage / 25D, x).copy();
|
|
|
|
}
|
|
|
|
else if (stack.getItem() instanceof ItemArmor && !source.isUnblockable())
|
|
|
|
{
|
|
|
|
ItemArmor armor = (ItemArmor)stack.getItem();
|
2015-05-27 06:34:32 +00:00
|
|
|
prop = new ArmorProperties(0, armor.damageReduceAmount / 25D, Integer.MAX_VALUE);
|
2012-08-06 22:07:53 +00:00
|
|
|
}
|
|
|
|
if (prop != null)
|
|
|
|
{
|
|
|
|
prop.Slot = x;
|
|
|
|
dmgVals.add(prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dmgVals.size() > 0)
|
|
|
|
{
|
2013-01-02 04:57:45 +00:00
|
|
|
ArmorProperties[] props = dmgVals.toArray(new ArmorProperties[dmgVals.size()]);
|
2012-08-06 22:07:53 +00:00
|
|
|
StandardizeList(props, damage);
|
|
|
|
int level = props[0].Priority;
|
|
|
|
double ratio = 0;
|
|
|
|
for (ArmorProperties prop : props)
|
|
|
|
{
|
|
|
|
if (level != prop.Priority)
|
|
|
|
{
|
|
|
|
damage -= (damage * ratio);
|
|
|
|
ratio = 0;
|
|
|
|
level = prop.Priority;
|
|
|
|
}
|
|
|
|
ratio += prop.AbsorbRatio;
|
|
|
|
|
|
|
|
double absorb = damage * prop.AbsorbRatio;
|
|
|
|
if (absorb > 0)
|
|
|
|
{
|
|
|
|
ItemStack stack = inventory[prop.Slot];
|
|
|
|
int itemDamage = (int)(absorb / 25D < 1 ? 1 : absorb / 25D);
|
|
|
|
if (stack.getItem() instanceof ISpecialArmor)
|
|
|
|
{
|
|
|
|
((ISpecialArmor)stack.getItem()).damageArmor(entity, stack, source, itemDamage, prop.Slot);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
|
|
|
System.out.println("Item: " + stack.toString() + " Absorbed: " + (absorb / 25D) + " Damaged: " + itemDamage);
|
|
|
|
}
|
|
|
|
stack.damageItem(itemDamage, entity);
|
|
|
|
}
|
|
|
|
if (stack.stackSize <= 0)
|
|
|
|
{
|
2012-08-07 03:45:37 +00:00
|
|
|
/*if (entity instanceof EntityPlayer)
|
2012-08-06 22:07:53 +00:00
|
|
|
{
|
|
|
|
stack.onItemDestroyedByUse((EntityPlayer)entity);
|
2012-08-07 03:45:37 +00:00
|
|
|
}*/
|
2012-08-06 22:07:53 +00:00
|
|
|
inventory[prop.Slot] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
damage -= (damage * ratio);
|
|
|
|
}
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
2013-06-30 12:50:11 +00:00
|
|
|
System.out.println("Return: " + (int)(damage / 25.0F) + " " + damage);
|
2012-08-06 22:07:53 +00:00
|
|
|
}
|
2013-06-30 12:50:11 +00:00
|
|
|
return (float)(damage / 25.0F);
|
2012-08-06 22:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sorts and standardizes the distribution of damage over armor.
|
|
|
|
*
|
|
|
|
* @param armor The armor information
|
|
|
|
* @param damage The total damage being received
|
|
|
|
*/
|
|
|
|
private static void StandardizeList(ArmorProperties[] armor, double damage)
|
|
|
|
{
|
|
|
|
Arrays.sort(armor);
|
|
|
|
|
|
|
|
int start = 0;
|
|
|
|
double total = 0;
|
|
|
|
int priority = armor[0].Priority;
|
|
|
|
int pStart = 0;
|
|
|
|
boolean pChange = false;
|
|
|
|
boolean pFinished = false;
|
|
|
|
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
|
|
|
for (ArmorProperties prop : armor)
|
|
|
|
{
|
|
|
|
System.out.println(prop);
|
|
|
|
}
|
|
|
|
System.out.println("========================");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int x = 0; x < armor.length; x++)
|
|
|
|
{
|
|
|
|
total += armor[x].AbsorbRatio;
|
|
|
|
if (x == armor.length - 1 || armor[x].Priority != priority)
|
|
|
|
{
|
|
|
|
if (armor[x].Priority != priority)
|
|
|
|
{
|
|
|
|
total -= armor[x].AbsorbRatio;
|
|
|
|
x--;
|
|
|
|
pChange = true;
|
|
|
|
}
|
|
|
|
if (total > 1)
|
|
|
|
{
|
|
|
|
for (int y = start; y <= x; y++)
|
|
|
|
{
|
|
|
|
double newRatio = armor[y].AbsorbRatio / total;
|
|
|
|
if (newRatio * damage > armor[y].AbsorbMax)
|
|
|
|
{
|
|
|
|
armor[y].AbsorbRatio = (double)armor[y].AbsorbMax / damage;
|
|
|
|
total = 0;
|
|
|
|
for (int z = pStart; z <= y; z++)
|
|
|
|
{
|
|
|
|
total += armor[z].AbsorbRatio;
|
|
|
|
}
|
|
|
|
start = y + 1;
|
|
|
|
x = y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
armor[y].AbsorbRatio = newRatio;
|
|
|
|
pFinished = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pChange && pFinished)
|
|
|
|
{
|
|
|
|
damage -= (damage * total);
|
|
|
|
total = 0;
|
|
|
|
start = x + 1;
|
|
|
|
priority = armor[start].Priority;
|
|
|
|
pStart = start;
|
|
|
|
pChange = false;
|
|
|
|
pFinished = false;
|
|
|
|
if (damage <= 0)
|
|
|
|
{
|
|
|
|
for (int y = x + 1; y < armor.length; y++)
|
|
|
|
{
|
|
|
|
armor[y].AbsorbRatio = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int y = start; y <= x; y++)
|
|
|
|
{
|
|
|
|
total -= armor[y].AbsorbRatio;
|
|
|
|
if (damage * armor[y].AbsorbRatio > armor[y].AbsorbMax)
|
|
|
|
{
|
2013-01-02 04:57:45 +00:00
|
|
|
armor[y].AbsorbRatio = (double)armor[y].AbsorbMax / damage;
|
2012-08-06 22:07:53 +00:00
|
|
|
}
|
|
|
|
total += armor[y].AbsorbRatio;
|
|
|
|
}
|
|
|
|
damage -= (damage * total);
|
|
|
|
total = 0;
|
|
|
|
if (x != armor.length - 1)
|
|
|
|
{
|
|
|
|
start = x + 1;
|
|
|
|
priority = armor[start].Priority;
|
|
|
|
pStart = start;
|
|
|
|
pChange = false;
|
|
|
|
if (damage <= 0)
|
|
|
|
{
|
|
|
|
for (int y = x + 1; y < armor.length; y++)
|
|
|
|
{
|
|
|
|
armor[y].AbsorbRatio = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
|
|
|
for (ArmorProperties prop : armor)
|
|
|
|
{
|
|
|
|
System.out.println(prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-18 05:55:48 +00:00
|
|
|
@Override
|
2012-08-06 22:07:53 +00:00
|
|
|
public int compareTo(ArmorProperties o)
|
|
|
|
{
|
|
|
|
if (o.Priority != Priority)
|
|
|
|
{
|
|
|
|
return o.Priority - Priority;
|
|
|
|
}
|
|
|
|
double left = ( AbsorbRatio == 0 ? 0 : AbsorbMax * 100.0D / AbsorbRatio);
|
|
|
|
double right = (o.AbsorbRatio == 0 ? 0 : o.AbsorbMax * 100.0D / o.AbsorbRatio);
|
|
|
|
return (int)(left - right);
|
|
|
|
}
|
|
|
|
|
2014-01-18 05:55:48 +00:00
|
|
|
@Override
|
2012-08-06 22:07:53 +00:00
|
|
|
public String toString()
|
|
|
|
{
|
|
|
|
return String.format("%d, %d, %f, %d", Priority, AbsorbMax, AbsorbRatio, (AbsorbRatio == 0 ? 0 : (int)(AbsorbMax * 100.0D / AbsorbRatio)));
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArmorProperties copy()
|
|
|
|
{
|
|
|
|
return new ArmorProperties(Priority, AbsorbRatio, AbsorbMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|