Permit duplicate materials for item objectives, part 1. See #1646

This commit is contained in:
PikaMug 2021-05-13 04:19:18 -04:00
parent ebda39975e
commit 9949365cdf
4 changed files with 488 additions and 453 deletions

View File

@ -395,21 +395,29 @@ public class QuestData {
}
};
public LinkedHashMap<ItemStack, Integer> itemsConsumed = new LinkedHashMap<ItemStack, Integer>() {
public LinkedList<ItemStack> itemsConsumed = new LinkedList<ItemStack>() {
private static final long serialVersionUID = -5475073316902757883L;
@Override
public Integer put(final ItemStack key, final Integer val) {
final Integer data = super.put(key, val);
public ItemStack set(final int index, final ItemStack key) {
final ItemStack data = super.set(index, key);
if (doJournalUpdate)
quester.updateJournal();
return data;
}
@Override
public Integer remove(final Object key) {
final Integer i = super.remove(key);
public boolean add(final ItemStack key) {
final boolean data = super.add(key);
if (doJournalUpdate)
quester.updateJournal();
return data;
}
@Override
public boolean remove(final Object key) {
final boolean i = super.remove(key);
if (doJournalUpdate)
quester.updateJournal();
return i;
@ -423,10 +431,11 @@ public class QuestData {
}
@Override
public void putAll(final Map<? extends ItemStack, ? extends Integer> m) {
super.putAll(m);
public boolean addAll(final Collection<? extends ItemStack> m) {
final boolean i = super.addAll(m);
if (doJournalUpdate)
quester.updateJournal();
return i;
}
};

View File

@ -1085,16 +1085,18 @@ public class Quester implements Comparable<Quester> {
}
objectives.add(message.replace("<item>", ItemUtil.getName(is)));
}
int consumeIndex = 0;
for (final ItemStack is : stage.itemsToConsume) {
int consumed = 0;
if (data.itemsConsumed.containsKey(is)) {
consumed = data.itemsConsumed.get(is);
if (data.itemsConsumed.size() > consumeIndex) {
consumed = data.itemsConsumed.get(consumeIndex).getAmount();
}
final int amt = is.getAmount();
final ChatColor color = consumed < amt ? ChatColor.GREEN : ChatColor.GRAY;
final int toConsume = is.getAmount();
consumeIndex++;
final ChatColor color = consumed < toConsume ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "consumeItem");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + consumed + "/" + is.getAmount());
message = message.replace("<count>", "" + color + consumed + "/" + toConsume);
} else {
// Legacy
message += color + ": " + consumed + "/" + is.getAmount();
@ -1104,89 +1106,6 @@ public class Quester implements Comparable<Quester> {
}
objectives.add(message.replace("<item>", ItemUtil.getName(is)));
}
if (stage.cowsToMilk != null) {
final ChatColor color = data.getCowsMilked() < stage.cowsToMilk ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "milkCow");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getCowsMilked() + "/" + stage.cowsToMilk);
} else {
// Legacy
message += color + ": " + data.getCowsMilked() + "/" + stage.cowsToMilk;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
if (getCurrentStage(quest).fishToCatch != null) {
final ChatColor color = data.getFishCaught() < stage.fishToCatch ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "catchFish");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getFishCaught() + "/" + stage.fishToCatch);
} else {
// Legacy
message += color + ": " + data.getFishCaught() + "/" + stage.fishToCatch;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
for (final EntityType e : getCurrentStage(quest).mobsToKill) {
for (final EntityType e2 : getQuestData(quest).mobsKilled) {
if (e == e2) {
if (data.mobNumKilled.size() > data.mobsKilled.indexOf(e2)
&& stage.mobNumToKill.size() > stage.mobsToKill.indexOf(e)) {
final ChatColor color = data.mobNumKilled.get(data.mobsKilled.indexOf(e2))
< stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))
? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "";
if (stage.locationsToKillWithin.isEmpty()) {
message += Lang.get(getPlayer(), "kill");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))));
} else {
// Legacy
message += ChatColor.AQUA + " <mob>" + color + ": "
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
}
} else {
message += Lang.get(getPlayer(), "killAtLocation").replace("<location>",
stage.killNames.get(stage.mobsToKill.indexOf(e)));
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))));
} else {
message += color + ": " + (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
}
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message.replace("<mob>", MiscUtil.getProperMobName(e)));
}
}
}
}
if (stage.playersToKill != null) {
final ChatColor color = data.getPlayersKilled() < stage.playersToKill ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "killPlayer");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getPlayersKilled() + "/" + stage.playersToKill);
} else {
// Legacy
message += color + ": " + data.getPlayersKilled() + "/" + stage.playersToKill;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
int index = 0;
for (final ItemStack is : stage.itemsToDeliver) {
int delivered = 0;
@ -1253,6 +1172,47 @@ public class Quester implements Comparable<Quester> {
}
}
}
for (final EntityType e : getCurrentStage(quest).mobsToKill) {
for (final EntityType e2 : getQuestData(quest).mobsKilled) {
if (e == e2) {
if (data.mobNumKilled.size() > data.mobsKilled.indexOf(e2)
&& stage.mobNumToKill.size() > stage.mobsToKill.indexOf(e)) {
final ChatColor color = data.mobNumKilled.get(data.mobsKilled.indexOf(e2))
< stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))
? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "";
if (stage.locationsToKillWithin.isEmpty()) {
message += Lang.get(getPlayer(), "kill");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))));
} else {
// Legacy
message += ChatColor.AQUA + " <mob>" + color + ": "
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
}
} else {
message += Lang.get(getPlayer(), "killAtLocation").replace("<location>",
stage.killNames.get(stage.mobsToKill.indexOf(e)));
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e))));
} else {
message += color + ": " + (data.mobNumKilled.get(data.mobsKilled.indexOf(e2))) + "/"
+ (stage.mobNumToKill.get(stage.mobsToKill.indexOf(e)));
}
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message.replace("<mob>", MiscUtil.getProperMobName(e)));
}
}
}
}
for (final Entry<EntityType, Integer> e : getCurrentStage(quest).mobsToTame.entrySet()) {
for (final Entry<EntityType, Integer> e2 : getQuestData(quest).mobsTamed.entrySet()) {
if (e.getKey().equals(e2.getKey())) {
@ -1271,6 +1231,34 @@ public class Quester implements Comparable<Quester> {
}
}
}
if (getCurrentStage(quest).fishToCatch != null) {
final ChatColor color = data.getFishCaught() < stage.fishToCatch ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "catchFish");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getFishCaught() + "/" + stage.fishToCatch);
} else {
// Legacy
message += color + ": " + data.getFishCaught() + "/" + stage.fishToCatch;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
if (stage.cowsToMilk != null) {
final ChatColor color = data.getCowsMilked() < stage.cowsToMilk ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "milkCow");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getCowsMilked() + "/" + stage.cowsToMilk);
} else {
// Legacy
message += color + ": " + data.getCowsMilked() + "/" + stage.cowsToMilk;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
for (final Entry<DyeColor, Integer> e : getCurrentStage(quest).sheepToShear.entrySet()) {
for (final Entry<DyeColor, Integer> e2 : getQuestData(quest).sheepSheared.entrySet()) {
if (e.getKey().equals(e2.getKey())) {
@ -1287,6 +1275,20 @@ public class Quester implements Comparable<Quester> {
}
}
}
if (stage.playersToKill != null) {
final ChatColor color = data.getPlayersKilled() < stage.playersToKill ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + Lang.get(getPlayer(), "killPlayer");
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + data.getPlayersKilled() + "/" + stage.playersToKill);
} else {
// Legacy
message += color + ": " + data.getPlayersKilled() + "/" + stage.playersToKill;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(getPlayer(), message);
}
objectives.add(message);
}
for (final Location l : getCurrentStage(quest).locationsToReach) {
for (final Location l2 : getQuestData(quest).locationsReached) {
if (l.equals(l2)) {
@ -2120,56 +2122,225 @@ public class Quester implements Comparable<Quester> {
* @param i The item being consumed
*/
public void consumeItem(final Quest quest, final ItemStack i) {
ItemStack found = null;
for (final ItemStack is : getQuestData(quest).itemsConsumed.keySet()) {
int currentIndex = -1;
final LinkedList<Integer> matches = new LinkedList<Integer>();
for (final ItemStack is : getQuestData(quest).itemsConsumed) {
currentIndex++;
if (ItemUtil.compareItems(i, is, true) == 0) {
found = is;
break;
matches.add(currentIndex);
}
}
if (found == null) {
if (matches.isEmpty()) {
return;
}
final int amount = getQuestData(quest).itemsConsumed.get(found);
if (getCurrentStage(quest).itemsToConsume.indexOf(found) < 0) {
plugin.getLogger().severe("Index out of bounds while consuming " + found.getType() + " x "
+ found.getAmount() + " for quest " + quest.getName() + " with " + i.getType() + " x "
+ i.getAmount() + " already consumed. List amount reports value of " + amount
+ ". Please report this error on Github!");
sendMessage(ChatColor.RED + "Quests had a problem consuming your item, please contact an administrator!");
for (final Integer match : matches) {
final LinkedList<ItemStack> items = new LinkedList<ItemStack>(getQuestData(quest).itemsConsumed);
final ItemStack found = items.get(match);
final int amount = found.getAmount();
final int toConsume = getCurrentStage(quest).itemsToConsume.get(match).getAmount();
final ObjectiveType type = ObjectiveType.CONSUME_ITEM;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, amount, toConsume));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newAmount = i.getAmount() + amount;
final Material m = i.getType();
if (amount < toConsume) {
if (newAmount >= toConsume) {
final ItemStack newStack = found;
found.setAmount(toConsume);
getQuestData(quest).itemsConsumed.set(items.indexOf(found), newStack);
finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null, null,
null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).itemsConsumed.set(items.indexOf(found), newStack);
q.finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null,
null, null, null, null);
return null;
});
} else {
final ItemStack newStack = found;
found.setAmount(newAmount);
getQuestData(quest).itemsConsumed.set(items.indexOf(found), newStack);
}
return;
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, newAmount, toConsume));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark item as delivered to a NPC if Quester has such an objective
*
* @param quest The quest for which the item is being delivered
* @param n The NPC being delivered to
* @param i The item being delivered
*/
@SuppressWarnings("deprecation")
public void deliverToNPC(final Quest quest, final NPC n, final ItemStack i) {
if (n == null) {
return;
}
final int req = getCurrentStage(quest).itemsToConsume.get(getCurrentStage(quest).itemsToConsume.indexOf(found))
.getAmount();
final ObjectiveType type = ObjectiveType.CONSUME_ITEM;
int currentIndex = -1;
final LinkedList<Integer> matches = new LinkedList<Integer>();
for (final ItemStack is : getQuestData(quest).itemsDelivered) {
currentIndex++;
if (ItemUtil.compareItems(i, is, true) == 0) {
matches.add(currentIndex);
}
}
if (matches.isEmpty()) {
return;
}
final Player player = getPlayer();
for (final Integer match : matches) {
final LinkedList<ItemStack> items = new LinkedList<ItemStack>(getQuestData(quest).itemsDelivered);
if (!getCurrentStage(quest).getItemDeliveryTargets().get(match).equals(n.getId())) {
continue;
}
final ItemStack found = items.get(match);
final int amount = found.getAmount();
final int toDeliver = getCurrentStage(quest).itemsToDeliver.get(match).getAmount();
final ObjectiveType type = ObjectiveType.DELIVER_ITEM;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, amount, toDeliver));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newAmount = i.getAmount() + amount;
final Material m = i.getType();
if (amount < toDeliver) {
final int index = player.getInventory().first(i);
if (index == -1) {
// Already delivered in previous loop
return;
}
if (newAmount >= toDeliver) {
final ItemStack newStack = found;
found.setAmount(toDeliver);
getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
if ((i.getAmount() + amount) >= toDeliver) {
// Take away remaining amount to be delivered
final ItemStack clone = i.clone();
clone.setAmount(i.getAmount() - (toDeliver - amount));
player.getInventory().setItem(index, clone);
} else {
player.getInventory().setItem(index, null);
}
player.updateInventory();
finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null, null,
null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
q.finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null,
null, null, null, null);
return null;
});
} else {
final ItemStack newStack = found;
found.setAmount(newAmount);
getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
player.getInventory().setItem(index, null);
player.updateInventory();
final String[] message = ConfigUtil.parseStringWithPossibleLineBreaks(getCurrentStage(quest)
.deliverMessages.get(new Random().nextInt(getCurrentStage(quest).deliverMessages
.size())), plugin.getDependencies().getCitizens().getNPCRegistry()
.getById(getCurrentStage(quest).itemDeliveryTargets.get(items.indexOf(found))));
player.sendMessage(message);
}
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, newAmount, toDeliver));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark NPC as interacted with if Quester has such an objective
*
* @param quest The quest for which the NPC is being interacted with
* @param n The NPC being interacted with
*/
public void interactWithNPC(final Quest quest, final NPC n) {
final ObjectiveType type = ObjectiveType.TALK_TO_NPC;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, amount, req));
new Objective(type, 1, 1));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newAmount = i.getAmount() + amount;
if (amount < req) {
final Material m = i.getType();
if (newAmount >= req) {
getQuestData(quest).itemsConsumed.put(found, req);
finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null, null, null,
null, null);
if (!getQuestData(quest).citizensInteracted.containsKey(n.getId())) {
return;
}
final Boolean b = getQuestData(quest).citizensInteracted.get(n.getId());
if (b != null && !b) {
getQuestData(quest).citizensInteracted.put(n.getId(), true);
finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1), new ItemStack(Material.AIR, 1)),
null, null, n, null, null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).citizensInteracted.put(n.getId(), true);
q.finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, 1)), null, null, n, null, null, null, null);
return null;
});
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, 1, 1));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark NPC as killed if the Quester has such an objective
*
* @param quest The quest for which the NPC is being killed
* @param n The NPC being killed
*/
public void killNPC(final Quest quest, final NPC n) {
if (!getQuestData(quest).citizensKilled.contains(n.getId())) {
return;
}
final int index = getQuestData(quest).citizensKilled.indexOf(n.getId());
final int npcsKilled = getQuestData(quest).citizenNumKilled.get(index);
final int npcsToKill = getCurrentStage(quest).citizenNumToKill.get(index);
final ObjectiveType type = ObjectiveType.KILL_NPC;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, npcsKilled, npcsToKill));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newNpcsKilled = getQuestData(quest).citizenNumKilled.get(index) + 1;
if (npcsKilled < npcsToKill) {
getQuestData(quest).citizenNumKilled.set(index, newNpcsKilled);
if (newNpcsKilled >= npcsToKill) {
finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, npcsToKill)), null, null, n, null, null, null, null);
// Multiplayer
final ItemStack finalFound = found;
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).itemsConsumed.put(finalFound, req);
q.finishObjective(quest, new Objective(type, new ItemStack(m, 1), finalFound), null, null, null,
null, null, null, null);
q.getQuestData(quest).citizenNumKilled.set(index, getQuestData(quest).citizenNumKilled
.get(index));
q.finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, npcsToKill)), null, null, n, null, null, null, null);
return null;
});
} else {
getQuestData(quest).itemsConsumed.put(found, newAmount);
}
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, newAmount, req));
new Objective(type, newNpcsKilled, npcsToKill));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
@ -2392,175 +2563,6 @@ public class Quester implements Comparable<Quester> {
new Objective(type, newPlayersKilled, playersToKill));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
/**
* Mark item as delivered to a NPC if Quester has such an objective
*
* @param quest The quest for which the item is being delivered
* @param n The NPC being delivered to
* @param i The item being delivered
*/
@SuppressWarnings("deprecation")
public void deliverToNPC(final Quest quest, final NPC n, final ItemStack i) {
if (n == null) {
return;
}
int currentIndex = -1;
final LinkedList<Integer> matches = new LinkedList<Integer>();
for (final ItemStack is : getQuestData(quest).itemsDelivered) {
currentIndex++;
if (ItemUtil.compareItems(i, is, true) == 0) {
matches.add(currentIndex);
}
}
if (matches.isEmpty()) {
return;
}
final Player player = getPlayer();
for (final Integer match : matches) {
final LinkedList<ItemStack> items = new LinkedList<ItemStack>(getQuestData(quest).itemsDelivered);
if (!getCurrentStage(quest).getItemDeliveryTargets().get(match).equals(n.getId())) {
continue;
}
final ItemStack found = items.get(match);
final int amount = found.getAmount();
final int toDeliver = getCurrentStage(quest).itemsToDeliver.get(match).getAmount();
final ObjectiveType type = ObjectiveType.DELIVER_ITEM;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, amount, toDeliver));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newAmount = i.getAmount() + amount;
final Material m = i.getType();
if (amount < toDeliver) {
final int index = player.getInventory().first(i);
if (index == -1) {
// Already delivered in previous loop
return;
}
if (newAmount >= toDeliver) {
final ItemStack newStack = found;
found.setAmount(toDeliver);
getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
if ((i.getAmount() + amount) >= toDeliver) {
// Take away remaining amount to be delivered
final ItemStack clone = i.clone();
clone.setAmount(i.getAmount() - (toDeliver - amount));
player.getInventory().setItem(index, clone);
} else {
player.getInventory().setItem(index, null);
}
player.updateInventory();
finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null, null,
null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
q.finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null,
null, null, null, null);
return null;
});
} else {
final ItemStack newStack = found;
found.setAmount(newAmount);
getQuestData(quest).itemsDelivered.set(items.indexOf(found), newStack);
player.getInventory().setItem(index, null);
player.updateInventory();
final String[] message = ConfigUtil.parseStringWithPossibleLineBreaks(getCurrentStage(quest)
.deliverMessages.get(new Random().nextInt(getCurrentStage(quest).deliverMessages
.size())), plugin.getDependencies().getCitizens().getNPCRegistry()
.getById(getCurrentStage(quest).itemDeliveryTargets.get(items.indexOf(found))));
player.sendMessage(message);
}
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, newAmount, toDeliver));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark NPC as interacted with if Quester has such an objective
*
* @param quest The quest for which the NPC is being interacted with
* @param n The NPC being interacted with
*/
public void interactWithNPC(final Quest quest, final NPC n) {
final ObjectiveType type = ObjectiveType.TALK_TO_NPC;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, 1, 1));
plugin.getServer().getPluginManager().callEvent(preEvent);
if (!getQuestData(quest).citizensInteracted.containsKey(n.getId())) {
return;
}
final Boolean b = getQuestData(quest).citizensInteracted.get(n.getId());
if (b != null && !b) {
getQuestData(quest).citizensInteracted.put(n.getId(), true);
finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1), new ItemStack(Material.AIR, 1)),
null, null, n, null, null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).citizensInteracted.put(n.getId(), true);
q.finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, 1)), null, null, n, null, null, null, null);
return null;
});
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, 1, 1));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark NPC as killed if the Quester has such an objective
*
* @param quest The quest for which the NPC is being killed
* @param n The NPC being killed
*/
public void killNPC(final Quest quest, final NPC n) {
if (!getQuestData(quest).citizensKilled.contains(n.getId())) {
return;
}
final int index = getQuestData(quest).citizensKilled.indexOf(n.getId());
final int npcsKilled = getQuestData(quest).citizenNumKilled.get(index);
final int npcsToKill = getCurrentStage(quest).citizenNumToKill.get(index);
final ObjectiveType type = ObjectiveType.KILL_NPC;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, npcsKilled, npcsToKill));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newNpcsKilled = getQuestData(quest).citizenNumKilled.get(index) + 1;
if (npcsKilled < npcsToKill) {
getQuestData(quest).citizenNumKilled.set(index, newNpcsKilled);
if (newNpcsKilled >= npcsToKill) {
finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, npcsToKill)), null, null, n, null, null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).citizenNumKilled.set(index, getQuestData(quest).citizenNumKilled
.get(index));
q.finishObjective(quest, new Objective(type, new ItemStack(Material.AIR, 1),
new ItemStack(Material.AIR, npcsToKill)), null, null, n, null, null, null, null);
return null;
});
}
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, newNpcsKilled, npcsToKill));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
/**
* Mark location as reached if the Quester has such an objective
@ -3279,26 +3281,19 @@ public class Quester implements Comparable<Quester> {
}
}
if (quest.getStage(stage).itemsToConsume.isEmpty() == false) {
for (final ItemStack is : quest.getStage(stage).itemsToConsume) {
data.itemsConsumed.put(is, 0);
for (final ItemStack i : quest.getStage(stage).itemsToConsume) {
final ItemStack temp = new ItemStack(i.getType(), 0, i.getDurability());
try {
temp.addEnchantments(i.getEnchantments());
} catch (final Exception e) {
plugin.getLogger().warning("Unable to add enchantment(s) " + i.getEnchantments().toString()
+ " to consume item " + i.getType().name() + " x " + i.getAmount() + " for quest ID "
+ quest.getId());
}
temp.setItemMeta(i.getItemMeta());
data.itemsConsumed.add(temp);
}
}
if (quest.getStage(stage).mobsToKill.isEmpty() == false) {
for (final EntityType e : quest.getStage(stage).mobsToKill) {
data.mobsKilled.add(e);
data.mobNumKilled.add(0);
if (quest.getStage(stage).locationsToKillWithin.isEmpty() == false) {
data.locationsToKillWithin.add(quest.getStage(stage).locationsToKillWithin.get(data.mobsKilled
.indexOf(e)));
}
if (quest.getStage(stage).radiiToKillWithin.isEmpty() == false) {
data.radiiToKillWithin.add(quest.getStage(stage).radiiToKillWithin.get(data.mobsKilled.indexOf(e)));
}
}
}
data.setCowsMilked(0);
data.setFishCaught(0);
data.setPlayersKilled(0);
if (quest.getStage(stage).itemsToDeliver.isEmpty() == false) {
for (final ItemStack i : quest.getStage(stage).itemsToDeliver) {
final ItemStack temp = new ItemStack(i.getType(), 0, i.getDurability());
@ -3324,6 +3319,22 @@ public class Quester implements Comparable<Quester> {
data.citizenNumKilled.add(0);
}
}
if (quest.getStage(stage).mobsToKill.isEmpty() == false) {
for (final EntityType e : quest.getStage(stage).mobsToKill) {
data.mobsKilled.add(e);
data.mobNumKilled.add(0);
if (quest.getStage(stage).locationsToKillWithin.isEmpty() == false) {
data.locationsToKillWithin.add(quest.getStage(stage).locationsToKillWithin.get(data.mobsKilled
.indexOf(e)));
}
if (quest.getStage(stage).radiiToKillWithin.isEmpty() == false) {
data.radiiToKillWithin.add(quest.getStage(stage).radiiToKillWithin.get(data.mobsKilled.indexOf(e)));
}
}
}
data.setCowsMilked(0);
data.setFishCaught(0);
data.setPlayersKilled(0);
if (quest.getStage(stage).locationsToReach.isEmpty() == false) {
for (final Location l : quest.getStage(stage).locationsToReach) {
data.locationsReached.add(l);
@ -3530,11 +3541,36 @@ public class Quester implements Comparable<Quester> {
}
if (questData.itemsConsumed.isEmpty() == false) {
final LinkedList<Integer> consumeAmounts = new LinkedList<Integer>();
for (final Entry<ItemStack, Integer> e : questData.itemsConsumed.entrySet()) {
consumeAmounts.add(e.getValue());
for (final ItemStack m : questData.itemsConsumed) {
consumeAmounts.add(m.getAmount());
}
questSec.set("item-consume-amounts", consumeAmounts);
}
if (questData.itemsDelivered.isEmpty() == false) {
final LinkedList<Integer> deliveryAmounts = new LinkedList<Integer>();
for (final ItemStack m : questData.itemsDelivered) {
deliveryAmounts.add(m.getAmount());
}
questSec.set("item-delivery-amounts", deliveryAmounts);
}
if (questData.citizensInteracted.isEmpty() == false) {
final LinkedList<Integer> npcIds = new LinkedList<Integer>();
final LinkedList<Boolean> hasTalked = new LinkedList<Boolean>();
for (final Integer n : questData.citizensInteracted.keySet()) {
npcIds.add(n);
hasTalked.add(questData.citizensInteracted.get(n));
}
questSec.set("citizen-ids-to-talk-to", npcIds);
questSec.set("has-talked-to", hasTalked);
}
if (questData.citizensKilled.isEmpty() == false) {
final LinkedList<Integer> npcIds = new LinkedList<Integer>();
for (final Integer n : questData.citizensKilled) {
npcIds.add(n);
}
questSec.set("citizen-ids-killed", npcIds);
questSec.set("citizen-amounts-killed", questData.citizenNumKilled);
}
if (getCurrentStage(quest) != null) {
if (getCurrentStage(quest).cowsToMilk != null) {
questSec.set("cows-milked", questData.getCowsMilked());
@ -3570,31 +3606,6 @@ public class Quester implements Comparable<Quester> {
questSec.set("mob-kill-location-radii", radii);
}
}
if (questData.itemsDelivered.isEmpty() == false) {
final LinkedList<Integer> deliveryAmounts = new LinkedList<Integer>();
for (final ItemStack m : questData.itemsDelivered) {
deliveryAmounts.add(m.getAmount());
}
questSec.set("item-delivery-amounts", deliveryAmounts);
}
if (questData.citizensInteracted.isEmpty() == false) {
final LinkedList<Integer> npcIds = new LinkedList<Integer>();
final LinkedList<Boolean> hasTalked = new LinkedList<Boolean>();
for (final Integer n : questData.citizensInteracted.keySet()) {
npcIds.add(n);
hasTalked.add(questData.citizensInteracted.get(n));
}
questSec.set("citizen-ids-to-talk-to", npcIds);
questSec.set("has-talked-to", hasTalked);
}
if (questData.citizensKilled.isEmpty() == false) {
final LinkedList<Integer> npcIds = new LinkedList<Integer>();
for (final Integer n : questData.citizensKilled) {
npcIds.add(n);
}
questSec.set("citizen-ids-killed", npcIds);
questSec.set("citizen-amounts-killed", questData.citizenNumKilled);
}
if (questData.locationsReached.isEmpty() == false) {
final LinkedList<String> locations = new LinkedList<String>();
final LinkedList<Boolean> has = new LinkedList<Boolean>();

View File

@ -1210,12 +1210,14 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
quester.sendMessage(message.replace("<item>", ItemUtil.getName(is)));
}
}
int consumeIndex = 0;
for (final ItemStack is : stage.itemsToConsume) {
int consumed = 0;
if (data.itemsConsumed.containsKey(is)) {
consumed = data.itemsConsumed.get(is);
if (data.itemsConsumed.size() > consumeIndex) {
consumed = data.itemsConsumed.get(consumeIndex).getAmount();
}
final int amt = is.getAmount();
consumeIndex++;
final ChatColor color = consumed < amt ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "consumeItem");
if (message.contains("<count>")) {
@ -1240,6 +1242,78 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
quester.sendMessage(message.replace("<item>", ItemUtil.getName(is)));
}
}
int index = 0;
for (final ItemStack is : stage.itemsToDeliver) {
int delivered = 0;
if (data.itemsDelivered.size() > index) {
delivered = data.itemsDelivered.get(index).getAmount();
}
final int toDeliver = is.getAmount();
final Integer npc = stage.itemDeliveryTargets.get(index);
index++;
final ChatColor color = delivered < toDeliver ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "deliver").replace("<npc>", depends.getNPCName(npc));
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + delivered + "/" + toDeliver);
} else {
// Legacy
message += color + ": " + delivered + "/" + toDeliver;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
localeManager.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
is.getEnchantments());
} else {
quester.sendMessage(message.replace("<item>", ItemUtil.getName(is)));
}
}
for (final Integer n : stage.citizensToInteract) {
for (final Entry<Integer, Boolean> e : data.citizensInteracted.entrySet()) {
if (e.getKey().equals(n)) {
final ChatColor color = e.getValue() == false ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "talkTo")
.replace("<npc>", depends.getNPCName(n));
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
quester.sendMessage(message);
}
}
}
for (final Integer n : stage.citizensToKill) {
for (final Integer n2 : data.citizensKilled) {
if (n.equals(n2)) {
if (data.citizenNumKilled.size() > data.citizensKilled.indexOf(n2)
&& stage.citizenNumToKill.size() > stage.citizensToKill.indexOf(n)) {
final ChatColor color = data.citizenNumKilled.get(data.citizensKilled.indexOf(n2))
< stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n))
? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "kill");
if (message.contains("<mob>")) {
message = message.replace("<mob>", depends.getNPCName(n));
} else {
message += " " + depends.getNPCName(n);
}
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ data.citizenNumKilled.get(stage.citizensToKill.indexOf(n)) + "/"
+ stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n)));
} else {
// Legacy
message += color + ": " + data.citizenNumKilled.get(stage.citizensToKill.indexOf(n)) + "/"
+ stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n));
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
quester.sendMessage(message);
}
}
}
}
if (stage.cowsToMilk != null) {
final ChatColor color = data.getCowsMilked() < stage.cowsToMilk ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "milkCow");
@ -1327,77 +1401,6 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
}
quester.sendMessage(message);
}
int index = 0;
for (final ItemStack is : stage.itemsToDeliver) {
int delivered = 0;
if (data.itemsDelivered.size() > index) {
delivered = data.itemsDelivered.get(index).getAmount();
}
final int toDeliver = is.getAmount();
final Integer npc = stage.itemDeliveryTargets.get(index);
index++;
final ChatColor color = delivered < toDeliver ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "deliver").replace("<npc>", depends.getNPCName(npc));
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color + delivered + "/" + toDeliver);
} else {
// Legacy
message += color + ": " + delivered + "/" + toDeliver;
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
if (getSettings().canTranslateNames() && !is.hasItemMeta() && !is.getItemMeta().hasDisplayName()) {
localeManager.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
is.getEnchantments());
} else {
quester.sendMessage(message.replace("<item>", ItemUtil.getName(is)));
}
}
for (final Integer n : stage.citizensToInteract) {
for (final Entry<Integer, Boolean> e : data.citizensInteracted.entrySet()) {
if (e.getKey().equals(n)) {
final ChatColor color = e.getValue() == false ? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "talkTo")
.replace("<npc>", depends.getNPCName(n));
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
quester.sendMessage(message);
}
}
}
for (final Integer n : stage.citizensToKill) {
for (final Integer n2 : data.citizensKilled) {
if (n.equals(n2)) {
if (data.citizenNumKilled.size() > data.citizensKilled.indexOf(n2)
&& stage.citizenNumToKill.size() > stage.citizensToKill.indexOf(n)) {
final ChatColor color = data.citizenNumKilled.get(data.citizensKilled.indexOf(n2))
< stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n))
? ChatColor.GREEN : ChatColor.GRAY;
String message = color + "- " + Lang.get(quester.getPlayer(), "kill");
if (message.contains("<mob>")) {
message = message.replace("<mob>", depends.getNPCName(n));
} else {
message += " " + depends.getNPCName(n);
}
if (message.contains("<count>")) {
message = message.replace("<count>", "" + color
+ data.citizenNumKilled.get(stage.citizensToKill.indexOf(n)) + "/"
+ stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n)));
} else {
// Legacy
message += color + ": " + data.citizenNumKilled.get(stage.citizensToKill.indexOf(n)) + "/"
+ stage.citizenNumToKill.get(stage.citizensToKill.indexOf(n));
}
if (depends.getPlaceholderApi() != null) {
message = PlaceholderAPI.setPlaceholders(quester.getPlayer(), message);
}
quester.sendMessage(message);
}
}
}
}
for (final Entry<EntityType, Integer> e : stage.mobsToTame.entrySet()) {
for (final Entry<EntityType, Integer> e2 : data.mobsTamed.entrySet()) {
if (e.getKey().equals(e2.getKey())) {

View File

@ -311,12 +311,61 @@ public class SeparatedYamlStorage implements StorageImplementation {
}
}
if (questSec.contains("item-consume-amounts")) {
final List<Integer> consumeAmounts = questSec.getIntegerList("item-consume-amounts");
/*final List<Integer> consumeAmounts = questSec.getIntegerList("item-consume-amounts");
for (int i = 0; i < consumeAmounts.size(); i++) {
if (i < quester.getCurrentStage(quest).getItemsToConsume().size()) {
quester.getQuestData(quest).itemsConsumed.put(quester.getCurrentStage(quest)
.getItemsToConsume().get(i), consumeAmounts.get(i));
quester.getQuestData(quest).itemsConsumed.set(i, quester.getCurrentStage(quest)
.getItemsToConsume().get(i).clone());
}
}*/
final List<Integer> consumeAmounts = questSec.getIntegerList("item-consume-amounts");
int index = 0;
for (final int amt : consumeAmounts) {
final ItemStack is = quester.getCurrentStage(quest).getItemsToConsume().get(index);
final ItemStack temp = is.clone();
temp.setAmount(amt);
if (quester.getQuestData(quest).itemsConsumed.size() > 0) {
quester.getQuestData(quest).itemsConsumed.set(index, temp);
}
index++;
}
}
if (questSec.contains("item-delivery-amounts")) {
final List<Integer> deliveryAmounts = questSec.getIntegerList("item-delivery-amounts");
int index = 0;
for (final int amt : deliveryAmounts) {
final ItemStack is = quester.getCurrentStage(quest).getItemsToDeliver().get(index);
final ItemStack temp = new ItemStack(is.getType(), amt, is.getDurability());
try {
temp.addEnchantments(is.getEnchantments());
} catch (final Exception e) {
plugin.getLogger().warning("Unable to add enchantment(s) " + is.getEnchantments().toString()
+ " to delivery item " + is.getType().name() + " x " + amt + " for quest "
+ quest.getName());
}
temp.setItemMeta(is.getItemMeta());
if (quester.getQuestData(quest).itemsDelivered.size() > 0) {
quester.getQuestData(quest).itemsDelivered.set(index, temp);
}
index++;
}
}
if (questSec.contains("citizen-ids-to-talk-to")) {
final List<Integer> ids = questSec.getIntegerList("citizen-ids-to-talk-to");
final List<Boolean> has = questSec.getBooleanList("has-talked-to");
for (final int i : ids) {
quester.getQuestData(quest).citizensInteracted.put(i, has.get(ids.indexOf(i)));
}
}
if (questSec.contains("citizen-ids-killed")) {
final List<Integer> ids = questSec.getIntegerList("citizen-ids-killed");
final List<Integer> num = questSec.getIntegerList("citizen-amounts-killed");
quester.getQuestData(quest).citizensKilled.clear();
quester.getQuestData(quest).citizenNumKilled.clear();
for (final int i : ids) {
quester.getQuestData(quest).citizensKilled.add(i);
quester.getQuestData(quest).citizenNumKilled.add(num.get(ids.indexOf(i)));
}
}
if (questSec.contains("cows-milked")) {
@ -358,43 +407,6 @@ public class SeparatedYamlStorage implements StorageImplementation {
}
}
}
if (questSec.contains("item-delivery-amounts")) {
final List<Integer> deliveryAmounts = questSec.getIntegerList("item-delivery-amounts");
int index = 0;
for (final int amt : deliveryAmounts) {
final ItemStack is = quester.getCurrentStage(quest).getItemsToDeliver().get(index);
final ItemStack temp = new ItemStack(is.getType(), amt, is.getDurability());
try {
temp.addEnchantments(is.getEnchantments());
} catch (final Exception e) {
plugin.getLogger().warning("Unable to add enchantment(s) " + is.getEnchantments().toString()
+ " to delivery item " + is.getType().name() + " x " + amt + " for quest "
+ quest.getName());
}
temp.setItemMeta(is.getItemMeta());
if (quester.getQuestData(quest).itemsDelivered.size() > 0) {
quester.getQuestData(quest).itemsDelivered.set(index, temp);
}
index++;
}
}
if (questSec.contains("citizen-ids-to-talk-to")) {
final List<Integer> ids = questSec.getIntegerList("citizen-ids-to-talk-to");
final List<Boolean> has = questSec.getBooleanList("has-talked-to");
for (final int i : ids) {
quester.getQuestData(quest).citizensInteracted.put(i, has.get(ids.indexOf(i)));
}
}
if (questSec.contains("citizen-ids-killed")) {
final List<Integer> ids = questSec.getIntegerList("citizen-ids-killed");
final List<Integer> num = questSec.getIntegerList("citizen-amounts-killed");
quester.getQuestData(quest).citizensKilled.clear();
quester.getQuestData(quest).citizenNumKilled.clear();
for (final int i : ids) {
quester.getQuestData(quest).citizensKilled.add(i);
quester.getQuestData(quest).citizenNumKilled.add(num.get(ids.indexOf(i)));
}
}
if (questSec.contains("locations-to-reach")) {
final LinkedList<Location> locations = new LinkedList<Location>();
final List<Boolean> has = questSec.getBooleanList("has-reached-location");