Implement ability presets

This commit is contained in:
abel1502 2025-05-17 12:47:09 +03:00
parent 853b6576ad
commit e59f8b441d
No known key found for this signature in database
GPG Key ID: 076926596A536338
5 changed files with 868 additions and 822 deletions

View File

@ -0,0 +1,32 @@
package com.hbm.handler.ability;
import java.util.HashMap;
// All abilities available on a given tool
public class AvailableAbilities {
private HashMap<IBaseAbility, Integer> abilities = new HashMap<IBaseAbility, Integer>();
AvailableAbilities() {}
AvailableAbilities addAbility(IBaseAbility ability, int level) {
if (level < 0 || level >= ability.levels()) {
throw new IllegalArgumentException("Illegal level " + level + " for ability " + ability.getName());
}
abilities.put(ability, level);
return this;
}
AvailableAbilities removeAbility(IBaseAbility ability) {
abilities.remove(ability);
return this;
}
boolean supportsAbility(IBaseAbility ability) {
return abilities.containsKey(ability);
}
int maxLevel(IBaseAbility ability) {
return abilities.getOrDefault(ability, -1);
}
}

View File

@ -28,233 +28,225 @@ public interface IToolAreaAbility extends IBaseAbility {
// If true is returned, no block breaking is handled by the tool
// (neither for the original block nor for the extras)
boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool);
public static enum AreaAbility {
// region handlers
None(new IToolAreaAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
return false;
}
}),
Recursion(new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.recursion";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityVein;
}
public final int[] radiusAtLevel = {3, 4, 5, 6, 7, 9, 10};
@Override
public int levels() {
return radiusAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + radiusAtLevel[level] + ")";
}
// Note: if reusing it across different instatces of a tool
// is a problem here, then it had already been one before
// the refactor! The solution is to simply make this a local
// of the onDig method and pass it around as a parameter.
private Set<ThreeInts> pos = new HashSet<>();
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
Block b = world.getBlock(x, y, z);
if(!ToolConfig.recursiveStone) {
Item item = Item.getItemFromBlock(b);
List<ItemStack> stone = OreDictionary.getOres(OreDictManager.KEY_STONE);
for(ItemStack stack : stone) {
if(stack.getItem() == item)
return false;
}
List<ItemStack> cobble = OreDictionary.getOres(OreDictManager.KEY_COBBLESTONE);
for(ItemStack stack : cobble) {
if(stack.getItem() == item)
return false;
}
}
if(b == Blocks.netherrack && !ToolConfig.recursiveNetherrack)
return false;
pos.clear();
recurse(world, x, y, z, x, y, z, player, tool, 0, radiusAtLevel[level]);
return false;
}
private final List<ThreeInts> offsets = new ArrayList<ThreeInts>(3*3*3-1) {{
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx != 0 || dy != 0 || dz != 0) {
add(new ThreeInts(dx, dy, dz));
}
}
}
}
}};
private void recurse(World world, int x, int y, int z, int refX, int refY, int refZ, EntityPlayer player, IItemWithAbility tool, int depth, int radius) {
List<ThreeInts> shuffledOffsets = new ArrayList<>(offsets);
Collections.shuffle(shuffledOffsets);
for(ThreeInts offset : shuffledOffsets) {
breakExtra(world, x + offset.x, y + offset.y, z + offset.z, refX, refY, refZ, player, tool, depth, radius);
}
}
private void breakExtra(World world, int x, int y, int z, int refX, int refY, int refZ, EntityPlayer player, IItemWithAbility tool, int depth, int radius) {
if(pos.contains(new ThreeInts(x, y, z)))
return;
depth += 1;
if(depth > ToolConfig.recursionDepth)
return;
pos.add(new ThreeInts(x, y, z));
//don't lose the ref block just yet
if(x == refX && y == refY && z == refZ)
return;
if(Vec3.createVectorHelper(x - refX, y - refY, z - refZ).lengthVector() > radius)
return;
Block b = world.getBlock(x, y, z);
Block ref = world.getBlock(refX, refY, refZ);
int meta = world.getBlockMetadata(x, y, z);
int refMeta = world.getBlockMetadata(refX, refY, refZ);
if(!isSameBlock(b, ref))
return;
if(meta != refMeta)
return;
if(player.getHeldItem() == null)
return;
tool.breakExtraBlock(world, x, y, z, player, refX, refY, refZ);
recurse(world, x, y, z, refX, refY, refZ, player, tool, depth, radius);
}
private boolean isSameBlock(Block b1, Block b2) {
if(b1 == b2) return true;
if((b1 == Blocks.redstone_ore && b2 == Blocks.lit_redstone_ore) || (b1 == Blocks.lit_redstone_ore && b2 == Blocks.redstone_ore)) return true;
return false;
}
}),
Hammer(new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.hammer";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityHammer;
}
public final int[] rangeAtLevel = {1, 2, 3, 4};
@Override
public int levels() {
return rangeAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + rangeAtLevel[level] + ")";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
int range = rangeAtLevel[level];
for(int a = x - range; a <= x + range; a++) {
for(int b = y - range; b <= y + range; b++) {
for(int c = z - range; c <= z + range; c++) {
if(a == x && b == y && c == z)
continue;
tool.breakExtraBlock(world, a, b ,c, player, x, y, z);
}
}
}
return false;
}
}),
Explosion(new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.explosion";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityExplosion;
}
public final float[] strengthAtLevel = {2.5F, 5F, 10F, 15F};
@Override
public int levels() {
return strengthAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + strengthAtLevel[level] + ")";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
float strength = strengthAtLevel[level];
ExplosionNT ex = new ExplosionNT(player.worldObj, player, x + 0.5, y + 0.5, z + 0.5, strength);
ex.addAttrib(ExAttrib.ALLDROP);
ex.addAttrib(ExAttrib.NOHURT);
ex.addAttrib(ExAttrib.NOPARTICLE);
ex.doExplosionA();
ex.doExplosionB(false);
player.worldObj.createExplosion(player, x + 0.5, y + 0.5, z + 0.5, 0.1F, false);
return true;
}
});
// endregion handlers
public IToolAreaAbility handler;
AreaAbility(IToolAreaAbility handler) {
this.handler = handler;
// region handlers
public static final IToolAreaAbility NONE = new IToolAreaAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
return false;
}
};
public static final IToolAreaAbility RECURSION = new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.recursion";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityVein;
}
public final int[] radiusAtLevel = {3, 4, 5, 6, 7, 9, 10};
@Override
public int levels() {
return radiusAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + radiusAtLevel[level] + ")";
}
// Note: if reusing it across different instatces of a tool
// is a problem here, then it had already been one before
// the refactor! The solution is to simply make this a local
// of the onDig method and pass it around as a parameter.
private Set<ThreeInts> pos = new HashSet<>();
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
Block b = world.getBlock(x, y, z);
if(!ToolConfig.recursiveStone) {
Item item = Item.getItemFromBlock(b);
List<ItemStack> stone = OreDictionary.getOres(OreDictManager.KEY_STONE);
for(ItemStack stack : stone) {
if(stack.getItem() == item)
return false;
}
List<ItemStack> cobble = OreDictionary.getOres(OreDictManager.KEY_COBBLESTONE);
for(ItemStack stack : cobble) {
if(stack.getItem() == item)
return false;
}
}
if(b == Blocks.netherrack && !ToolConfig.recursiveNetherrack)
return false;
pos.clear();
recurse(world, x, y, z, x, y, z, player, tool, 0, radiusAtLevel[level]);
return false;
}
private final List<ThreeInts> offsets = new ArrayList<ThreeInts>(3*3*3-1) {{
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx != 0 || dy != 0 || dz != 0) {
add(new ThreeInts(dx, dy, dz));
}
}
}
}
}};
private void recurse(World world, int x, int y, int z, int refX, int refY, int refZ, EntityPlayer player, IItemWithAbility tool, int depth, int radius) {
List<ThreeInts> shuffledOffsets = new ArrayList<>(offsets);
Collections.shuffle(shuffledOffsets);
for(ThreeInts offset : shuffledOffsets) {
breakExtra(world, x + offset.x, y + offset.y, z + offset.z, refX, refY, refZ, player, tool, depth, radius);
}
}
private void breakExtra(World world, int x, int y, int z, int refX, int refY, int refZ, EntityPlayer player, IItemWithAbility tool, int depth, int radius) {
if(pos.contains(new ThreeInts(x, y, z)))
return;
depth += 1;
if(depth > ToolConfig.recursionDepth)
return;
pos.add(new ThreeInts(x, y, z));
//don't lose the ref block just yet
if(x == refX && y == refY && z == refZ)
return;
if(Vec3.createVectorHelper(x - refX, y - refY, z - refZ).lengthVector() > radius)
return;
Block b = world.getBlock(x, y, z);
Block ref = world.getBlock(refX, refY, refZ);
int meta = world.getBlockMetadata(x, y, z);
int refMeta = world.getBlockMetadata(refX, refY, refZ);
if(!isSameBlock(b, ref))
return;
if(meta != refMeta)
return;
if(player.getHeldItem() == null)
return;
tool.breakExtraBlock(world, x, y, z, player, refX, refY, refZ);
recurse(world, x, y, z, refX, refY, refZ, player, tool, depth, radius);
}
private boolean isSameBlock(Block b1, Block b2) {
if(b1 == b2) return true;
if((b1 == Blocks.redstone_ore && b2 == Blocks.lit_redstone_ore) || (b1 == Blocks.lit_redstone_ore && b2 == Blocks.redstone_ore)) return true;
return false;
}
};
public static final IToolAreaAbility HAMMER = new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.hammer";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityHammer;
}
public final int[] rangeAtLevel = {1, 2, 3, 4};
@Override
public int levels() {
return rangeAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + rangeAtLevel[level] + ")";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
int range = rangeAtLevel[level];
for(int a = x - range; a <= x + range; a++) {
for(int b = y - range; b <= y + range; b++) {
for(int c = z - range; c <= z + range; c++) {
if(a == x && b == y && c == z)
continue;
tool.breakExtraBlock(world, a, b ,c, player, x, y, z);
}
}
}
return false;
}
};
public static final IToolAreaAbility EXPLOSION = new IToolAreaAbility() {
@Override
public String getName() {
return "tool.ability.explosion";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityExplosion;
}
public final float[] strengthAtLevel = {2.5F, 5F, 10F, 15F};
@Override
public int levels() {
return strengthAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + strengthAtLevel[level] + ")";
}
@Override
public boolean onDig(int level, World world, int x, int y, int z, EntityPlayer player, IItemWithAbility tool) {
float strength = strengthAtLevel[level];
ExplosionNT ex = new ExplosionNT(player.worldObj, player, x + 0.5, y + 0.5, z + 0.5, strength);
ex.addAttrib(ExAttrib.ALLDROP);
ex.addAttrib(ExAttrib.NOHURT);
ex.addAttrib(ExAttrib.NOPARTICLE);
ex.doExplosionA();
ex.doExplosionB(false);
player.worldObj.createExplosion(player, x + 0.5, y + 0.5, z + 0.5, 0.1F, false);
return true;
}
};
// endregion handlers
}

View File

@ -41,281 +41,273 @@ public interface IToolHarvestAbility extends IBaseAbility {
}
}
public static enum HarvestAbility {
// region handlers
None(new IToolHarvestAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
}),
Silk(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.silktouch";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilitySilk;
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
@Override
public void preHarvestAll(int level, World world, EntityPlayer player) {
ItemStack stack = player.getHeldItem();
EnchantmentUtil.addEnchantment(stack, Enchantment.silkTouch, 1);
}
@Override
public void postHarvestAll(int level, World world, EntityPlayer player) {
// ToC-ToU mismatch should be impossible
// because both calls happen on the same tick.
// Even if can be forced somehow, the player doesn't gain any benefit from it.
ItemStack stack = player.getHeldItem();
EnchantmentUtil.removeEnchantment(stack, Enchantment.silkTouch);
}
}),
Luck(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.luck";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityLuck;
}
public final int[] powerAtLevel = {1, 2, 3, 4, 5, 9};
@Override
public int levels() {
return powerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + powerAtLevel[level] + ")";
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
@Override
public void preHarvestAll(int level, World world, EntityPlayer player) {
ItemStack stack = player.getHeldItem();
EnchantmentUtil.addEnchantment(stack, Enchantment.fortune, powerAtLevel[level]);
}
@Override
public void postHarvestAll(int level, World world, EntityPlayer player) {
// ToC-ToU mismatch should be impossible
// because both calls happen on the same tick.
// Even if can be forced somehow, the player doesn't gain any benefit from it.
ItemStack stack = player.getHeldItem();
EnchantmentUtil.removeEnchantment(stack, Enchantment.fortune);
}
}),
Smelter(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.smelter";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityFurnace;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
List<ItemStack> drops = block.getDrops(world, x, y, z, world.getBlockMetadata(x, y, z), 0);
boolean doesSmelt = false;
for(int i = 0; i < drops.size(); i++) {
ItemStack stack = drops.get(i).copy();
ItemStack result = FurnaceRecipes.smelting().getSmeltingResult(stack);
if(result != null) {
result = result.copy();
result.stackSize *= stack.stackSize;
drops.set(i, result);
doesSmelt = true;
}
}
if(doesSmelt) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
for(ItemStack stack : drops)
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, stack.copy()));
}
}
}),
Shredder(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.shredder";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityShredder;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
ItemStack result = ShredderRecipes.getShredderResult(stack);
if(result != null && result.getItem() != ModItems.scrap) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, result.copy()));
}
}
}),
Centrifuge(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.centrifuge";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityCentrifuge;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
ItemStack[] result = CentrifugeRecipes.getOutput(stack);
if(result != null) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
for(ItemStack st : result) {
if(st != null)
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, st.copy()));
}
}
}
}),
Crystallizer(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.crystallizer";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityCrystallizer;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
CrystallizerRecipe result = CrystallizerRecipes.getOutput(stack, Fluids.PEROXIDE);
if(result != null) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, result.output.copy()));
}
}
}),
Mercury(new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.mercury";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityMercury;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
int mercury = 0;
if(block == Blocks.redstone_ore)
mercury = player.getRNG().nextInt(5) + 4;
if(block == Blocks.redstone_block)
mercury = player.getRNG().nextInt(7) + 8;
if(mercury > 0) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ingot_mercury, mercury)));
}
}
});
// endregion handlers
public IToolHarvestAbility handler;
HarvestAbility(IToolHarvestAbility handler) {
this.handler = handler;
// region handlers
public static final IToolHarvestAbility NONE = new IToolHarvestAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
};
public static final IToolHarvestAbility SILK = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.silktouch";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilitySilk;
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
@Override
public void preHarvestAll(int level, World world, EntityPlayer player) {
ItemStack stack = player.getHeldItem();
EnchantmentUtil.addEnchantment(stack, Enchantment.silkTouch, 1);
}
@Override
public void postHarvestAll(int level, World world, EntityPlayer player) {
// ToC-ToU mismatch should be impossible
// because both calls happen on the same tick.
// Even if can be forced somehow, the player doesn't gain any benefit from it.
ItemStack stack = player.getHeldItem();
EnchantmentUtil.removeEnchantment(stack, Enchantment.silkTouch);
}
};
public static final IToolHarvestAbility LUCK = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.luck";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityLuck;
}
public final int[] powerAtLevel = {1, 2, 3, 4, 5, 9};
@Override
public int levels() {
return powerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + powerAtLevel[level] + ")";
}
@Override
public boolean skipDefaultDrops(int level) {
return false;
}
@Override
public void preHarvestAll(int level, World world, EntityPlayer player) {
ItemStack stack = player.getHeldItem();
EnchantmentUtil.addEnchantment(stack, Enchantment.fortune, powerAtLevel[level]);
}
@Override
public void postHarvestAll(int level, World world, EntityPlayer player) {
// ToC-ToU mismatch should be impossible
// because both calls happen on the same tick.
// Even if can be forced somehow, the player doesn't gain any benefit from it.
ItemStack stack = player.getHeldItem();
EnchantmentUtil.removeEnchantment(stack, Enchantment.fortune);
}
};
public static final IToolHarvestAbility SMELTER = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.smelter";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityFurnace;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
List<ItemStack> drops = block.getDrops(world, x, y, z, world.getBlockMetadata(x, y, z), 0);
boolean doesSmelt = false;
for(int i = 0; i < drops.size(); i++) {
ItemStack stack = drops.get(i).copy();
ItemStack result = FurnaceRecipes.smelting().getSmeltingResult(stack);
if(result != null) {
result = result.copy();
result.stackSize *= stack.stackSize;
drops.set(i, result);
doesSmelt = true;
}
}
if(doesSmelt) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
for(ItemStack stack : drops)
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, stack.copy()));
}
}
};
public static final IToolHarvestAbility SHREDDER = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.shredder";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityShredder;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
ItemStack result = ShredderRecipes.getShredderResult(stack);
if(result != null && result.getItem() != ModItems.scrap) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, result.copy()));
}
}
};
public static final IToolHarvestAbility CENTRIFUGE = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.centrifuge";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityCentrifuge;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
ItemStack[] result = CentrifugeRecipes.getOutput(stack);
if(result != null) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
for(ItemStack st : result) {
if(st != null)
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, st.copy()));
}
}
}
};
public static final IToolHarvestAbility CRYSTALLIZER = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.crystallizer";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityCrystallizer;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
ItemStack stack = new ItemStack(block, 1, meta);
CrystallizerRecipe result = CrystallizerRecipes.getOutput(stack, Fluids.PEROXIDE);
if(result != null) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, result.output.copy()));
}
}
};
public static final IToolHarvestAbility MERCURY = new IToolHarvestAbility() {
@Override
public String getName() {
return "tool.ability.mercury";
}
@Override
public boolean isAllowed() {
return ToolConfig.abilityMercury;
}
@Override
public boolean skipDefaultDrops(int level) {
return true;
}
@Override
public void onHarvestBlock(int level, World world, int x, int y, int z, EntityPlayer player, Block block, int meta) {
//a band-aid on a gaping wound
if(block == Blocks.lit_redstone_ore)
block = Blocks.redstone_ore;
int mercury = 0;
if(block == Blocks.redstone_ore)
mercury = player.getRNG().nextInt(5) + 4;
if(block == Blocks.redstone_block)
mercury = player.getRNG().nextInt(7) + 8;
if(mercury > 0) {
IToolHarvestAbility.super.onHarvestBlock(level, world, x, y, z, player, block, meta);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ingot_mercury, mercury)));
}
}
};
// endregion handlers
}

View File

@ -36,324 +36,316 @@ import net.minecraft.world.World;
public interface IWeaponAbility extends IBaseAbility {
void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool);
public static enum WeaponAbility {
// region handlers
None(new IWeaponAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {}
}),
Radiation(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.radiation";
}
public final float[] radAtLevel = {15F, 50F, 500F};
@Override
public int levels() {
return radAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + radAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase)
ContaminationUtil.contaminate((EntityLivingBase)victim, HazardType.RADIATION, ContaminationType.CREATIVE, radAtLevel[level]);
}
}),
Vampire(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.vampire";
}
public final float[] amountAtLevel = {2F, 3F, 5F, 10F, 50F};
@Override
public int levels() {
return amountAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + amountAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
float amount = amountAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0) return;
living.setHealth(living.getHealth() - amount);
if(living.getHealth() <= 0) living.onDeath(DamageSource.magic);
player.heal(amount);
}
}
}),
Stun(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.stun";
}
public final int[] durationAtLevel = {2, 3, 5, 10, 15};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int duration = durationAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
living.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, duration * 20, 4));
living.addPotionEffect(new PotionEffect(Potion.weakness.id, duration * 20, 4));
}
}
}),
Blend(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.blender";
}
public final int[] dividerAtLevel = {12};
@Override
public int levels() {
return dividerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (1:" + dividerAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int divider = dividerAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0.0F) {
int count = Math.min((int)Math.ceil(living.getMaxHealth() / divider), 250); //safeguard to prevent funnies from bosses with obscene health
world.playSoundEffect(living.posX, living.posY + living.height * 0.5, living.posZ, "mob.zombie.woodbreak", 0.5F, 1.0F);
victim.attackEntityFrom(ModDamageSource.turbofan, 100);
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "giblets");
data.setInteger("count", count * 4);
data.setInteger("ent", victim.getEntityId());
data.setInteger("cDiv", 5);
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, victim.posX, victim.posY + victim.height * 0.5, victim.posZ), new TargetPoint(victim.dimension, victim.posX, victim.posY + victim.height * 0.5, victim.posZ, 150));
living.entityDropItem(new ItemStack(ModItems.flesh, 10, 0), 0.0F);
}
}
}
}),
Phosphorus(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.phosphorus";
}
public final int[] durationAtLevel = {60, 90};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int duration = durationAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
living.addPotionEffect(new PotionEffect(HbmPotion.phosphorus.id, duration * 20, 4));
}
}
}),
Fire(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.fire";
}
public final int[] durationAtLevel = {5, 10};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase) {
victim.setFire(durationAtLevel[level]);
}
}
}),
Chainsaw(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.chainsaw";
}
public final int[] dividerAtLevel = {10, 15};
@Override
public int levels() {
return dividerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (1:" + dividerAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int divider = dividerAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0.0F) {
int count = Math.min((int)Math.ceil(living.getMaxHealth() / divider), 250); //safeguard to prevent funnies from bosses with obscene health
for(int i = 0; i < count; i++) {
living.entityDropItem(new ItemStack(ModItems.nitra_small), 1);
world.spawnEntityInWorld(new EntityXPOrb(world, living.posX, living.posY, living.posZ, 1));
}
if(player instanceof EntityPlayerMP) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "vanillaburst");
data.setInteger("count", count * 4);
data.setDouble("motion", 0.1D);
data.setString("mode", "blockdust");
data.setInteger("block", Block.getIdFromBlock(Blocks.redstone_block));
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, living.posX, living.posY + living.height * 0.5, living.posZ), new TargetPoint(living.dimension, living.posX, living.posY, living.posZ, 50));
}
world.playSoundEffect(living.posX, living.posY + living.height * 0.5, living.posZ, "hbm:weapon.chainsaw", 0.5F, 1.0F);
}
}
}
}),
Beheader(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.beheader";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase && ((EntityLivingBase) victim).getHealth() <= 0.0F) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living instanceof EntitySkeleton) {
if(((EntitySkeleton)living).getSkeletonType() == 0) {
living.entityDropItem(new ItemStack(Items.skull, 1, 0), 0.0F);
} else {
if(world.rand.nextInt(20) == 0)
living.entityDropItem(new ItemStack(Items.skull, 1, 1), 0.0F);
else
living.entityDropItem(new ItemStack(Items.coal, 3), 0.0F);
}
} else if(living instanceof EntityZombie) {
living.entityDropItem(new ItemStack(Items.skull, 1, 2), 0.0F);
} else if(living instanceof EntityCreeper) {
living.entityDropItem(new ItemStack(Items.skull, 1, 4), 0.0F);
} else if(living instanceof EntityMagmaCube) {
living.entityDropItem(new ItemStack(Items.magma_cream, 3), 0.0F);
} else if(living instanceof EntitySlime) {
living.entityDropItem(new ItemStack(Items.slime_ball, 3), 0.0F);
} else if(living instanceof EntityPlayer) {
ItemStack head = new ItemStack(Items.skull, 1, 3);
head.stackTagCompound = new NBTTagCompound();
head.stackTagCompound.setString("SkullOwner", ((EntityPlayer) living).getDisplayName());
living.entityDropItem(head, 0.0F);
} else {
living.entityDropItem(new ItemStack(Items.rotten_flesh, 3, 0), 0.0F);
living.entityDropItem(new ItemStack(Items.bone, 2, 0), 0.0F);
}
}
}
}),
Bobble(new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.bobble";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityMob && ((EntityMob) victim).getHealth() <= 0.0F) {
EntityMob mob = (EntityMob) victim;
int chance = 1000;
if(mob.getMaxHealth() > 20) {
chance = 750;
}
if(world.rand.nextInt(chance) == 0)
mob.entityDropItem(new ItemStack(ModBlocks.bobblehead, 1, world.rand.nextInt(BobbleType.values().length - 1) + 1), 0.0F);
}
}
});
// endregion handlers
public IWeaponAbility handler;
WeaponAbility(IWeaponAbility handler) {
this.handler = handler;
// region handlers
public static final IWeaponAbility NONE = new IWeaponAbility() {
@Override
public String getName() {
// TODO: null? empty? otherwise i18n
return "";
}
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {}
};
public static final IWeaponAbility RADIATION = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.radiation";
}
public final float[] radAtLevel = {15F, 50F, 500F};
@Override
public int levels() {
return radAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + radAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase)
ContaminationUtil.contaminate((EntityLivingBase)victim, HazardType.RADIATION, ContaminationType.CREATIVE, radAtLevel[level]);
}
};
public static final IWeaponAbility VAMPIRE = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.vampire";
}
public final float[] amountAtLevel = {2F, 3F, 5F, 10F, 50F};
@Override
public int levels() {
return amountAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + amountAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
float amount = amountAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0) return;
living.setHealth(living.getHealth() - amount);
if(living.getHealth() <= 0) living.onDeath(DamageSource.magic);
player.heal(amount);
}
}
};
public static final IWeaponAbility STUN = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.stun";
}
public final int[] durationAtLevel = {2, 3, 5, 10, 15};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int duration = durationAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
living.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, duration * 20, 4));
living.addPotionEffect(new PotionEffect(Potion.weakness.id, duration * 20, 4));
}
}
};
public static final IWeaponAbility BLEND = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.blender";
}
public final int[] dividerAtLevel = {12};
@Override
public int levels() {
return dividerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (1:" + dividerAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int divider = dividerAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0.0F) {
int count = Math.min((int)Math.ceil(living.getMaxHealth() / divider), 250); //safeguard to prevent funnies from bosses with obscene health
world.playSoundEffect(living.posX, living.posY + living.height * 0.5, living.posZ, "mob.zombie.woodbreak", 0.5F, 1.0F);
victim.attackEntityFrom(ModDamageSource.turbofan, 100);
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "giblets");
data.setInteger("count", count * 4);
data.setInteger("ent", victim.getEntityId());
data.setInteger("cDiv", 5);
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, victim.posX, victim.posY + victim.height * 0.5, victim.posZ), new TargetPoint(victim.dimension, victim.posX, victim.posY + victim.height * 0.5, victim.posZ, 150));
living.entityDropItem(new ItemStack(ModItems.flesh, 10, 0), 0.0F);
}
}
}
};
public static final IWeaponAbility PHOSPHORUS = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.phosphorus";
}
public final int[] durationAtLevel = {60, 90};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int duration = durationAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
living.addPotionEffect(new PotionEffect(HbmPotion.phosphorus.id, duration * 20, 4));
}
}
};
public static final IWeaponAbility FIRE = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.fire";
}
public final int[] durationAtLevel = {5, 10};
@Override
public int levels() {
return durationAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (" + durationAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase) {
victim.setFire(durationAtLevel[level]);
}
}
};
public static final IWeaponAbility CHAINSAW = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.chainsaw";
}
public final int[] dividerAtLevel = {10, 15};
@Override
public int levels() {
return dividerAtLevel.length;
}
@Override
public String getExtension(int level) {
return " (1:" + dividerAtLevel[level] + ")";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
int divider = dividerAtLevel[level];
if(victim instanceof EntityLivingBase) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living.getHealth() <= 0.0F) {
int count = Math.min((int)Math.ceil(living.getMaxHealth() / divider), 250); //safeguard to prevent funnies from bosses with obscene health
for(int i = 0; i < count; i++) {
living.entityDropItem(new ItemStack(ModItems.nitra_small), 1);
world.spawnEntityInWorld(new EntityXPOrb(world, living.posX, living.posY, living.posZ, 1));
}
if(player instanceof EntityPlayerMP) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "vanillaburst");
data.setInteger("count", count * 4);
data.setDouble("motion", 0.1D);
data.setString("mode", "blockdust");
data.setInteger("block", Block.getIdFromBlock(Blocks.redstone_block));
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, living.posX, living.posY + living.height * 0.5, living.posZ), new TargetPoint(living.dimension, living.posX, living.posY, living.posZ, 50));
}
world.playSoundEffect(living.posX, living.posY + living.height * 0.5, living.posZ, "hbm:weapon.chainsaw", 0.5F, 1.0F);
}
}
}
};
public static final IWeaponAbility BEHEADER = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.beheader";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityLivingBase && ((EntityLivingBase) victim).getHealth() <= 0.0F) {
EntityLivingBase living = (EntityLivingBase) victim;
if(living instanceof EntitySkeleton) {
if(((EntitySkeleton)living).getSkeletonType() == 0) {
living.entityDropItem(new ItemStack(Items.skull, 1, 0), 0.0F);
} else {
if(world.rand.nextInt(20) == 0)
living.entityDropItem(new ItemStack(Items.skull, 1, 1), 0.0F);
else
living.entityDropItem(new ItemStack(Items.coal, 3), 0.0F);
}
} else if(living instanceof EntityZombie) {
living.entityDropItem(new ItemStack(Items.skull, 1, 2), 0.0F);
} else if(living instanceof EntityCreeper) {
living.entityDropItem(new ItemStack(Items.skull, 1, 4), 0.0F);
} else if(living instanceof EntityMagmaCube) {
living.entityDropItem(new ItemStack(Items.magma_cream, 3), 0.0F);
} else if(living instanceof EntitySlime) {
living.entityDropItem(new ItemStack(Items.slime_ball, 3), 0.0F);
} else if(living instanceof EntityPlayer) {
ItemStack head = new ItemStack(Items.skull, 1, 3);
head.stackTagCompound = new NBTTagCompound();
head.stackTagCompound.setString("SkullOwner", ((EntityPlayer) living).getDisplayName());
living.entityDropItem(head, 0.0F);
} else {
living.entityDropItem(new ItemStack(Items.rotten_flesh, 3, 0), 0.0F);
living.entityDropItem(new ItemStack(Items.bone, 2, 0), 0.0F);
}
}
}
};
public static final IWeaponAbility BOBBLE = new IWeaponAbility() {
@Override
public String getName() {
return "weapon.ability.bobble";
}
@Override
public void onHit(int level, World world, EntityPlayer player, Entity victim, IItemWithAbility tool) {
if(victim instanceof EntityMob && ((EntityMob) victim).getHealth() <= 0.0F) {
EntityMob mob = (EntityMob) victim;
int chance = 1000;
if(mob.getMaxHealth() > 20) {
chance = 750;
}
if(world.rand.nextInt(chance) == 0)
mob.entityDropItem(new ItemStack(ModBlocks.bobblehead, 1, world.rand.nextInt(BobbleType.values().length - 1) + 1), 0.0F);
}
}
};
// endregion handlers
}

View File

@ -0,0 +1,38 @@
package com.hbm.handler.ability;
public class ToolPreset {
public IToolAreaAbility areaAbility = IToolAreaAbility.NONE;
public int areaAbilityLevel = 0;
public IToolHarvestAbility harvestAbility = IToolHarvestAbility.NONE;
public int harvestAbilityLevel = 0;
public ToolPreset() {}
public ToolPreset(IToolAreaAbility areaAbility, IToolHarvestAbility harvestAbility) {
this.areaAbility = areaAbility;
this.harvestAbility = harvestAbility;
}
public ToolPreset(IToolAreaAbility areaAbility, int areaAbilityLevel, IToolHarvestAbility harvestAbility, int harvestAbilityLevel) {
this.areaAbility = areaAbility;
this.areaAbilityLevel = areaAbilityLevel;
this.harvestAbility = harvestAbility;
this.harvestAbilityLevel = harvestAbilityLevel;
}
public String getMessage() {
String areaPart = areaAbility.getFullName(areaAbilityLevel);
String harvestPart = harvestAbility.getFullName(harvestAbilityLevel);
if (harvestPart.isEmpty() && areaPart.isEmpty())
return "[Tool ability deactivated]";
if (harvestPart.isEmpty())
return "[Enabled " + areaPart + "]";
if (areaPart.isEmpty())
return "[Enabled " + harvestPart + "]";
return "[Enabled " + areaPart + " + " + harvestPart + "]";
}
}