mirror of
https://github.com/BentoBoxWorld/Challenges.git
synced 2024-12-30 21:07:47 +01:00
Rework TryToComplete. (#109)
* Rework TryToComplete. Implement ability to complete challenge multiple times at once. To do it, I split everything in checking/removing/rewarding steps. In checking step, it calculates if it is possible to complete with minimal requirements and then calculates maximal repeating factor. In removing step, it removes everything that is necessary. In rewarding step, it give rewards by necessary factor (multilayer). I rework item/block/entity removing as factors may be influenced at the last element, so I improve everything by memory usage. Create necessary sets/lists/queues for faster access to already collected items. * Add method that returns removed items, if somehow algorithm did not manage to remove all items. Fix issue when removeItems method did not merge ItemStacks as they had different item amount. Return and fix TryToCompleteTest. * Implement Multiple Challenge Completion command and GUI. (#73) /[gamemode] challenges complete [number] allows to complete challenges [number] amount (or less if not enough items) Via GUI users can right click on challenge and if it is repeatable, then it will open AnvilGUI that accepts only numbers as input.
This commit is contained in:
parent
d9486bbbdb
commit
c8088f275d
@ -604,9 +604,23 @@ public class ChallengesManager
|
|||||||
* @param challengeID - challengeID
|
* @param challengeID - challengeID
|
||||||
*/
|
*/
|
||||||
private void setChallengeComplete(@NonNull String storageDataID, @NonNull String challengeID)
|
private void setChallengeComplete(@NonNull String storageDataID, @NonNull String challengeID)
|
||||||
|
{
|
||||||
|
this.setChallengeComplete(storageDataID, challengeID, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the challenge with given ID as complete and increments the number of times it has been
|
||||||
|
* completed
|
||||||
|
*
|
||||||
|
* @param storageDataID - playerData ID
|
||||||
|
* @param challengeID - challengeID
|
||||||
|
* @param count - how many times challenge is completed
|
||||||
|
*/
|
||||||
|
private void setChallengeComplete(@NonNull String storageDataID, @NonNull String challengeID, int count)
|
||||||
{
|
{
|
||||||
this.addPlayerData(storageDataID);
|
this.addPlayerData(storageDataID);
|
||||||
this.playerCacheData.get(storageDataID).setChallengeDone(challengeID);
|
this.playerCacheData.get(storageDataID).addChallengeDone(challengeID, count);
|
||||||
// Save
|
// Save
|
||||||
this.savePlayerData(storageDataID);
|
this.savePlayerData(storageDataID);
|
||||||
}
|
}
|
||||||
@ -842,9 +856,9 @@ public class ChallengesManager
|
|||||||
* @param world - World where completion must be called.
|
* @param world - World where completion must be called.
|
||||||
* @param challenge - That must be completed.
|
* @param challenge - That must be completed.
|
||||||
*/
|
*/
|
||||||
public void setChallengeComplete(User user, World world, Challenge challenge)
|
public void setChallengeComplete(User user, World world, Challenge challenge, int completionCount)
|
||||||
{
|
{
|
||||||
this.setChallengeComplete(user.getUniqueId(), world, challenge);
|
this.setChallengeComplete(user.getUniqueId(), world, challenge, completionCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -854,13 +868,14 @@ public class ChallengesManager
|
|||||||
* @param world - World where completion must be called.
|
* @param world - World where completion must be called.
|
||||||
* @param challenge - That must be completed.
|
* @param challenge - That must be completed.
|
||||||
*/
|
*/
|
||||||
public void setChallengeComplete(UUID userID, World world, Challenge challenge)
|
public void setChallengeComplete(UUID userID, World world, Challenge challenge, int completionCount)
|
||||||
{
|
{
|
||||||
String storageID = this.getDataUniqueID(userID, Util.getWorld(world));
|
String storageID = this.getDataUniqueID(userID, Util.getWorld(world));
|
||||||
this.setChallengeComplete(storageID, challenge.getUniqueId());
|
this.setChallengeComplete(storageID, challenge.getUniqueId());
|
||||||
this.addLogEntry(storageID, new LogEntry.Builder("COMPLETE").
|
this.addLogEntry(storageID, new LogEntry.Builder("COMPLETE").
|
||||||
data("user-id", userID.toString()).
|
data("user-id", userID.toString()).
|
||||||
data("challenge-id", challenge.getUniqueId()).
|
data("challenge-id", challenge.getUniqueId()).
|
||||||
|
data("completion-count", Integer.toString(completionCount)).
|
||||||
build());
|
build());
|
||||||
|
|
||||||
// Fire event that user completes challenge
|
// Fire event that user completes challenge
|
||||||
@ -868,7 +883,7 @@ public class ChallengesManager
|
|||||||
new ChallengeCompletedEvent(challenge.getUniqueId(),
|
new ChallengeCompletedEvent(challenge.getUniqueId(),
|
||||||
userID,
|
userID,
|
||||||
false,
|
false,
|
||||||
1));
|
completionCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,15 +112,14 @@ public class CompleteChallengeCommand extends CompositeCommand
|
|||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
// TODO: not implemented YET
|
case 4:
|
||||||
// case 4:
|
// Suggest a number of completions.
|
||||||
// // Suggest a number of completions.
|
if (lastString.isEmpty() || lastString.matches("[0-9]*"))
|
||||||
// if (lastString.isEmpty() || lastString.matches("[0-9]*"))
|
{
|
||||||
// {
|
returnList.addAll(Util.tabLimit(Collections.singletonList("<number>"), lastString));
|
||||||
// returnList.addAll(Util.tabLimit(Collections.singletonList("<number>"), lastString));
|
}
|
||||||
// }
|
|
||||||
//
|
break;
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
returnList.addAll(Util.tabLimit(Collections.singletonList("help"), lastString));
|
returnList.addAll(Util.tabLimit(Collections.singletonList("help"), lastString));
|
||||||
|
@ -217,8 +217,21 @@ public class ChallengesPlayerData implements DataObject
|
|||||||
*/
|
*/
|
||||||
public void setChallengeDone(@NonNull String challengeName)
|
public void setChallengeDone(@NonNull String challengeName)
|
||||||
{
|
{
|
||||||
int times = challengeStatus.getOrDefault(challengeName, 0) + 1;
|
this.addChallengeDone(challengeName, 1);
|
||||||
challengeStatus.put(challengeName, times);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a challenge as having been completed. Will increment the number of times and
|
||||||
|
* timestamp
|
||||||
|
*
|
||||||
|
* @param challengeName - unique challenge name
|
||||||
|
* @param times - how many new times should be added
|
||||||
|
*/
|
||||||
|
public void addChallengeDone(@NonNull String challengeName, int times)
|
||||||
|
{
|
||||||
|
int newTimes = challengeStatus.getOrDefault(challengeName, 0) + times;
|
||||||
|
challengeStatus.put(challengeName, newTimes);
|
||||||
challengesTimestamp.put(challengeName, System.currentTimeMillis());
|
challengesTimestamp.put(challengeName, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.wesjd.anvilgui.AnvilGUI;
|
||||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||||
@ -356,14 +357,47 @@ public class ChallengesGUI extends CommonGUI
|
|||||||
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
|
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
|
||||||
this.addon.getChallengesSettings().getLoreLineLength())).
|
this.addon.getChallengesSettings().getLoreLineLength())).
|
||||||
clickHandler((panel, user1, clickType, slot) -> {
|
clickHandler((panel, user1, clickType, slot) -> {
|
||||||
if (TryToComplete.complete(this.addon,
|
|
||||||
this.user,
|
// Add ability to input how many repeats player should do.
|
||||||
challenge,
|
// Do not open if challenge is not repeatable.
|
||||||
this.world,
|
if (clickType.isRightClick() && challenge.isRepeatable())
|
||||||
this.topLabel,
|
|
||||||
this.permissionPrefix))
|
|
||||||
{
|
{
|
||||||
panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem());
|
new AnvilGUI(this.addon.getPlugin(),
|
||||||
|
this.user.getPlayer(),
|
||||||
|
"1",
|
||||||
|
(player, reply) -> {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (TryToComplete.complete(this.addon,
|
||||||
|
this.user,
|
||||||
|
challenge,
|
||||||
|
this.world,
|
||||||
|
this.topLabel,
|
||||||
|
this.permissionPrefix,
|
||||||
|
Integer.parseInt(reply)))
|
||||||
|
{
|
||||||
|
panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.user.sendMessage("challenges.errors.not-a-integer", "[value]", reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (TryToComplete.complete(this.addon,
|
||||||
|
this.user,
|
||||||
|
challenge,
|
||||||
|
this.world,
|
||||||
|
this.topLabel,
|
||||||
|
this.permissionPrefix))
|
||||||
|
{
|
||||||
|
panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
package world.bentobox.challenges.tasks;
|
package world.bentobox.challenges.tasks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -23,7 +25,6 @@ import world.bentobox.challenges.ChallengesManager;
|
|||||||
import world.bentobox.challenges.database.object.Challenge;
|
import world.bentobox.challenges.database.object.Challenge;
|
||||||
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
|
import world.bentobox.challenges.database.object.Challenge.ChallengeType;
|
||||||
import world.bentobox.challenges.database.object.ChallengeLevel;
|
import world.bentobox.challenges.database.object.ChallengeLevel;
|
||||||
import world.bentobox.challenges.utils.GuiUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,9 +183,32 @@ public class TryToComplete
|
|||||||
World world,
|
World world,
|
||||||
String topLabel,
|
String topLabel,
|
||||||
String permissionPrefix)
|
String permissionPrefix)
|
||||||
|
{
|
||||||
|
return TryToComplete.complete(addon, user, challenge, world, topLabel, permissionPrefix, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This static method allows complete challenge and get result about completion.
|
||||||
|
* @param addon - Challenges Addon.
|
||||||
|
* @param user - User who performs challenge.
|
||||||
|
* @param challenge - Challenge that should be completed.
|
||||||
|
* @param world - World where completion may occur.
|
||||||
|
* @param topLabel - Label of the top command.
|
||||||
|
* @param permissionPrefix - Permission prefix for GameMode addon.
|
||||||
|
* @param maxTimes - Integer that represents how many times user wants to complete challenges.
|
||||||
|
* @return true, if challenge is completed, otherwise false.
|
||||||
|
*/
|
||||||
|
public static boolean complete(ChallengesAddon addon,
|
||||||
|
User user,
|
||||||
|
Challenge challenge,
|
||||||
|
World world,
|
||||||
|
String topLabel,
|
||||||
|
String permissionPrefix,
|
||||||
|
int maxTimes)
|
||||||
{
|
{
|
||||||
return new TryToComplete(addon, user, challenge, world, topLabel, permissionPrefix).
|
return new TryToComplete(addon, user, challenge, world, topLabel, permissionPrefix).
|
||||||
build().meetsRequirements;
|
build(maxTimes).meetsRequirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -197,17 +221,41 @@ public class TryToComplete
|
|||||||
* This method checks if challenge can be done, and complete it, if it is possible.
|
* This method checks if challenge can be done, and complete it, if it is possible.
|
||||||
* @return ChallengeResult object, that contains completion status.
|
* @return ChallengeResult object, that contains completion status.
|
||||||
*/
|
*/
|
||||||
public ChallengeResult build()
|
public ChallengeResult build(int maxTimes)
|
||||||
{
|
{
|
||||||
// Check if can complete challenge
|
// Check if can complete challenge
|
||||||
ChallengeResult result = this.checkIfCanCompleteChallenge();
|
ChallengeResult result = this.checkIfCanCompleteChallenge(maxTimes);
|
||||||
|
|
||||||
if (!result.meetsRequirements)
|
if (!result.isMeetsRequirements())
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.repeat)
|
this.fullFillRequirements(result);
|
||||||
|
|
||||||
|
// Validation to avoid rewarding if something goes wrong in removing requirements.
|
||||||
|
|
||||||
|
if (!result.isMeetsRequirements())
|
||||||
|
{
|
||||||
|
if (result.removedItems != null)
|
||||||
|
{
|
||||||
|
result.removedItems.forEach((item, amount) ->
|
||||||
|
{
|
||||||
|
ItemStack returnItem = item.clone();
|
||||||
|
returnItem.setAmount(amount);
|
||||||
|
|
||||||
|
this.user.getInventory().addItem(returnItem).forEach((k, v) ->
|
||||||
|
this.user.getWorld().dropItem(this.user.getLocation(), v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entities and blocks will not be restored.
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If challenge was not completed then reward items for completing it first time.
|
||||||
|
if (!result.wasCompleted())
|
||||||
{
|
{
|
||||||
// Item rewards
|
// Item rewards
|
||||||
for (ItemStack reward : this.challenge.getRewardItems())
|
for (ItemStack reward : this.challenge.getRewardItems())
|
||||||
@ -230,7 +278,11 @@ public class TryToComplete
|
|||||||
// Run commands
|
// Run commands
|
||||||
this.runCommands(this.challenge.getRewardCommands());
|
this.runCommands(this.challenge.getRewardCommands());
|
||||||
|
|
||||||
this.user.sendMessage("challenges.messages.you-completed-challenge", "[value]", this.challenge.getFriendlyName());
|
// Send message about first completion only if it is completed only once.
|
||||||
|
if (result.getFactor() == 1)
|
||||||
|
{
|
||||||
|
this.user.sendMessage("challenges.messages.you-completed-challenge", "[value]", this.challenge.getFriendlyName());
|
||||||
|
}
|
||||||
|
|
||||||
if (this.addon.getChallengesSettings().isBroadcastMessages())
|
if (this.addon.getChallengesSettings().isBroadcastMessages())
|
||||||
{
|
{
|
||||||
@ -257,36 +309,58 @@ public class TryToComplete
|
|||||||
20);
|
20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (result.wasCompleted() || result.getFactor() > 1)
|
||||||
{
|
{
|
||||||
|
int rewardFactor = result.getFactor() - (result.wasCompleted() ? 0 : 1);
|
||||||
|
|
||||||
// Item Repeat Rewards
|
// Item Repeat Rewards
|
||||||
for (ItemStack reward : this.challenge.getRepeatItemReward())
|
for (ItemStack reward : this.challenge.getRepeatItemReward())
|
||||||
{
|
{
|
||||||
// Clone is necessary because otherwise it will chane reward itemstack
|
// Clone is necessary because otherwise it will chane reward itemstack
|
||||||
// amount.
|
// amount.
|
||||||
this.user.getInventory().addItem(reward.clone()).forEach((k, v) ->
|
|
||||||
this.user.getWorld().dropItem(this.user.getLocation(), v));
|
for (int i = 0; i < rewardFactor; i++)
|
||||||
|
{
|
||||||
|
this.user.getInventory().addItem(reward.clone()).forEach((k, v) ->
|
||||||
|
this.user.getWorld().dropItem(this.user.getLocation(), v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Money Repeat Reward
|
// Money Repeat Reward
|
||||||
if (this.addon.isEconomyProvided())
|
if (this.addon.isEconomyProvided())
|
||||||
{
|
{
|
||||||
this.addon.getEconomyProvider().deposit(this.user, this.challenge.getRepeatMoneyReward());
|
this.addon.getEconomyProvider().deposit(this.user,
|
||||||
|
this.challenge.getRepeatMoneyReward() * rewardFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Experience Repeat Reward
|
// Experience Repeat Reward
|
||||||
this.user.getPlayer().giveExp(this.challenge.getRepeatExperienceReward());
|
this.user.getPlayer().giveExp(
|
||||||
|
this.challenge.getRepeatExperienceReward() * rewardFactor);
|
||||||
|
|
||||||
// Run commands
|
// Run commands
|
||||||
this.runCommands(this.challenge.getRepeatRewardCommands());
|
for (int i = 0; i < rewardFactor; i++)
|
||||||
|
{
|
||||||
|
this.runCommands(this.challenge.getRepeatRewardCommands());
|
||||||
|
}
|
||||||
|
|
||||||
this.user.sendMessage("challenges.messages.you-repeated-challenge", "[value]", this.challenge.getFriendlyName());
|
if (result.getFactor() > 1)
|
||||||
|
{
|
||||||
|
this.user.sendMessage("challenges.messages.you-repeated-challenge-multiple",
|
||||||
|
"[value]", this.challenge.getFriendlyName(),
|
||||||
|
"[count]", Integer.toString(result.getFactor()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.user.sendMessage("challenges.messages.you-repeated-challenge", "[value]", this.challenge.getFriendlyName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as complete
|
// Mark as complete
|
||||||
this.manager.setChallengeComplete(this.user, this.world, this.challenge);
|
this.manager.setChallengeComplete(this.user, this.world, this.challenge, result.getFactor());
|
||||||
|
|
||||||
if (!result.repeat)
|
// Check level completion.
|
||||||
|
if (!result.wasCompleted())
|
||||||
{
|
{
|
||||||
ChallengeLevel level = this.manager.getLevel(this.challenge);
|
ChallengeLevel level = this.manager.getLevel(this.challenge);
|
||||||
|
|
||||||
@ -350,11 +424,77 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method full fills all challenge type requirements, that is not full filled yet.
|
||||||
|
* @param result Challenge Results
|
||||||
|
*/
|
||||||
|
private void fullFillRequirements(ChallengeResult result)
|
||||||
|
{
|
||||||
|
if (this.challenge.getChallengeType().equals(ChallengeType.ISLAND))
|
||||||
|
{
|
||||||
|
if (result.meetsRequirements &&
|
||||||
|
this.challenge.isRemoveEntities() &&
|
||||||
|
!this.challenge.getRequiredEntities().isEmpty())
|
||||||
|
{
|
||||||
|
this.removeEntities(result.entities, result.getFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.meetsRequirements &&
|
||||||
|
this.challenge.isRemoveBlocks() &&
|
||||||
|
!this.challenge.getRequiredBlocks().isEmpty())
|
||||||
|
{
|
||||||
|
this.removeBlocks(result.blocks, result.getFactor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.challenge.getChallengeType().equals(ChallengeType.INVENTORY))
|
||||||
|
{
|
||||||
|
|
||||||
|
// If remove items, then remove them
|
||||||
|
if (this.challenge.isTakeItems())
|
||||||
|
{
|
||||||
|
int sumEverything = result.requiredItems.stream().
|
||||||
|
mapToInt(itemStack -> itemStack.getAmount() * result.getFactor()).
|
||||||
|
sum();
|
||||||
|
|
||||||
|
Map<ItemStack, Integer> removedItems =
|
||||||
|
this.removeItems(result.requiredItems, result.getFactor());
|
||||||
|
|
||||||
|
int removedAmount = removedItems.values().stream().mapToInt(num -> num).sum();
|
||||||
|
|
||||||
|
// Something is not removed.
|
||||||
|
if (sumEverything != removedAmount)
|
||||||
|
{
|
||||||
|
this.user.sendMessage("challenges.errors.cannot-remove-items");
|
||||||
|
|
||||||
|
result.removedItems = removedItems;
|
||||||
|
result.meetsRequirements = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.challenge.getChallengeType().equals(ChallengeType.OTHER))
|
||||||
|
{
|
||||||
|
if (this.addon.isEconomyProvided() && this.challenge.isTakeMoney())
|
||||||
|
{
|
||||||
|
this.addon.getEconomyProvider().withdraw(this.user, this.challenge.getRequiredMoney());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.challenge.isTakeExperience() &&
|
||||||
|
this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
|
||||||
|
{
|
||||||
|
// Cannot take anything from creative game mode.
|
||||||
|
this.user.getPlayer().setTotalExperience(
|
||||||
|
this.user.getPlayer().getTotalExperience() - this.challenge.getRequiredExperience());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a challenge can be completed or not
|
* Checks if a challenge can be completed or not
|
||||||
* It returns ChallengeResult.
|
* It returns ChallengeResult.
|
||||||
|
* @param maxTimes - times that user wanted to complete
|
||||||
*/
|
*/
|
||||||
private ChallengeResult checkIfCanCompleteChallenge()
|
private ChallengeResult checkIfCanCompleteChallenge(int maxTimes)
|
||||||
{
|
{
|
||||||
ChallengeResult result;
|
ChallengeResult result;
|
||||||
|
|
||||||
@ -422,21 +562,27 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
else if (type.equals(ChallengeType.INVENTORY))
|
else if (type.equals(ChallengeType.INVENTORY))
|
||||||
{
|
{
|
||||||
result = this.checkInventory();
|
result = this.checkInventory(this.getAvailableCompletionTimes(maxTimes));
|
||||||
}
|
}
|
||||||
else if (type.equals(ChallengeType.ISLAND))
|
else if (type.equals(ChallengeType.ISLAND))
|
||||||
{
|
{
|
||||||
result = this.checkSurrounding();
|
result = this.checkSurrounding(this.getAvailableCompletionTimes(maxTimes));
|
||||||
}
|
}
|
||||||
else if (type.equals(ChallengeType.OTHER))
|
else if (type.equals(ChallengeType.OTHER))
|
||||||
{
|
{
|
||||||
result = this.checkOthers();
|
result = this.checkOthers(this.getAvailableCompletionTimes(maxTimes));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = EMPTY_RESULT;
|
result = EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark if challenge is completed.
|
||||||
|
if (result.isMeetsRequirements())
|
||||||
|
{
|
||||||
|
result.setCompleted(this.manager.isChallengeComplete(this.user, this.world, this.challenge));
|
||||||
|
}
|
||||||
|
|
||||||
// Everything fails till this point.
|
// Everything fails till this point.
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -452,6 +598,35 @@ public class TryToComplete
|
|||||||
this.challenge.getRequiredPermissions().stream().allMatch(s -> this.user.hasPermission(s));
|
this.challenge.getRequiredPermissions().stream().allMatch(s -> this.user.hasPermission(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if it is possible to complete maxTimes current challenge by
|
||||||
|
* challenge constraints and already completed times.
|
||||||
|
* @param vantedTimes How many times user wants to complete challenge
|
||||||
|
* @return how many times user is able complete challenge by its constraints.
|
||||||
|
*/
|
||||||
|
private int getAvailableCompletionTimes(int vantedTimes)
|
||||||
|
{
|
||||||
|
if (!this.challenge.isRepeatable())
|
||||||
|
{
|
||||||
|
// Challenge is not repeatable
|
||||||
|
vantedTimes = 1;
|
||||||
|
}
|
||||||
|
else if (this.challenge.getMaxTimes() != 0)
|
||||||
|
{
|
||||||
|
// Challenge has limitations
|
||||||
|
long availableTimes = this.challenge.getMaxTimes() - this.manager.getChallengeTimes(this.user, this.world, this.challenge);
|
||||||
|
|
||||||
|
if (availableTimes < vantedTimes)
|
||||||
|
{
|
||||||
|
vantedTimes = (int) availableTimes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vantedTimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method runs all commands from command list.
|
* This method runs all commands from command list.
|
||||||
* @param commands List of commands that must be performed.
|
* @param commands List of commands that must be performed.
|
||||||
@ -520,8 +695,9 @@ public class TryToComplete
|
|||||||
/**
|
/**
|
||||||
* Checks if a inventory challenge can be completed or not
|
* Checks if a inventory challenge can be completed or not
|
||||||
* It returns ChallengeResult.
|
* It returns ChallengeResult.
|
||||||
|
* @param maxTimes - times that user wanted to complete
|
||||||
*/
|
*/
|
||||||
private ChallengeResult checkInventory()
|
private ChallengeResult checkInventory(int maxTimes)
|
||||||
{
|
{
|
||||||
// Run through inventory
|
// Run through inventory
|
||||||
List<ItemStack> requiredItems = new ArrayList<>(this.challenge.getRequiredItems().size());
|
List<ItemStack> requiredItems = new ArrayList<>(this.challenge.getRequiredItems().size());
|
||||||
@ -560,77 +736,62 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sumEverything = 0;
|
|
||||||
|
|
||||||
// Check if all required items are in players inventory.
|
// Check if all required items are in players inventory.
|
||||||
for (ItemStack required : requiredItems)
|
for (ItemStack required : requiredItems)
|
||||||
{
|
{
|
||||||
|
int numInInventory;
|
||||||
|
|
||||||
if (this.canIgnoreMeta(required.getType()))
|
if (this.canIgnoreMeta(required.getType()))
|
||||||
{
|
{
|
||||||
int numInInventory =
|
numInInventory =
|
||||||
Arrays.stream(this.user.getInventory().getContents()).
|
Arrays.stream(this.user.getInventory().getContents()).
|
||||||
filter(Objects::nonNull).
|
filter(Objects::nonNull).
|
||||||
filter(i -> i.getType().equals(required.getType())).
|
filter(i -> i.getType().equals(required.getType())).
|
||||||
mapToInt(ItemStack::getAmount).
|
mapToInt(ItemStack::getAmount).
|
||||||
sum();
|
sum();
|
||||||
|
|
||||||
if (numInInventory < required.getAmount())
|
|
||||||
{
|
|
||||||
this.user.sendMessage("challenges.errors.not-enough-items",
|
|
||||||
"[items]",
|
|
||||||
Util.prettifyText(required.getType().toString()));
|
|
||||||
return EMPTY_RESULT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!this.user.getInventory().containsAtLeast(required, required.getAmount()))
|
numInInventory =
|
||||||
{
|
Arrays.stream(this.user.getInventory().getContents()).
|
||||||
this.user.sendMessage("challenges.errors.not-enough-items",
|
filter(Objects::nonNull).
|
||||||
"[items]",
|
filter(i -> i.isSimilar(required)).
|
||||||
Util.prettifyText(required.getType().toString()));
|
mapToInt(ItemStack::getAmount).
|
||||||
return EMPTY_RESULT;
|
sum();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sumEverything += required.getAmount();
|
if (numInInventory < required.getAmount())
|
||||||
}
|
|
||||||
|
|
||||||
// If remove items, then remove them
|
|
||||||
if (this.challenge.isTakeItems())
|
|
||||||
{
|
|
||||||
Map<Material, Integer> removedItems = this.removeItems(requiredItems);
|
|
||||||
|
|
||||||
int removedAmount = removedItems.values().stream().mapToInt(num -> num).sum();
|
|
||||||
|
|
||||||
// Something is not removed.
|
|
||||||
if (sumEverything != removedAmount)
|
|
||||||
{
|
{
|
||||||
this.user.sendMessage("challenges.errors.cannot-remove-items");
|
this.user.sendMessage("challenges.errors.not-enough-items",
|
||||||
// TODO: Necessary to implement returning removed items.
|
"[items]",
|
||||||
|
Util.prettifyText(required.getType().toString()));
|
||||||
return EMPTY_RESULT;
|
return EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxTimes = Math.min(maxTimes, numInInventory / required.getAmount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the result
|
// Return the result
|
||||||
return new ChallengeResult().setMeetsRequirements().setRepeat(
|
return new ChallengeResult().
|
||||||
this.manager.isChallengeComplete(this.user, this.world, this.challenge));
|
setMeetsRequirements().
|
||||||
|
setCompleteFactor(maxTimes).
|
||||||
|
setRequiredItems(requiredItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes items from a user's inventory
|
* Removes items from a user's inventory
|
||||||
* @param requiredItemList - a list of item stacks to be removed
|
* @param requiredItemList - a list of item stacks to be removed
|
||||||
|
* @param factor - factor for required items.
|
||||||
*/
|
*/
|
||||||
Map<Material, Integer> removeItems(List<ItemStack> requiredItemList)
|
Map<ItemStack, Integer> removeItems(List<ItemStack> requiredItemList, int factor)
|
||||||
{
|
{
|
||||||
Map<Material, Integer> removed = new HashMap<>();
|
Map<ItemStack, Integer> removed = new HashMap<>();
|
||||||
|
|
||||||
for (ItemStack required : requiredItemList)
|
for (ItemStack required : requiredItemList)
|
||||||
{
|
{
|
||||||
int amountToBeRemoved = required.getAmount();
|
int amountToBeRemoved = required.getAmount() * factor;
|
||||||
|
|
||||||
List<ItemStack> itemsInInventory;
|
List<ItemStack> itemsInInventory;
|
||||||
|
|
||||||
@ -651,22 +812,25 @@ public class TryToComplete
|
|||||||
collect(Collectors.toList());
|
collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ItemStack i : itemsInInventory)
|
for (ItemStack itemStack : itemsInInventory)
|
||||||
{
|
{
|
||||||
if (amountToBeRemoved > 0)
|
if (amountToBeRemoved > 0)
|
||||||
{
|
{
|
||||||
|
ItemStack dummy = itemStack.clone();
|
||||||
|
dummy.setAmount(1);
|
||||||
|
|
||||||
// Remove either the full amount or the remaining amount
|
// Remove either the full amount or the remaining amount
|
||||||
if (i.getAmount() >= amountToBeRemoved)
|
if (itemStack.getAmount() >= amountToBeRemoved)
|
||||||
{
|
{
|
||||||
i.setAmount(i.getAmount() - amountToBeRemoved);
|
itemStack.setAmount(itemStack.getAmount() - amountToBeRemoved);
|
||||||
removed.merge(i.getType(), amountToBeRemoved, Integer::sum);
|
removed.merge(dummy, amountToBeRemoved, Integer::sum);
|
||||||
amountToBeRemoved = 0;
|
amountToBeRemoved = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
removed.merge(i.getType(), i.getAmount(), Integer::sum);
|
removed.merge(dummy, itemStack.getAmount(), Integer::sum);
|
||||||
amountToBeRemoved -= i.getAmount();
|
amountToBeRemoved -= itemStack.getAmount();
|
||||||
i.setAmount(0);
|
itemStack.setAmount(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,8 +877,9 @@ public class TryToComplete
|
|||||||
/**
|
/**
|
||||||
* Checks if a island challenge can be completed or not
|
* Checks if a island challenge can be completed or not
|
||||||
* It returns ChallengeResult.
|
* It returns ChallengeResult.
|
||||||
|
* @param factor - times that user wanted to complete
|
||||||
*/
|
*/
|
||||||
private ChallengeResult checkSurrounding()
|
private ChallengeResult checkSurrounding(int factor)
|
||||||
{
|
{
|
||||||
// Init location in player position.
|
// Init location in player position.
|
||||||
BoundingBox boundingBox = this.user.getPlayer().getBoundingBox().clone();
|
BoundingBox boundingBox = this.user.getPlayer().getBoundingBox().clone();
|
||||||
@ -754,66 +919,73 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChallengeResult result = this.searchForEntities(this.challenge.getRequiredEntities(), boundingBox);
|
ChallengeResult result = this.searchForEntities(this.challenge.getRequiredEntities(), factor, boundingBox);
|
||||||
|
|
||||||
if (result.meetsRequirements && !this.challenge.getRequiredBlocks().isEmpty())
|
if (result.isMeetsRequirements() && !this.challenge.getRequiredBlocks().isEmpty())
|
||||||
{
|
{
|
||||||
// Search for items only if entities found
|
// Search for items only if entities found
|
||||||
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), boundingBox);
|
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), result.getFactor(), boundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.meetsRequirements &&
|
|
||||||
this.challenge.isRemoveEntities() &&
|
|
||||||
!this.challenge.getRequiredEntities().isEmpty())
|
|
||||||
{
|
|
||||||
this.removeEntities(boundingBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.meetsRequirements &&
|
|
||||||
this.challenge.isRemoveBlocks() &&
|
|
||||||
!this.challenge.getRequiredBlocks().isEmpty())
|
|
||||||
{
|
|
||||||
this.removeBlocks(boundingBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if challenge is repeated.
|
|
||||||
result.setRepeat(this.manager.isChallengeComplete(this.user, this.world, this.challenge));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method search required blocks in given challenge boundingBox.
|
* This method search required blocks in given challenge boundingBox.
|
||||||
* @param map RequiredBlock Map.
|
* @param requiredMap RequiredBlock Map.
|
||||||
|
* @param factor - requirement multilayer.
|
||||||
* @param boundingBox Bounding box of island challenge
|
* @param boundingBox Bounding box of island challenge
|
||||||
* @return ChallengeResult
|
* @return ChallengeResult
|
||||||
*/
|
*/
|
||||||
private ChallengeResult searchForBlocks(Map<Material, Integer> map, BoundingBox boundingBox)
|
private ChallengeResult searchForBlocks(Map<Material, Integer> requiredMap, int factor, BoundingBox boundingBox)
|
||||||
{
|
{
|
||||||
Map<Material, Integer> blocks = new EnumMap<>(map);
|
if (requiredMap.isEmpty())
|
||||||
|
|
||||||
if (blocks.isEmpty())
|
|
||||||
{
|
{
|
||||||
return new ChallengeResult().setMeetsRequirements();
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<Material, Integer> blocks = new EnumMap<>(requiredMap);
|
||||||
|
Map<Material, Integer> blocksFound = new HashMap<>(requiredMap.size());
|
||||||
|
|
||||||
|
// This queue will contain only blocks whit required type ordered by distance till player.
|
||||||
|
Queue<Block> blockFromWorld = new PriorityQueue<>((o1, o2) -> {
|
||||||
|
if (o1.getType().equals(o2.getType()))
|
||||||
|
{
|
||||||
|
return Double.compare(o1.getLocation().distance(this.user.getLocation()),
|
||||||
|
o2.getLocation().distance(this.user.getLocation()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return o1.getType().compareTo(o2.getType());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
|
for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
|
||||||
{
|
{
|
||||||
for (int y = (int) boundingBox.getMinY(); y <= boundingBox.getMaxY(); y++)
|
for (int y = (int) boundingBox.getMinY(); y <= boundingBox.getMaxY(); y++)
|
||||||
{
|
{
|
||||||
for (int z = (int) boundingBox.getMinZ(); z <= boundingBox.getMaxZ(); z++)
|
for (int z = (int) boundingBox.getMinZ(); z <= boundingBox.getMaxZ(); z++)
|
||||||
{
|
{
|
||||||
Material mat = this.user.getWorld().getBlockAt(x, y, z).getType();
|
Block block = this.user.getWorld().getBlockAt(x, y, z);
|
||||||
// Remove one
|
|
||||||
blocks.computeIfPresent(mat, (b, amount) -> amount - 1);
|
|
||||||
// Remove any that have an amount of 0
|
|
||||||
blocks.entrySet().removeIf(en -> en.getValue() <= 0);
|
|
||||||
|
|
||||||
if (blocks.isEmpty())
|
if (requiredMap.containsKey(block.getType()))
|
||||||
{
|
{
|
||||||
// Return as soon as it s empty as no point to search more.
|
blockFromWorld.add(block);
|
||||||
return new ChallengeResult().setMeetsRequirements();
|
|
||||||
|
blocksFound.putIfAbsent(block.getType(), 1);
|
||||||
|
blocksFound.computeIfPresent(block.getType(), (reqEntity, amount) -> amount + 1);
|
||||||
|
|
||||||
|
// Remove one
|
||||||
|
blocks.computeIfPresent(block.getType(), (b, amount) -> amount - 1);
|
||||||
|
// Remove any that have an amount of 0
|
||||||
|
blocks.entrySet().removeIf(en -> en.getValue() <= 0);
|
||||||
|
|
||||||
|
if (blocks.isEmpty() && factor == 1)
|
||||||
|
{
|
||||||
|
// Return as soon as it s empty as no point to search more.
|
||||||
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor).setBlockQueue(blockFromWorld);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -821,7 +993,21 @@ public class TryToComplete
|
|||||||
|
|
||||||
if (blocks.isEmpty())
|
if (blocks.isEmpty())
|
||||||
{
|
{
|
||||||
return new ChallengeResult().setMeetsRequirements();
|
if (factor > 1)
|
||||||
|
{
|
||||||
|
// Calculate minimal completion count.
|
||||||
|
|
||||||
|
for (Map.Entry<Material, Integer> entry : blocksFound.entrySet())
|
||||||
|
{
|
||||||
|
factor = Math.min(factor,
|
||||||
|
entry.getValue() / requiredMap.get(entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// kick garbage collector
|
||||||
|
blocksFound.clear();
|
||||||
|
|
||||||
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor).setBlockQueue(blockFromWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.user.sendMessage("challenges.errors.not-close-enough", "[number]", String.valueOf(this.challenge.getSearchRadius()));
|
this.user.sendMessage("challenges.errors.not-close-enough", "[number]", String.valueOf(this.challenge.getSearchRadius()));
|
||||||
@ -830,94 +1016,134 @@ public class TryToComplete
|
|||||||
"[amount]", String.valueOf(v),
|
"[amount]", String.valueOf(v),
|
||||||
"[item]", Util.prettifyText(k.toString())));
|
"[item]", Util.prettifyText(k.toString())));
|
||||||
|
|
||||||
|
|
||||||
|
// kick garbage collector
|
||||||
|
blocks.clear();
|
||||||
|
blocksFound.clear();
|
||||||
|
requiredMap.clear();
|
||||||
|
|
||||||
return EMPTY_RESULT;
|
return EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method search required entities in given radius from user position and entity is inside boundingBox.
|
* This method search required entities in given radius from user position and entity is inside boundingBox.
|
||||||
* @param map RequiredEntities Map.
|
* @param requiredMap RequiredEntities Map.
|
||||||
|
* @param factor - requirements multiplier.
|
||||||
* @param boundingBox Bounding box of island challenge
|
* @param boundingBox Bounding box of island challenge
|
||||||
* @return ChallengeResult
|
* @return ChallengeResult
|
||||||
*/
|
*/
|
||||||
private ChallengeResult searchForEntities(Map<EntityType, Integer> map, BoundingBox boundingBox)
|
private ChallengeResult searchForEntities(Map<EntityType, Integer> requiredMap,
|
||||||
|
int factor,
|
||||||
|
BoundingBox boundingBox)
|
||||||
{
|
{
|
||||||
Map<EntityType, Integer> entities = map.isEmpty() ? new EnumMap<>(EntityType.class) : new EnumMap<>(map);
|
if (requiredMap.isEmpty())
|
||||||
|
|
||||||
if (entities.isEmpty())
|
|
||||||
{
|
{
|
||||||
return new ChallengeResult().setMeetsRequirements();
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int searchRadius = this.challenge.getSearchRadius();
|
// Collect all entities that could be removed.
|
||||||
|
Map<EntityType, Integer> entitiesFound = new HashMap<>();
|
||||||
|
Map<EntityType, Integer> minimalRequirements = new EnumMap<>(requiredMap);
|
||||||
|
|
||||||
this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
|
// Create queue that contains all required entities ordered by distance till player.
|
||||||
// Check if entity is inside challenge bounding box
|
Queue<Entity> entityQueue = new PriorityQueue<>((o1, o2) -> {
|
||||||
if (boundingBox.contains(entity.getBoundingBox()))
|
if (o1.getType().equals(o2.getType()))
|
||||||
{
|
{
|
||||||
// Look through all the nearby Entities, filtering by type
|
return Double.compare(o1.getLocation().distance(this.user.getLocation()),
|
||||||
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
o2.getLocation().distance(this.user.getLocation()));
|
||||||
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return o1.getType().compareTo(o2.getType());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (entities.isEmpty())
|
this.world.getNearbyEntities(boundingBox).forEach(entity -> {
|
||||||
|
// Check if entity is inside challenge bounding box
|
||||||
|
if (requiredMap.containsKey(entity.getType()))
|
||||||
|
{
|
||||||
|
entitiesFound.putIfAbsent(entity.getType(), 1);
|
||||||
|
entitiesFound.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount + 1);
|
||||||
|
|
||||||
|
// Look through all the nearby Entities, filtering by type
|
||||||
|
minimalRequirements.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
||||||
|
minimalRequirements.entrySet().removeIf(e -> e.getValue() == 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (minimalRequirements.isEmpty())
|
||||||
{
|
{
|
||||||
return new ChallengeResult().setMeetsRequirements();
|
if (factor > 1)
|
||||||
|
{
|
||||||
|
// Calculate minimal completion count.
|
||||||
|
|
||||||
|
for (Map.Entry<EntityType, Integer> entry : entitiesFound.entrySet())
|
||||||
|
{
|
||||||
|
factor = Math.min(factor,
|
||||||
|
entry.getValue() / requiredMap.get(entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick garbage collector
|
||||||
|
entitiesFound.clear();
|
||||||
|
|
||||||
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor).setEntityQueue(entityQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
entities.forEach((reqEnt, amount) -> this.user.sendMessage("challenges.errors.you-still-need",
|
minimalRequirements.forEach((reqEnt, amount) -> this.user.sendMessage("challenges.errors.you-still-need",
|
||||||
"[amount]", String.valueOf(amount),
|
"[amount]", String.valueOf(amount),
|
||||||
"[item]", Util.prettifyText(reqEnt.toString())));
|
"[item]", Util.prettifyText(reqEnt.toString())));
|
||||||
|
|
||||||
|
// Kick garbage collector
|
||||||
|
entitiesFound.clear();
|
||||||
|
minimalRequirements.clear();
|
||||||
|
entityQueue.clear();
|
||||||
|
|
||||||
return EMPTY_RESULT;
|
return EMPTY_RESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes required block and set air instead of it.
|
* This method removes required block and set air instead of it.
|
||||||
* @param boundingBox Bounding box of island challenge
|
* @param blockQueue Queue with blocks that could be removed
|
||||||
|
* @param factor requirement factor for each block type.
|
||||||
*/
|
*/
|
||||||
private void removeBlocks(BoundingBox boundingBox)
|
private void removeBlocks(Queue<Block> blockQueue, int factor)
|
||||||
{
|
{
|
||||||
Map<Material, Integer> blocks = new EnumMap<>(this.challenge.getRequiredBlocks());
|
Map<Material, Integer> blocks = new EnumMap<>(this.challenge.getRequiredBlocks());
|
||||||
|
|
||||||
for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
|
// Increase required blocks by factor.
|
||||||
{
|
blocks.entrySet().forEach(entry -> entry.setValue(entry.getValue() * factor));
|
||||||
for (int y = (int) boundingBox.getMinY(); y <= boundingBox.getMaxY(); y++)
|
|
||||||
|
blockQueue.forEach(block -> {
|
||||||
|
if (blocks.containsKey(block.getType()))
|
||||||
{
|
{
|
||||||
for (int z = (int) boundingBox.getMinZ(); z <= boundingBox.getMaxZ(); z++)
|
blocks.computeIfPresent(block.getType(), (b, amount) -> amount - 1);
|
||||||
{
|
blocks.entrySet().removeIf(en -> en.getValue() <= 0);
|
||||||
Block block = this.user.getWorld().getBlockAt(new Location(this.user.getWorld(), x, y, z));
|
|
||||||
|
|
||||||
if (blocks.containsKey(block.getType()))
|
block.setType(Material.AIR);
|
||||||
{
|
|
||||||
blocks.computeIfPresent(block.getType(), (b, amount) -> amount - 1);
|
|
||||||
blocks.entrySet().removeIf(en -> en.getValue() <= 0);
|
|
||||||
|
|
||||||
block.setType(Material.AIR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes required entities.
|
* This method removes required entities.
|
||||||
* @param boundingBox Bounding box of island challenge
|
* @param entityQueue Queue with entities that could be removed
|
||||||
|
* @param factor requirement factor for each entity type.
|
||||||
*/
|
*/
|
||||||
private void removeEntities(BoundingBox boundingBox)
|
private void removeEntities(Queue<Entity> entityQueue, int factor)
|
||||||
{
|
{
|
||||||
Map<EntityType, Integer> entities = this.challenge.getRequiredEntities().isEmpty() ?
|
Map<EntityType, Integer> entities = this.challenge.getRequiredEntities().isEmpty() ?
|
||||||
new EnumMap<>(EntityType.class) : new EnumMap<>(this.challenge.getRequiredEntities());
|
new EnumMap<>(EntityType.class) : new EnumMap<>(this.challenge.getRequiredEntities());
|
||||||
|
|
||||||
int searchRadius = this.challenge.getSearchRadius();
|
// Increase required entities by factor.
|
||||||
|
entities.entrySet().forEach(entry -> entry.setValue(entry.getValue() * factor));
|
||||||
|
|
||||||
this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
|
// Go through entity queue and remove entities that are requried.
|
||||||
// Look through all the nearby Entities, filtering by type
|
entityQueue.forEach(entity -> {
|
||||||
|
if (entities.containsKey(entity.getType()))
|
||||||
if (entities.containsKey(entity.getType()) && boundingBox.contains(entity.getBoundingBox()))
|
|
||||||
{
|
{
|
||||||
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
||||||
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
||||||
@ -935,8 +1161,9 @@ public class TryToComplete
|
|||||||
/**
|
/**
|
||||||
* Checks if a other challenge can be completed or not
|
* Checks if a other challenge can be completed or not
|
||||||
* It returns ChallengeResult.
|
* It returns ChallengeResult.
|
||||||
|
* @param factor - times that user wanted to complete
|
||||||
*/
|
*/
|
||||||
private ChallengeResult checkOthers()
|
private ChallengeResult checkOthers(int factor)
|
||||||
{
|
{
|
||||||
if (!this.addon.isLevelProvided() &&
|
if (!this.addon.isLevelProvided() &&
|
||||||
this.challenge.getRequiredIslandLevel() != 0)
|
this.challenge.getRequiredIslandLevel() != 0)
|
||||||
@ -981,21 +1208,19 @@ public class TryToComplete
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this.addon.isEconomyProvided() && this.challenge.isTakeMoney())
|
// calculate factor
|
||||||
{
|
|
||||||
this.addon.getEconomyProvider().withdraw(this.user, this.challenge.getRequiredMoney());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.challenge.isTakeExperience() &&
|
if (this.addon.isEconomyProvided() && this.challenge.isTakeMoney())
|
||||||
this.user.getPlayer().getGameMode() != GameMode.CREATIVE)
|
{
|
||||||
{
|
factor = Math.min(factor, (int) this.addon.getEconomyProvider().getBalance(this.user) / this.challenge.getRequiredMoney());
|
||||||
// Cannot take anything from creative game mode.
|
}
|
||||||
this.user.getPlayer().setTotalExperience(
|
|
||||||
this.user.getPlayer().getTotalExperience() - this.challenge.getRequiredExperience());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ChallengeResult().setMeetsRequirements().
|
if (this.challenge.getRequiredExperience() > 0 && this.challenge.isTakeExperience())
|
||||||
setRepeat(this.manager.isChallengeComplete(this.user, this.world, this.challenge));
|
{
|
||||||
|
factor = Math.min(factor, this.user.getPlayer().getTotalExperience() / this.challenge.getRequiredExperience());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ChallengeResult().setMeetsRequirements().setCompleteFactor(factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EMPTY_RESULT;
|
return EMPTY_RESULT;
|
||||||
@ -1060,12 +1285,9 @@ public class TryToComplete
|
|||||||
*/
|
*/
|
||||||
private class ChallengeResult
|
private class ChallengeResult
|
||||||
{
|
{
|
||||||
private boolean meetsRequirements;
|
|
||||||
|
|
||||||
private boolean repeat;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This method sets that challenge meets all requirements at least once.
|
||||||
|
* @return Current object.
|
||||||
*/
|
*/
|
||||||
ChallengeResult setMeetsRequirements()
|
ChallengeResult setMeetsRequirements()
|
||||||
{
|
{
|
||||||
@ -1075,12 +1297,145 @@ public class TryToComplete
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param repeat the repeat to set
|
* Method sets that challenge is completed once already
|
||||||
|
* @param completed boolean that indicate that challenge has been already completed.
|
||||||
|
* @return Current object.
|
||||||
*/
|
*/
|
||||||
ChallengeResult setRepeat(boolean repeat)
|
ChallengeResult setCompleted(boolean completed)
|
||||||
{
|
{
|
||||||
this.repeat = repeat;
|
this.completed = completed;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method sets how many times challenge can be completed.
|
||||||
|
* @param factor Integer that represents completion count.
|
||||||
|
* @return Current object.
|
||||||
|
*/
|
||||||
|
ChallengeResult setCompleteFactor(int factor)
|
||||||
|
{
|
||||||
|
this.factor = factor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Requirement memory
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method sets requiredItems for inventory challenge.
|
||||||
|
* @param requiredItems items that are required by inventory challenge.
|
||||||
|
* @return Current object.
|
||||||
|
*/
|
||||||
|
ChallengeResult setRequiredItems(List<ItemStack> requiredItems)
|
||||||
|
{
|
||||||
|
this.requiredItems = requiredItems;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method sets queue that contains all blocks with required material type.
|
||||||
|
* @param blocks queue that contains required materials from world.
|
||||||
|
* @return Current object.
|
||||||
|
*/
|
||||||
|
ChallengeResult setBlockQueue(Queue<Block> blocks)
|
||||||
|
{
|
||||||
|
this.blocks = blocks;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method sets queue that contains all entities with required entity type.
|
||||||
|
* @param entities queue that contains required entities from world.
|
||||||
|
* @return Current object.
|
||||||
|
*/
|
||||||
|
ChallengeResult setEntityQueue(Queue<Entity> entities)
|
||||||
|
{
|
||||||
|
this.entities = entities;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Getters
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns value of was completed variable.
|
||||||
|
* @return value of completed variable
|
||||||
|
*/
|
||||||
|
boolean wasCompleted()
|
||||||
|
{
|
||||||
|
return this.completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns how many times challenge can be completed.
|
||||||
|
* @return completion count.
|
||||||
|
*/
|
||||||
|
int getFactor()
|
||||||
|
{
|
||||||
|
return this.factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns if challenge requirements has been met at least once.
|
||||||
|
* @return value of meets requirements variable.
|
||||||
|
*/
|
||||||
|
boolean isMeetsRequirements()
|
||||||
|
{
|
||||||
|
return this.meetsRequirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Variables
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean that indicate that challenge has already bean completed once before.
|
||||||
|
*/
|
||||||
|
private boolean completed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that challenge can be completed.
|
||||||
|
*/
|
||||||
|
private boolean meetsRequirements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integer that represents how many times challenge is completed
|
||||||
|
*/
|
||||||
|
private int factor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List that contains required items for Inventory Challenge
|
||||||
|
* Necessary as it contains grouped items by type or similarity, not by limit 64.
|
||||||
|
*/
|
||||||
|
private List<ItemStack> requiredItems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map that contains removed items and their removed count.
|
||||||
|
*/
|
||||||
|
private Map<ItemStack, Integer> removedItems = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue of blocks that contains all blocks with the same type as requiredBlock from
|
||||||
|
* challenge requirements.
|
||||||
|
*/
|
||||||
|
private Queue<Block> blocks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue of entities that contains all entities with the same type as requiredEntities from
|
||||||
|
* challenge requirements.
|
||||||
|
*/
|
||||||
|
private Queue<Entity> entities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,9 +319,10 @@ challenges:
|
|||||||
admin:
|
admin:
|
||||||
hit-things: 'Hit things to add them to the list of things required. Right click when done.'
|
hit-things: 'Hit things to add them to the list of things required. Right click when done.'
|
||||||
you-added: 'You added one [thing] to the challenge'
|
you-added: 'You added one [thing] to the challenge'
|
||||||
challenge-created: '[challenge] created!'
|
challenge-created: '[challenge]&r created!'
|
||||||
you-completed-challenge: '&2You completed the [value] &r&2challenge!'
|
you-completed-challenge: '&2You completed the [value] &r&2challenge!'
|
||||||
you-repeated-challenge: '&2You repeated the [value] &r&2challenge!'
|
you-repeated-challenge: '&2You repeated the [value] &r&2challenge!'
|
||||||
|
you-repeated-challenge-multiple: '&2You repeated the [value] &r&2challenge [count] times!'
|
||||||
you-completed-level: '&2You completed the [value] &r&2level!'
|
you-completed-level: '&2You completed the [value] &r&2level!'
|
||||||
name-has-completed-challenge: '&5[name] has completed the [value] &r&5challenge!'
|
name-has-completed-challenge: '&5[name] has completed the [value] &r&5challenge!'
|
||||||
name-has-completed-level: '&5[name] has completed the [value] &r&5level!'
|
name-has-completed-level: '&5[name] has completed the [value] &r&5level!'
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package world.bentobox.challenges.tasks;
|
package world.bentobox.challenges.tasks;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Matchers.*;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.inventory.ItemFactory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
|
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
|
||||||
import world.bentobox.challenges.ChallengesAddon;
|
import world.bentobox.challenges.ChallengesAddon;
|
||||||
@ -26,147 +29,202 @@ import world.bentobox.bentobox.api.user.User;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
* TODO: This test should be fixed.
|
|
||||||
*/
|
*/
|
||||||
@RunWith(PowerMockRunner.class)
|
@RunWith(PowerMockRunner.class)
|
||||||
|
@PrepareForTest({ Bukkit.class})
|
||||||
public class TryToCompleteTest {
|
public class TryToCompleteTest {
|
||||||
|
|
||||||
private User user;
|
private User user;
|
||||||
ItemStack[] stacks = { new ItemStack(Material.PAPER, 32),
|
ItemStack[] stacks = { new ItemStack(Material.PAPER, 32),
|
||||||
new ItemStack(Material.ACACIA_BOAT),
|
new ItemStack(Material.ACACIA_BOAT),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
new ItemStack(Material.CACTUS, 32),
|
new ItemStack(Material.CACTUS, 32),
|
||||||
new ItemStack(Material.CACTUS, 32),
|
new ItemStack(Material.CACTUS, 32),
|
||||||
new ItemStack(Material.CACTUS, 32),
|
new ItemStack(Material.CACTUS, 32),
|
||||||
new ItemStack(Material.GOLD_BLOCK, 32)
|
new ItemStack(Material.BRICK_STAIRS, 64),
|
||||||
};
|
new ItemStack(Material.BRICK_STAIRS, 64),
|
||||||
List<ItemStack> required;
|
new ItemStack(Material.BRICK_STAIRS, 5),
|
||||||
private ChallengesAddon addon;
|
new ItemStack(Material.GOLD_BLOCK, 32)
|
||||||
private PlayerInventory inv;
|
};
|
||||||
|
List<ItemStack> required;
|
||||||
|
private ChallengesAddon addon;
|
||||||
|
private PlayerInventory inv;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws java.lang.Exception
|
* @throws java.lang.Exception
|
||||||
*/
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
user = mock(User.class);
|
user = mock(User.class);
|
||||||
inv = mock(PlayerInventory.class);
|
inv = mock(PlayerInventory.class);
|
||||||
when(inv.getContents()).thenReturn(stacks);
|
when(inv.getContents()).thenReturn(stacks);
|
||||||
when(user.getInventory()).thenReturn(inv);
|
when(user.getInventory()).thenReturn(inv);
|
||||||
addon = mock(ChallengesAddon.class);
|
addon = mock(ChallengesAddon.class);
|
||||||
required = new ArrayList<>();
|
required = new ArrayList<>();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Server server = mock(Server.class);
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
ItemFactory itemFactory = mock(ItemFactory.class);
|
||||||
*/
|
when(server.getItemFactory()).thenReturn(itemFactory);
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testRemoveItemsSuccess() {
|
|
||||||
Material reqMat = Material.PAPER;
|
|
||||||
int reqQty = 21;
|
|
||||||
required.add(new ItemStack(reqMat, reqQty));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.get(reqMat) == reqQty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Test will not work with items that has meta data.
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
when(itemFactory.getItemMeta(any())).thenReturn(null);
|
||||||
*/
|
when(itemFactory.equals(null, null)).thenReturn(true);
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testRemoveItemsMax() {
|
|
||||||
Material reqMat = Material.PAPER;
|
|
||||||
int reqQty = 50;
|
|
||||||
required.add(new ItemStack(reqMat, reqQty));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.get(reqMat) == 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
PowerMockito.mockStatic(Bukkit.class);
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
when(Bukkit.getServer()).thenReturn(server);
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testRemoveItemsZero() {
|
|
||||||
Material reqMat = Material.PAPER;
|
|
||||||
int reqQty = 0;
|
|
||||||
required.add(new ItemStack(reqMat, reqQty));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.get(reqMat) == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger());
|
||||||
*/
|
}
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void testRemoveItemsSuccessMultiple() {
|
|
||||||
required.add(new ItemStack(Material.PAPER, 11));
|
|
||||||
required.add(new ItemStack(Material.PAPER, 5));
|
|
||||||
required.add(new ItemStack(Material.PAPER, 5));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.get(Material.PAPER) == 21);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
public void testRemoveItemsSuccess() {
|
||||||
public void testRemoveItemsSuccessMultipleOther() {
|
Material requiredMaterial = Material.PAPER;
|
||||||
required.add(new ItemStack(Material.CACTUS, 5));
|
int requiredQuantity = 21;
|
||||||
required.add(new ItemStack(Material.PAPER, 11));
|
|
||||||
required.add(new ItemStack(Material.PAPER, 5));
|
|
||||||
required.add(new ItemStack(Material.PAPER, 5));
|
|
||||||
required.add(new ItemStack(Material.CACTUS, 5));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.get(Material.PAPER) == 21);
|
|
||||||
assertTrue(removed.get(Material.CACTUS) == 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.required.add(new ItemStack(requiredMaterial, requiredQuantity));
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
TryToComplete x = new TryToComplete(this.addon);
|
||||||
*/
|
x.user(this.user);
|
||||||
@Test
|
Map<ItemStack, Integer> removed = x.removeItems(this.required, 1);
|
||||||
@Ignore
|
|
||||||
public void testRemoveItemsMultipleOtherFail() {
|
|
||||||
required.add(new ItemStack(Material.ACACIA_FENCE, 5));
|
|
||||||
required.add(new ItemStack(Material.ARROW, 11));
|
|
||||||
required.add(new ItemStack(Material.STONE, 5));
|
|
||||||
required.add(new ItemStack(Material.BAKED_POTATO, 5));
|
|
||||||
required.add(new ItemStack(Material.GHAST_SPAWN_EGG, 5));
|
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
|
||||||
assertTrue(removed.isEmpty());
|
|
||||||
|
|
||||||
}
|
assertEquals((int) removed.getOrDefault(new ItemStack(requiredMaterial, 1), 0), requiredQuantity);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for {@link TryToComplete#removeItems(java.util.List)}.
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
public void testRemoveItemsMax() {
|
||||||
public void testRemoveItemsFail() {
|
Material requiredMaterial = Material.PAPER;
|
||||||
required.add(new ItemStack(Material.GOLD_BLOCK, 55));
|
int requiredQuantity = 50;
|
||||||
TryToComplete x = new TryToComplete(addon);
|
|
||||||
x.user(user);
|
this.required.add(new ItemStack(requiredMaterial, requiredQuantity));
|
||||||
Map<Material, Integer> removed = x.removeItems(required);
|
TryToComplete x = new TryToComplete(this.addon);
|
||||||
// It will remove 32, but not any more
|
x.user(this.user);
|
||||||
assertTrue(removed.get(Material.GOLD_BLOCK) == 32);
|
Map<ItemStack, Integer> removed = x.removeItems(this.required, 1);
|
||||||
// An error will be thrown
|
|
||||||
Mockito.verify(addon, Mockito.times(1)).logError(Mockito.anyString());
|
assertNotEquals((int) removed.getOrDefault(new ItemStack(requiredMaterial, 1), 0), requiredQuantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveItemsZero() {
|
||||||
|
Material requiredMaterial = Material.PAPER;
|
||||||
|
int requiredQuantity = 0;
|
||||||
|
|
||||||
|
this.required.add(new ItemStack(requiredMaterial, requiredQuantity));
|
||||||
|
TryToComplete x = new TryToComplete(this.addon);
|
||||||
|
x.user(this.user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(this.required, 1);
|
||||||
|
|
||||||
|
assertTrue(removed.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveItemsSuccessMultiple() {
|
||||||
|
required.add(new ItemStack(Material.PAPER, 11));
|
||||||
|
required.add(new ItemStack(Material.PAPER, 5));
|
||||||
|
required.add(new ItemStack(Material.PAPER, 5));
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 1);
|
||||||
|
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.PAPER, 1), 0), 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveItemsSuccessMultipleOther() {
|
||||||
|
required.add(new ItemStack(Material.CACTUS, 5));
|
||||||
|
required.add(new ItemStack(Material.PAPER, 11));
|
||||||
|
required.add(new ItemStack(Material.PAPER, 5));
|
||||||
|
required.add(new ItemStack(Material.PAPER, 5));
|
||||||
|
required.add(new ItemStack(Material.CACTUS, 5));
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 1);
|
||||||
|
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.PAPER, 1), 0), 21);
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.CACTUS, 1), 0), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveItemsMultipleOtherFail() {
|
||||||
|
required.add(new ItemStack(Material.ACACIA_FENCE, 5));
|
||||||
|
required.add(new ItemStack(Material.ARROW, 11));
|
||||||
|
required.add(new ItemStack(Material.STONE, 5));
|
||||||
|
required.add(new ItemStack(Material.BAKED_POTATO, 5));
|
||||||
|
required.add(new ItemStack(Material.GHAST_SPAWN_EGG, 5));
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 1);
|
||||||
|
assertTrue(removed.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveItemsFail() {
|
||||||
|
ItemStack input = new ItemStack(Material.GOLD_BLOCK, 55);
|
||||||
|
required.add(input);
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 1);
|
||||||
|
|
||||||
|
// It will remove 32, but not any more
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.GOLD_BLOCK, 1), 0), 32);
|
||||||
|
|
||||||
|
// An error will be thrown
|
||||||
|
Mockito.verify(addon, Mockito.times(1)).logError(Mockito.anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRequireTwoStacks() {
|
||||||
|
required.add(new ItemStack(Material.BRICK_STAIRS, 64));
|
||||||
|
required.add(new ItemStack(Material.BRICK_STAIRS, 64));
|
||||||
|
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 1);
|
||||||
|
|
||||||
|
// It should remove both stacks
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.BRICK_STAIRS, 1), 0), 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link TryToComplete#removeItems(java.util.List, int)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testFactorStacks() {
|
||||||
|
required.add(new ItemStack(Material.BRICK_STAIRS, 32));
|
||||||
|
|
||||||
|
TryToComplete x = new TryToComplete(addon);
|
||||||
|
x.user(user);
|
||||||
|
Map<ItemStack, Integer> removed = x.removeItems(required, 4);
|
||||||
|
|
||||||
|
// It should remove both stacks
|
||||||
|
assertEquals((int) removed.getOrDefault(new ItemStack(Material.BRICK_STAIRS, 1), 0), 128);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user