package blusunrize.immersiveengineering.api.tool;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
/**
* @author BluSunrize - 12.08.2016
* <p>
* A registry for custom bullet types
*/
public class BulletHandler
{
public static ItemStack emptyCasing;
public static ItemStack emptyShell;
public static ItemStack basicCartridge;
/**
* A list of all cartridges that shoot a homing bullet. Used to add Wolfpack Cartridges
*/
public static List<String> homingCartridges = new ArrayList<String>();
public static HashMap<String, IBullet> registry = new LinkedHashMap<String, IBullet>();
public static void registerBullet(String name, IBullet bullet)
{
registry.put(name, bullet);
}
public static IBullet getBullet(String name)
{
return registry.get(name);
}
public static String findRegistryName(IBullet bullet)
{
if(bullet!=null)
for(Map.Entry<String, IBullet> entry : registry.entrySet())
if(bullet.equals(entry.getValue()))
return entry.getKey();
return null;
}
public static ItemStack getBulletStack(String key)
{
ItemStack stack = basicCartridge.copy();
stack.setTagCompound(new NBTTagCompound());
stack.getTagCompound().setString("bullet", key);
return stack;
}
public interface IBullet
{
/**
* @return whether this cartridge should appear as an item and should be fired from revolver. Return false if this is a bullet the player can't get access to
*/
default boolean isProperCartridge()
{
return true;
}
default String getUnlocalizedName(ItemStack cartridge, String baseName)
{
return baseName;
}
default void addTooltip(ItemStack stack, @Nullable EntityPlayer player, List<String> list, boolean advanced)
{
}
default int getProjectileCount(@Nullable EntityPlayer shooter)
{
return 1;
}
/**
* @param shooter
* @param cartridge
* @param projectile
* @param charged whether the revolver has the electron tube upgrade
* @return the given or a custom entity
*/
default Entity getProjectile(@Nullable EntityPlayer shooter, ItemStack cartridge, Entity projectile, boolean charged)
{
return projectile;
}
/**
* called when the bullet hits a target
*/
void onHitTarget(World world, RayTraceResult target, @Nullable EntityLivingBase shooter, Entity projectile, boolean headshot);
/**
* @return the casing left when fired. Can return the static ItemStacks in BulletHandler
*/
ItemStack getCasing(ItemStack stack);
/**
* @return the textures (layers) for the item
*/
ResourceLocation[] getTextures();
/**
* @return the colour applied to the given layer
*/
int getColour(ItemStack stack, int layer);
/**
* @return whether this cartridge should be allowed to be placed in, and used from a turret.<br>
* Bullets that rely on a player using them should return false, since turrets parse null for a player
*/
default boolean isValidForTurret()
{
return false;
}
}
public static class DamagingBullet implements IBullet
{
/**
* The entities in the array are Projectile, Shooter, Target
*/
final Function<Entity[], DamageSource> damageSourceGetter;
final float damage;
boolean resetHurt = false;
boolean setFire = false;
ItemStack casing;
ResourceLocation[] textures;
public DamagingBullet(Function<Entity[], DamageSource> damageSourceGetter, float damage, ItemStack casing, ResourceLocation... textures)
{
this(damageSourceGetter, damage, false, false, casing, textures);
}
public DamagingBullet(Function<Entity[], DamageSource> damageSourceGetter, float damage, boolean resetHurt, boolean setFire, ItemStack casing, ResourceLocation... textures)
{
this.damageSourceGetter = damageSourceGetter;
this.damage = damage;
this.resetHurt = resetHurt;
this.setFire = setFire;
this.casing = casing;
this.textures = textures;
}
float getDamage(boolean headshot)
{
return this.damage * (headshot ? 1.5f : 1f);
}
@Override
public void onHitTarget(World world, RayTraceResult target, @Nullable EntityLivingBase shooter, Entity projectile, boolean headshot)
{
if(!world.isRemote && target.entityHit != null && damageSourceGetter != null)
if(target.entityHit.attackEntityFrom(damageSourceGetter.apply(new Entity[]{projectile, shooter, target.entityHit}), getDamage(headshot)))
{
if(resetHurt)
target.entityHit.hurtResistantTime = 0;
if(setFire)
target.entityHit.setFire(3);
}
}
@Override
public ItemStack getCasing(ItemStack stack)
{
return casing;
}
@Override
public ResourceLocation[] getTextures()
{
return textures;
}
@Override
public int getColour(ItemStack stack, int layer)
{
return 0xffffffff;
}
@Override
public boolean isValidForTurret()
{
return true;
}
}
}