From 4da27da27bf6c3c2235278ad7af80b254e7e3667 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 22 Jun 2018 00:04:33 +0100 Subject: [PATCH] Merge missions from JR --- .../src/mineplex/core/mission/Mission.java | 177 +++++++++ .../mineplex/core/mission/MissionClient.java | 128 +++++++ .../mineplex/core/mission/MissionLength.java | 36 ++ .../mineplex/core/mission/MissionManager.java | 346 ++++++++++++++++++ .../core/mission/MissionPopulator.java | 22 ++ .../core/mission/MissionRepository.java | 52 +++ .../mineplex/core/mission/MissionTracker.java | 27 ++ .../mission/commands/StartMissionCommand.java | 46 +++ .../core/mission/ui/MissionMainPage.java | 99 +++++ .../mineplex/core/mission/ui/MissionShop.java | 22 ++ .../core/reward/rewards/ExperienceReward.java | 8 +- .../core/reward/rewards/GemReward.java | 30 +- .../core/reward/rewards/InventoryReward.java | 20 +- .../reward/rewards/QuantifiableReward.java | 8 + .../core/reward/rewards/SpinTicketReward.java | 8 +- .../reward/rewards/TreasureShardReward.java | 23 +- 16 files changed, 1031 insertions(+), 21 deletions(-) create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/Mission.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionClient.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionLength.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionManager.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionPopulator.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionRepository.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/MissionTracker.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/commands/StartMissionCommand.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionMainPage.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionShop.java create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/QuantifiableReward.java diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/Mission.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/Mission.java new file mode 100644 index 000000000..d38e7056f --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/Mission.java @@ -0,0 +1,177 @@ +package mineplex.core.mission; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import mineplex.core.mission.trackers.BlockBreakTracker; +import mineplex.core.reward.Reward; + +public class Mission +{ + + private final int _id; + private final String _name; + private final MissionLength _length; + private final int _requiredProgress; + private final String _statName; + private final T _data; + private final List _rewards; + private final String _description; + + private Mission(int id, String name, MissionLength length, int requiredProgress, String statName, T data, List rewards, String description) + { + _id = id; + _name = name; + _length = length; + _requiredProgress = requiredProgress; + _statName = statName; + _data = data; + _rewards = rewards; + _description = String.format(description, requiredProgress); + } + + public int getId() + { + return _id; + } + + public String getName() + { + return _name; + } + + public MissionLength getLength() + { + return _length; + } + + public String getStatName() + { + return _statName; + } + + public int getRequiredProgress() + { + return _requiredProgress; + } + + public boolean validateData(T data) + { + return _data == null || _data.equals(data); + } + + public List getRewards() + { + return _rewards; + } + + public String getDescription() + { + return _description; + } + + public boolean isComplete(int progress) + { + return progress >= getRequiredProgress(); + } + + public static QuestBuilder newBuilder(MissionManager manager, int id) + { + return new QuestBuilder<>(manager, id); + } + + public static final class QuestBuilder + { + + private final MissionManager _manager; + private final int _id; + + private String _name; + private MissionLength _length; + private int _requiredProgress; + private MissionTracker _tracker; + private T _data; + private final List _rewards; + private String _description; + + private QuestBuilder(MissionManager manager, int id) + { + _manager = manager; + _id = id; + _rewards = new ArrayList<>(2); + } + + public QuestBuilder name(String name) + { + _name = name; + return this; + } + + public QuestBuilder length(MissionLength length) + { + _length = length; + return this; + } + + public QuestBuilder requiredProgress(int requiredProgress) + { + _requiredProgress = requiredProgress; + return this; + } + + public QuestBuilder trackBlockBreak() + { + _tracker = _manager.getTracker(BlockBreakTracker.class); + return this; + } + + public QuestBuilder trackData(T data) + { + _data = data; + return this; + } + + public QuestBuilder rewards(Reward... rewards) + { + _rewards.addAll(Arrays.asList(rewards)); + return this; + } + + public QuestBuilder description(String description) + { + _description = description; + return this; + } + + public void build() + { + if (_name == null || _name.isEmpty()) + { + throw new IllegalStateException("The name cannot be null or empty! Mission [" + _id + "]"); + } + else if (_length == null) + { + throw new IllegalStateException("The length cannot be null! Mission [" + _id + "]"); + } + else if (_requiredProgress <= 0) + { + throw new IllegalStateException("The required progress must be greater than 0! Mission [" + _id + "]"); + } + else if (_tracker == null) + { + throw new IllegalStateException("The tracker cannot be null! Mission [" + _id + "]"); + } + else if (_rewards.isEmpty()) + { + throw new IllegalStateException("The rewards cannot be empty! Mission [" + _id + "]"); + } + else if (_description == null || _description.isEmpty()) + { + throw new IllegalStateException("The description cannot be null or empty! Mission [" + _id + "]"); + } + + _manager.addQuest(new Mission<>(_id, _name, _length, _requiredProgress, _tracker.getStatName(), _data, _rewards, _description)); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionClient.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionClient.java new file mode 100644 index 000000000..397f80a36 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionClient.java @@ -0,0 +1,128 @@ +package mineplex.core.mission; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class MissionClient +{ + + private final Map _progress, _unsavedProgress; + private final Set _completed; + + MissionClient() + { + _progress = new HashMap<>(); + _unsavedProgress = new HashMap<>(); + _completed = new HashSet<>(); + } + + void startMission(Mission mission, int startingAmount) + { + if (mission.isComplete(startingAmount)) + { + _completed.add(mission); + } + else + { + _progress.put(mission, startingAmount); + } + } + + void completeQuest(Mission mission) + { + _progress.remove(mission); + _completed.add(mission); + } + + public boolean canProgress(Mission mission, T data) + { + return _progress.containsKey(mission) && mission.validateData(data); + } + + public int incrementProgress(Mission mission, int amount, boolean unsaved) + { + int previousAmount = getProgress(mission) + incrementMap(_unsavedProgress, mission, amount); + + if (unsaved && isAtPercentage(previousAmount, amount, mission.getRequiredProgress(), 1)) + { + return 100; + } + if (isAtPercentage(previousAmount, amount, mission.getRequiredProgress(), 0.75)) + { + return 75; + } + else if (isAtPercentage(previousAmount, amount, mission.getRequiredProgress(), 0.5)) + { + return 50; + } + else if (isAtPercentage(previousAmount, amount, mission.getRequiredProgress(), 0.25)) + { + return 25; + } + + return 0; + } + + private int incrementMap(Map map, Mission mission, int amount) + { + int newAmount = map.getOrDefault(mission, 0) + amount; + map.put(mission, newAmount); + return newAmount; + } + + private boolean isAtPercentage(int previous, int amount, int max, double percent) + { + double previousPercent = (double) previous / max, nowPercent = (double) (previous + amount) / max; + + return previousPercent < percent && nowPercent >= percent; + } + + public Map saveProgress() + { + Map unsaved = new HashMap<>(_unsavedProgress); + + _unsavedProgress.forEach((mission, progress) -> incrementMap(_progress, mission, progress)); + clearUnsavedProgress(); + + return unsaved; + } + + public void clearUnsavedProgress() + { + _unsavedProgress.clear(); + } + + public int getProgress(Mission mission) + { + return _progress.getOrDefault(mission, -1); + } + + public boolean isComplete(Mission mission) + { + return _completed.contains(mission); + } + + public boolean isActive(Mission mission) + { + return _progress.containsKey(mission) || isComplete(mission); + } + + public Map getAllQuests() + { + Map quests = new HashMap<>(_progress); + + _completed.forEach(mission -> quests.put(mission, mission.getRequiredProgress())); + + return quests; + } + + public int getMissionsOf(MissionLength length) + { + return (int) getAllQuests().keySet().stream() + .map(Mission::getLength) + .filter(other -> other == length) + .count(); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionLength.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionLength.java new file mode 100644 index 000000000..e95aad3b3 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionLength.java @@ -0,0 +1,36 @@ +package mineplex.core.mission; + +import java.util.Calendar; + +public enum MissionLength +{ + + DAY("Daily", "Resets everyday", Calendar.DAY_OF_WEEK), + WEEK("Weekly", "Resets every Monday", Calendar.WEEK_OF_YEAR), + EVENT("Special Event", "Limited time only!", -1); + + private final String _name, _resetInfo; + private final int _calendarField; + + MissionLength(String name, String resetInfo, int calendarField) + { + _name = name; + _resetInfo = resetInfo; + _calendarField = calendarField; + } + + public String getName() + { + return _name; + } + + public String getResetInfo() + { + return _resetInfo; + } + + public int getCalendarField() + { + return _calendarField; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionManager.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionManager.java new file mode 100644 index 000000000..1d8d73ad4 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionManager.java @@ -0,0 +1,346 @@ +package mineplex.core.mission; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Slime; +import org.bukkit.event.EventHandler; + +import mineplex.core.MiniDbClientPlugin; +import mineplex.core.ReflectivelyCreateMiniPlugin; +import mineplex.core.account.permissions.Permission; +import mineplex.core.account.permissions.PermissionGroup; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilServer; +import mineplex.core.donation.DonationManager; +import mineplex.core.mission.commands.StartMissionCommand; +import mineplex.core.mission.ui.MissionShop; +import mineplex.core.newnpc.NPC; +import mineplex.core.newnpc.NewNPCManager; +import mineplex.core.newnpc.SimpleNPC; +import mineplex.core.newnpc.event.NPCInteractEvent; + +@ReflectivelyCreateMiniPlugin +public class MissionManager extends MiniDbClientPlugin +{ + + public enum Perm implements Permission + { + START_MISSION_COMMAND + } + + private static final String NPC_METADATA = "MISSION_NPC"; + + private final DonationManager _donationManager; + + private final List _missions; + private final Set _missionTrackers; + private final MissionRepository _repository; + private final MissionShop _shop; + + private boolean _requireManualSaving; + + private MissionManager() + { + super("Mission"); + + _donationManager = require(DonationManager.class); + + _missions = new ArrayList<>(); + _missionTrackers = new HashSet<>(); + _repository = new MissionRepository(); + _shop = new MissionShop(this); + + populateTrackers(); + + generatePermissions(); + + runSyncTimer(this::processUnsavedProgress, 20, 60); + } + + private void generatePermissions() + { + PermissionGroup.ADMIN.setPermission(Perm.START_MISSION_COMMAND, true, true); + } + + @Override + public void addCommands() + { + addCommand(new StartMissionCommand(this)); + } + + private void populateTrackers() + { + addTracker(); + } + + void addQuest(Mission mission) + { + _missions.add(mission); + } + + private void addTracker(MissionTracker... trackers) + { + for (MissionTracker tracker : trackers) + { + registerEvents(tracker); + _missionTrackers.add(tracker); + } + } + + public void setRequireManualSaving(boolean requireManualSaving) + { + _requireManualSaving = requireManualSaving; + } + + @Override + public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException + { + MissionClient client = Get(uuid); + Calendar calendar = Calendar.getInstance(); + + while (resultSet.next()) + { + int missionId = resultSet.getInt("missionId"); + int progress = resultSet.getInt("progress"); + Timestamp startTime = resultSet.getTimestamp("startTime"); + + Mission mission = getMission(missionId); + + if (mission == null) + { + continue; + } + + int lengthField = mission.getLength().getCalendarField(); + + if (lengthField == -1) + { + return; + } + + Calendar start = Calendar.getInstance(); + start.setTimeInMillis(startTime.getTime()); + + if (calendar.get(lengthField) != start.get(lengthField)) + { + runAsync(() -> _repository.clearProgress(accountId, missionId)); + } + else + { + client.startMission(mission, progress); + } + } + } + + @Override + protected MissionClient addPlayer(UUID uuid) + { + return new MissionClient(); + } + + @Override + public String getQuery(int accountId, String uuid, String name) + { + return "SELECT * FROM accountMissions WHERE accountId=" + accountId + ";"; + } + + public void startMission(Player player, Mission mission) + { + runAsync(() -> + { + if (_repository.startMission(ClientManager.getAccountId(player), mission.getId())) + { + Get(player).startMission(mission, 0); + player.sendMessage(F.main(getName(), "Started a new " + F.name(mission.getLength().getName()) + " mission! " + F.name(mission.getName()) + ".")); + } + }); + } + + public void completeMission(Player player, Mission mission) + { + MissionClient client = Get(player); + + if (client.isComplete(mission)) + { + return; + } + + player.sendMessage(""); + player.sendMessage(" " + C.mHead + C.Bold + mission.getLength().getName() + " Mission Complete! " + C.mBody + C.Bold + mission.getName()); + player.sendMessage(" " + C.cGray + mission.getDescription()); + player.sendMessage(""); + + mission.getRewards().forEach(reward -> reward.giveReward(player, data -> + { + String message = data.getRarity().getColor() + data.getFriendlyName(); + + if (data.getHeader() == null) + { + message = data.getRarity().getDarkColor() + "> " + message; + } + + player.sendMessage(" " + message); + })); + + player.sendMessage(""); + player.playSound(player.getLocation(), Sound.LEVEL_UP, 1, (float) Math.random()); + + client.completeQuest(mission); + runAsync(() -> _repository.completeQuest(ClientManager.getAccountId(player), mission.getId())); + } + + @SuppressWarnings("unchecked") + public void incrementProgress(Player player, int amount, String statName, T data) + { + MissionClient client = Get(player); + + applyForMissions(mission -> + { + if (!client.canProgress(mission, data)) + { + return; + } + + int percentage = client.incrementProgress(mission, amount, _requireManualSaving); + + if (percentage > 0) + { + player.sendMessage(F.main(getName(), F.name(mission.getName()) + " mission is " + F.count(percentage + "%") + " complete.")); + } + }, statName); + } + + // TODO this may not be good enough. might have to bulk query or change implementation? + private void processUnsavedProgress() + { + for (Player player : UtilServer.getPlayersCollection()) + { + selectNewMissions(player); + + if (!_requireManualSaving) + { + saveProgress(player); + } + } + } + + private void selectNewMissions(Player player) + { + MissionClient client = Get(player); + + selectNewMissions(player, client, MissionLength.DAY, 3); + selectNewMissions(player, client, MissionLength.WEEK, 2); + } + + private void selectNewMissions(Player player, MissionClient client, MissionLength length, int max) + { + int current = client.getMissionsOf(length); + + if (current >= max) + { + return; + } + + List missions = getMissionsOf(length); + missions.removeIf(client::isActive); + + for (int i = current; i <= max; i++) + { + Mission mission = UtilAlg.Random(missions); + + if (mission == null) + { + return; + } + + missions.remove(mission); + startMission(player, mission); + } + } + + private List getMissionsOf(MissionLength length) + { + return _missions.stream() + .filter(mission -> mission.getLength() != length) + .collect(Collectors.toList()); + } + + public void saveProgress(Player player) + { + MissionClient client = Get(player); + Map unsaved = client.saveProgress(); + + if (unsaved.isEmpty()) + { + return; + } + + int accountId = ClientManager.getAccountId(player); + + runAsync(() -> unsaved.forEach((mission, progress) -> + { + if (_repository.incrementProgress(accountId, mission.getId(), progress) && mission.isComplete(client.getProgress(mission))) + { + runSync(() -> completeMission(player, mission)); + } + })); + } + + private void applyForMissions(Consumer function, String statName) + { + _missions.stream() + .filter(mission -> mission.getStatName().equals(statName)) + .forEach(function); + } + + public Mission getMission(int id) + { + return _missions.stream() + .filter(mission -> mission.getId() == id) + .findFirst() + .orElse(null); + } + + public void createNPC(NewNPCManager manager, Location location) + { + NPC npc = SimpleNPC.of(location, Slime.class, NPC_METADATA); + + manager.addNPC(npc); + + LivingEntity entity = npc.getEntity(); + + entity.setCustomName(C.mElem + C.Bold + "SeƱor Missions"); + entity.setCustomNameVisible(true); + } + + @EventHandler + public void npcInteract(NPCInteractEvent event) + { + if (event.getNpc().getMetadata().equals(NPC_METADATA)) + { + _shop.attemptShopOpen(event.getPlayer()); + } + } + + public DonationManager getDonationManager() + { + return _donationManager; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionPopulator.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionPopulator.java new file mode 100644 index 000000000..e7f3c2a57 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionPopulator.java @@ -0,0 +1,22 @@ +package mineplex.core.mission; + +import org.bukkit.Material; + +public class MissionPopulator +{ + + public static void populateMissions(MissionManager manager) + { + Mission.newBuilder(manager, 1) + .name("Wood Collector") + .description("Cut %s Logs") + .length(MissionLength.DAY) + .requiredProgress(10) + .trackBlockBreak() + .trackData(Material.LOG) + .rewards() + .build(); + + } + +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionRepository.java new file mode 100644 index 000000000..9b8096b09 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionRepository.java @@ -0,0 +1,52 @@ +package mineplex.core.mission; + +import mineplex.serverdata.database.DBPool; +import mineplex.serverdata.database.RepositoryBase; +import mineplex.serverdata.database.column.ColumnInt; + +public class MissionRepository extends RepositoryBase +{ + + private static final String START_QUEST = "INSERT INTO accountMissions (accountId, missionId) VALUES (?,?);"; + private static final String INCREMENT_PROGRESS = "UPDATE accountMissions SET progress=progress+? WHERE accountId=? AND missionId=?;"; + private static final String COMPLETE_QUEST = "UPDATE accountMissions SET complete=1 WHERE accountId=? AND missionId=?;"; + private static final String CLEAR_PROGRESS = "DELETE FROM accountMissions WHERE accountId=? AND missionId=?"; + + MissionRepository() + { + super(DBPool.getAccount()); + } + + public boolean startMission(int accountId, int missionId) + { + return accountId != -1 && executeInsert(START_QUEST, null, + new ColumnInt("accountId", accountId), + new ColumnInt("missionId", missionId) + ) > 0; + } + + public boolean incrementProgress(int accountId, int missionId, int progress) + { + return accountId != -1 && executeUpdate(INCREMENT_PROGRESS, + new ColumnInt("progress", progress), + new ColumnInt("accountId", accountId), + new ColumnInt("missionId", missionId) + ) > 0; + } + + public boolean completeQuest(int accountId, int missionId) + { + return accountId != -1 && executeUpdate(COMPLETE_QUEST, + new ColumnInt("accountId", accountId), + new ColumnInt("missionId", missionId) + ) > 0; + } + + public boolean clearProgress(int accountId, int missionId) + { + return accountId != -1 && executeUpdate(CLEAR_PROGRESS, + new ColumnInt("accountId", accountId), + new ColumnInt("missionId", missionId) + ) > 0; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionTracker.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionTracker.java new file mode 100644 index 000000000..6938791e9 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/MissionTracker.java @@ -0,0 +1,27 @@ +package mineplex.core.mission; + +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; + +public class MissionTracker implements Listener +{ + + protected final MissionManager _manager; + private final String _statName; + + public MissionTracker(MissionManager manager, String statName) + { + _manager = manager; + _statName = statName; + } + + protected void incrementProgress(Player player, int amount, T data) + { + _manager.incrementProgress(player, amount, _statName, data); + } + + public String getStatName() + { + return _statName; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/commands/StartMissionCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/commands/StartMissionCommand.java new file mode 100644 index 000000000..4a6eea4a5 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/commands/StartMissionCommand.java @@ -0,0 +1,46 @@ +package mineplex.core.mission.commands; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.util.F; +import mineplex.core.mission.Mission; +import mineplex.core.mission.MissionManager; +import mineplex.core.mission.MissionManager.Perm; + +public class StartMissionCommand extends CommandBase +{ + + public StartMissionCommand(MissionManager plugin) + { + super(plugin, Perm.START_MISSION_COMMAND, "startmission"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (args.length < 1) + { + caller.sendMessage(F.main(Plugin.getName(), "/" + _aliasUsed + " ")); + return; + } + + try + { + int id = Integer.parseInt(args[0]); + Mission mission = Plugin.getMission(id); + + if (mission == null) + { + caller.sendMessage(F.main(Plugin.getName(), "That is not a valid mission id.")); + return; + } + + Plugin.startMission(caller, mission); + } + catch (NumberFormatException e) + { + caller.sendMessage(F.main(Plugin.getName(), F.elem(args[0]) + " is not a number.")); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionMainPage.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionMainPage.java new file mode 100644 index 000000000..5e663c211 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionMainPage.java @@ -0,0 +1,99 @@ +package mineplex.core.mission.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.mission.Mission; +import mineplex.core.mission.MissionClient; +import mineplex.core.mission.MissionLength; +import mineplex.core.mission.MissionManager; +import mineplex.core.reward.rewards.QuantifiableReward; +import mineplex.core.reward.RewardData; +import mineplex.core.shop.page.ShopPageBase; + +public class MissionMainPage extends ShopPageBase +{ + + MissionMainPage(MissionManager plugin, MissionShop shop, Player player) + { + super(plugin, shop, plugin.getClientManager(), plugin.getDonationManager(), "Missions", player, 27); + + buildPage(); + } + + @Override + protected void buildPage() + { + int slot = 10; + MissionClient client = _plugin.Get(getPlayer()); + + Set questsSet = client.getAllQuests().keySet(); + List questSorted = new ArrayList<>(questsSet); + + questSorted.sort((o1, o2) -> + { + int primaryComp = o1.getLength().compareTo(o2.getLength()); + + if (primaryComp != 0) + { + return primaryComp; + } + + return o1.getName().compareTo(o2.getName()); + }); + + MissionLength lastLength = null; + + for (Mission mission : questSorted) + { + int progress = client.getProgress(mission); + + ItemBuilder builder = new ItemBuilder(Material.PAPER) + .setTitle(C.mHead + mission.getName() + C.mBody + " (" + mission.getLength().getName() + ")") + .addLore(mission.getDescription(), ""); + + mission.getRewards().forEach(reward -> + { + RewardData rewardData = reward.getFakeRewardData(getPlayer()); + String amount = ""; + + if (reward instanceof QuantifiableReward) + { + amount = ((QuantifiableReward) reward).getQuantity() + " "; + } + + builder.addLore(C.mBody + " - " + rewardData.getRarity().getColor() + amount + rewardData.getFriendlyName()); + }); + + builder.addLore("", mission.getLength().getResetInfo(), ""); + + if (!client.isComplete(mission)) + { + builder.setGlow(true); + builder.addLore(F.property("Progress", C.mCount + progress + C.Reset + "/" + C.mCount + mission.getRequiredProgress())); + } + else + { + builder.addLore(C.cGreen + "You have completed this mission"); + } + + if (lastLength == null) + { + lastLength = mission.getLength(); + } + else if (lastLength != mission.getLength()) + { + slot++; + } + + addButtonNoAction(slot++, builder.build()); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionShop.java b/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionShop.java new file mode 100644 index 000000000..63014cbcf --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/mission/ui/MissionShop.java @@ -0,0 +1,22 @@ +package mineplex.core.mission.ui; + +import org.bukkit.entity.Player; + +import mineplex.core.mission.MissionManager; +import mineplex.core.shop.ShopBase; +import mineplex.core.shop.page.ShopPageBase; + +public class MissionShop extends ShopBase +{ + + public MissionShop(MissionManager plugin) + { + super(plugin, plugin.getClientManager(), plugin.getDonationManager(), "Mission"); + } + + @Override + protected ShopPageBase> buildPagesFor(Player player) + { + return new MissionMainPage(getPlugin(), this, player); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/ExperienceReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/ExperienceReward.java index b4a50bf3b..f818e52d9 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/ExperienceReward.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/ExperienceReward.java @@ -13,7 +13,7 @@ import mineplex.core.reward.RewardData; import mineplex.core.stats.StatsManager; import mineplex.core.treasure.reward.RewardRarity; -public class ExperienceReward extends Reward +public class ExperienceReward extends Reward implements QuantifiableReward { private static final StatsManager STATS_MANAGER = Managers.require(StatsManager.class); @@ -53,4 +53,10 @@ public class ExperienceReward extends Reward { return true; } + + @Override + public int getQuantity() + { + return _minExperience; + } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/GemReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/GemReward.java index d2d332437..6c8ca81e2 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/GemReward.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/GemReward.java @@ -5,16 +5,16 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import mineplex.core.common.currency.GlobalCurrency; -import mineplex.core.treasure.reward.RewardRarity; +import mineplex.core.common.util.UtilMath; import mineplex.core.reward.Reward; import mineplex.core.reward.RewardData; -import mineplex.core.reward.RewardType; +import mineplex.core.treasure.reward.RewardRarity; -public class GemReward extends Reward +public class GemReward extends Reward implements QuantifiableReward { - private int _minGemCount; - private int _maxGemCount; + private final int _minGemCount; + private final int _maxGemCount; public GemReward(int minGemCount, int maxGemCount, int shardValue, RewardRarity rarity) { @@ -27,11 +27,19 @@ public class GemReward extends Reward @Override public RewardData giveRewardCustom(Player player) { - int gemsToReward = RANDOM.nextInt(_maxGemCount - _minGemCount) + _minGemCount; + int gems; - DONATION_MANAGER.rewardCurrency(GlobalCurrency.GEM, player, "Treasure Chest", gemsToReward); + if (_minGemCount == _maxGemCount) + { + gems = _minGemCount; + } + else + { + gems = UtilMath.rRange(_minGemCount, _maxGemCount); + } + DONATION_MANAGER.rewardCurrency(GlobalCurrency.GEM, player, "Treasure Chest", gems); - return new RewardData(null, getRarity().getColor() + gemsToReward + " Gems", new ItemStack(Material.EMERALD), getRarity()); + return new RewardData(null, getRarity().getColor() + gems + " Gems", new ItemStack(Material.EMERALD), getRarity()); } @Override @@ -51,4 +59,10 @@ public class GemReward extends Reward { return obj instanceof GemReward; } + + @Override + public int getQuantity() + { + return _minGemCount; + } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/InventoryReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/InventoryReward.java index d4ef9fc37..045516cc5 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/InventoryReward.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/InventoryReward.java @@ -7,15 +7,15 @@ import mineplex.core.reward.Reward; import mineplex.core.reward.RewardData; import mineplex.core.treasure.reward.RewardRarity; -public class InventoryReward extends Reward +public class InventoryReward extends Reward implements QuantifiableReward { - private ItemStack _itemStack; - private String _name; - private String _packageName; - private String _header; - private int _minAmount; - private int _maxAmount; + private final ItemStack _itemStack; + private final String _name; + private final String _packageName; + private final String _header; + private final int _minAmount; + private final int _maxAmount; public InventoryReward(String name, String packageName, String header, ItemStack itemStack, RewardRarity rarity, int shardValue) { @@ -91,4 +91,10 @@ public class InventoryReward extends Reward { return _packageName.hashCode(); } + + @Override + public int getQuantity() + { + return _minAmount; + } } \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/QuantifiableReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/QuantifiableReward.java new file mode 100644 index 000000000..a7f0f02f5 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/QuantifiableReward.java @@ -0,0 +1,8 @@ +package mineplex.core.reward.rewards; + +public interface QuantifiableReward +{ + + int getQuantity(); + +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/SpinTicketReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/SpinTicketReward.java index c09ceae96..6bd238b8d 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/SpinTicketReward.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/SpinTicketReward.java @@ -16,7 +16,7 @@ import mineplex.core.reward.RewardData; import mineplex.core.treasure.reward.RewardRarity; import mineplex.serverdata.database.DBPool; -public class SpinTicketReward extends Reward +public class SpinTicketReward extends Reward implements QuantifiableReward { private static final ItemStack ITEM_STACK = new ItemStack(Material.PAPER); @@ -102,4 +102,10 @@ public class SpinTicketReward extends Reward { return getClass().hashCode(); } + + @Override + public int getQuantity() + { + return _min; + } } \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/TreasureShardReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/TreasureShardReward.java index f904836bc..d14a076da 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/TreasureShardReward.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/TreasureShardReward.java @@ -12,14 +12,14 @@ import mineplex.core.reward.Reward; import mineplex.core.reward.RewardData; import mineplex.core.treasure.reward.RewardRarity; -public class TreasureShardReward extends Reward +public class TreasureShardReward extends Reward implements QuantifiableReward { private static final ItemStack ITEM_STACK = new ItemStack(Material.PRISMARINE_SHARD); private Reward _otherReward; - private int _shardsMin = 0; - private int _shardsMax = 0; + private final int _shardsMin; + private final int _shardsMax; public TreasureShardReward(Reward otherReward, RewardRarity rarity) { @@ -48,7 +48,16 @@ public class TreasureShardReward extends Reward public RewardData giveRewardCustom(Player player) { RewardData rewardData; - final int shards = UtilMath.rRange(_shardsMin, _shardsMax); + int shards; + + if (_shardsMin == _shardsMax) + { + shards = _shardsMin; + } + else + { + shards = UtilMath.rRange(_shardsMin, _shardsMax);; + } if (_otherReward != null) { @@ -85,5 +94,11 @@ public class TreasureShardReward extends Reward { return obj instanceof TreasureShardReward; } + + @Override + public int getQuantity() + { + return _shardsMin; + } }