Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add horse armour hack #396

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,14 @@ hacks:
#a list of materials players shouldn't be allowed to place at all
noplace:
#- GRINDSTONE Leaving this here for reference
HorseArmour:
enabled: true
# Register custom crafting recipes for horse armour?
registerRecipes: true
# Custom durability implementation
customDurability: true
# Custom unbreaking implementation
customUnbreaking: true
HorseStats:
enabled: true
wand: COMPASS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.programmerdan.minecraft.simpleadminhacks.configs;

import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

public final class HorseArmourConfig extends SimpleHackConfig {
@ApiStatus.Internal
public HorseArmourConfig(
final @NotNull SimpleAdminHacks plugin,
final @NotNull ConfigurationSection base
) {
super(plugin, base);
}

@Override
protected void wireup(
final @NotNull ConfigurationSection config
) { }

public boolean shouldRegisterCraftingRecipes() {
return getBase().getBoolean("registerRecipes", true);
}

public boolean reimplementDurability() {
return getBase().getBoolean("customDurability", true);
}

public boolean reimplementUnbreaking() {
return getBase().getBoolean("customUnbreaking", true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks;

import com.destroystokyo.paper.MaterialTags;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.configs.HorseArmourConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Horse;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;

public final class HorseArmour extends SimpleHack<HorseArmourConfig> implements Listener {
@ApiStatus.Internal
public HorseArmour(
final @NotNull SimpleAdminHacks plugin,
final @NotNull HorseArmourConfig config
) {
super(plugin, config);
}

@ApiStatus.Internal
public static @NotNull HorseArmourConfig generate(
final @NotNull SimpleAdminHacks plugin,
final @NotNull ConfigurationSection config
) {
return new HorseArmourConfig(plugin, config);
}

private static final List<ShapedRecipe> RECIPES = List.of(
createHorseArmourRecipe("iron_plated_horse_armour", Material.IRON_INGOT, Material.IRON_HORSE_ARMOR),
createHorseArmourRecipe("gold_plated_horse_armour", Material.GOLD_INGOT, Material.GOLDEN_HORSE_ARMOR),
createHorseArmourRecipe("diamond_plated_horse_armour", Material.DIAMOND, Material.DIAMOND_HORSE_ARMOR)
);

@Override
public void onEnable() {
super.onEnable();
if (config().shouldRegisterCraftingRecipes()) {
RECIPES.forEach(Bukkit::addRecipe);
}
plugin().registerListener(this);
}

@Override
public void onDisable() {
for (final ShapedRecipe recipe : RECIPES) {
Bukkit.removeRecipe(recipe.getKey());
}
HandlerList.unregisterAll(this);
super.onDisable();
}

@EventHandler(ignoreCancelled = true)
private void reimplementDurability(
final @NotNull EntityDamageEvent event
) {
// Do nothing if this feature isn't enabled
if (!config().reimplementDurability()) {
return;
}

// Do nothing if the entity is not a horse
if (!(event.getEntity() instanceof final Horse horse)) {
return;
}

// Do nothing if the horse is not wearing armour
final ItemStack armourItem = horse.getInventory().getArmor();
if (ItemUtils.isEmptyItem(armourItem)) {
return;
}
final Material armourMaterial = armourItem.getType();
if (!MaterialTags.HORSE_ARMORS.isTagged(armourMaterial)) {
return;
}

// Do nothing if the armour didn't mitigate any of the damage
@SuppressWarnings("deprecation")
final double damageMitigated = event.getDamage(EntityDamageEvent.DamageModifier.ARMOR) * -1;
if (damageMitigated <= 0) {
return;
}

final ItemMeta armourMeta = armourItem.getItemMeta();
if (!(armourMeta instanceof final Damageable damageableMeta)) {
this.logger.warning("Horse armour could not be cast to Damageable!");
return;
}

// Reimplement Unbreaking
if (config().reimplementUnbreaking()) {
final int unbreakingLevel = armourMeta.getEnchantLevel(Enchantment.UNBREAKING);
if (unbreakingLevel > 0) {
// https://minecraft.fandom.com/wiki/Unbreaking#Usage
final double chanceOfReducingDurability = (40d / (unbreakingLevel + 1d)) + 60d;
if (ThreadLocalRandom.current().nextDouble(0, 100) >= chanceOfReducingDurability) {
return;
}
}
}

final int maxDurability;
if (damageableMeta.hasMaxDamage()) {
maxDurability = damageableMeta.getMaxDamage();
}
else {
switch (armourMaterial) {
case LEATHER_HORSE_ARMOR -> maxDurability = Material.LEATHER_CHESTPLATE.getMaxDurability();
case IRON_HORSE_ARMOR -> maxDurability = Material.IRON_CHESTPLATE.getMaxDurability();
case GOLDEN_HORSE_ARMOR -> maxDurability = Material.GOLDEN_CHESTPLATE.getMaxDurability();
case DIAMOND_HORSE_ARMOR -> maxDurability = Material.DIAMOND_CHESTPLATE.getMaxDurability();
default -> {
// Just in case another type of horse armour gets added
this.logger.warning("New kind of horse armour! Add it to the HorseArmour SAH!");
return;
}
}
damageableMeta.setMaxDamage(maxDurability);
}

// Break the item if durability is fully expended
int currentDurability = damageableMeta.getDamage();
if (++currentDurability >= maxDurability) {
/** {@link net.minecraft.world.entity.LivingEntity#breakItem(net.minecraft.world.item.ItemStack)} */
horse.getWorld().playSound(horse.getLocation(), Sound.ENTITY_ITEM_BREAK, 0.8f, 0.8f + ThreadLocalRandom.current().nextFloat() * 0.4f);
horse.getWorld().spawnParticle(Particle.ITEM, horse.getLocation(), 5, armourItem);
horse.getInventory().setArmor(null);
return;
}
damageableMeta.setDamage(currentDurability);

armourItem.setItemMeta(armourMeta);
}

private static @NotNull ShapedRecipe createHorseArmourRecipe(
final @NotNull String slug,
final @NotNull Material ingredient,
final @NotNull Material result
) {
final var recipe = new ShapedRecipe(
new NamespacedKey("sah", slug),
new ItemStack(result)
);
recipe.shape(
"i i",
"iai",
"i i"
);
recipe.setIngredient('i', ingredient);
recipe.setIngredient('a', Material.LEATHER_HORSE_ARMOR);
return recipe;
}
}
8 changes: 8 additions & 0 deletions plugins/simpleadminhacks-paper/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,14 @@ hacks:
rainReduction:
enabled: false
rainOccurrenceChance: .5
HorseArmour:
enabled: true
# Register custom crafting recipes for horse armour?
registerRecipes: true
# Custom durability implementation
customDurability: true
# Custom unbreaking implementation
customUnbreaking: true
HorseStats:
enabled: false
wand: COMPASS
Expand Down
Loading