summaryrefslogtreecommitdiff
path: root/src/main/java/net/uomc/mineshaft/blacksmith
diff options
context:
space:
mode:
authordavidovski <david@davidovski.xyz>2025-10-31 17:49:48 +0000
committerdavidovski <david@davidovski.xyz>2025-10-31 17:49:48 +0000
commit5a008748459e230de0e875afff59e3b92c7aca0c (patch)
tree0d09aebd1bb5628237959a6d1b49d1a7772d86a6 /src/main/java/net/uomc/mineshaft/blacksmith
parentfff63aaea786a5f1c59bbf99c999a2aa7bb810e5 (diff)
Work on v0.6
Diffstat (limited to 'src/main/java/net/uomc/mineshaft/blacksmith')
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Armour.java54
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Blacksmith.java320
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/BlacksmithCommand.java151
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Map.java0
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Pickaxe.java211
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Sword.java77
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Tool.java33
-rw-r--r--src/main/java/net/uomc/mineshaft/blacksmith/Tools.java48
8 files changed, 894 insertions, 0 deletions
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Armour.java b/src/main/java/net/uomc/mineshaft/blacksmith/Armour.java
new file mode 100644
index 0000000..592a4c3
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Armour.java
@@ -0,0 +1,54 @@
+package net.uomc.mineshaft.blacksmith;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+
+public class Armour extends Tool {
+ public static final int MAX_ARMOUR_LEVEL = 5;
+
+ public Armour(Mineshaft mineshaft, Member member) {
+ super(mineshaft, member, "armour");
+ }
+
+ public String getName() {
+ return armourLevelToName(getLevel());
+ }
+
+ public static String armourLevelToName(long level) {
+ switch ((int) level) {
+ case 0:
+ return "None";
+ case 1:
+ return "Copper";
+ case 2:
+ return "Iron";
+ case 3:
+ return "Gold";
+ case 4:
+ return "Diamond";
+ default:
+ return "Netherite";
+ }
+ }
+ public int getMaxLevel() {
+ return MAX_ARMOUR_LEVEL;
+ }
+
+ public long getDamageReduction() {
+ switch ((int) getLevel()) {
+ case 0: // "None";
+ return 0;
+ case 1: // "Copper";
+ return 3;
+ case 2: // "Iron";
+ return 6;
+ case 3: // "Gold";
+ return 9;
+ case 4: // "Diamond";
+ return 12;
+ default: // "Netherite";
+ return 15;
+ }
+ }
+
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Blacksmith.java b/src/main/java/net/uomc/mineshaft/blacksmith/Blacksmith.java
new file mode 100644
index 0000000..be3ad3c
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Blacksmith.java
@@ -0,0 +1,320 @@
+package net.uomc.mineshaft.blacksmith;
+
+import java.util.Map;
+
+import org.apache.commons.math3.distribution.BinomialDistribution;
+
+import com.mouldycheerio.dbot.util.PeelingUtils;
+
+import java.util.Collections;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+import net.uomc.mineshaft.MineshaftItem;
+import net.uomc.mineshaft.SavedStat;
+import net.uomc.mineshaft.farm.Farm;
+
+class Blacksmith extends Farm {
+
+ public static long UPDATES_PER_LEVEL = 10;
+ public static long MS_PER_UPDATE = 1000l * 60l * 10l;
+ private SavedStat questionsStat;
+
+ public Blacksmith(Mineshaft bot) {
+ super(bot, MineshaftItem.BLACKSMITH);
+ questionsStat = getBot().getPlayerStats().getStat("blacksmith_questions");
+ }
+
+ public boolean upgradeArmour(Member member) {
+ int armourLevel = getBot().getArmour(member).getLevel();
+ if (armourLevel >= Armour.MAX_ARMOUR_LEVEL) {
+ return false;
+ }
+ armourLevel += 1;
+
+ setPlanted(member, -armourLevel);
+
+ getBot().getArmour(member).setLevel(0);
+
+ setQuantity(member, armourLevel * UPDATES_PER_LEVEL);
+ return true;
+ }
+
+ public boolean upgradeSword(Member member) {
+ int swordLevel = getBot().getSword(member).getLevel();
+ if (swordLevel >= Sword.MAX_SWORD_LEVEL) {
+ return false;
+ }
+ swordLevel += 1;
+
+ setPlanted(member, -swordLevel);
+
+ getBot().getSword(member).setLevel(0);
+
+ setQuantity(member, swordLevel * UPDATES_PER_LEVEL);
+ return true;
+ }
+
+
+ public boolean isWorking(Member member) {
+ return getPlanted(member) != 0;
+ }
+
+ public boolean isSword(Member member) {
+ return getPlanted(member) > 0;
+ }
+
+ public int getWorkingLevel(Member member) {
+ return (int) Math.abs(getPlanted(member));
+ }
+
+ public boolean canUpgradeSword(Member member) {
+ return getBot().getSword(member).getLevel() < Sword.MAX_SWORD_LEVEL;
+ }
+
+ public boolean canUpgradeArmour(Member member) {
+ return getBot().getArmour(member).getLevel() < Armour.MAX_ARMOUR_LEVEL;
+ }
+
+ public String getNextSwordName(Member member) {
+ return Sword.swordLevelToName(getBot().getSword(member).getLevel() + 1) + " Sword";
+ }
+
+ public String getNextArmourName(Member member) {
+ return Armour.armourLevelToName(getBot().getArmour(member).getLevel() + 1) + " Armour";
+ }
+
+ public String getWorkingName(Member member) {
+ if (!isWorking(member)) {
+ return "";
+ }
+
+ if (isSword(member)) {
+ return Sword.swordLevelToName(getWorkingLevel(member)) + " Sword";
+ }
+
+ return Armour.armourLevelToName(getWorkingLevel(member)) + " Armour";
+ }
+
+ public void update(Member member) {
+ if (!isWorking(member))
+ return;
+
+ long next = getNextUpdate(member);
+ long now = System.currentTimeMillis();
+ if (next == 0) {
+ next = now;
+ }
+
+ if (next > now)
+ return;
+
+ long since = now - next;
+ long updates = since / MS_PER_UPDATE;
+
+ if (updates < 1) {
+ return;
+ }
+
+ BinomialDistribution bd = new BinomialDistribution((int) updates, getProgressChance(member));
+ setQuantity(member, getQuantity(member) - bd.sample());
+
+ setNextUpdate(member, getNextUpdate(member) + MS_PER_UPDATE*updates);
+ }
+
+ public double getProgressChance(Member member) {
+ long forges = getValidForgeCount(member);
+
+ if (forges < 1) {
+ return 0.0;
+ }
+
+ return 1 - (0.5 * Math.pow(forges, -0.5));
+ }
+
+ public long getValidForgeCount(Member member) {
+ long forges = getBot().getItem(member, MineshaftItem.FORGE);
+ long blacksmiths = getBot().getItem(member, MineshaftItem.BLACKSMITH);
+ return Math.min(forges, blacksmiths);
+ }
+
+ public double getProgress(Member member) {
+ if (!isWorking(member))
+ return 0.0;
+
+ long max = getWorkingLevel(member) * UPDATES_PER_LEVEL;
+ long current = getQuantity(member);
+ return (max - Math.min(current, 0)) / max;
+ }
+
+ public long getTimeEstimate(Member member, long updates) {
+ return (long) (MS_PER_UPDATE * (1 - getProgressChance(member)) * updates);
+ }
+
+ public long getTimeEstimateRemaining(Member member) {
+ return getTimeEstimate(member, getQuantity(member));
+ }
+
+ public long getTimeEstimateForNextArmour(Member member) {
+ int armourLevel = getBot().getArmour(member).getLevel();
+ return getTimeEstimate(member, armourLevel + 1);
+ }
+
+ public long getTimeEstimateForNextSword(Member member) {
+ int swordLevel = getBot().getSword(member).getLevel();
+ return getTimeEstimate(member, swordLevel + 1);
+ }
+
+ public Map<MineshaftItem, Long> getSwordUpgradeCost(Member member) {
+ int level = getBot().getSword(member).getLevel();
+
+ switch ((int) level) {
+ case 0:
+ return Collections.singletonMap(MineshaftItem.COPPER, 800l);
+ case 1:
+ return Collections.singletonMap(MineshaftItem.IRON, 1600l);
+ case 2:
+ return Collections.singletonMap(MineshaftItem.GOLD, 1600l);
+ case 3:
+ return Collections.singletonMap(MineshaftItem.DIAMOND, 1600l);
+ case 4:
+ return Collections.singletonMap(MineshaftItem.NETHERITE, 1600l);
+ }
+
+ return Collections.emptyMap();
+ }
+
+ public Map<MineshaftItem, Long> getArmourUpgradeCost(Member member) {
+ int level = getBot().getArmour(member).getLevel();
+
+ switch ((int) level) {
+ case 0:
+ return Collections.singletonMap(MineshaftItem.COPPER, 600l);
+ case 1:
+ return Collections.singletonMap(MineshaftItem.IRON, 1200l);
+ case 2:
+ return Collections.singletonMap(MineshaftItem.GOLD, 1200l);
+ case 3:
+ return Collections.singletonMap(MineshaftItem.DIAMOND, 1200l);
+ case 4:
+ return Collections.singletonMap(MineshaftItem.NETHERITE, 1200l);
+ }
+
+ return Collections.emptyMap();
+ }
+
+ public boolean isReady(Member member) {
+ if (!isWorking(member))
+ return false;
+
+ return getQuantity(member) < 0;
+ }
+
+ public void incrementQuestions(Member member) {
+ questionsStat.increment(member, 1);
+ }
+
+ public void resetQuestions(Member member) {
+ questionsStat.set(member, 0);
+ }
+
+ public long getQuestions(Member member) {
+ return questionsStat.get(member);
+ }
+
+ public String getWorkingString(Member member) {
+ long questions = getQuestions(member);
+ StringBuilder b = new StringBuilder();
+
+ long forges = getValidForgeCount(member);
+ if (forges > 1)
+ b.append("We are busy working on your ");
+ else
+ b.append("I am busy working on your ");
+
+ b.append(getWorkingName(member));
+ b.append(".\n");
+
+ if (questions < 1)
+ return b.toString();
+
+ if (questions == 1)
+ b.append("Please do not disturb me. ");
+
+ if (questions == 2)
+ b.append("Go away I'm busy. ");
+
+ if (questions == 3)
+ b.append("Leave me alone, let me work in peace... ");
+
+ if (questions == 4)
+ b.append("Stop bugging me. ");
+
+ if (questions == 5)
+ b.append("Fine, ");
+
+ if (questions >= 5) {
+ double progress = getProgress(member);
+ b.append("I am about " + + Math.round(100*progress) + "** of the way to finishing.\n");
+ }
+
+ if (questions == 6)
+ b.append("Happy? Now leave me alone. ");
+
+ if (questions == 7)
+ b.append("Is there anything more you want?");
+
+ if (questions == 8)
+ b.append("Thats the best I can give you ");
+
+ if (questions == 9)
+ b.append("You want a time estimate? If you keep bugging me I will never finish");
+
+ if (questions == 10)
+ b.append("Seriously, leave me alone! ");
+
+ if (questions == 11)
+ b.append("I have had it with you...");
+
+ if (questions >= 12)
+ b.append("It will be finished in *about* `" + PeelingUtils.formatTime(getTimeEstimateRemaining(member)) + "`\n");
+
+ if (questions == 12)
+ b.append("Happy now?");
+
+ if (questions == 13)
+ b.append("Is there anything else you want?");
+
+ if (questions == 14)
+ b.append("I can't give you any more info than that sorry...");
+
+ if (questions == 15)
+ b.append("Seriously that is all I know");
+
+ if (questions == 16)
+ b.append("If you keep asking then I won't ever finish");
+
+ if (questions == 17)
+ b.append("That is the best I have, sorry");
+
+ if (questions == 18)
+ b.append("Please be patient! ");
+
+ if (questions >= 19)
+ b.append("Please come back later! ");
+
+ if (questions == 50)
+ b.append("You sure are impatient aren't you?");
+
+ if (questions == 100)
+ b.append("This is the 100th time you've asked... I'm sure you are proud of yourself");
+
+ if (questions >= 500)
+ return "You have asked me too many times. No more updates sorry.";
+
+ return b.toString();
+
+ }
+
+
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/BlacksmithCommand.java b/src/main/java/net/uomc/mineshaft/blacksmith/BlacksmithCommand.java
new file mode 100644
index 0000000..db57d55
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/BlacksmithCommand.java
@@ -0,0 +1,151 @@
+package net.uomc.mineshaft.blacksmith;
+
+
+import java.awt.Color;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import com.mouldycheerio.dbot.CustomBot;
+import com.mouldycheerio.dbot.commands.CommandDetails;
+import com.mouldycheerio.dbot.commands.CommandFail;
+import com.mouldycheerio.dbot.commands.DetailedCommand;
+import com.mouldycheerio.dbot.util.PeelingUtils;
+
+import net.dv8tion.jda.api.EmbedBuilder;
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
+import net.uomc.mineshaft.Mineshaft;
+import net.uomc.mineshaft.MineshaftItem;
+
+public class BlacksmithCommand extends DetailedCommand {
+
+ private static final Color COMMAND_COLOUR = PeelingUtils.hex2Rgb("#252525");
+ private static final String COMMAND_TITLE = "Blacksmith";
+ private static final String COMMAND_IMAGE = "https://minecraft.wiki/images/Plains_Armorer.png?0dee1";
+
+ Mineshaft bot;
+ Blacksmith blacksmith;
+
+ public BlacksmithCommand(Mineshaft bot) {
+ setCommandDetails(CommandDetails.from("blacksmith", "upgrade your tools", "blacksmith upgrade"));
+ this.bot = bot;
+
+ blacksmith = new Blacksmith(bot);
+
+ bot.getCommandController().addCommand("upgrade", (e, b, args) -> {
+ // allow also upgrading pickaxe
+ if (Arrays.stream(args).filter(a -> a.equalsIgnoreCase("pick") || a.equalsIgnoreCase("pickaxe")).findFirst().isPresent()) {
+ bot.getCommandController().getCommand("pickaxe").execute(e, bot, new String[]{"upgrade"});
+ return;
+ }
+
+ execute(e, bot, Stream.concat(Stream.of("upgrade"), Arrays.stream(args)).toArray(String[]::new));
+ });
+ }
+
+ @Override
+ public void execute(MessageReceivedEvent e, CustomBot b, String[] args) throws CommandFail {
+ Member m = e.getMember();
+ List<String> argList = Arrays.asList(args);
+
+ long blacksmiths = bot.getItem(m, MineshaftItem.BLACKSMITH);
+
+ if (blacksmiths < 1) {
+ b.sendErrorMessage(e, ":x: You need to have at least **"
+ + bot.getItem(MineshaftItem.BLACKSMITH).prettyValue(1)
+ + "** to use this!");
+ return;
+ }
+
+ long forges = bot.getItem(m, MineshaftItem.FORGE);
+
+ EmbedBuilder em = new EmbedBuilder();
+ em.setTitle(COMMAND_TITLE);
+ em.setThumbnail(COMMAND_IMAGE);
+ em.setColor(COMMAND_COLOUR);
+
+ blacksmith.update(m);
+
+ if (blacksmith.isWorking(m)) {
+ if (blacksmith.isReady(m)) {
+ // do get new sword
+ return;
+ }
+
+ em.setDescription(blacksmith.getWorkingString(m));
+ blacksmith.incrementQuestions(m);
+ e.getMessage().replyEmbeds(em.build()).queue();
+ return;
+ }
+
+ if (args.length > 1 && "upgrade".equalsIgnoreCase(args[0])) {
+ if (forges < 1) {
+ em.setDescription(String.format("Sorry, I can't work without a forge %s!", bot.getItem(MineshaftItem.FORGE).getSymbol()));
+ return;
+ }
+
+ if (!upgrade(e, argList))
+ bot.sendErrorMessage(e, String.format(":x: Usage `%supgrade [sword|armour]`", bot.getPrefixManager().getPrefix(e.getGuild())));
+ return;
+ }
+
+
+ em.appendDescription(String.format("Hello, I am your blacksmith. I can upgrade your tools and armour for you `%supgrade [sword|armour]`\n\n",
+ bot.getPrefixManager().getPrefix(e.getGuild())
+ ));
+
+ String swordName = "You have a **" + bot.getSword(m).getName() + " Sword**";
+ Map<MineshaftItem, Long> swordUpgradeCost = blacksmith.getSwordUpgradeCost(m);
+
+ if (bot.getSword(m).getLevel() == 0) {
+ swordName = "**You have no sword**";
+ }
+
+ String armourName = "You have a **" + bot.getArmour(m).getName() + " Armour**";
+ Map<MineshaftItem, Long> armourUpgradeCost = blacksmith.getArmourUpgradeCost(m);
+
+ if (bot.getArmour(m).getLevel() == 0) {
+ armourName = "**You have no armour**";
+ }
+
+ em.appendDescription(String.format("%s\n", swordName));
+ if (blacksmith.canUpgradeSword(m))
+ em.appendDescription(String.format("Upgrade to **%s** for **%s**\n",
+ blacksmith.getNextSwordName(m),
+ String.join(",", bot.createItemList(swordUpgradeCost).split("\n"))));
+
+ em.appendDescription("\n");
+
+ em.appendDescription(String.format("**%s**\n", armourName));
+ if (blacksmith.canUpgradeArmour(m))
+ em.appendDescription(String.format("Upgrade to **%s** for **%s**\n",
+ blacksmith.getNextArmourName(m),
+ String.join(",", bot.createItemList(armourUpgradeCost).split("\n"))));
+
+ em.appendDescription("\n");
+
+ if (blacksmiths > 1) {
+ long forgeCount = blacksmith.getValidForgeCount(m);
+ String total = bot.prettyValue(MineshaftItem.BLACKSMITH, blacksmiths);
+ if (forgeCount < blacksmiths) {
+ em.appendDescription("**" + forgeCount + "/" + total + "** are able to work.\n");
+ em.appendDescription("Get more " + bot.getItem(MineshaftItem.FORGE).getSymbol() + " so they can work!");
+ } else {
+ em.appendDescription("Your **" + total + "** are all able to work!");
+ }
+ } else if (blacksmiths == 1) {
+ em.appendDescription("I am currently working alone. Hire more **" + bot.getItem(MineshaftItem.BLACKSMITH).getSymbol() + "** to speed up progress!");
+ } else {
+ em.appendDescription("I need a " + bot.getItem(MineshaftItem.FORGE).getSymbol() + " so I can get to work!");
+ }
+
+ e.getMessage().replyEmbeds(em.build()).queue();
+
+ }
+
+ private boolean upgrade(MessageReceivedEvent e, List<String> argList) {
+ throw new UnsupportedOperationException("Unimplemented method 'upgrade'");
+ }
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Map.java b/src/main/java/net/uomc/mineshaft/blacksmith/Map.java
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Map.java
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Pickaxe.java b/src/main/java/net/uomc/mineshaft/blacksmith/Pickaxe.java
new file mode 100644
index 0000000..ffe18d5
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Pickaxe.java
@@ -0,0 +1,211 @@
+package net.uomc.mineshaft.blacksmith;
+
+import java.sql.SQLException;
+import java.util.Collections;
+
+import com.mouldycheerio.dbot.util.DatabaseUtils;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+import net.uomc.mineshaft.SavedStat;
+
+public class Pickaxe extends Tool {
+
+ public static final int MAX_PICKAXE_LEVEL = 5;
+
+ public static final String LEVEL_TABLE = "pickaxe_level";
+ public static final String FORTUNE_TABLE = "pickaxe_ench_fortune";
+ public static final String EFFICIENCY_TABLE = "pickaxe_ench_efficiency";
+
+ private SavedStat levelStat;
+ private SavedStat fortuneStat;
+ private SavedStat efficiencyStat;
+
+ public Pickaxe(Mineshaft mineshaft, Member member) {
+ super(mineshaft, member, "pickaxe");
+ initStats();
+ }
+
+ private void initStats() {
+ System.out.println("initing stats");
+ try {
+ upgradeTableVersion();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ levelStat = bot.getPlayerStats().getStat(LEVEL_TABLE);
+ fortuneStat = bot.getPlayerStats().getStat(FORTUNE_TABLE);
+ efficiencyStat = bot.getPlayerStats().getStat(EFFICIENCY_TABLE);
+ }
+
+ private void upgradeTableVersion() throws SQLException {
+ String dbPath = bot.getPlayerStats().getDbPath();
+ String oldLevelTable = "levels";
+ System.out.println("checking if table " + oldLevelTable + " exists...");
+ if (DatabaseUtils.tableExists(dbPath, oldLevelTable)) {
+ System.out.println("it does!");
+ if (DatabaseUtils.tableExists(dbPath, LEVEL_TABLE)) {
+ DatabaseUtils.deleteTable(dbPath, LEVEL_TABLE);
+ }
+
+ DatabaseUtils.renameTable(dbPath, oldLevelTable, LEVEL_TABLE);
+ }
+
+ String oldFortuneTable = "ench_fortune";
+ if (DatabaseUtils.tableExists(dbPath, oldFortuneTable)) {
+ if (DatabaseUtils.tableExists(dbPath, FORTUNE_TABLE)) {
+ DatabaseUtils.deleteTable(dbPath, FORTUNE_TABLE);
+ }
+
+ DatabaseUtils.renameTable(dbPath, oldFortuneTable, FORTUNE_TABLE);
+ }
+
+ String oldEfficiencyTable = "ench_efficiency";
+ if (DatabaseUtils.tableExists(dbPath, oldEfficiencyTable)) {
+ if (DatabaseUtils.tableExists(dbPath, EFFICIENCY_TABLE)) {
+ DatabaseUtils.deleteTable(dbPath, EFFICIENCY_TABLE);
+ }
+
+ DatabaseUtils.renameTable(dbPath, oldEfficiencyTable, EFFICIENCY_TABLE);
+ }
+ }
+
+
+ public void setLevel(long value) {
+ levelStat.set(member, value);
+ }
+
+ public int getLevel() {
+ return (int) levelStat.get(member);
+ }
+
+ public void setEfficiency(int value) {
+ efficiencyStat.set(member, value);
+ }
+
+ public int getEfficiency() {
+ return (int) efficiencyStat.get(member);
+ }
+
+ public void setFortune(int value) {
+ efficiencyStat.set(member, value);
+ }
+
+ public int getFortune() {
+ return (int) fortuneStat.get(member);
+ }
+
+ public boolean isEnchanted() {
+ long fortune = getFortune();
+ long eff = getEfficiency();
+ return fortune+eff > 0;
+ }
+
+ public String getName() {
+ long level = getLevel();
+ return pickaxeLevelToName(level);
+ }
+
+ public String getNextName() {
+ long level = getLevel() + 1;
+ if (level == getMaxLevel())
+ level = getMaxLevel();
+
+ return pickaxeLevelToName(level);
+ }
+
+ public static String pickaxeLevelToName(long level) {
+ switch ((int) level) {
+ case 0:
+ return "Stone";
+ case 1:
+ return "Copper";
+ case 2:
+ return "Iron";
+ case 3:
+ return "Gold";
+ case 4:
+ return "Diamond";
+ default:
+ return "Netherite";
+ }
+ }
+
+ public String getImage() {
+ long level = getLevel();
+ switch ((int) level) {
+ case 0:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Enchanted_Stone_Pickaxe.gif"
+ : "https://minecraft.wiki/images/Stone_Pickaxe_JE2_BE2.png";
+ case 1:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Enchanted_Copper_Pickaxe.webp"
+ : "https://minecraft.wiki/images/Copper_Pickaxe_JE1_BE1.png";
+ case 2:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Enchanted_Iron_Pickaxe.gif"
+ : "https://minecraft.wiki/images/Iron_Pickaxe_JE3_BE2.png";
+ case 3:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Enchanted_Golden_Pickaxe.gif"
+ : "https://minecraft.wiki/images/Golden_Pickaxe_JE4_BE3.png";
+ case 4:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Enchanted_Diamond_Pickaxe.gif"
+ : "https://minecraft.wiki/images/Diamond_Pickaxe_JE3_BE3.png";
+ default:
+ return isEnchanted() ?
+ "https://minecraft.wiki/images/Netherite_Pickaxe_JE3.png"
+ : "https://minecraft.wiki/images/Enchanted_Netherite_Pickaxe.gif";
+ }
+ }
+
+ public int getMaxLevel() {
+ return MAX_PICKAXE_LEVEL;
+ }
+
+ public int incrementFortune() {
+ fortuneStat.increment(member, 1);
+ return (int) getFortune();
+ }
+
+ public int incrementEfficiency() {
+ efficiencyStat.increment(member, 1);
+ return (int) getEfficiency();
+ }
+
+ public static String getRomanNumber(int number) {
+ return String.join("", Collections.nCopies(number, "I"))
+ .replace("IIIII", "V")
+ .replace("IIII", "IV")
+ .replace("VV", "X")
+ .replace("VIV", "IX")
+ .replace("XXXXX", "L")
+ .replace("XXXX", "XL")
+ .replace("LL", "C")
+ .replace("LXL", "XC")
+ .replace("CCCCC", "D")
+ .replace("CCCC", "CD")
+ .replace("DD", "M")
+ .replace("DCD", "CM");
+ }
+
+ public String getEnchantmentString() {
+ int fortune = getFortune();
+ int efficiency = getEfficiency();
+ String curr = "";
+ if (fortune > 0 || efficiency > 0) {
+ curr = "is enchanted with ";
+ if (fortune > 0)
+ curr += "**Fortune " + Pickaxe.getRomanNumber(fortune) + "** ";
+ if (efficiency > 0)
+ curr += "**Efficiency " + Pickaxe.getRomanNumber(efficiency) + "** ";
+ } else {
+ curr = "has no enchantments";
+ }
+ return curr;
+ }
+
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Sword.java b/src/main/java/net/uomc/mineshaft/blacksmith/Sword.java
new file mode 100644
index 0000000..aa3fcea
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Sword.java
@@ -0,0 +1,77 @@
+package net.uomc.mineshaft.blacksmith;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+
+public class Sword extends Tool {
+ public static final int MAX_SWORD_LEVEL = 5;
+
+ public Sword(Mineshaft mineshaft, Member member) {
+ super(mineshaft, member, "sword");
+ }
+
+ public String getName() {
+ return swordLevelToName(getLevel());
+ }
+
+ public String getEmoji() {
+ // TODO add if enchanted
+ return swordToEmoji(getLevel());
+ }
+
+ public static String swordToEmoji(int level) {
+ switch ((int) level) {
+ case 0:
+ return "";
+ case 1:
+ return "<:copper_sword:1432879763193856060>";
+ case 2:
+ return "<:iron_sword:1432879761268412446>";
+ case 3:
+ return "<:gold_sword:1432879759385432155>";
+ case 4:
+ return "<:diamond_sword:1432879757065850941>";
+ default:
+ return "<:netherite_sword:1432879754712711278>";
+ }
+ }
+
+ public static String swordLevelToName(int level) {
+ switch ((int) level) {
+ case 0:
+ return "None";
+ case 1:
+ return "Copper";
+ case 2:
+ return "Iron";
+ case 3:
+ return "Gold";
+ case 4:
+ return "Diamond";
+ default:
+ return "Netherite";
+ }
+ }
+
+ public int getMaxLevel() {
+ return MAX_SWORD_LEVEL;
+ }
+
+ public long getDamageBonus() {
+ switch ((int) getLevel()) {
+ case 0: // "None";
+ return 0;
+ case 1: // "Copper";
+ return 2;
+ case 2: // "Iron";
+ return 4;
+ case 3: // "Gold";
+ return 6;
+ case 4: // "Diamond";
+ return 8;
+ default: // "Netherite";
+ return 10;
+ }
+ }
+
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Tool.java b/src/main/java/net/uomc/mineshaft/blacksmith/Tool.java
new file mode 100644
index 0000000..0a154e3
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Tool.java
@@ -0,0 +1,33 @@
+package net.uomc.mineshaft.blacksmith;
+
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+import net.uomc.mineshaft.SavedStat;
+
+public class Tool {
+ Mineshaft bot;
+ Member member;
+
+ SavedStat levelStat;
+ String name;
+
+ public Tool(Mineshaft mineshaft, Member member, String name) {
+ this.name = name;
+ this.bot = mineshaft;
+ this.member = member;
+ initStats();
+ }
+
+ private void initStats() {
+ levelStat = bot.getPlayerStats().getStat(name + "_level");
+ }
+
+ public int getLevel() {
+ return (int) levelStat.get(member);
+ }
+
+ public void setLevel(int level) {
+ levelStat.set(member, level);
+ }
+
+}
diff --git a/src/main/java/net/uomc/mineshaft/blacksmith/Tools.java b/src/main/java/net/uomc/mineshaft/blacksmith/Tools.java
new file mode 100644
index 0000000..7727aca
--- /dev/null
+++ b/src/main/java/net/uomc/mineshaft/blacksmith/Tools.java
@@ -0,0 +1,48 @@
+package net.uomc.mineshaft.blacksmith;
+
+import java.util.HashMap;
+import java.util.Map;
+import net.dv8tion.jda.api.entities.Member;
+import net.uomc.mineshaft.Mineshaft;
+
+public class Tools {
+ private Mineshaft bot;
+
+ private Map<Member, Pickaxe> pickaxes;
+ private Map<Member, Armour> armours;
+ private Map<Member, Sword> swords;
+
+ public Tools(Mineshaft mineshaft) {
+ this.bot = mineshaft;
+ pickaxes = new HashMap<Member, Pickaxe>();
+ swords = new HashMap<Member, Sword>();
+ armours = new HashMap<Member, Armour>();
+ }
+
+ public Pickaxe getPickaxe(Member member) {
+ if (!pickaxes.containsKey(member)) {
+ Pickaxe pick = new Pickaxe(bot, member);
+ pickaxes.put(member, pick);
+ }
+
+ return pickaxes.get(member);
+ }
+
+ public Armour getArmour(Member member) {
+ if (!armours.containsKey(member)) {
+ Armour armour = new Armour(bot, member);
+ armours.put(member, armour);
+ }
+
+ return armours.get(member);
+ }
+ public Sword getSword(Member member) {
+ if (!swords.containsKey(member)) {
+ Sword sword = new Sword(bot, member);
+ swords.put(member, sword);
+ }
+
+ return swords.get(member);
+ }
+
+}