38a20f98c2
These two directories contain code that was removed from the src and dependencies of the compiled files. They were removed due to being either a. unnecessary or b. a royal pain in my booty.
296 lines
9.2 KiB
Java
296 lines
9.2 KiB
Java
package mineplex.core.treasure.reward;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import mineplex.core.MiniPlugin;
|
|
import mineplex.core.ReflectivelyCreateMiniPlugin;
|
|
import mineplex.core.common.util.UtilMath;
|
|
import mineplex.core.common.weight.WeightSet;
|
|
import mineplex.core.reward.Reward;
|
|
import mineplex.core.reward.rewards.RankReward;
|
|
import mineplex.core.reward.rewards.TreasureShardReward;
|
|
import mineplex.core.treasure.types.Treasure;
|
|
|
|
/**
|
|
* This manager serves as a random reward generator.
|
|
* A lot of this was adapted from the previous reward manager, so if you've come here to
|
|
* fix something then prepare yourself for a shock.
|
|
*/
|
|
@ReflectivelyCreateMiniPlugin
|
|
public class TreasureRewardManager extends MiniPlugin
|
|
{
|
|
|
|
/**
|
|
* For all the reward algorithms, if a condition cannot be met within {@value} iterations then it gives up.
|
|
* {@value} is a very generous threshold and most likely, unless due to error, each one should complete in one
|
|
* or two iterations.
|
|
*/
|
|
private static final int MAX_ATTEMPTS = 40;
|
|
|
|
private final Map<Treasure, Map<RewardRarity, WeightSet<Reward>>> _rewardPoolMap;
|
|
|
|
private TreasureRewardManager()
|
|
{
|
|
super("Treasure Rewards");
|
|
|
|
_rewardPoolMap = new HashMap<>();
|
|
}
|
|
|
|
/**
|
|
* Adds a reward into the pool for a particular chest type.
|
|
*
|
|
* @param treasure The {@link Treasure}'s pool you want to add the reward to.
|
|
* @param reward The {@link Reward} you want to add to the pool.
|
|
* @param weight The weight of the reward, bigger weight, more probable to be picked.
|
|
*/
|
|
public void addReward(Treasure treasure, Reward reward, int weight)
|
|
{
|
|
// Populate the map if absent
|
|
_rewardPoolMap.computeIfAbsent(treasure, k -> new HashMap<>());
|
|
|
|
// Populate the inner map if absent
|
|
Map<RewardRarity, WeightSet<Reward>> map = _rewardPoolMap.get(treasure);
|
|
map.computeIfAbsent(reward.getRarity(), k -> new WeightSet<>());
|
|
// Add the reward to the WeightSet
|
|
map.get(reward.getRarity()).add(weight, reward);
|
|
}
|
|
|
|
/**
|
|
* Returns whether or not a player has all the items within a chest's pool
|
|
*
|
|
* @param player The player you want to checl.
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @return a boolean value of if the player has all the items within a chest's pool.
|
|
*/
|
|
public boolean hasAllItems(Player player, Treasure treasure)
|
|
{
|
|
Map<RewardRarity, WeightSet<Reward>> rewardMap = _rewardPoolMap.get(treasure);
|
|
|
|
// Null entry, programmer error
|
|
return rewardMap == null || getOwnedItems(player, treasure) == getTotalItems(treasure);
|
|
}
|
|
|
|
/**
|
|
* Returns the number of items a player owns within a chest's pool
|
|
*
|
|
* @param player The player you want to check.
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @return an integer value of the amount of items the player has within a chest's pool.
|
|
*/
|
|
public int getOwnedItems(Player player, Treasure treasure)
|
|
{
|
|
Map<RewardRarity, WeightSet<Reward>> rewardMap = _rewardPoolMap.get(treasure);
|
|
|
|
// Null entry, programmer error
|
|
if (rewardMap == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int owned = 0;
|
|
|
|
// Check every reward
|
|
for (WeightSet<Reward> weightSet : rewardMap.values())
|
|
{
|
|
for (Reward reward : weightSet.elements())
|
|
{
|
|
// If the player cannot be given that reward
|
|
if (!reward.canGiveReward(player))
|
|
{
|
|
owned++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return owned;
|
|
}
|
|
|
|
/**
|
|
* Returns the total number of items within a chest's pool.
|
|
*
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @return an integer value of the amount of items the chest has within it's pool.
|
|
*/
|
|
public int getTotalItems(Treasure treasure)
|
|
{
|
|
Map<RewardRarity, WeightSet<Reward>> rewardMap = _rewardPoolMap.get(treasure);
|
|
|
|
// Null entry, programmer error
|
|
if (rewardMap == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int amount = 0;
|
|
|
|
// Check every reward
|
|
for (WeightSet<Reward> weightSet : rewardMap.values())
|
|
{
|
|
amount += weightSet.elements().size();
|
|
}
|
|
|
|
return amount;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of random rewards that can be awarded to a player.
|
|
*
|
|
* @param player The player you want to give the rewards to.
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @return A {@link List} the size of {@link Treasure#getRewardsPerChest()} and with the contents of random rewards
|
|
* that can be given to the player or null if an error has occurred.
|
|
*/
|
|
public List<Reward> getRewards(Player player, Treasure treasure)
|
|
{
|
|
Map<RewardRarity, WeightSet<Reward>> rewardMap = _rewardPoolMap.get(treasure);
|
|
|
|
// Null entry, programmer error
|
|
if (rewardMap == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// The list of rewards that will be returned
|
|
List<Reward> rewards = new ArrayList<>(treasure.getRewardsPerChest());
|
|
// These variables here are used to ensure that each chest opening will always contain at least one uncommon
|
|
// but never more than one mythical.
|
|
boolean hasUncommon = false;
|
|
boolean hasMythical = false;
|
|
int attempts = 0;
|
|
|
|
for (int i = 0; i < treasure.getRewardsPerChest(); i++)
|
|
{
|
|
attempts++;
|
|
Reward reward = nextReward(player, treasure, rewardMap, i, hasUncommon, hasMythical);
|
|
|
|
// If the reward was null then the reward could not have been given to the player
|
|
if (reward == null)
|
|
{
|
|
// At this point if it has taken 20+ attempts to find a reward and it's still null, then there seems to
|
|
// be a problem with the chest's pool or a programmer error.
|
|
if (attempts > MAX_ATTEMPTS)
|
|
{
|
|
return null;
|
|
}
|
|
// We run the loop again
|
|
i--;
|
|
continue;
|
|
}
|
|
|
|
RewardRarity rarity = reward.getRarity();
|
|
|
|
// If the reward is as or more uncommon than an uncommon
|
|
if (rarity.ordinal() >= RewardRarity.UNCOMMON.ordinal())
|
|
{
|
|
hasUncommon = true;
|
|
}
|
|
|
|
// If the reward is as more uncommon than an mythical
|
|
if (rarity.ordinal() >= RewardRarity.MYTHICAL.ordinal())
|
|
{
|
|
hasMythical = true;
|
|
}
|
|
|
|
// Add the reward to our list of rewards
|
|
rewards.add(reward);
|
|
}
|
|
|
|
// Due to the last reward always being an uncommon or better, we swap it randomly with another element as to
|
|
// appear more random.
|
|
Collections.swap(rewards, rewards.size() - 1, UtilMath.r(rewards.size()));
|
|
|
|
return rewards;
|
|
}
|
|
|
|
/**
|
|
* This determines the rarity of the reward.
|
|
*
|
|
* @param player The player you want to give the reward to.
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @param rewardMap The map of rarities and weights.
|
|
* @param index The current index of this reward, for example the first chest to open will have an index of 0, second 1 etc...
|
|
* @param hasUncommon Does the current list of rewards contain an uncommon or better?
|
|
* @param hasMythical Does the current list of rewards contain a mythical or better?
|
|
* @return A random reward that can be given to the player or null if not or an error has occurred.
|
|
*/
|
|
private Reward nextReward(Player player, Treasure treasure, Map<RewardRarity, WeightSet<Reward>> rewardMap, int index, boolean hasUncommon, boolean hasMythical)
|
|
{
|
|
RewardRarity rarity = treasure.getRewardType().generateRarity();
|
|
int attempts = 0;
|
|
|
|
// If the reward list already contains a mythical, keep trying until it isn't one
|
|
while (attempts++ < MAX_ATTEMPTS && hasMythical && rarity == RewardRarity.MYTHICAL)
|
|
{
|
|
rarity = treasure.getRewardType().generateRarity();
|
|
}
|
|
|
|
// If we are on the last reward and there hasn't been an uncommon then make sure this reward is uncommon
|
|
// Additional duplicates check is needed as chests without duplicates can only contain rare or above.
|
|
if (!hasUncommon && treasure.isDuplicates() && treasure.getRewardsPerChest() > 1 && index == treasure.getRewardsPerChest() - 1)
|
|
{
|
|
rarity = RewardRarity.UNCOMMON;
|
|
}
|
|
|
|
WeightSet<Reward> rewardSet = rewardMap.get(rarity);
|
|
|
|
// Null entry, programmer error
|
|
if (rewardSet == null || rewardSet.elements().isEmpty())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// If the chest doesn't give duplicates
|
|
if (!treasure.isDuplicates())
|
|
{
|
|
// Clone the set as we modify it below
|
|
rewardSet = new WeightSet<>(rewardSet);
|
|
// Remove all elements if they cannot be given to a player
|
|
rewardSet.removeIf(rewardWeight -> !rewardWeight.getValue().canGiveReward(player));
|
|
}
|
|
|
|
// Nothing for this rarity
|
|
if (rewardSet.elements().isEmpty())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return nextReward(player, treasure, rewardSet);
|
|
}
|
|
|
|
/**
|
|
* This determines the actual reward.
|
|
*
|
|
* @param player The player you want to give the reward to.
|
|
* @param treasure The {@link Treasure} you want to search through the pool of.
|
|
* @param rewardSet The set of reward weights.
|
|
* @return A random reward that can be given to the player or null if not or an error has occurred.
|
|
*/
|
|
private Reward nextReward(Player player, Treasure treasure, WeightSet<Reward> rewardSet)
|
|
{
|
|
// Get a random reward
|
|
Reward reward = rewardSet.generateRandom();
|
|
|
|
// If the chest can award duplicates and the player cannot be given the reward, give a shard reward instead.
|
|
if (!reward.canGiveReward(player))
|
|
{
|
|
if (reward instanceof RankReward)
|
|
{
|
|
return null;
|
|
}
|
|
else if (treasure.isDuplicates())
|
|
{
|
|
return new TreasureShardReward(reward, reward.getRarity());
|
|
}
|
|
}
|
|
|
|
return reward;
|
|
}
|
|
}
|