package net.uomc.mineshaft.farm; import static java.util.stream.Collectors.toMap; 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.IntStream; 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 FarmCommand extends DetailedCommand { private static final Color COMMAND_COLOUR = PeelingUtils.hex2Rgb("#589430"); public static final long TIME_BETWEEN_UPDATES = 1000l * 60l * 10l; public static final int MAX_CROP_LEVEL = 2; private static final String COMMAND_TITLE = "Farm"; public static final long XP_PER_ITEM = 5000l; Mineshaft bot; List farms; public FarmCommand(Mineshaft bot) { setCommandDetails(CommandDetails.from("farm", "access your farm", "farm")); this.bot = bot; farms = new ArrayList<>(); farms.add(new Farm(bot, MineshaftItem.CANE)); farms.add(new Farm(bot, MineshaftItem.CARROT)); farms.add(new Farm(bot, MineshaftItem.POTATO)); } @Override public void execute(MessageReceivedEvent e, CustomBot b, String[] args) throws CommandFail { List argList = Arrays.asList(args); if (bot.getPickaxes().isNether(e.getMember())) { bot.sendErrorMessage(e, ":x: You cannot access your farm from the nether"); return; } update(e.getMember()); if (args.length > 0 && "harvest".equalsIgnoreCase(args[0])) { harvest(e, args); return; } if (args.length > 0 && "expand".equalsIgnoreCase(args[0])) { expand(e, argList); return; } if (args.length > 0 && "plant".equalsIgnoreCase(args[0])) { if (!plant(e, argList)) bot.sendErrorMessage(e, String.format(":x: Usage `%sfarm plant [amount] [carrot|potato|cane]`", bot.getPrefixManager().getPrefix(e.getGuild()))); return; } long farmLevel = bot.getPickaxes().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()), bot.getPrefixManager().getPrefix(e.getGuild()), bot.getItem(MineshaftItem.BONEMEAL).getSymbol(), bot.getPrefixManager().getPrefix(e.getGuild()))); description.append(String.format("Your farm current can currently hold `%s` crops\n\n", PeelingUtils.amountToString(farmLevel))); AtomicLong amount = new AtomicLong(); farms.forEach(farm -> { long level = Math.min(farm.getQuantity(e.getMember()), MAX_CROP_LEVEL); long planted = farm.getPlanted(e.getMember()); amount.addAndGet(planted); String emoji = getCropEmoji(farm.getItem(), (int) level); if (planted < 1) return; IntStream.range(0, (int) Math.min(planted,12)).forEach(i -> { description.append(emoji); }); description.append(String.format("(%sx%s)\n", bot.getItem(farm.getItem()).getSymbol(), planted)); }); if (amount.get() == 0) { description.append("*You have no crops*"); } EmbedBuilder em = new EmbedBuilder(); em.setTitle(COMMAND_TITLE); em.setDescription(description); em.setColor(COMMAND_COLOUR); if (farmLevel == 0) { em.setFooter(EmojiParser.parseToUnicode(":bulb:") +"Use bonemeal to expand your farm with m!farm expand"); } e.getMessage().replyEmbeds(em.build()).queue(); } private boolean expand(MessageReceivedEvent e, List args) { MineshaftItem item = MineshaftItem.BONEMEAL; long q = getItemAmountFromArgs(e, args, item); if (q > bot.getItem(e.getMember(), item) || q < 1) { bot.sendErrorMessage(e, ":x: You do not have enough " + bot.getItem(item).getSymbol()); return false; } 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()); bot.sendSuccessMessage(e, ":white_check_mark: You expanded your farm. Now it can hold " + farmLevel + " crops"); return true; } private long getItemAmountFromArgs(MessageReceivedEvent e, List args, MineshaftItem item) { Optional all = args.stream().filter(s -> s.equals("all")).findFirst(); if (all.isEmpty()) { Optional quantity = args.stream().filter(s -> PeelingUtils.isLong(s)).map(s -> Long.parseLong(s)).findFirst(); if (quantity.isPresent()) return Math.abs(quantity.get()); } return bot.getItem(item).get(e.getMember()); } public String getCropEmoji(MineshaftItem item, int level) { return Crop.valueOf(item.toString().toUpperCase()).getEmoji()[(int)Math.max(0, Math.min(2, level))]; } public void update(Member m) { farms.forEach(farm -> { update(farm, m); }); } public void update(Farm 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 / TIME_BETWEEN_UPDATES; farm.setQuantity(m, Math.min(farm.getQuantity(m) + updates, MAX_CROP_LEVEL)); farm.setNextUpdate(m, next + TIME_BETWEEN_UPDATES*updates); } public void harvest(MessageReceivedEvent e, String[] args) { Map award = new HashMap<>(); AtomicLong total = new AtomicLong(); farms.forEach( f -> { long amount = harvest(f, e.getMember()); total.addAndGet(amount); if (amount > 0) award.put(f.getItem(), amount); }); String description = String.format("You harvested your crops: %s\nDon't forget to replant your farm!", bot.createItemList(award, "+%s", ",")); if (total.get() == 0) { bot.sendErrorMessage(e, ":x: You have no crops!"); return; } EmbedBuilder em = new EmbedBuilder(); em.setTitle(COMMAND_TITLE); em.setDescription(description); em.setColor(COMMAND_COLOUR); e.getMessage().replyEmbeds(em.build()).queue(); } public boolean plant(MessageReceivedEvent e, List args) { if (args.size() > 3) return false; Optional resourceName = args.stream().filter(s -> !s.equalsIgnoreCase("all") && !s.equalsIgnoreCase("plant") && !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 q = 0; Optional all = args.stream().filter(s -> s.equals("all")).findFirst(); if (all.isEmpty()) { Optional 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 = bot.getItem(item).get(e.getMember()); } Optional farm = farms.stream().filter(f -> f.getItem() == item).findFirst(); if (farm.isEmpty()) { bot.sendErrorMessage(e, ":x: This item cannot be planted"); return true; } if (q > bot.getItem(item).get(e.getMember())) { bot.sendErrorMessage(e, ":x: You dont have enough " + bot.getItem(item).getSymbol()); return true; } long planted = plant(farm.get(), e.getMember(), q); if (planted > 0) bot.sendSuccessMessage(e, String.format("You planted %s in your farm", bot.getItem(item).prettyValue(planted))); else bot.sendErrorMessage(e, ":x: You have no more space in your farm!\n Expand with `m!farm expand [amount]`"); return true; } public long harvest(Farm farm, Member member) { long toGive = ((1+farm.getQuantity(member))) * farm.getPlanted(member); farm.setQuantity(member, 0); farm.setPlanted(member, 0); bot.addItem(member, farm.getItem(), toGive); bot.addItem(member, MineshaftItem.XP, (long) (Math.random() * XP_PER_ITEM * toGive)); return toGive; } public long plant(Farm farm, Member member, long amount) { long farmLevel = bot.getPickaxes().getFarmLevel(member); long totalPlanted = getTotalPlanted(member); if (totalPlanted + amount > farmLevel) { amount = farmLevel - totalPlanted; } if (amount <= 0) { return 0; } farm.incrementPlanted(member, amount); farm.setQuantity(member, 0); bot.removeItem(member, farm.getItem(), amount); return amount; } public long getTotalPlanted(Member m) { return farms.stream().mapToLong(f -> f.getPlanted(m)).sum(); } }