Skip to content

Commit

Permalink
Implement an option to set which item type will ignore metadata per c…
Browse files Browse the repository at this point in the history
…hallenge.

Fixes #261
Fixes #252
  • Loading branch information
BONNe committed Sep 24, 2021
1 parent 99a3e3f commit 08d1561
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
package world.bentobox.challenges.database.object.requirements;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;

import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;

import com.google.gson.annotations.Expose;
Expand Down Expand Up @@ -81,6 +79,34 @@ public void setTakeItems(boolean takeItems)
}


/**
* Gets ignore meta data.
*
* @return the ignore meta data
*/
public Set<Material> getIgnoreMetaData()
{
if (this.ignoreMetaData == null)
{
// Fixes null-pointer, that should not be possible, but may be.
this.ignoreMetaData = new HashSet<>();
}

return this.ignoreMetaData;
}


/**
* Sets ignore meta data.
*
* @param ignoreMetaData the ignore meta data
*/
public void setIgnoreMetaData(Set<Material> ignoreMetaData)
{
this.ignoreMetaData = ignoreMetaData;
}


// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
Expand Down Expand Up @@ -114,6 +140,7 @@ public Requirements clone()
map(ItemStack::clone).
collect(Collectors.toCollection(() -> new ArrayList<>(this.requiredItems.size()))));
clone.setTakeItems(this.takeItems);
clone.setIgnoreMetaData(new HashSet<>(this.ignoreMetaData));

return clone;
}
Expand All @@ -129,6 +156,12 @@ public Requirements clone()
@Expose
private List<ItemStack> requiredItems = new ArrayList<>();

/**
* Set of item stacks that should ignore metadata.
*/
@Expose
private Set<Material> ignoreMetaData = new HashSet<>();

/**
* Boolean that indicate if challenge completion should remove items from inventory.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ private String generateInventoryChallenge(InventoryRequirements requirement)
{
StringBuilder builder = new StringBuilder();
builder.append(this.user.getTranslationOrNothing(reference + "item-title"));
Utils.groupEqualItems(requirement.getRequiredItems()).stream().
Utils.groupEqualItems(requirement.getRequiredItems(), requirement.getIgnoreMetaData()).stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
{
Expand Down Expand Up @@ -659,7 +659,7 @@ private String generateRepeatReward(Challenge challenge)
{
StringBuilder builder = new StringBuilder();
builder.append(this.user.getTranslationOrNothing(reference + "item-title"));
Utils.groupEqualItems(challenge.getRepeatItemReward()).stream().
Utils.groupEqualItems(challenge.getRepeatItemReward(), Collections.emptySet()).stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
{
Expand Down Expand Up @@ -760,7 +760,7 @@ private String generateReward(Challenge challenge)
{
StringBuilder builder = new StringBuilder();
builder.append(this.user.getTranslationOrNothing(reference + "item-title"));
Utils.groupEqualItems(challenge.getRewardItems()).stream().
Utils.groupEqualItems(challenge.getRewardItems(), Collections.emptySet()).stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
{
Expand Down Expand Up @@ -974,7 +974,7 @@ private String generateReward(ChallengeLevel level)
{
StringBuilder builder = new StringBuilder();
builder.append(this.user.getTranslationOrNothing(reference + "item-title"));
Utils.groupEqualItems(level.getRewardItems()).stream().
Utils.groupEqualItems(level.getRewardItems(), Collections.emptySet()).stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.Duration;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.bukkit.Material;
import org.bukkit.World;
Expand Down Expand Up @@ -207,6 +208,16 @@ private void buildInventoryRequirementsPanel(PanelBuilder panelBuilder)
panelBuilder.item(10, this.createRequirementButton(RequirementButton.REQUIRED_ITEMS));
panelBuilder.item(19, this.createRequirementButton(RequirementButton.REMOVE_ITEMS));

if (!this.challenge.<InventoryRequirements>getRequirements().getRequiredItems().isEmpty())
{
panelBuilder.item(12, this.createRequirementButton(RequirementButton.ADD_IGNORED_META));

if (!this.challenge.<InventoryRequirements>getRequirements().getIgnoreMetaData().isEmpty())
{
panelBuilder.item(21, this.createRequirementButton(RequirementButton.REMOVE_IGNORED_META));
}
}

panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS));
}

Expand Down Expand Up @@ -683,7 +694,7 @@ private PanelItem createRequirementButton(RequirementButton button)
return this.createIslandRequirementButton(button);
}
// Buttons for Inventory Requirements
case REQUIRED_ITEMS, REMOVE_ITEMS -> {
case REQUIRED_ITEMS, REMOVE_ITEMS, ADD_IGNORED_META, REMOVE_IGNORED_META -> {
return this.createInventoryRequirementButton(button);
}
// Buttons for Other Requirements
Expand Down Expand Up @@ -882,7 +893,8 @@ private PanelItem createInventoryRequirementButton(RequirementButton button)
{
description.add(this.user.getTranslation(reference + "title"));

Utils.groupEqualItems(requirements.getRequiredItems()).stream().
Utils.groupEqualItems(requirements.getRequiredItems(), requirements.getIgnoreMetaData()).
stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
Expand Down Expand Up @@ -923,6 +935,90 @@ private PanelItem createInventoryRequirementButton(RequirementButton button)
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case ADD_IGNORED_META -> {
if (requirements.getIgnoreMetaData().isEmpty())
{
description.add(this.user.getTranslation(reference + "none"));
}
else
{
description.add(this.user.getTranslation(reference + "title"));

requirements.getIgnoreMetaData().stream().
sorted(Comparator.comparing(Material::name)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
"[item]", Utils.prettifyObject(itemStack, this.user))));
}

icon = new ItemStack(Material.GREEN_SHULKER_BOX);

clickHandler = (panel, user, clickType, slot) -> {
if (requirements.getRequiredItems().isEmpty())
{
// Do nothing if no requirements are set.
return true;
}

// Allow choosing only from inventory items.
Set<Material> collection = Arrays.stream(Material.values()).collect(Collectors.toSet());
requirements.getRequiredItems().stream().
map(ItemStack::getType).
forEach(collection::remove);
collection.addAll(requirements.getIgnoreMetaData());

MultiBlockSelector.open(this.user,
MultiBlockSelector.Mode.ANY,
collection,
(status, materials) ->
{
if (status)
{
requirements.setIgnoreMetaData(new HashSet<>(materials));
}

this.build();
});
return true;
};
glow = false;

description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-add"));
}
case REMOVE_IGNORED_META -> {
icon = new ItemStack(Material.RED_SHULKER_BOX);

clickHandler = (panel, user, clickType, slot) -> {
if (requirements.getIgnoreMetaData().isEmpty())
{
// Do nothing if no requirements are set.
return true;
}

// Allow choosing only from inventory items.
Set<Material> collection = Arrays.stream(Material.values()).collect(Collectors.toSet());
collection.removeAll(requirements.getIgnoreMetaData());

MultiBlockSelector.open(this.user,
MultiBlockSelector.Mode.ANY,
collection,
(status, materials) ->
{
if (status)
{
requirements.getIgnoreMetaData().removeAll(materials);
}

this.build();
});
return true;
};
glow = false;

description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
}
default -> {
icon = new ItemStack(Material.PAPER);
clickHandler = null;
Expand Down Expand Up @@ -1346,7 +1442,8 @@ private PanelItem createRewardButton(RewardButton button)
{
description.add(this.user.getTranslation(reference + "title"));

Utils.groupEqualItems(this.challenge.getRewardItems()).stream().
Utils.groupEqualItems(this.challenge.getRewardItems(), Collections.emptySet()).
stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
Expand Down Expand Up @@ -1597,7 +1694,8 @@ private PanelItem createRewardButton(RewardButton button)
{
description.add(this.user.getTranslation(reference + "title"));

Utils.groupEqualItems(this.challenge.getRepeatItemReward()).stream().
Utils.groupEqualItems(this.challenge.getRepeatItemReward(), Collections.emptySet()).
stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
Expand Down Expand Up @@ -1869,6 +1967,8 @@ private enum RequirementButton
REQUIRED_PERMISSIONS,
REQUIRED_ITEMS,
REMOVE_ITEMS,
ADD_IGNORED_META,
REMOVE_IGNORED_META,
REQUIRED_EXPERIENCE,
REMOVE_EXPERIENCE,
REQUIRED_LEVEL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ private PanelItem createButton(Button button)
{
description.add(this.user.getTranslation(reference + "title"));

Utils.groupEqualItems(this.challengeLevel.getRewardItems()).stream().
Utils.groupEqualItems(this.challengeLevel.getRewardItems(), Collections.emptySet()).
stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
Expand Down
42 changes: 21 additions & 21 deletions src/main/java/world/bentobox/challenges/tasks/TryToComplete.java
Original file line number Diff line number Diff line change
Expand Up @@ -888,30 +888,29 @@ private ChallengeResult checkInventory(int maxTimes)
// Players in creative game mode has got all items. No point to search for them.
if (this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
{
requiredItems = Utils.groupEqualItems(this.getInventoryRequirements().getRequiredItems());
requiredItems = Utils.groupEqualItems(this.getInventoryRequirements().getRequiredItems(),
this.getInventoryRequirements().getIgnoreMetaData());

// Check if all required items are in players inventory.
for (ItemStack required : requiredItems)
{
int numInInventory;

if (Utils.canIgnoreMeta(required.getType()))
if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
{
numInInventory =
Arrays.stream(this.user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.getType().equals(required.getType())).
mapToInt(ItemStack::getAmount).
sum();
numInInventory = Arrays.stream(this.user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.getType().equals(required.getType())).
mapToInt(ItemStack::getAmount).
sum();
}
else
{
numInInventory =
Arrays.stream(this.user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.isSimilar(required)).
mapToInt(ItemStack::getAmount).
sum();
numInInventory = Arrays.stream(this.user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.isSimilar(required)).
mapToInt(ItemStack::getAmount).
sum();
}

if (numInInventory < required.getAmount())
Expand Down Expand Up @@ -952,22 +951,23 @@ Map<ItemStack, Integer> removeItems(List<ItemStack> requiredItemList, int factor
int amountToBeRemoved = required.getAmount() * factor;
List<ItemStack> itemsInInventory;

if (Utils.canIgnoreMeta(required.getType()))
if (this.getInventoryRequirements().getIgnoreMetaData().contains(required.getType()))
{
// Use collecting method that ignores item meta.
itemsInInventory = Arrays.stream(user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.getType().equals(required.getType())).
collect(Collectors.toList());
filter(Objects::nonNull).
filter(i -> i.getType().equals(required.getType())).
collect(Collectors.toList());
}
else
{
// Use collecting method that compares item meta.
itemsInInventory = Arrays.stream(user.getInventory().getContents()).
filter(Objects::nonNull).
filter(i -> i.isSimilar(required)).
collect(Collectors.toList());
filter(Objects::nonNull).
filter(i -> i.isSimilar(required)).
collect(Collectors.toList());
}

for (ItemStack itemStack : itemsInInventory)
{
if (amountToBeRemoved > 0)
Expand Down

0 comments on commit 08d1561

Please sign in to comment.