diff options
| author | davidovski <david@davidovski.xyz> | 2025-10-31 17:49:48 +0000 |
|---|---|---|
| committer | davidovski <david@davidovski.xyz> | 2025-10-31 17:49:48 +0000 |
| commit | 5a008748459e230de0e875afff59e3b92c7aca0c (patch) | |
| tree | 0d09aebd1bb5628237959a6d1b49d1a7772d86a6 /src/main/java | |
| parent | fff63aaea786a5f1c59bbf99c999a2aa7bb810e5 (diff) | |
Work on v0.6
Diffstat (limited to 'src/main/java')
31 files changed, 1853 insertions, 470 deletions
diff --git a/src/main/java/net/uomc/mineshaft/EatCommand.java b/src/main/java/net/uomc/mineshaft/EatCommand.java new file mode 100644 index 0000000..85a64e7 --- /dev/null +++ b/src/main/java/net/uomc/mineshaft/EatCommand.java @@ -0,0 +1,134 @@ +package net.uomc.mineshaft; + +import static java.util.Map.entry; +import java.awt.Color; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.jetbrains.annotations.NotNull; + +import com.mouldycheerio.dbot.commands.CommandDetails; +import com.mouldycheerio.dbot.commands.cooldowns.CooldownCommand; +import com.mouldycheerio.dbot.commands.cooldowns.CooldownController; +import com.mouldycheerio.dbot.util.PeelingUtils; +import com.vdurmont.emoji.EmojiParser; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.uomc.mineshaft.resources.commands.LeaderBoardCommand; + +public class EatCommand extends CooldownCommand { + + private static final UnicodeEmoji EAT_EMOJI = Emoji.fromUnicode(EmojiParser.parseToUnicode(":fork_and_knife:")); + private static final Color COMMAND_COLOR = PeelingUtils.hex2Rgb("#b23028"); + private Mineshaft bot; + private Map<MineshaftItem, Long> edible; + + public EatCommand(Mineshaft bot) { + super(bot); + setCommandDetails(CommandDetails.from("eat", "eat", "eat")); + this.bot = bot; + setCooldown(60l * 1000l); + + edible = Map.ofEntries( + entry(MineshaftItem.POTATO, 1l), + entry(MineshaftItem.CARROT, 1l), + entry(MineshaftItem.FISH, 2l), + entry(MineshaftItem.COOKED_FISH, 10l), + entry(MineshaftItem.BAKED_POTATO, 8l) + ); + } + + @Override + public boolean trigger(MessageReceivedEvent e) { + String[] args = e.getMessage().getContentRaw().split("\\s+"); + if (args.length > 1) { + String arg = String.join("_", Arrays.asList(Arrays.copyOfRange(args, 1, args.length))); + + MineshaftItem item = MineshaftItem.valueOf(arg.toUpperCase()); + if (item == null) { + bot.sendErrorMessage(e, ":x: Please provide a valid item! `m!eat [item]`"); + return false; + } + + return eat(e, item); + } + + String edible = getEdibleItems(e.getMember()); + + if (edible.length() < 0) { + bot.sendErrorMessage(e, ":x: You have no edible items!"); + return false; + } + + EmbedBuilder em = new EmbedBuilder(); + em.setColor(COMMAND_COLOR); + em.setTitle("Eat"); + em.setDescription("Use `m!eat [item]` to eat an item! The following items can be eaten:\n\n"); + em.appendDescription(edible); + + e.getMessage().replyEmbeds(em.build()).queue(); + return false; + } + + public Mineshaft getBot() { + return bot; + } + + public String getEdibleItems(Member m) { + return edible.entrySet().stream().filter(entry -> bot.hasItem(m, entry.getKey())).map(entry -> + bot.prettyValue(entry.getKey(), 1) + "🡒" + PlayerHealths.getHPString(entry.getValue()) + ).collect(Collectors.joining("\n")); + } + + public boolean eat(MessageReceivedEvent event, MineshaftItem item) { + Member member = event.getMember(); + if (!bot.hasItem(member, item)) { + bot.sendErrorMessage(event, "You don't have any " + bot.getItem(item).getSymbol() + " to eat!"); + return false; + } + + if (!isEdible(item)) { + bot.sendErrorMessage(event, "This item not edible!"); + return false; + } + long hp = bot.getHealths().getHP(member); + + if (hp >= PlayerHealths.MAX_HP) { + bot.sendErrorMessage(event, "You can't eat this! You are already at " + PlayerHealths.getHPString(hp)); + return false; + } + + long itemHp = edible.get(item); + hp += itemHp; + if (hp > PlayerHealths.MAX_HP) { + hp = PlayerHealths.MAX_HP; + } + + bot.removeItem(member, item, 1); + bot.getHealths().setHP(member, hp); + + event.getMessage().addReaction(EAT_EMOJI).queue(r -> { + event.getMessage().reply( + EAT_EMOJI.getFormatted() + " You ate " + bot.prettyValue(item, 1) + + ". You are now on " + bot.getHealths().getHPString(member) + " (+" + itemHp + ")" + ).delay(10, TimeUnit.SECONDS) + .flatMap(m -> m.delete()).queue(); + }); + + return true; + } + + public boolean isEdible(MineshaftItem item) { + return edible.entrySet().stream().filter(entry -> entry.getKey() == item).findFirst().isPresent(); + } +} diff --git a/src/main/java/net/uomc/mineshaft/EnchantCommand.java b/src/main/java/net/uomc/mineshaft/EnchantCommand.java index f147636..293351c 100644 --- a/src/main/java/net/uomc/mineshaft/EnchantCommand.java +++ b/src/main/java/net/uomc/mineshaft/EnchantCommand.java @@ -9,7 +9,9 @@ import com.mouldycheerio.dbot.util.PeelingUtils; import com.vdurmont.emoji.EmojiParser; 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.blacksmith.Pickaxe; public class EnchantCommand extends DetailedCommand { @@ -41,9 +43,12 @@ public class EnchantCommand extends DetailedCommand { return; } - int fortune = bot.getPickaxes().getPickaxeFortune(e.getMember()); - int efficiency = bot.getPickaxes().getPickaxeEfficiency(e.getMember()); - long bookshelves = bot.getItem(e.getMember(), MineshaftItem.BOOKSHELF); + Member m = e.getMember(); + Pickaxe pick = bot.getPickaxe(m); + + int fortune = pick.getFortune(); + int efficiency = pick.getEfficiency(); + long bookshelves = bot.getItem(m, MineshaftItem.BOOKSHELF); String bookshelfDiscountPercent = "-" + (int) Math.ceil((1 -bookshelfDiscount(bookshelves))*100) + "%"; long xpLevel = getXpLevel(fortune+efficiency, bookshelves); @@ -52,7 +57,7 @@ public class EnchantCommand extends DetailedCommand { long xpLevelNormal = getXpLevel(fortune+efficiency, 0); long lapisLevelNormal = getLapisLevel(fortune+efficiency, 0); - String curr = "Your pickaxe " + getPickaxeEnchantmentsString(fortune, efficiency); + String curr = "Your pickaxe " + pick.getEnchantmentString(); curr += "\n\n"; String description = curr + "Enchant your pickaxe with `" + b.getPrefixManager().getPrefix(e.getGuild()) + "enchant pickaxe`\n\n"; @@ -89,20 +94,6 @@ public class EnchantCommand extends DetailedCommand { e.getMessage().replyEmbeds(em.build()).queue(); } - public String getPickaxeEnchantmentsString(int fortune, int efficiency) { - String curr = ""; - if (fortune > 0 || efficiency > 0) { - curr = "is enchanted with "; - if (fortune > 0) - curr += "**Fortune " + Pickaxes.getRomanNumber(fortune) + "** "; - if (efficiency > 0) - curr += "**Efficiency " + Pickaxes.getRomanNumber(efficiency) + "** "; - } else { - curr = "has no enchantments"; - } - return curr; - } - private long getLapisLevel(int fortune, long bookshelves) { return (long) (Math.pow(2, fortune + 4) * bookshelfDiscount(bookshelves)); } @@ -121,15 +112,18 @@ public class EnchantCommand extends DetailedCommand { private void enchant(MessageReceivedEvent e, String[] args) { - int fortune = bot.getPickaxes().getPickaxeFortune(e.getMember()); - int efficiency = bot.getPickaxes().getPickaxeEfficiency(e.getMember()); + Member m = e.getMember(); + Pickaxe pick = bot.getPickaxe(m); + + int fortune = pick.getFortune(); + int efficiency = pick.getEfficiency(); - long bookshelves = bot.getItem(e.getMember(), MineshaftItem.BOOKSHELF); + long bookshelves = bot.getItem(m, MineshaftItem.BOOKSHELF); long xpLevel = getXpLevel(fortune + efficiency, bookshelves); long lapisLevel = getLapisLevel(fortune + efficiency, bookshelves); - long memberLapis = bot.getItem(e.getMember(), MineshaftItem.LAPIS); - long memberXp = bot.getItem(e.getMember(), MineshaftItem.XP); + long memberLapis = bot.getItem(m, MineshaftItem.LAPIS); + long memberXp = bot.getItem(m, MineshaftItem.XP); if (memberLapis < lapisLevel) { bot.sendErrorMessage(e, ":x: You need " + bot.getItem(MineshaftItem.LAPIS).prettyValue(lapisLevel - memberLapis) + " more lapis!" ); @@ -141,18 +135,18 @@ public class EnchantCommand extends DetailedCommand { return; } - bot.removeItem(e.getMember(), MineshaftItem.LAPIS, lapisLevel); - bot.removeItem(e.getMember(), MineshaftItem.XP, xpLevel); + bot.removeItem(m, MineshaftItem.LAPIS, lapisLevel); + bot.removeItem(m, MineshaftItem.XP, xpLevel); String newEnch = ""; if (Math.random() > 0.5) { - int level = bot.getPickaxes().incrementFortune(e.getMember()); - newEnch = "**Fortune " + Pickaxes.getRomanNumber(level) + "**"; + int level = pick.incrementFortune(); + newEnch = "**Fortune " + Pickaxe.getRomanNumber(level) + "**"; } else { - int level = bot.getPickaxes().incrementEfficiency(e.getMember()); - newEnch = "**Efficiency " + Pickaxes.getRomanNumber(level) + "**"; - + int level = pick.incrementEfficiency(); + newEnch = "**Efficiency " + Pickaxe.getRomanNumber(level) + "**"; } + bot.sendSuccessMessage(e, ":white_check_mark: You enchanted your pickaxe. You now have " + newEnch); } } diff --git a/src/main/java/net/uomc/mineshaft/FishCommand.java b/src/main/java/net/uomc/mineshaft/FishCommand.java index 37612ca..484e49b 100644 --- a/src/main/java/net/uomc/mineshaft/FishCommand.java +++ b/src/main/java/net/uomc/mineshaft/FishCommand.java @@ -37,6 +37,8 @@ public class FishCommand extends CooldownCommand { private static final String TITLE = "Fishing"; private static final String IMAGE_ROD = "https://minecraft.wiki/images/Fishing_Rod_JE2_BE2.png"; + private static final String FISHED_STAT = "times_fished"; + private Mineshaft bot; protected FishCommand(Mineshaft bot) { @@ -50,7 +52,7 @@ public class FishCommand extends CooldownCommand { @Override public boolean trigger(MessageReceivedEvent e) { - if (bot.getPickaxes().isNether(e.getMember())) { + if (bot.getPlayerStats().isNether(e.getMember())) { bot.sendErrorMessage(e, ":x: You cannot fish in the nether"); return false; } diff --git a/src/main/java/net/uomc/mineshaft/MineCommand.java b/src/main/java/net/uomc/mineshaft/MineCommand.java index 03207e3..dc9ae6d 100644 --- a/src/main/java/net/uomc/mineshaft/MineCommand.java +++ b/src/main/java/net/uomc/mineshaft/MineCommand.java @@ -4,16 +4,13 @@ package net.uomc.mineshaft; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.json.JSONObject; -import com.mouldycheerio.dbot.CustomBot; import com.mouldycheerio.dbot.commands.CommandDetails; import com.mouldycheerio.dbot.commands.cooldowns.CooldownCommand; import com.mouldycheerio.dbot.util.EventWaiter; @@ -23,11 +20,9 @@ import com.vdurmont.emoji.EmojiParser; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import net.uomc.mineshaft.resources.ResourceManager; public class MineCommand extends CooldownCommand { @@ -50,6 +45,8 @@ public class MineCommand extends CooldownCommand { private static final double SKULL_SPAWN_AMOUNT = 1; private static final double NETHERITE_SPAWN_AMOUNT = 1; + private static final String MINED_STAT = "times_mined"; + private Map<String, String> ores; private List<String> oresList; private List<String> netherOresList; @@ -138,7 +135,7 @@ public class MineCommand extends CooldownCommand { } public MineshaftItem getOre(Member m, boolean nether) { - int pickaxe = m == null ? Pickaxes.MAX_PICKAXE_LEVEL : bot.getPickaxes().getPickaxeLevel(m); + int pickaxe = m == null ? bot.getPickaxe(m).getMaxLevel() : bot.getPickaxe(m).getLevel(); double random = Math.random(); int maxOre = levelToMaxOre(pickaxe); @@ -156,7 +153,7 @@ public class MineCommand extends CooldownCommand { @Override public boolean trigger(MessageReceivedEvent e) { - boolean nether = bot.getPickaxes().isNether(e.getMember()); + boolean nether = bot.getPlayerStats().isNether(e.getMember()); MineshaftItem ore = getOre(e.getMember(), nether); int i; if (nether) { @@ -181,7 +178,7 @@ public class MineCommand extends CooldownCommand { if (!e.getMessage().getContentRaw().equalsIgnoreCase(getPickString(ore))) return false; - if (oreLevel > levelToMaxOre(bot.getPickaxes().getPickaxeLevel(e.getMember()))) + if (oreLevel > levelToMaxOre(bot.getPickaxe(e.getMember()).getLevel())) return false; return true; @@ -235,6 +232,7 @@ public class MineCommand extends CooldownCommand { Map<MineshaftItem, Long> awards = getAwards(member, ore); bot.addItems(member, awards); + bot.getPlayerStats().getStat(MINED_STAT).increment(member); String awardsList = bot.createItemList(awards, "+%s"); embedBuilder.setDescription(member.getAsMention() + " mined the ore!\n " + awardsList); @@ -333,11 +331,11 @@ public class MineCommand extends CooldownCommand { } public double getEfficiencyCurve(Member m) { - return 1 + Math.pow(0.5, bot.getPickaxes().getPickaxeEfficiency(m) / 2); - + return 1 + Math.pow(0.5, bot.getPickaxe(m).getEfficiency() / 2); } + private double getPickaxeFortuneCurve(Member m) { - int fortune = bot.getPickaxes().getPickaxeFortune(m); + int fortune = bot.getPickaxe(m).getFortune(); return fortune + Math.pow(1.2, fortune + 1); } diff --git a/src/main/java/net/uomc/mineshaft/Mineshaft.java b/src/main/java/net/uomc/mineshaft/Mineshaft.java index 41e4ce4..f2cbe4a 100644 --- a/src/main/java/net/uomc/mineshaft/Mineshaft.java +++ b/src/main/java/net/uomc/mineshaft/Mineshaft.java @@ -1,8 +1,14 @@ package net.uomc.mineshaft; +import net.uomc.mineshaft.blacksmith.Armour; +import net.uomc.mineshaft.blacksmith.BlacksmithCommand; +import net.uomc.mineshaft.blacksmith.Pickaxe; +import net.uomc.mineshaft.blacksmith.Sword; +import net.uomc.mineshaft.blacksmith.Tools; import net.uomc.mineshaft.crafting.Crafting; import net.uomc.mineshaft.farm.CompostCommand; import net.uomc.mineshaft.farm.FarmCommand; +import net.uomc.mineshaft.farm.CampfireCommand; import net.uomc.mineshaft.farm.TradeCommand; import net.uomc.mineshaft.resources.Resource; import java.io.IOException; @@ -12,19 +18,17 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; +import java.util.Optional; import java.util.stream.Collectors; import javax.security.auth.login.LoginException; -import org.apache.commons.collections4.map.LinkedMap; import org.json.JSONException; import org.json.JSONObject; import com.mouldycheerio.dbot.CustomBot; import com.mouldycheerio.dbot.commands.AvatarCommand; import com.mouldycheerio.dbot.commands.CommandDetails; -import com.mouldycheerio.dbot.commands.DetailedCommand; import com.mouldycheerio.dbot.commands.ProfileCommand; import com.mouldycheerio.dbot.commands.ServerInfoCommand; import com.mouldycheerio.dbot.commands.cooldowns.CooldownCommand; @@ -33,7 +37,6 @@ import com.mouldycheerio.dbot.starboard.StarboardController; import com.mouldycheerio.dbot.util.PeelingUtils; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.uomc.mineshaft.resources.ResourceManager; import net.uomc.mineshaft.resources.market.MarketCommand; @@ -42,7 +45,8 @@ public class Mineshaft extends CustomBot { private StarboardController starboardController; private FullLogger logger; private ResourceManager resourceManager; - private Pickaxes pickaxes; + private PlayerStats playerStats; + private Tools tools; private Crafting crafting; private MineCommand mineCommand; private EnchantCommand enchantCommand; @@ -51,7 +55,8 @@ public class Mineshaft extends CustomBot { public Mineshaft(JSONObject config) throws LoginException, JSONException, IOException, InterruptedException { super(config); - pickaxes = new Pickaxes(this); + playerStats = new PlayerStats(this); + tools = new Tools(this); healths = new PlayerHealths(this); crafting = new Crafting(this); getCommandController().addCommand(crafting); @@ -81,6 +86,20 @@ public class Mineshaft extends CustomBot { getCommandController().addCommand(new RobCommand(this)); getCommandController().addCommand(new TradeCommand(this)); + // TODO remove this comand + getCommandController().addCommand(CommandDetails.from("setsword"), (e, b, args) -> { + List<String> argList = Arrays.asList(args); + Optional<Integer> level = argList.stream().filter(s -> PeelingUtils.isInteger(s)) + .map(s -> Integer.parseInt(s)).findFirst(); + getSword(e.getMember()).setLevel(level.get()); + sendSuccessMessage(e, "Set sword level of " + e.getMember().getAsMention() + " to " + level.get()); + }); + + // TODO remove this comand + getCommandController().addCommand(CommandDetails.from("getsword"), (e, b, args) -> { + sendSuccessMessage(e, + "" + e.getMember().getAsMention() + " has sword level: " + getSword(e.getMember()).getLevel()); + }); getCommandController().removeCommand("help"); getCommandController().addCommand(CommandDetails.from("help"), (e, b, args) -> { @@ -172,7 +191,10 @@ public class Mineshaft extends CustomBot { getCommandController().addCommand(new MineshaftGiveResourcesCommand(this)); getCommandController().addCommand(new FarmCommand(this)); + getCommandController().addCommand(new CampfireCommand(this)); getCommandController().addCommand(new CompostCommand(this)); + getCommandController().addCommand(new EatCommand(this)); + getCommandController().addCommand(new BlacksmithCommand(this)); logger = new FullLogger(this); } @@ -235,6 +257,14 @@ public class Mineshaft extends CustomBot { return resourceManager.getResource(member, item.toString()); } + public boolean hasItem(Member member, MineshaftItem item) { + return getItem(member, item) > 0; + } + + public String prettyValue(MineshaftItem item, long value) { + return getItem(item).prettyValue(value); + } + public Resource getItem(MineshaftItem item) { return resourceManager.getResource(item.toString()); } @@ -282,6 +312,7 @@ public class Mineshaft extends CustomBot { public String createItemList(Map<MineshaftItem, Long> items) { LinkedHashMap<MineshaftItem, Long> itemsLinked = new LinkedHashMap<>(items); return resourceManager.createResourceList(itemsLinked.entrySet().stream() + .filter(e -> e.getValue() > 0) .collect(Collectors.toMap( e -> e.getKey().toString(), Map.Entry::getValue @@ -325,8 +356,23 @@ public class Mineshaft extends CustomBot { }).reduce(Boolean.TRUE, Boolean::logicalAnd); } - public Pickaxes getPickaxes() { - return pickaxes; + public PlayerStats getPlayerStats() { + return playerStats; + } + public Tools getTools() { + return tools; + } + + public Pickaxe getPickaxe(Member member) { + return tools.getPickaxe(member); + } + + public Sword getSword(Member member) { + return tools.getSword(member); + } + + public Armour getArmour(Member member) { + return tools.getArmour(member); } public MineCommand getMineCommand() { diff --git a/src/main/java/net/uomc/mineshaft/MineshaftGiveResourcesCommand.java b/src/main/java/net/uomc/mineshaft/MineshaftGiveResourcesCommand.java index 553bb76..3d05ab7 100644 --- a/src/main/java/net/uomc/mineshaft/MineshaftGiveResourcesCommand.java +++ b/src/main/java/net/uomc/mineshaft/MineshaftGiveResourcesCommand.java @@ -82,7 +82,7 @@ public class MineshaftGiveResourcesCommand extends DetailedCommand { return; } - if (bot.getPickaxes().isNether(member) != bot.getPickaxes().isNether(e.getMember())) { + if (bot.getPlayerStats().isNether(member) != bot.getPlayerStats().isNether(e.getMember())) { op.sendErrorMessage(e, ":x: You can't give items to players in other dimensions!"); return; } diff --git a/src/main/java/net/uomc/mineshaft/MineshaftItem.java b/src/main/java/net/uomc/mineshaft/MineshaftItem.java index 8956b93..90b6291 100644 --- a/src/main/java/net/uomc/mineshaft/MineshaftItem.java +++ b/src/main/java/net/uomc/mineshaft/MineshaftItem.java @@ -33,6 +33,11 @@ public enum MineshaftItem { COMPOSTER, BONEMEAL, IRON_FARM, + CAMPFIRE, + BAKED_POTATO, + COOKED_FISH, + BLACKSMITH, + FORGE, ; MineshaftItem() { diff --git a/src/main/java/net/uomc/mineshaft/MineshaftLeaderBoardCommand.java b/src/main/java/net/uomc/mineshaft/MineshaftLeaderBoardCommand.java index 91c9ef6..722b873 100644 --- a/src/main/java/net/uomc/mineshaft/MineshaftLeaderBoardCommand.java +++ b/src/main/java/net/uomc/mineshaft/MineshaftLeaderBoardCommand.java @@ -14,6 +14,7 @@ import com.mouldycheerio.dbot.commands.DetailedCommand; import com.mouldycheerio.dbot.util.PeelingUtils; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.uomc.mineshaft.blacksmith.Pickaxe; import net.uomc.mineshaft.resources.Resource; public class MineshaftLeaderBoardCommand extends DetailedCommand { @@ -33,26 +34,30 @@ public class MineshaftLeaderBoardCommand extends DetailedCommand { if (resource == null) { if (args[0].equalsIgnoreCase("pickaxes") || args[0].equalsIgnoreCase("pickaxe")) { bot.sendMessage(e, "Leaderboard", makeMessage( - bot.getPickaxes().getMembers(e.getGuild()), "pickaxe level", + bot.getPlayerStats().getStat(Pickaxe.LEVEL_TABLE).getMembers(e.getGuild()), "pickaxe level", entry -> { String ench = ""; - long level = bot.getPickaxes().getLevel(entry.getKey(), e.getGuild().getId()); - long fortune = bot.getPickaxes().getFortune(entry.getKey(), e.getGuild().getId()); - long efficiency = bot.getPickaxes().getEfficiency(entry.getKey(), e.getGuild().getId()); + long level = bot.getPlayerStats().getStat(Pickaxe.LEVEL_TABLE).get(entry.getKey(), e.getGuild().getId()); + long fortune = bot.getPlayerStats().getStat(Pickaxe.FORTUNE_TABLE).get(entry.getKey(), e.getGuild().getId()); + long efficiency = bot.getPlayerStats().getStat(Pickaxe.FORTUNE_TABLE).get(entry.getKey(), e.getGuild().getId()); if (fortune > 0 || efficiency > 0) { ench = String.format("(Eff%s,Fort%s)", efficiency, fortune); } - return Pickaxes.pickaxeLevelToName(level) + ench ; + return Pickaxe.pickaxeLevelToName(level) + ench ; }, - user -> bot.getPickaxes().getLevel(user, e.getGuild().getId()) + bot.getPickaxes().getEfficiency(user, e.getGuild().getId()) + bot.getPickaxes().getFortune(user, e.getGuild().getId()))); + user -> bot.getPlayerStats().getStat(Pickaxe.LEVEL_TABLE).get(user, e.getGuild().getId()) + + bot.getPlayerStats().getStat(Pickaxe.EFFICIENCY_TABLE).get(user, + e.getGuild().getId()) + + bot.getPlayerStats().getStat(Pickaxe.FORTUNE_TABLE).get(user, + e.getGuild().getId()))); return; } if (args[0].equalsIgnoreCase("farm") || args[0].equalsIgnoreCase("farmlevel")) { bot.sendMessage(e, "Leaderboard", makeMessage( - bot.getPickaxes().getMembers(e.getGuild()), "farm level", + bot.getPlayerStats().getStat(PlayerStats.FARM_LEVEL_TABLE).getMembers(e.getGuild()), "farm level", entry -> PeelingUtils.amountToString(entry.getValue()), - user -> bot.getPickaxes().getFarmLevel(user, e.getGuild().getId()) + user -> bot.getPlayerStats().getFarmLevel(user, e.getGuild().getId()) )); return; } diff --git a/src/main/java/net/uomc/mineshaft/PickaxeCommand.java b/src/main/java/net/uomc/mineshaft/PickaxeCommand.java index 31ac11c..a81ccd1 100644 --- a/src/main/java/net/uomc/mineshaft/PickaxeCommand.java +++ b/src/main/java/net/uomc/mineshaft/PickaxeCommand.java @@ -13,6 +13,7 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.uomc.mineshaft.blacksmith.Pickaxe; public class PickaxeCommand extends DetailedCommand { @@ -26,10 +27,11 @@ public class PickaxeCommand extends DetailedCommand { @Override public void execute(MessageReceivedEvent e, CustomBot b, String[] args) throws CommandFail { if (args.length > 0 && "upgrade".equalsIgnoreCase(args[0])) { - int level = bot.getPickaxes().getPickaxeLevel(e.getMember()); - Map<MineshaftItem, Long> upgradeCost = upgradeCost(e.getMember()); + Pickaxe pick = bot.getPickaxe(e.getMember()); + int level = pick.getLevel(); + Map<MineshaftItem, Long> upgradeCost = upgradeCost(pick); - if (level >= bot.getPickaxes().getMaPickaxeLevel()) { + if (level >= pick.getMaxLevel()) { bot.sendErrorMessage(e, ":x: Your pickaxe is already at the maximum level"); return; } @@ -42,31 +44,29 @@ public class PickaxeCommand extends DetailedCommand { } bot.removeItems(e.getMember(), upgradeCost); - bot.getPickaxes().setLevel(e.getMember(), level + 1); - String pickName = bot.getPickaxes().getPickaxeName(e.getMember()); + pick.setLevel(level + 1); + String pickName = pick.getName(); bot.sendSuccessMessage(e, "Your pickaxe has been upgraded to a **" + pickName + " Pickaxe**"); return; } - String pickName = bot.getPickaxes().getPickaxeName(e.getMember()); - String nextPick = bot.getPickaxes().getNextPickaxeName(e.getMember()); - String pickImage = bot.getPickaxes().getPickaxeImage(e.getMember()); - int fortune = bot.getPickaxes().getPickaxeFortune(e.getMember()); - int efficiency = bot.getPickaxes().getPickaxeEfficiency(e.getMember()); - Member target = PeelingUtils.getSingleMentionFromArgs(e); String p1 = target.equals(e.getMember()) ? "You currently have" : String.format("%s currently has", e.getMember().getEffectiveName()); String p2 = target.equals(e.getMember()) ? "Your pickaxe" : String.format("%s's pickaxe", e.getMember().getEffectiveName()); + Pickaxe pick = bot.getPickaxe(target); + String pickName = pick.getName(); + String nextPick = pick.getNextName(); + String pickImage = pick.getImage(); - Map<MineshaftItem, Long> upgradeCost = upgradeCost(target); + Map<MineshaftItem, Long> upgradeCost = upgradeCost(pick); String upgradeString = "\n\nTo upgrade to a **" + nextPick + " Pickaxe **, use `" + bot.getCommandController().getPrefix() + "pickaxe upgrade`.\nUpgrade cost: **" + String.join(",", bot.createItemList(upgradeCost).split("\n")) + "**"; if (!target.equals(e.getMember())){ upgradeString = ""; } - String enchants = String.format("\n%s ", p2) + bot.getEnchantCommand().getPickaxeEnchantmentsString(fortune, efficiency); + String enchants = String.format("\n%s ", p2) + pick.getEnchantmentString(); EmbedBuilder em = new EmbedBuilder(); em.setTitle(p2); @@ -76,10 +76,10 @@ public class PickaxeCommand extends DetailedCommand { e.getMessage().replyEmbeds(em.build()).queue(); } - private Map<MineshaftItem, Long> upgradeCost(Member m) { + private Map<MineshaftItem, Long> upgradeCost(Pickaxe pick) { Map<MineshaftItem, Long> cost = new HashMap<>(); - int level = bot.getPickaxes().getPickaxeLevel(m); + int level = pick.getLevel(); switch ((int) level) { case 0: diff --git a/src/main/java/net/uomc/mineshaft/Pickaxes.java b/src/main/java/net/uomc/mineshaft/Pickaxes.java deleted file mode 100644 index 39fa030..0000000 --- a/src/main/java/net/uomc/mineshaft/Pickaxes.java +++ /dev/null @@ -1,276 +0,0 @@ -package net.uomc.mineshaft; - -import java.io.File; -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.json.JSONObject; - -import com.mouldycheerio.dbot.util.DatabaseUtils; -import com.mouldycheerio.dbot.util.PeelingUtils; - -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Member; - -public class Pickaxes { - - public static final int MAX_PICKAXE_LEVEL = 5; - - private static final String LEVEL_TABLE = "levels"; - private static final String FORTUNE_TABLE = "ench_fortune"; - private static final String EFFICIENCY_TABLE = "ench_efficiency"; - private static final String DIMENSION_TABLE = "dimension"; - - private static final String FARM_LEVEL_TABLE = "farms"; - - private String pickaxesDb; - - public Pickaxes(Mineshaft mineshaft) { - pickaxesDb = (new File(mineshaft.getDatadir(), "pickaxes.db")).getPath(); - initDB(); - } - - private void initDB() { - try { - DatabaseUtils.createSimpleKVtable(pickaxesDb, FORTUNE_TABLE); - } catch (SQLException e) { - } - try { - DatabaseUtils.createSimpleKVtable(pickaxesDb, DIMENSION_TABLE); - } catch (SQLException e) { - } - try { - DatabaseUtils.createSimpleKVtable(pickaxesDb, EFFICIENCY_TABLE); - } catch (SQLException e) { - } - try { - DatabaseUtils.createSimpleKVtable(pickaxesDb, LEVEL_TABLE); - } catch (SQLException e) { - } - try { - DatabaseUtils.createSimpleKVtable(pickaxesDb, FARM_LEVEL_TABLE); - } catch (SQLException e) { - } - } - - public void setFarmLevel(Member member, long value) { - try { - DatabaseUtils.putInKVtable(pickaxesDb, FARM_LEVEL_TABLE, member.getId() + ":" + member.getGuild().getId(), value); - } catch (SQLException e) { - e.printStackTrace(); - } - } - public long getFarmLevel(String member, String guild) { - try { - return DatabaseUtils.getInKVtable(pickaxesDb, FARM_LEVEL_TABLE, member + ":" + guild); - } catch (SQLException e) { - e.printStackTrace(); - } - return 0l; - } - - public long getFarmLevel(Member member) { - return getFarmLevel(member.getId(), member.getGuild().getId()); - } - - public void setLevel(Member member, long value) { - try { - DatabaseUtils.putInKVtable(pickaxesDb, LEVEL_TABLE, member.getId() + ":" + member.getGuild().getId(), value); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public long getLevel(String member, String guild) { - try { - return DatabaseUtils.getInKVtable(pickaxesDb, LEVEL_TABLE, member + ":" + guild); - } catch (SQLException e) { - e.printStackTrace(); - } - return 0l; - } - - public long getLevel(Member member) { - return getLevel(member.getId(), member.getGuild().getId()); - } - public List<String> getMembersGuilds() { - try { - return DatabaseUtils.listKeys(pickaxesDb, LEVEL_TABLE); - } catch (SQLException e) { - e.printStackTrace(); - } - return Collections.emptyList(); - } - - public List<String> getMembers(Guild guild) { - return getMembersGuilds().stream().filter(m -> guild.getId().equals(m.split(":")[1])).map(m -> m.split(":")[0]).collect(Collectors.toList()); - } - - private void setEfficiency(Member member, long value) { - try { - DatabaseUtils.putInKVtable(pickaxesDb, EFFICIENCY_TABLE, member.getId() + ":" + member.getGuild().getId(), value); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public long getEfficiency(String member, String guild) { - try { - return DatabaseUtils.getInKVtable(pickaxesDb, EFFICIENCY_TABLE, member + ":" + guild); - } catch (SQLException e) { - e.printStackTrace(); - } - return 0l; - } - - public long getEfficiency(Member member) { - return getEfficiency(member.getId(), member.getGuild().getId()); - } - - private void setFortune(Member member, long value) { - try { - DatabaseUtils.putInKVtable(pickaxesDb, FORTUNE_TABLE, member.getId() + ":" + member.getGuild().getId(), value); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public long getFortune(String member, String guild) { - try { - return DatabaseUtils.getInKVtable(pickaxesDb, FORTUNE_TABLE, member + ":" + guild); - } catch (SQLException e) { - e.printStackTrace(); - } - return 0l; - } - - public long getFortune(Member member) { - return getFortune(member.getId(), member.getGuild().getId()); - } - - public void setNether(Member member, boolean nether) { - try { - DatabaseUtils.putInKVtable(pickaxesDb, DIMENSION_TABLE, member.getId() + ":" + member.getGuild().getId(), nether ? 1: 0); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public boolean isNether(Member member) { - try { - return DatabaseUtils.getInKVtable(pickaxesDb, DIMENSION_TABLE, member.getId() + ":" + member.getGuild().getId()) == 1; - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - - public boolean isEnchanted(Member member) { - long fortune = getFortune(member); - return fortune > 0; - } - - public String getPickaxeName(Member member) { - long level = getLevel(member); - return pickaxeLevelToName(level); - } - - public String getNextPickaxeName(Member member) { - long level = getLevel(member) + 1; - if (level == getMaPickaxeLevel()) - level = getMaPickaxeLevel(); - 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 getPickaxeImage(Member member) { - long level = getLevel(member); - switch ((int) level) { - case 0: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Enchanted_Stone_Pickaxe.gif" - : "https://minecraft.wiki/images/Stone_Pickaxe_JE2_BE2.png"; - case 1: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Enchanted_Copper_Pickaxe.webp" - : "https://minecraft.wiki/images/Copper_Pickaxe_JE1_BE1.png"; - case 2: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Enchanted_Iron_Pickaxe.gif" - : "https://minecraft.wiki/images/Iron_Pickaxe_JE3_BE2.png"; - case 3: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Enchanted_Golden_Pickaxe.gif" - : "https://minecraft.wiki/images/Golden_Pickaxe_JE4_BE3.png"; - case 4: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Enchanted_Diamond_Pickaxe.gif" - : "https://minecraft.wiki/images/Diamond_Pickaxe_JE3_BE3.png"; - default: - return isEnchanted(member) ? - "https://minecraft.wiki/images/Netherite_Pickaxe_JE3.png" - : "https://minecraft.wiki/images/Enchanted_Netherite_Pickaxe.gif"; - } - } - - public int getMaPickaxeLevel() { - return MAX_PICKAXE_LEVEL; - } - - public int getPickaxeLevel(Member member) { - return (int) getLevel(member); - } - - public int getPickaxeFortune(Member member) { - return (int) getFortune(member); - } - - public int getPickaxeEfficiency(Member member) { - return (int) getEfficiency(member); - } - - public int incrementFortune(Member member) { - setFortune(member, getFortune(member) + 1); - return (int) getFortune(member); - } - - public int incrementEfficiency(Member member) { - setEfficiency(member, getEfficiency(member) + 1); - return (int) getEfficiency(member); - } - - 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"); - } - -} diff --git a/src/main/java/net/uomc/mineshaft/PlayerHealths.java b/src/main/java/net/uomc/mineshaft/PlayerHealths.java index 395f71a..0b3af79 100644 --- a/src/main/java/net/uomc/mineshaft/PlayerHealths.java +++ b/src/main/java/net/uomc/mineshaft/PlayerHealths.java @@ -1,13 +1,12 @@ package net.uomc.mineshaft; -import java.io.File; -import java.sql.SQLException; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.Collections; import com.mouldycheerio.dbot.commands.CommandDetails; -import com.mouldycheerio.dbot.util.DatabaseUtils; import com.mouldycheerio.dbot.util.PeelingUtils; import com.vdurmont.emoji.EmojiManager; import com.vdurmont.emoji.EmojiParser; @@ -21,43 +20,41 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent; public class PlayerHealths { private static final String HP_TABLE = "hp"; - private static final String HP_EMOJI = "<:hp:1428837195329962115>"; - private String healthDb; + public static final String HP_EMOJI = "<:hp:1428837195329962115>"; private Mineshaft bot; - private static final long MAX_HP = 20; + public static final long MAX_HP = 20; + + private SavedStat healthStat; public PlayerHealths(Mineshaft bot) { this.bot = bot; - healthDb = (new File(bot.getDatadir(), "players.db")).getPath(); - initDB(); + healthStat = bot.getPlayerStats().getStat(HP_TABLE); + healthStat.setDefaultValue(MAX_HP); bot.getCommandController().addCommand(CommandDetails.from("hp,health"), (e, b, args) -> { Member member = PeelingUtils.getSingleMentionFromArgs(e); + + + if (e.getMember().getId().equals(b.getOwnerID())){ + Optional<Long> amount = Arrays.asList(args).stream().filter(s -> PeelingUtils.isLong(s)).map(s -> Long.parseLong(s)) + .findFirst(); + if (!amount.isEmpty()) { + setHP(member, amount.get()); + } + } + b.sendMessage(e, member.getEffectiveName() + "'s health", (member.equals(e.getMember()) ? "Your " : member.getEffectiveName() + "'s") + " health: " + getHPString(member)); }); } public void setHP(Member member, long value) { - try { - DatabaseUtils.putInKVtable(healthDb, HP_TABLE, member.getId() + ":" + member.getGuild().getId(), value); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - private long getHP(String member, String guild) { - try { - return DatabaseUtils.getInKVtable(healthDb, HP_TABLE, member + ":" + guild); - } catch (SQLException e) { - e.printStackTrace(); - } - return MAX_HP; + healthStat.set(member, value); } public long getHP(Member member) { - return getHP(member.getId(), member.getGuild().getId()); + return healthStat.get(member); } public String getHPString(Member member) { @@ -68,65 +65,82 @@ public class PlayerHealths { return "**" + hp + HP_EMOJI + "**"; } - public long damage(MessageReceivedEvent event, Member member, long amount, String reason) { - long hp = getHP(member); - hp -= amount; - if (hp <= 0) { - killPlayer(event, member, reason); - setHP(member, MAX_HP); - } else { - setHP(member, hp); + public long calculateDamage(Member member, long damage) { + return calculateDamage(member, null, true, damage); + } + + public long calculateDamage(Member member, boolean countArmour, long damage) { + return calculateDamage(member, null, countArmour, damage); + } + + public long calculateDamage(Member target, Member attacker, boolean countArmour, long damage) { + return calculateDamage(target, attacker, countArmour, true, damage); + } + + public long calculateDamage(Member target, Member attacker, boolean countArmour, boolean randomise, long damage) { + long bonus = 0; + if (attacker != null) { + bonus = bot.getSword(attacker).getDamageBonus(); } - return hp; + double n = 1; + + if (randomise) { + n = Math.random(); + } + + return (long) (n * Math.abs(damage)) + bonus - bot.getArmour(target).getDamageReduction(); + } + + public long damage(MessageReceivedEvent event, Member member, long amount, String reason) { + return damageAndDropIfKill(event, member, amount, reason, Collections.emptyMap()); } public long damageAndDropIfKill(MessageReceivedEvent event, Member member, long amount, String reason, Map<MineshaftItem, Long> items) { - long hp = getHP(member); - hp -= amount; - if (hp <= 0) { - killPlayerAndDrop(event, member, reason, items); - setHP(member, MAX_HP); - } else { + + long hp = getHP(member) - amount; + + if (hp > 0) { setHP(member, hp); + return hp; } + + killPlayerAndDrop(event, member, reason, items); + return hp; } public long damageAndDropIfKill(Message message, Member member, long amount, String reason, Map<MineshaftItem, Long> items) { long hp = getHP(member); hp -= amount; - if (hp <= 0) { - killPlayerAndDrop(message, member, reason, items); - setHP(member, MAX_HP); - } else { + + if (hp > 0) { setHP(member, hp); + return hp; } + + killPlayerAndDrop(message, member, reason, items); return hp; } public long damage(Message message, Member member, long amount, String reason) { - long hp = getHP(member); - hp -= amount; - if (hp <= 0) { - killPlayer(message, member, reason); - setHP(member, MAX_HP); - } else { + long hp = getHP(member) - amount; + + if (hp > 0) { setHP(member, hp); + return hp; } - return hp; - } - private void initDB() { - try { - DatabaseUtils.createSimpleKVtable(healthDb, HP_TABLE); - } catch (SQLException e) { - } + killPlayer(message, member, reason); + return hp; } public void killPlayerAndDrop(Message message, Member member, String deathMessage, Map<MineshaftItem, Long> items) { + setHP(member, MAX_HP); Map<MineshaftItem, Long> drops = DropUtil.getDeathDrops(bot, member); - drops = bot.sumItems(drops, items); + + if (!items.isEmpty()) + drops = bot.sumItems(drops, items); bot.removeItems(member, drops); @@ -137,6 +151,7 @@ public class PlayerHealths { DropUtil.spawnDropEdit(bot, message, embed, drops); return; } + String title = getDeathTitle(member, deathMessage); MessageEmbed embed = DropUtil.getDropEmbed(bot, drops, deathMessage, title); @@ -148,10 +163,10 @@ public class PlayerHealths { } public void killPlayer(MessageReceivedEvent event, Member member, String deathMessage ) { - killPlayerAndDrop(event, member, deathMessage, new HashMap<>()); + killPlayerAndDrop(event, member, deathMessage, Collections.emptyMap()); } public void killPlayer(Message message, Member member, String deathMessage ) { - killPlayerAndDrop(message, member, deathMessage, new HashMap<>()); + killPlayerAndDrop(message, member, deathMessage, Collections.emptyMap()); } private String getDeathTitle(Member member, String deathMessage) { diff --git a/src/main/java/net/uomc/mineshaft/PlayerStats.java b/src/main/java/net/uomc/mineshaft/PlayerStats.java new file mode 100644 index 0000000..40ef349 --- /dev/null +++ b/src/main/java/net/uomc/mineshaft/PlayerStats.java @@ -0,0 +1,80 @@ +package net.uomc.mineshaft; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import net.dv8tion.jda.api.entities.Member; + +public class PlayerStats { + + public static final int MAX_PICKAXE_LEVEL = 5; + + public static final String DIMENSION_TABLE = "dimension"; + public static final String FARM_LEVEL_TABLE = "farms"; + + private String playersDb; + + private Map<String, SavedStat> stats; + + public PlayerStats(Mineshaft mineshaft) { + File playersDbFile = new File(mineshaft.getDatadir(), "players.db"); + + // migrate old file if exists + if (!playersDbFile.exists()) { + File oldplayersDbFile = new File(mineshaft.getDatadir(), "pickaxes.db"); + if (oldplayersDbFile.exists()) { + oldplayersDbFile.renameTo(playersDbFile); + } + } + + stats = new HashMap<>(); + + playersDb = playersDbFile.getPath(); + initStats(); + } + + private void initStats() { + createStat(DIMENSION_TABLE); + createStat(FARM_LEVEL_TABLE); + } + + public SavedStat createStat(String name) { + SavedStat savedStat = new SavedStat(playersDb, name); + stats.put(name, savedStat); + return savedStat; + } + + + public SavedStat getStat(String name) { + if (stats.containsKey(name)) + return stats.get(name); + + SavedStat savedStat = new SavedStat(playersDb, name); + stats.put(name, savedStat); + return savedStat; + } + + public void setFarmLevel(Member member, long value) { + getStat(FARM_LEVEL_TABLE).set(member, value); + } + + public long getFarmLevel(String member, String guild) { + return getStat(FARM_LEVEL_TABLE).get(member, guild); + } + + public long getFarmLevel(Member member) { + return getFarmLevel(member.getId(), member.getGuild().getId()); + } + + public void setNether(Member member, boolean nether) { + getStat(DIMENSION_TABLE).set(member, nether ? 1 : 0); + } + + public boolean isNether(Member member) { + return getStat(DIMENSION_TABLE).get(member) == 1; + } + + public String getDbPath() { + return playersDb; + } +} diff --git a/src/main/java/net/uomc/mineshaft/Portal.java b/src/main/java/net/uomc/mineshaft/Portal.java index 2d3df02..499bdb4 100644 --- a/src/main/java/net/uomc/mineshaft/Portal.java +++ b/src/main/java/net/uomc/mineshaft/Portal.java @@ -53,13 +53,13 @@ public class Portal extends CooldownCommand { em.setColor(PeelingUtils.hex2Rgb("#8947e8")); em.setThumbnail(COMMAND_IMAGE); - if (bot.getPickaxes().isNether(e.getMember())) { - bot.getPickaxes().setNether(e.getMember(), false); + if (bot.getPlayerStats().isNether(e.getMember())) { + bot.getPlayerStats().setNether(e.getMember(), false); em.setDescription("You go through the potal... everything is back to normal\n\n**You are now in the overworld**"); em.setImage(OVERWORLD_IMAGE); } else { - bot.getPickaxes().setNether(e.getMember(), true); + bot.getPlayerStats().setNether(e.getMember(), true); em.setDescription("You go through the potal... things look different on this side...\n\n**You are now in the nether**"); em.setFooter(COMMAND_IMAGE); em.setImage(NETHER_IMAGE); diff --git a/src/main/java/net/uomc/mineshaft/RobCommand.java b/src/main/java/net/uomc/mineshaft/RobCommand.java index ace95e7..bfc0c51 100644 --- a/src/main/java/net/uomc/mineshaft/RobCommand.java +++ b/src/main/java/net/uomc/mineshaft/RobCommand.java @@ -1,47 +1,41 @@ package net.uomc.mineshaft; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; -import java.util.Random; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; import com.mouldycheerio.dbot.commands.CommandDetails; import com.mouldycheerio.dbot.commands.cooldowns.CooldownCommand; -import com.mouldycheerio.dbot.util.PeelingUtils; import com.mouldycheerio.dbot.util.EventWaiter; +import com.mouldycheerio.dbot.util.PeelingUtils; import com.vdurmont.emoji.EmojiParser; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; public class RobCommand extends CooldownCommand { - private static final long DROP_DURATION_SECONDS = 90; - private static final String LOOT_STRING = "loot"; - - private static final long MAX_DAMAGE = 20; + private static final UnicodeEmoji FLEE_EMOJI = Emoji.fromUnicode(EmojiParser.parseToUnicode(":runner:")); + private static final UnicodeEmoji FIGHT_EMOJI = Emoji.fromUnicode(EmojiParser.parseToUnicode(":crossed_swords:")); + private static final long BASE_DAMAGE = 14; + private static final long CONFIRM_WAIT_SECONDS = 10; + private static final double FLEE_CHANCE = 0.3; private Mineshaft bot; - private @NotNull String embedTitle; - private @NotNull String pvpEmoji; + private String pvpEmoji; protected RobCommand(Mineshaft bot) { super(bot); - setCooldown(60l * 30l * 1000l); + // TODO reset this + // setCooldown(60l * 30l * 1000l); + setCooldown(0l); this.bot = bot; - setDetails(CommandDetails.from("kill,pvp,rob", "kill another player")); - embedTitle = EmojiParser.parseToUnicode(":crossed_swords:"); + setDetails(CommandDetails.from("kill,pvp,rob,fight,challenge", "kill another player")); pvpEmoji = EmojiParser.parseToUnicode(":crossed_swords:"); } @@ -59,36 +53,144 @@ public class RobCommand extends CooldownCommand { return false; } Member target = mentionToMember.get(); + if (target.equals(e.getMember())) { + e.getMessage().reply(":x: You cannot fight yourself!").queue(); + return false; + } - if (bot.getPickaxes().isNether(target) != bot.getPickaxes().isNether(e.getMember())) { - e.getMessage().reply(":x: You tried to kill " + target.getAsMention() + " but they were in a different dimension!").queue(); + if (!canFight(e.getMember())) { + e.getMessage().reply(":x: You tried to kill " + target.getAsMention() + + " you don't have a sword to fight with!\nUse `m!blacksmith` to forge one").queue(); + return false; + } + + if (bot.getPlayerStats().isNether(target) != bot.getPlayerStats().isNether(e.getMember())) { + e.getMessage().reply( + ":x: You tried to kill " + target.getAsMention() + " but they were in a different dimension!") + .queue(); return false; } e.getMessage().addReaction(Emoji.fromUnicode(pvpEmoji)).queue(); EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle(pvpEmoji); - eb.getDescriptionBuilder().append(e.getAuthor().getAsMention() + " is fighting " + target.getAsMention() + "..." ); + eb.setTitle("pvp"); + String startString = e.getAuthor().getAsMention() + " is fighting " + target.getAsMention() + "...\n\n"; + eb.getDescriptionBuilder().append(startString); + + eb.appendDescription(target.getAsMention() + ": React with " + FLEE_EMOJI.getFormatted() + " to flee"); + if (canFight(target)) { + eb.appendDescription(" or " + FIGHT_EMOJI.getFormatted() + " to fight back!"); + } + + eb.appendDescription("\n"); + eb.appendDescription(":warning: This chance will expire " + + PeelingUtils.formatTimeRelativeFromNow(CONFIRM_WAIT_SECONDS * 1000l) + "\n"); + eb.setColor(bot.color); - long damage = getDamage(e.getMember()); + long damage = bot.getHealths().calculateDamage(target, e.getMember(), false, BASE_DAMAGE); + + e.getMessage().replyEmbeds(eb.build()).queue(message -> { + + message.addReaction(FLEE_EMOJI).queue(); + if (canFight(target)) { + message.addReaction(FIGHT_EMOJI).queue(); + } + + message.addReaction(FLEE_EMOJI).queue((Void ignored) -> { + EventWaiter eventWaiter = new EventWaiter(); + e.getChannel().getJDA().addEventListener(eventWaiter); + + eventWaiter.waitForEvent(MessageReactionAddEvent.class, + e1 -> e1.getMessageId().equals(message.getId()) && e1.getUser().getId().equals(target.getId()) + && (FLEE_EMOJI.equals(e1.getReaction().getEmoji().asUnicode()) + || FIGHT_EMOJI.equals(e1.getReaction().getEmoji().asUnicode())), + e1 -> { + message.clearReactions().queue(); + eb.setDescription(startString); + + // target has a chance to evade the battle entirely + if (FLEE_EMOJI.equals(e1.getReaction().getEmoji().asUnicode())) { + if (Math.random() < FLEE_CHANCE) { + eb.appendDescription(FLEE_EMOJI.getFormatted() + target.getAsMention() + + " Managed to escape!\n"); + message.editMessageEmbeds(eb.build()).queueAfter(1, TimeUnit.SECONDS, m -> { + m.editMessageEmbeds(eb.build()).queue(); + }); + return; + + } else { + // fight happens anyway, if they can fight they will fight second + eb.appendDescription( + ":x:" + target.getAsMention() + " tried running away but failed!\n\n"); + message.editMessageEmbeds(eb.build()).queueAfter(1, TimeUnit.SECONDS, m1 -> { + fightBack(m1, e.getMember(), target, damage, eb); + }); + return; + } + } + + // target gets to fight first then attacker fights + if (FIGHT_EMOJI.equals(e1.getReaction().getEmoji().asUnicode()) && canFight(target)) { + eb.appendDescription(FIGHT_EMOJI.getFormatted() + target.getAsMention() + + " Anticipated the attack and got the first strike\n"); + message.editMessageEmbeds(eb.build()).queueAfter(1, TimeUnit.SECONDS, m1 -> { + fightBack(m1, target, e.getMember(), damage, eb); + }); + return; + } + + // attacker gets an attack and thats it + addFightMessage(message, target, e.getMember(), eb, damage, null); + }, CONFIRM_WAIT_SECONDS, TimeUnit.SECONDS, () -> { + message.clearReactions().queue(); + eb.setDescription(startString); + message.editMessageEmbeds(eb.build()).queueAfter(1, TimeUnit.SECONDS, m -> { + // attacker gets an attack (ambush) + addFightMessage(m, target, e.getMember(), eb, damage, null); + }); + }); + }); + }); + return true; + } + + public void fightBack(Message message, Member target, Member agressor, long attackerDamage, EmbedBuilder eb) { + long damage = bot.getHealths().calculateDamage(agressor, target, false, BASE_DAMAGE); + + addFightMessage(message, agressor, target, eb, damage, m -> { + addFightMessage(message, target, agressor, eb, attackerDamage, null); + }); + } + + public void addFightMessage(Message message, Member target, Member attacker, EmbedBuilder eb, long damage, + Consumer<Message> callback) { + String damageString = " (" + PlayerHealths.getHPString(-damage) + ")"; - e.getMessage().replyEmbeds(eb.build()).delay(5, TimeUnit.SECONDS, e.getJDA().getRateLimitPool()).flatMap(m -> { - String deathMessage = pvpEmoji + target.getAsMention() + " was slain by " + e.getAuthor().getAsMention() - + damageString; - long hp = bot.getHealths().damage(m, target, damage, deathMessage); - return hp > 0; - }, m -> { - eb.setDescription(e.getAuthor().getAsMention() + " attacked " + target.getAsMention() + damageString - + "\n\n" + "They are now on " + bot.getHealths().getHPString(target)); - return m.editMessageEmbeds(eb.build()); - }).queue(); - return true; + String swordEmoji = bot.getSword(attacker).getEmoji(); + String deathMessage = swordEmoji + target.getAsMention() + " was slain by " + attacker.getAsMention() + + damageString; + long hp = bot.getHealths().damage(message, target, damage, deathMessage); + + if (hp <= 0) { + return; + } + + eb.appendDescription( + swordEmoji + attacker.getAsMention() + " attacked " + target.getAsMention() + damageString + "\n"); + + if (callback != null) { + message.editMessageEmbeds(eb.build()).queue(callback); + } else { + eb.appendDescription("\n" + target.getAsMention() + " is now on " + bot.getHealths().getHPString(target)); + message.editMessageEmbeds(eb.build()).queue(); + } + return; } - private long getDamage(Member member) { - return (long) Math.ceil(MAX_DAMAGE * Math.random()); + public boolean canFight(Member member) { + return bot.getSword(member).getLevel() != 0; } } diff --git a/src/main/java/net/uomc/mineshaft/SavedStat.java b/src/main/java/net/uomc/mineshaft/SavedStat.java new file mode 100644 index 0000000..01718d5 --- /dev/null +++ b/src/main/java/net/uomc/mineshaft/SavedStat.java @@ -0,0 +1,81 @@ +package net.uomc.mineshaft; + +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import com.mouldycheerio.dbot.util.DatabaseUtils; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; + +public class SavedStat { + private long defaultValue = 0l; + private String dbPath; + private String tableName; + + public SavedStat(String dbPath, String tableName) { + this.dbPath = dbPath; + this.tableName = tableName; + createTable(); + } + + private void createTable() { + try { + DatabaseUtils.createSimpleKVtable(dbPath, tableName); + } catch (SQLException e) { + } + } + + public void set(Member member, long value) { + try { + DatabaseUtils.putInKVtable(dbPath, tableName, member.getId() + ":" + member.getGuild().getId(), value); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public long get(String member, String guild) { + try { + return DatabaseUtils.getInKVtable(dbPath, tableName, member + ":" + guild); + } catch (SQLException e) { + e.printStackTrace(); + } + return defaultValue; + } + + public long get(Member member) { + return get(member.getId(), member.getGuild().getId()); + } + + public List<String> getMembers(Guild guild) { + return getMembersGuilds().stream().filter(m -> guild.getId().equals(m.split(":")[1])).map(m -> m.split(":")[0]).collect(Collectors.toList()); + } + + public List<String> getMembersGuilds() { + try { + return DatabaseUtils.listKeys(dbPath, tableName); + } catch (SQLException e) { + e.printStackTrace(); + } + return Collections.emptyList(); + } + + public long getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(long defaultValue) { + this.defaultValue = defaultValue; + } + + public void increment(Member member, long amount) { + set(member, get(member) + amount); + } + + public void increment(Member member) { + set(member, get(member) + 1); + } + +} diff --git a/src/main/java/net/uomc/mineshaft/SleepCommand.java b/src/main/java/net/uomc/mineshaft/SleepCommand.java index ef97b8b..389e78b 100644 --- a/src/main/java/net/uomc/mineshaft/SleepCommand.java +++ b/src/main/java/net/uomc/mineshaft/SleepCommand.java @@ -4,6 +4,7 @@ import java.awt.Color; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ public class SleepCommand extends CooldownCommand { private static final int MAX_ITEMS_DROP = 10; private static final int MIN_ITEMS_DROP = 3; private static final long MAX_DAMAGE = 30; - private static final long MIN_DAMAGE = 20; + private static final long MIN_DAMAGE = 19; private Mineshaft bot; private static final String damageEmoji = EmojiParser.parseToUnicode(":fire:"); @@ -52,7 +53,7 @@ public class SleepCommand extends CooldownCommand { return false; } - if (bot.getPickaxes().isNether(e.getMember())) { + if (bot.getPlayerStats().isNether(e.getMember())) { long damage = (long) Math.ceil((MAX_DAMAGE-MIN_DAMAGE)*Math.random() + MIN_DAMAGE); String actionString = "Your bed exploded! " + PlayerHealths.getHPString(-damage) + "\n"; EmbedBuilder em = new EmbedBuilder(); @@ -63,24 +64,28 @@ public class SleepCommand extends CooldownCommand { bot.removeItem(e.getMember(), MineshaftItem.BED, 1); - e.getChannel().sendMessageEmbeds(em.build()).queue(m -> { + e.getMessage().replyEmbeds(em.build()).queue(m -> { int itemsDrop = (int) (Math.random() * (MAX_ITEMS_DROP-MIN_ITEMS_DROP) + MIN_ITEMS_DROP); Map<MineshaftItem, Long> award = new LinkedHashMap<>(); for (int i = 0; i < itemsDrop; ++i) { - award = bot.sumItems(award, + award.putAll(bot.sumItems(award, bot.getMineCommand().getAwards(null, bot.getMineCommand().getOre( - null, true))); + null, true)))); } long finalHP = bot.getHealths().damageAndDropIfKill(m, e.getMember(), damage, damageEmoji + " " + e.getMember().getAsMention() + " died to Intentional Game Design", award); if (finalHP > 0) { - bot.addItems(e.getMember(), award); + em.appendDescription(bot.createItemList(award, "+%s")); - MessageEmbed embed = DropUtil.getDropEmbed(bot, award, em.build()); - DropUtil.spawnDropEdit(bot, m, embed, award); + m.editMessageEmbeds(em.build()).queueAfter(2, TimeUnit.SECONDS, m2 -> { + bot.addItems(e.getMember(), award); + }); + + //MessageEmbed embed = DropUtil.getDropEmbed(bot, award, em.build()); + //DropUtil.spawnDropEdit(bot, m, embed, award); } }); 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); + } + +} diff --git a/src/main/java/net/uomc/mineshaft/crafting/Crafting.java b/src/main/java/net/uomc/mineshaft/crafting/Crafting.java index 6e2f670..9b257a2 100644 --- a/src/main/java/net/uomc/mineshaft/crafting/Crafting.java +++ b/src/main/java/net/uomc/mineshaft/crafting/Crafting.java @@ -151,7 +151,7 @@ public class Crafting extends DetailedCommand { return "**" + r.getPrettyName() + "**\n" + bot.createItemList(recipe.getIngredients(), "%s", ", ") - + " -> " + + " 🡒 " + r.prettyValue(recipe.getQuantity()); }).collect(Collectors.joining("\n\n")); } diff --git a/src/main/java/net/uomc/mineshaft/farm/Campfire.java b/src/main/java/net/uomc/mineshaft/farm/Campfire.java new file mode 100644 index 0000000..d7d25c7 --- /dev/null +++ b/src/main/java/net/uomc/mineshaft/farm/Campfire.java @@ -0,0 +1,24 @@ +package net.uomc.mineshaft.farm; + +import net.uomc.mineshaft.Mineshaft; +import net.uomc.mineshaft.MineshaftItem; + +class Campfire extends Farm { + + private MineshaftItem cookedItem; + private long cookingTime; + + public Campfire(Mineshaft bot, MineshaftItem item, MineshaftItem cookedItem, long cookingTime) { + super(bot, item); + this.cookedItem = cookedItem; + this.cookingTime = cookingTime; + } + + public MineshaftItem getCookedItem() { + return cookedItem; + } + + public long getCookingTime() { + return cookingTime; + } +} diff --git a/src/main/java/net/uomc/mineshaft/farm/CampfireCommand.java b/src/main/java/net/uomc/mineshaft/farm/CampfireCommand.java new file mode 100644 index 0000000..e3138dc --- /dev/null +++ b/src/main/java/net/uomc/mineshaft/farm/CampfireCommand.java @@ -0,0 +1,258 @@ +package net.uomc.mineshaft.farm; + +import static net.uomc.mineshaft.PlayerHealths.HP_EMOJI; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +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 com.vdurmont.emoji.EmojiParser; + +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 CampfireCommand extends DetailedCommand { + + private static final Color COMMAND_COLOUR = PeelingUtils.hex2Rgb("#a45802"); + private static final String COMMAND_TITLE = "Campfire"; + private static final String COMMAND_IMAGE = "https://minecraft.wiki/images/Campfire_%28S%29_JE2_BE2.gif"; + public static final int ITEMS_PER_CAMPFIRE = 4; + public static final long POTATO_COOKING_TIME = 1000l * 40l; + public static final long FISH_COOKING_TIME = 1000l * 90l; + + Mineshaft bot; + List<Campfire> farms; + + public CampfireCommand(Mineshaft bot) { + setCommandDetails(CommandDetails.from("campfire", "cook your food", "farm")); + this.bot = bot; + + farms = new ArrayList<>(); + farms.add(new Campfire(bot, MineshaftItem.FISH, MineshaftItem.COOKED_FISH, FISH_COOKING_TIME)); + farms.add(new Campfire(bot, MineshaftItem.POTATO, MineshaftItem.BAKED_POTATO, POTATO_COOKING_TIME)); + + bot.getCommandController().addCommand("cook", (e, b, args) -> { + execute(e, bot, Stream.concat(Stream.of("cook"), 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 campfires = bot.getItem(m, MineshaftItem.CAMPFIRE); + + if (campfires < 1) { + b.sendErrorMessage(e, ":x: You need to have at least **" + + bot.getItem(MineshaftItem.CAMPFIRE).prettyValue(1) + + "** to use this!"); + return; + } + + update(m); + + if (args.length > 1 && "cook".equalsIgnoreCase(args[0])) { + if (!cook(e, argList)) + bot.sendErrorMessage(e, String.format(":x: Usage `%scook [potato|fish] [amount] `", bot.getPrefixManager().getPrefix(e.getGuild()))); + return; + } + + StringBuilder description = new StringBuilder(); + description.append(String.format("This is your campfire. You currently have %s\nUse `%scook [potato|fish] [amount]` to cook your food.\n\n", + bot.prettyValue(MineshaftItem.CAMPFIRE, campfires), + bot.getPrefixManager().getPrefix(e.getGuild()) + )); + + Map<MineshaftItem, Long> award = new HashMap<>(); + + List<String> cooking = new ArrayList<>(); + AtomicLong waitingAmount = new AtomicLong(); + + // remove items if there are too many items for the num of campfires + // + long already = farms.stream().mapToLong(f -> f.getPlanted(m) + f.getQuantity(m)).sum(); + if (already > campfires * ITEMS_PER_CAMPFIRE) { + AtomicLong toRemove = new AtomicLong(already - (campfires * ITEMS_PER_CAMPFIRE)); + while (toRemove.get() > 0) { + long amountEach = toRemove.get(); + farms.forEach(f -> { + long amount = amountEach; + if (amount == 0 || toRemove.get() < 1) + return; // we already removed enough + + + if (f.getQuantity(m) >= amount) { + // count the cooked as removed + toRemove.addAndGet(-f.getQuantity(m)); + return; + } + + if (f.getPlanted(m) < amount) { + amount = f.getPlanted(m); + + } + // otherwise remove from planted + toRemove.addAndGet(-amount); + f.setPlanted(m, f.getPlanted(m) - amount); + award.put(f.getItem(), amount); + }); + } + } + + // add the cooked items to the award + // + farms.forEach(farm -> { + long cooked = farm.getQuantity(m); + long waiting = farm.getPlanted(m); + + if (cooked > 0) { + award.put(farm.getCookedItem(), cooked); + farm.setQuantity(m, 0); + cooked = 0; + } + + if (waiting < 1) + return; + + cooking.add(String.format("%s%s", waiting, bot.getItem(farm.getItem()).getSymbol())); + waitingAmount.addAndGet(waiting); + }); + + + if (waitingAmount.get() == 0) { + description.append("*You have nothing on your campfire*\n"); + } else { + description.append("You are currently cooking: " + String.join(",", cooking) + "\n"); + } + + if (award.size() > 0) { + description.append("\n"); + description.append(bot.createItemList(award, "+%s")); + } + + EmbedBuilder em = new EmbedBuilder(); + em.setTitle(COMMAND_TITLE); + em.setThumbnail(COMMAND_IMAGE); + em.setDescription(description); + em.setColor(COMMAND_COLOUR); + + bot.addItems(m, award); + + if (campfires <= 1) { + em.setFooter(EmojiParser.parseToUnicode(":bulb:") + "Get more campfires to cook more food at a time"); + } else { + em.setFooter(EmojiParser.parseToUnicode(":bulb:") + String.format("Cooking food increases the amount of %s it gives when you %seat it.", "HP", bot.getPrefixManager().getPrefix(e.getGuild()))); + } + + e.getMessage().replyEmbeds(em.build()).queue(); + } + + public boolean cook(MessageReceivedEvent e, List<String> args) { + if (args.size() > 3) + return false; + + Optional<String> resourceName = args.stream().filter(s -> !s.equalsIgnoreCase("all") && !s.equalsIgnoreCase("cook") && !PeelingUtils.isLong(s)).findFirst(); + if (resourceName.isEmpty()) + return false; + + MineshaftItem item = MineshaftItem.valueOf(resourceName.get().toUpperCase()); + if (item == null) { + bot.sendErrorMessage(e, ":x: Please provide a valid item!"); + return true; + } + + long campfires = bot.getItem(e.getMember(), MineshaftItem.CAMPFIRE); + + long already = farms.stream().mapToLong(f -> f.getPlanted(e.getMember()) + f.getQuantity(e.getMember())).sum(); + + long q = 0; + Optional<String> all = args.stream().filter(s -> s.equals("all")).findFirst(); + if (all.isEmpty()) { + Optional<Long> quantity = args.stream().filter(s -> PeelingUtils.isLong(s)).map(s -> Long.parseLong(s)).findFirst(); + if (quantity.isEmpty()) + return false; + + q = Math.abs(quantity.get()); + } else { + q = Math.min(bot.getItem(item).get(e.getMember()), (campfires * ITEMS_PER_CAMPFIRE) - already ) ; + } + + + if (already + q > campfires * ITEMS_PER_CAMPFIRE) { + bot.sendErrorMessage(e, String.format(":x: You can only have %s items cooking at the same time!", campfires * ITEMS_PER_CAMPFIRE)); + return true; + } + + Optional<Campfire> farm = farms.stream().filter(f -> f.getItem() == item).findFirst(); + if (farm.isEmpty()) { + bot.sendErrorMessage(e, ":x: This item cannot be cooked"); + return true; + } + + if (q > bot.getItem(item).get(e.getMember())) { + bot.sendErrorMessage(e, ":x: You dont have enough " + bot.getItem(item).getSymbol()); + return true; + } + + if (farm.get().getPlanted(e.getMember()) == 0) { + farm.get().setNextUpdate(e.getMember(), System.currentTimeMillis() + farm.get().getCookingTime()); + } + + bot.removeItem(e.getMember(), item, q); + farm.get().setPlanted(e.getMember(), farm.get().getPlanted(e.getMember()) + q); + + bot.sendSuccessMessage(e, String.format("You put %s on your campfire%s! Come back later when they have finished cooking", bot.getItem(item).prettyValue(q), campfires > 1 ? "s" : "")); + return true; + } + + public void update(Member m) { + farms.forEach(farm -> { + update(farm, m); + }); + } + + public void update(Campfire farm, Member m) { + long next = farm.getNextUpdate(m); + long now = System.currentTimeMillis(); + if (next == 0) { + next = now; + } + + if (next > now) + return; + + long since = now - next; + long updates = since / farm.getCookingTime(); + //System.out.printf("[farm %s] updates is %d\n", farm.getItem(), updates); + + long campfires = bot.getItem(m, MineshaftItem.CAMPFIRE); + + long planted = farm.getPlanted(m); + + if (planted > 0) { + long toCook = (campfires * updates); + if (toCook > planted) { + toCook = planted; + } + + farm.setQuantity(m, farm.getQuantity(m) + toCook); + farm.setPlanted(m, planted - toCook); + } + farm.setNextUpdate(m, farm.getNextUpdate(m) + farm.getCookingTime()*updates); + } +} diff --git a/src/main/java/net/uomc/mineshaft/farm/CompostCommand.java b/src/main/java/net/uomc/mineshaft/farm/CompostCommand.java index 0da607d..ce5deea 100644 --- a/src/main/java/net/uomc/mineshaft/farm/CompostCommand.java +++ b/src/main/java/net/uomc/mineshaft/farm/CompostCommand.java @@ -73,7 +73,7 @@ public class CompostCommand extends CooldownCommand { long itemAmount = getMaxCompostable(e.getMember(), composters, i); long bonemealAmount = (long) (itemAmount / COMPOST_LEVEL); - description.append(String.format("%s->%s\n", bot.getItem(i).prettyValue(itemAmount), bot.getItem(MineshaftItem.BONEMEAL).prettyValue(bonemealAmount))); + description.append(String.format("%s🡒%s\n", bot.getItem(i).prettyValue(itemAmount), bot.getItem(MineshaftItem.BONEMEAL).prettyValue(bonemealAmount))); }); if (amount.get() == 0) { @@ -120,7 +120,7 @@ public class CompostCommand extends CooldownCommand { bot.addItem(e.getMember(), MineshaftItem.BONEMEAL, bonemealAmount); String content = String.format(":white_check_mark: You turned %s into %s", bot.getItem(item).prettyValue(itemAmount), bot.getItem(MineshaftItem.BONEMEAL).prettyValue(bonemealAmount)); - if (bot.getPickaxes().getFarmLevel(e.getMember()) < 1) { + if (bot.getPlayerStats().getFarmLevel(e.getMember()) < 1) { content += "\nUse your bonemeal to expand your `m!farm`"; } bot.sendSuccessMessage(e, content); diff --git a/src/main/java/net/uomc/mineshaft/farm/Farm.java b/src/main/java/net/uomc/mineshaft/farm/Farm.java index d990216..5326df1 100644 --- a/src/main/java/net/uomc/mineshaft/farm/Farm.java +++ b/src/main/java/net/uomc/mineshaft/farm/Farm.java @@ -9,7 +9,7 @@ import net.dv8tion.jda.api.entities.Member; import net.uomc.mineshaft.Mineshaft; import net.uomc.mineshaft.MineshaftItem; -class Farm{ +public class Farm { private MineshaftItem item; @@ -87,7 +87,7 @@ class Farm{ } catch (SQLException e) { e.printStackTrace(); } - return 0l; + return System.currentTimeMillis(); } public void incrementPlanted(Member member, long d) { @@ -103,6 +103,10 @@ class Farm{ return q; } + public Mineshaft getBot() { + return bot; + } + public MineshaftItem getItem() { return item; } diff --git a/src/main/java/net/uomc/mineshaft/farm/FarmCommand.java b/src/main/java/net/uomc/mineshaft/farm/FarmCommand.java index 43b7576..bf700ab 100644 --- a/src/main/java/net/uomc/mineshaft/farm/FarmCommand.java +++ b/src/main/java/net/uomc/mineshaft/farm/FarmCommand.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.IntStream; +import java.util.stream.Stream; import com.mouldycheerio.dbot.CustomBot; import com.mouldycheerio.dbot.commands.CommandDetails; @@ -44,13 +45,23 @@ public class FarmCommand extends DetailedCommand { farms.add(new Farm(bot, MineshaftItem.CANE)); farms.add(new Farm(bot, MineshaftItem.CARROT)); farms.add(new Farm(bot, MineshaftItem.POTATO)); + + bot.getCommandController().addCommand("plant", (e, b, args) -> { + execute(e, bot, Stream.concat(Stream.of("plant"), Arrays.stream(args)).toArray(String[]::new)); + }); + bot.getCommandController().addCommand("harvest", (e, b, args) -> { + execute(e, bot, Stream.concat(Stream.of("harvest"), Arrays.stream(args)).toArray(String[]::new)); + }); + bot.getCommandController().addCommand("expand", (e, b, args) -> { + execute(e, bot, Stream.concat(Stream.of("expand"), Arrays.stream(args)).toArray(String[]::new)); + }); } @Override public void execute(MessageReceivedEvent e, CustomBot b, String[] args) throws CommandFail { List<String> argList = Arrays.asList(args); - if (bot.getPickaxes().isNether(e.getMember())) { + if (bot.getPlayerStats().isNether(e.getMember())) { bot.sendErrorMessage(e, ":x: You cannot access your farm from the nether"); return; } @@ -72,7 +83,7 @@ public class FarmCommand extends DetailedCommand { return; } - long farmLevel = bot.getPickaxes().getFarmLevel(e.getMember()); + long farmLevel = bot.getPlayerStats().getFarmLevel(e.getMember()); StringBuilder description = new StringBuilder(); description.append(String.format("This is your farm.\nUse `%sfarm plant [carrot|potato|cane] [amount]` to plant\nUse `%sfarm harvest` to harvest your crops\nUse %s to expand your farm with `%sfarm expand`\n\n", bot.getPrefixManager().getPrefix(e.getGuild()), @@ -126,9 +137,9 @@ public class FarmCommand extends DetailedCommand { } bot.removeItem(e.getMember(), item, q); - long farmLevel = bot.getPickaxes().getFarmLevel(e.getMember()); - bot.getPickaxes().setFarmLevel(e.getMember(), farmLevel + q); - farmLevel = bot.getPickaxes().getFarmLevel(e.getMember()); + long farmLevel = bot.getPlayerStats().getFarmLevel(e.getMember()); + bot.getPlayerStats().setFarmLevel(e.getMember(), farmLevel + q); + farmLevel = bot.getPlayerStats().getFarmLevel(e.getMember()); bot.sendSuccessMessage(e, ":white_check_mark: You expanded your farm. Now it can hold " + farmLevel + " crops"); return true; @@ -254,7 +265,7 @@ public class FarmCommand extends DetailedCommand { } public long plant(Farm farm, Member member, long amount) { - long farmLevel = bot.getPickaxes().getFarmLevel(member); + long farmLevel = bot.getPlayerStats().getFarmLevel(member); long totalPlanted = getTotalPlanted(member); if (totalPlanted + amount > farmLevel) { amount = farmLevel - totalPlanted; diff --git a/src/main/java/net/uomc/mineshaft/farm/TradeCommand.java b/src/main/java/net/uomc/mineshaft/farm/TradeCommand.java index f512afe..ad3a1be 100644 --- a/src/main/java/net/uomc/mineshaft/farm/TradeCommand.java +++ b/src/main/java/net/uomc/mineshaft/farm/TradeCommand.java @@ -45,12 +45,13 @@ public class TradeCommand extends CooldownCommand { MineshaftItem.BOOK, MineshaftItem.LAPIS, MineshaftItem.COAL, + MineshaftItem.WOOL, }; public static MineshaftItem[] buyingItems = { MineshaftItem.CARROT, MineshaftItem.CANE, - MineshaftItem.POTATO + MineshaftItem.POTATO, }; Mineshaft bot; @@ -98,7 +99,7 @@ public class TradeCommand extends CooldownCommand { long userGive = bot.getItem(e.getMember(), giveItem); long userGet = bot.getItem(e.getMember(), getItem); - description += String.format("**%s**->**%s**", bot.getItem(giveItem).prettyValue(p), bot.getItem(getItem).prettyValue(q)); + description += String.format("**%s**🡒**%s**", bot.getItem(giveItem).prettyValue(p), bot.getItem(getItem).prettyValue(q)); description += String.format( "\n\n:warning:Warning this offer expires in %s and you will need to wait `%s` before trading again", |
