Allow other players to pickup quests

This commit is contained in:
Sam 2017-02-21 12:36:48 +00:00
parent 75f734c5e7
commit bde899212f
5 changed files with 185 additions and 21 deletions

View File

@ -1,4 +1,4 @@
package mineplex.gemhunters.quest.types;
package mineplex.gemhunters.quest;
import java.util.HashMap;
import java.util.Map;
@ -15,7 +15,6 @@ import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilServer;
import mineplex.core.donation.DonationManager;
import mineplex.gemhunters.economy.EconomyModule;
import mineplex.gemhunters.quest.QuestModule;
import mineplex.gemhunters.world.WorldDataModule;
public abstract class Quest implements Listener
@ -48,7 +47,7 @@ public abstract class Quest implements Listener
_donation = Managers.require(DonationManager.class);
_economy = Managers.require(EconomyModule.class);
_worldData = Managers.require(WorldDataModule.class);
_counter = new HashMap<>();
UtilServer.getServer().getPluginManager().registerEvents(this, UtilServer.getPlugin());
@ -60,6 +59,23 @@ public abstract class Quest implements Listener
remove(event.getPlayer());
}
public void transfer(Player from, Player to)
{
// If the player has already been progressing this quest and is
// further than the other don't bother transferring their data.
if (get(to) >= get(from))
{
return;
}
set(to, get(from));
}
public void set(Player player, int amount)
{
_counter.put(player.getUniqueId(), amount);
}
public int get(Player player)
{
return _counter.getOrDefault(player.getUniqueId(), 0);
@ -70,7 +86,7 @@ public abstract class Quest implements Listener
int newAmount = get(player) + amount;
_counter.put(player.getUniqueId(), newAmount);
_quest.updateQuestItem(this, player);
return newAmount;
}
@ -95,7 +111,7 @@ public abstract class Quest implements Listener
{
return _quest.isActive(this, player);
}
public abstract float getProgress(Player player);
public int getGoal()
@ -107,7 +123,7 @@ public abstract class Quest implements Listener
{
return _id;
}
public final String getName()
{
return _name;

View File

@ -7,10 +7,15 @@ import java.util.concurrent.TimeUnit;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import mineplex.core.MiniClientPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin;
@ -19,16 +24,18 @@ import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilItem;
import mineplex.core.common.util.UtilItem.ItemAttribute;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTextMiddle;
import mineplex.core.common.util.UtilTime;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.menu.Menu;
import mineplex.core.recharge.Recharge;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.gemhunters.quest.types.ChestOpenerQuest;
import mineplex.gemhunters.quest.types.Quest;
import mineplex.gemhunters.quest.types.SamitoDQuest;
import mineplex.gemhunters.world.WorldDataModule;
import net.md_5.bungee.api.ChatColor;
@ReflectivelyCreateMiniPlugin
public class QuestModule extends MiniClientPlugin<QuestPlayerData>
@ -36,17 +43,19 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
private static final int MAX_QUESTS = 5;
private static final long RESET_QUESTS_TIME = TimeUnit.MINUTES.toMillis(15);
private final Quest[] _quests = {
new ChestOpenerQuest(0, "Chest Opener", 100, 250, 5),
private static final Material MATERIAL = Material.PAPER;
private static final String ITEM_METADATA = "quest";
private final Quest[] _quests = {
new ChestOpenerQuest(0, "Chest Opener", 100, 250, 5),
new ChestOpenerQuest(1, "Grand Chest Opener", 200, 500, 20),
new ChestOpenerQuest(2, "Superior Chest Opener", 500, 750, 40),
new SamitoDQuest(3, "Give to the Homeless", "Donate " + F.count(String.valueOf(10)) + " gems to the Hobo.", 100, 300, 10)
new SamitoDQuest(3, "Give to the Homeless", "Donate " + F.count(String.valueOf(10)) + " gems to the Hobo.", 100, 300, 10)
};
private final WorldDataModule _worldData;
private QuestModule()
{
super("Quest");
@ -55,7 +64,8 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
Menu<?> menu = new QuestUI(this);
runSyncLater(() -> {
runSyncLater(() ->
{
for (Location location : _worldData.getCustomLocation("QUEST_NPC"))
{
@ -101,8 +111,97 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
}
}
@EventHandler
public void pickupItem(PlayerPickupItemEvent event)
{
if (event.isCancelled())
{
return;
}
Item item = event.getItem();
Player player = event.getPlayer();
Quest quest = fromItemStack(event.getItem().getItemStack());
if (quest == null)
{
return;
}
if (!item.hasMetadata(ITEM_METADATA))
{
return;
}
if (!Recharge.Instance.use(event.getPlayer(), "Quest Pickup " + quest.getId(), 2000, false, false))
{
event.setCancelled(true);
return;
}
boolean able = startQuest(quest, player);
if (!able)
{
event.setCancelled(true);
}
else
{
UUID owner = UUID.fromString(item.getMetadata(ITEM_METADATA).get(0).asString());
Player other = UtilPlayer.searchExact(owner);
/*
* Noting here that when a player leaves their quest progress is removed.
* However that means that if a new player picks up their quest item we
* run into a problem where that will be null. Thus the progress on that
* quest is lost.
* More complications are added when a player quits out and their NPC is
* there instead until they finally really really quit out.
* This is one massive headache in order to keep quests alive while not
* running into some serious memory leaks.
* Furthermore the time complications of this project mean that there isn't
* enough time right now to implement this (however a enough time for me
* to type this lengthy comment about it). So in true style I'm cutting
* corners and saying that if a player quits out then don't allow other
* players to be able to pickup the quest.
*/
if (other == null)
{
event.setCancelled(true);
return;
}
}
}
@EventHandler
public void dropItem(PlayerDropItemEvent event)
{
if (event.isCancelled())
{
return;
}
Player player = event.getPlayer();
Quest quest = fromItemStack(event.getItemDrop().getItemStack());
if (quest == null)
{
return;
}
cancelQuest(quest, player);
handleDroppedQuest(event.getItemDrop(), player);
}
public void handleDroppedQuest(Item item, Player player)
{
item.setMetadata(ITEM_METADATA, new FixedMetadataValue(_plugin, player.getUniqueId().toString()));
}
public void updateQuests(Player player)
{
{
QuestPlayerData playerData = Get(player);
List<Integer> quests = playerData.getPossibleQuests();
@ -120,17 +219,17 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
}
}
public void startQuest(Quest quest, Player player)
public boolean startQuest(Quest quest, Player player)
{
if (isActive(quest, player))
{
player.sendMessage(F.main(_moduleName, "You have already accepted that quest."));
return;
return false;
}
else if (isComplete(quest, player))
{
player.sendMessage(F.main(_moduleName, "You have already completed that quest."));
return;
return false;
}
player.sendMessage(F.main(_moduleName, "Started " + F.name(quest.getName()) + "."));
@ -139,6 +238,8 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
playerData.getActiveQuests().add(quest.getId());
updateQuestItem(quest, player);
return true;
}
public void completeQuest(Quest quest, Player player)
@ -149,6 +250,8 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
return;
}
player.sendMessage(F.main(_moduleName, "Completed " + F.name(quest.getName()) + "."));
QuestPlayerData playerData = Get(player);
playerData.getActiveQuests().remove(Integer.valueOf(quest.getId()));
playerData.getCompletedQuests().add(quest.getId());
@ -156,6 +259,20 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
updateQuestItem(quest, player);
}
public void cancelQuest(Quest quest, Player player)
{
if (!isActive(quest, player))
{
player.sendMessage(F.main(_moduleName, "This quest is not active for you."));
return;
}
player.sendMessage(F.main(_moduleName, "Dropped " + F.name(quest.getName()) + "."));
QuestPlayerData playerData = Get(player);
playerData.getActiveQuests().remove(Integer.valueOf(quest.getId()));
}
public Quest getRandomQuest(QuestPlayerData playerData, Player player)
{
int attempts = 0;
@ -167,7 +284,7 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
int index = UtilMath.r(_quests.length);
Quest quest = _quests[index];
if (isActive(quest, player) || playerData.getPossibleQuests().contains(quest.getId()))
if (isActive(quest, player) || isPossible(quest, player))
{
continue;
}
@ -180,7 +297,7 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
public ItemStack getItemStack(Quest quest, Player player, boolean npc, boolean hasSpace)
{
ItemBuilder builder = new ItemBuilder(Material.PAPER);
ItemBuilder builder = new ItemBuilder(MATERIAL);
builder.setTitle(C.cGreen + quest.getName());
builder.addLore(C.blankLine, quest.getDescription(), C.blankLine);
@ -216,6 +333,31 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
return builder.build();
}
public Quest fromItemStack(ItemStack itemStack)
{
Material material = itemStack.getType();
ItemMeta meta = itemStack.getItemMeta();
if (material != MATERIAL || meta == null || !meta.hasLore())
{
return null;
}
String name = ChatColor.stripColor(meta.getDisplayName());
for (Quest quest : _quests)
{
if (!quest.getName().equals(name))
{
continue;
}
return quest;
}
return null;
}
public void updateQuestItem(Quest quest, Player player)
{
ItemStack itemStack = getItemStack(quest, player, false, true);
@ -234,6 +376,11 @@ public class QuestModule extends MiniClientPlugin<QuestPlayerData>
}
}
public boolean isPossible(Quest quest, Player player)
{
return Get(player).getPossibleQuests().contains(quest.getId());
}
public boolean isActive(Quest quest, Player player)
{
return Get(player).getActiveQuests().contains(quest.getId());

View File

@ -8,7 +8,6 @@ import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilUI;
import mineplex.core.menu.Button;
import mineplex.core.menu.Menu;
import mineplex.gemhunters.quest.types.Quest;
public class QuestUI extends Menu<QuestModule>
{

View File

@ -6,6 +6,7 @@ import org.bukkit.event.EventHandler;
import mineplex.core.common.util.F;
import mineplex.gemhunters.debug.DebugModule;
import mineplex.gemhunters.loot.event.PlayerChestOpenEvent;
import mineplex.gemhunters.quest.Quest;
public class ChestOpenerQuest extends Quest
{

View File

@ -12,6 +12,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilFirework;
import mineplex.core.common.util.UtilMath;
import mineplex.gemhunters.quest.Quest;
public class SamitoDQuest extends Quest
{