Unlimited custom xp perks Part 1

This commit is contained in:
nossr50
2019-05-08 06:44:19 -07:00
parent 0331c98c9b
commit 40598a0e96
52 changed files with 1579 additions and 1543 deletions

View File

@ -34,6 +34,19 @@ public final class ExperienceAPI {
return PrimarySkillType.getSkill(skillType) != null;
}
/**
* Grabs the XP multiplier for a player for this specific skill
* The multiplier will default to 1.0 and will be over written by any XP perks
*
* @param player target player
* @param primarySkillType target skill
* @return this players personal XP rate for target PrimarySkillType
*/
public float getPlayersPersonalXPRate(McMMOPlayer player, PrimarySkillType primarySkillType) {
//First check if the player has ANY of the custom perks
return player.getPlayerSpecificXPMult(primarySkillType);
}
/**
* Returns whether the given skill type string is both valid and not a
* child skill. (Child skills have no XP of their own, and their level is

View File

@ -307,10 +307,14 @@ public final class ConfigManager {
customSerializers = TypeSerializers.getDefaultSerializers().newChild();
mcMMO.p.getLogger().info("Registering custom type serializers for Configurate...");
customSerializers.registerType(new TypeToken<PrimarySkillType>() {}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<Material>() {}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<PartyFeature>() {}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<FormulaType>() {}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<PrimarySkillType>() {
}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<Material>() {
}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<PartyFeature>() {
}, new CustomEnumValueSerializer());
customSerializers.registerType(new TypeToken<FormulaType>() {
}, new CustomEnumValueSerializer());
customSerializers.registerType(TypeToken.of(Repairable.class), new RepairableSerializer());
customSerializers.registerType(TypeToken.of(Salvageable.class), new SalvageableSerializer());
customSerializers.registerType(TypeToken.of(MinecraftMaterialWrapper.class), new MinecraftMaterialWrapperSerializer());

View File

@ -0,0 +1,62 @@
package com.gmail.nossr50.config.hocon;
import com.gmail.nossr50.api.exceptions.InvalidSkillException;
import com.gmail.nossr50.datatypes.experience.CustomXPPerk;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.google.common.reflect.TypeResolver;
import com.google.common.reflect.TypeToken;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.objectmapping.serialize.TypeSerializer;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public class CustomXPPerkSerializer implements TypeSerializer<CustomXPPerk> {
@Nullable
@Override
public CustomXPPerk deserialize(@NonNull TypeToken<?> type, @NonNull ConfigurationNode value) throws ObjectMappingException {
String perkName = value.getNode("name").getValue(TypeToken.of(String.class));
CustomXPPerk customXPPerk = new CustomXPPerk(perkName);
//See if any children nodes match skills by name
for(ConfigurationNode configurationNode : value.getChildrenList())
{
try {
PrimarySkillType primarySkillType = matchIgnoreCase(configurationNode.getValue(TypeToken.of(String.class)));
float boostValue = configurationNode.getNode("XP-Multiplier").getValue(TypeToken.of(Float.class));
customXPPerk.setCustomXPValue(primarySkillType, boostValue);
} catch (InvalidSkillException e) {
mcMMO.p.getLogger().info("Custom XP perk has a skill defined that was not found, did you misspell it?");
e.printStackTrace();
} catch (ObjectMappingException e) {
e.printStackTrace();
}
}
return customXPPerk;
}
@Override
public void serialize(@NonNull TypeToken<?> type, @Nullable CustomXPPerk obj, @NonNull ConfigurationNode value) throws ObjectMappingException {
}
private PrimarySkillType matchIgnoreCase(String string) throws InvalidSkillException
{
for(PrimarySkillType primarySkillType : PrimarySkillType.values())
{
if(string.equalsIgnoreCase(primarySkillType.toString()))
return primarySkillType;
}
throw new InvalidSkillException();
}
/*
CustomXPPerk customXPPerk = new CustomXPPerk("examplecustomxpperk");
customXPPerk.setCustomXPValue(PrimarySkillType.MINING, 13.37f);
customXPPerk.setCustomXPValue(PrimarySkillType.WOODCUTTING, 4.0f);
*/
}

View File

@ -1,9 +1,11 @@
package com.gmail.nossr50.config.hocon.experience;
import com.gmail.nossr50.datatypes.experience.CustomXPPerk;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.util.HashMap;
import java.util.HashSet;
@ConfigSerializable
public class ConfigExperience {
@ -21,10 +23,21 @@ public class ConfigExperience {
@Setting(value = "Skill-XP-Settings", comment = "XP values and multipliers for each skill")
private ConfigExperienceSkills configExperienceSkills = new ConfigExperienceSkills();
@Setting(value = "Skill-XP-Perks", comment = "Define a set of custom XP boosts given to players with matching permission nodes.")
private ConfigExperienceCustomBoosts configExperienceCustomBoosts = new ConfigExperienceCustomBoosts();
/*
* BOILER PLATE GETTERS
*/
public HashSet<CustomXPPerk> getCustomXPBoosts() {
return configExperienceCustomBoosts.getCustomXPBoosts();
}
public ConfigExperienceCustomBoosts getConfigExperienceCustomBoosts() {
return configExperienceCustomBoosts;
}
public ConfigExperienceSkillMultiplier getConfigExperienceSkillMultiplier() {
return configExperienceSkillMultiplier;
}

View File

@ -0,0 +1,31 @@
package com.gmail.nossr50.config.hocon.experience;
import com.gmail.nossr50.datatypes.experience.CustomXPPerk;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.util.HashSet;
@ConfigSerializable
public class ConfigExperienceCustomBoosts {
private static final HashSet<CustomXPPerk> CUSTOM_BOOST_SET_DEFAULT;
static {
CUSTOM_BOOST_SET_DEFAULT = new HashSet<>();
CustomXPPerk customXPPerk = new CustomXPPerk("examplecustomxpperk");
customXPPerk.setCustomXPValue(PrimarySkillType.MINING, 13.37f);
customXPPerk.setCustomXPValue(PrimarySkillType.WOODCUTTING, 4.0f);
CUSTOM_BOOST_SET_DEFAULT.add(customXPPerk);
}
@Setting(value = "Custom-Global-XP-Permissions", comment = "You can give custom global xp perks to players by adding 'mcmmo.customperks.xp.<PERK NAME HERE>' to your players" +
"\nEnter the name of a permission node and the value of the XP boost that permission node should have." +
"\nPlayers do not benefit from custom xp perks without being assigned positive permission nodes for said xp perks")
private HashSet<CustomXPPerk> customXPBoosts = CUSTOM_BOOST_SET_DEFAULT;
public HashSet<CustomXPPerk> getCustomXPBoosts() {
return customXPBoosts;
}
}

View File

@ -13,12 +13,11 @@ public class ConfigExperienceSkillMultiplier {
static {
SKILL_GLOBAL_MULT_DEFAULT = new HashMap<>();
for(PrimarySkillType primarySkillType : PrimarySkillType.values())
{
if(primarySkillType.isChildSkill())
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType.isChildSkill())
continue;
SKILL_GLOBAL_MULT_DEFAULT.put(primarySkillType,1.0D);
SKILL_GLOBAL_MULT_DEFAULT.put(primarySkillType, 1.0D);
}
}

View File

@ -15,9 +15,8 @@ public class ConfigExperienceFormula {
static {
SKILL_FORMULA_MODIFIER_DEFAULT = new HashMap<>();
for(PrimarySkillType primarySkillType : PrimarySkillType.values())
{
if(primarySkillType.isChildSkill())
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType.isChildSkill())
continue;
SKILL_FORMULA_MODIFIER_DEFAULT.put(primarySkillType, 1.0D);

View File

@ -10,13 +10,13 @@ public class ConfigLevelEarlyGameBoost {
public static final double BOOST_MULTIPLIER_DEFAULT = 0.05D;
@Setting(value = "Enabled", comment = "If set to true, the early game XP boost will be applied." +
"\nDefault value: "+EARLY_GAME_BOOST_DEFAULT)
"\nDefault value: " + EARLY_GAME_BOOST_DEFAULT)
private boolean enableEarlyGameBoost = EARLY_GAME_BOOST_DEFAULT;
@Setting(value = "Max-Level-Percentage", comment = "This value is multiplied by a skills level cap to see determine when to stop giving a boost." +
"\nLevels in mcMMO are not capped by default, so if the skill has no set level cap it will instead use the value 100 or 1000 (if in RetroMode)" +
"\nWith default settings, this will result in the first 5 levels (or 50 in Retro) being boosted" +
"\nDefault value: "+BOOST_MULTIPLIER_DEFAULT)
"\nDefault value: " + BOOST_MULTIPLIER_DEFAULT)
private double earlyGameBoostMultiplier = BOOST_MULTIPLIER_DEFAULT;
public double getEarlyGameBoostMultiplier() {

View File

@ -62,6 +62,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
private final File usersFile;
private long lastUpdate = 0;
private long updateWaitTime;
protected FlatfileDatabaseManager() {
updateWaitTime = mcMMO.getConfigManager().getConfigDatabase().getConfigDatabaseFlatFile().getLeaderboardUpdateIntervalMinutes() * (1000 * 60);
usersFile = new File(mcMMO.getUsersFilePath());

View File

@ -0,0 +1,59 @@
package com.gmail.nossr50.datatypes.experience;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import java.util.HashMap;
public class CustomXPPerk {
private String perkName;
private HashMap<PrimarySkillType, Float> customXPMultiplierMap;
public CustomXPPerk(String perkName) {
this.perkName = perkName;
customXPMultiplierMap = new HashMap<>();
}
/**
* Set the value of a specific skills XP Multiplier
*
* @param primarySkillType target skill
* @param xpMult xp multiplier
*/
public void setCustomXPValue(PrimarySkillType primarySkillType, float xpMult) {
customXPMultiplierMap.put(primarySkillType, xpMult);
}
/**
* Get the value of a specific skills XP multiplier for this CustomXPPerk
* 1.0D is used for non-existent values
*
* @param primarySkillType target skill
* @return this custom perks XP multiplier for target skill, defaults to 1.0D if it doesn't exist
*/
public float getXPMultiplierValue(PrimarySkillType primarySkillType) {
if (customXPMultiplierMap.get(primarySkillType) == null)
return 1.0F;
return customXPMultiplierMap.get(primarySkillType);
}
/**
* Get the name of this Custom XP Perk
*
* @return the name of this Custom XP Perk
*/
public String getPerkName() {
return perkName;
}
/**
* Get the address of this custom XP perk permission
* This is the fully qualified name for this permission
*
* @return the perk permission name
*/
public String getPerkPermissionAddress() {
return "mcmmo.customperks.xp." + perkName;
}
}

View File

@ -4,7 +4,7 @@ import com.gmail.nossr50.mcMMO;
import org.bukkit.metadata.FixedMetadataValue;
/**
* Stores how many bonus drops a block should give
* Stores how many bonus drops a block should give
*/
public class BonusDropMeta extends FixedMetadataValue {

View File

@ -90,6 +90,7 @@ public class McMMOPlayer {
//private int chimeraWingLastUse;
private Location teleportCommence;
private boolean isUsingUnarmed;
private HashMap<PrimarySkillType, Float> personalXPModifiers;
public McMMOPlayer(Player player, PlayerProfile profile) {
String playerName = player.getName();
@ -127,6 +128,36 @@ public class McMMOPlayer {
}
experienceBarManager = new ExperienceBarManager(this);
fillPersonalXPModifiers(); //Cache players XP rates
}
/**
* Grabs custom XP values for a player if they exist, if they don't defaults them to 1.0
* Values are stored in a hash map for constant speed lookups
*/
private void fillPersonalXPModifiers() {
personalXPModifiers = new HashMap<>();
//Check each skill for custom XP perks
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
//Skip over child skills
if (primarySkillType.isChildSkill())
continue;
//Set the players custom XP modifier, defaults to 1.0D on missing entries
personalXPModifiers.put(primarySkillType, mcMMO.getPlayerLevelUtils().determineXpPerkValue(player, primarySkillType));
}
}
/**
* Gets a players current active XP rate for a specific skill
* This will default to 1.0D unless over written by custom XP perks
*
* @param primarySkillType target primary skill
* @return this players personal XP multiplier for target PrimarySkillType
*/
public float getPlayerSpecificXPMult(PrimarySkillType primarySkillType) {
return personalXPModifiers.get(primarySkillType);
}
/*public void hideXpBar(PrimarySkillType primarySkillType)
@ -754,7 +785,7 @@ public class McMMOPlayer {
}
}*/
return PerksUtils.handleXpPerks(player, xp, primarySkillType);
return xp * mcMMO.getPlayerLevelUtils().getPlayersPersonalXPRate(this, primarySkillType);
}
public void checkGodMode() {

View File

@ -1,7 +1,6 @@
package com.gmail.nossr50.datatypes.skills;
import com.gmail.nossr50.config.MainConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.SkillManager;

View File

@ -20,7 +20,9 @@ abstract public class McMMOScoreboardEvent extends Event {
protected Scoreboard targetBoard; //ConfigScoreboard involved in this event
protected Player targetPlayer;
/** GETTER & SETTER BOILERPLATE **/
/**
* GETTER & SETTER BOILERPLATE
**/
public McMMOScoreboardEvent(Scoreboard targetBoard, Scoreboard currentBoard, Player targetPlayer, ScoreboardEventReason scoreboardEventReason) {
this.scoreboardEventReason = scoreboardEventReason;

View File

@ -68,8 +68,7 @@ public class BlockListener implements Listener {
BonusDropMeta bonusDropMeta = (BonusDropMeta) event.getBlock().getMetadata(mcMMO.BONUS_DROPS_METAKEY).get(0);
int bonusCount = bonusDropMeta.asInt();
for (int i = 0; i < bonusCount; i++)
{
for (int i = 0; i < bonusCount; i++) {
event.getBlock().getWorld().dropItemNaturally(event.getBlockState().getLocation(), is);
}

View File

@ -383,8 +383,8 @@ public class InventoryListener implements Listener {
/* WORLD BLACKLIST CHECK */
//Location can be null here
if(event.getSource().getLocation() != null)
if(WorldBlacklist.isWorldBlacklisted(event.getSource().getLocation().getWorld()))
if (event.getSource().getLocation() != null)
if (WorldBlacklist.isWorldBlacklisted(event.getSource().getLocation().getWorld()))
return;
Inventory inventory = event.getDestination();

View File

@ -88,14 +88,12 @@ public class SelfListener implements Listener {
return;
}
if(mcMMO.getConfigManager().getConfigLeveling().isEnableEarlyGameBoost())
{
if (mcMMO.getConfigManager().getConfigLeveling().isEnableEarlyGameBoost()) {
int earlyGameBonusXP = 0;
//Give some bonus XP for low levels
if(mcMMOPlayer.getSkillLevel(primarySkillType) <= mcMMO.getPlayerLevelUtils().getEarlyGameCutoff(primarySkillType))
{
if (mcMMOPlayer.getSkillLevel(primarySkillType) <= mcMMO.getPlayerLevelUtils().getEarlyGameCutoff(primarySkillType)) {
earlyGameBonusXP += (mcMMOPlayer.getXpToLevel(primarySkillType) * 0.05);
event.setRawXpGained(event.getRawXpGained() + earlyGameBonusXP);
}

View File

@ -57,19 +57,18 @@ public final class LocaleLoader {
if (filesystemBundle != null) {
try {
return filesystemBundle.getString(key);
} catch (MissingResourceException ignored) {
}
catch (MissingResourceException ignored) {}
}
try {
return bundle.getString(key);
} catch (MissingResourceException ignored) {
}
catch (MissingResourceException ignored) {}
try {
return enBundle.getString(key);
}
catch (MissingResourceException ignored) {
} catch (MissingResourceException ignored) {
if (!key.contains("Guides")) {
mcMMO.p.getLogger().warning("Could not find locale string: " + key);
}

View File

@ -351,6 +351,7 @@ public class mcMMO extends JavaPlugin {
/**
* Returns a ServerSoftwareType based on version strings
* Custom software is returned as CRAFTBUKKIT
*
* @return the ServerSoftwareType which likely matches the server
*/
private ServerSoftwareType getServerSoftware() {
@ -364,6 +365,7 @@ public class mcMMO extends JavaPlugin {
/**
* Gets a string version of ServerSoftwareType
*
* @return Formatted String of ServerSoftwareType
*/
private String getServerSoftwareStr() {
@ -436,6 +438,7 @@ public class mcMMO extends JavaPlugin {
/**
* The directory in which override locales are kept
*
* @return the override locale directory
*/
public static String getLocalesDirectory() {
@ -444,6 +447,7 @@ public class mcMMO extends JavaPlugin {
/**
* If an XP rate event is currently in place
*
* @return
*/
public boolean isXPEventEnabled() {
@ -460,6 +464,7 @@ public class mcMMO extends JavaPlugin {
/**
* Sets the xpEventEnabled boolean
*
* @param enabled the new boolean state
*/
public void setXPEventEnabled(boolean enabled) {
@ -476,6 +481,7 @@ public class mcMMO extends JavaPlugin {
/**
* Debug helper method
* Prefixes log entries with [Debug]
*
* @param message the message to log with a Debug prefix
*/
public void debug(String message) {
@ -648,10 +654,6 @@ public class mcMMO extends JavaPlugin {
// Update power level tag scoreboards
new PowerLevelUpdatingTask().runTaskTimer(this, 2 * Misc.TICK_CONVERSION_FACTOR, 2 * Misc.TICK_CONVERSION_FACTOR);
/*if (getHolidayManager().nearingAprilFirst()) {
new CheckDateTask().runTaskTimer(this, 10L * Misc.TICK_CONVERSION_FACTOR, 1L * 60L * 60L * Misc.TICK_CONVERSION_FACTOR);
}*/
// Clear the registered XP data so players can earn XP again
if (ExperienceConfig.getInstance().getDiminishedReturnsEnabled()) {
new ClearRegisteredXPGainTask().runTaskTimer(this, 60, 60);

View File

@ -55,19 +55,16 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
if (size > MAX_LOOKUP) {
userNamesSection = userNames.subList(size - MAX_LOOKUP, size);
size -= MAX_LOOKUP;
}
else {
} else {
userNamesSection = userNames.subList(0, size);
size = 0;
}
try {
fetchedUUIDs.putAll(new UUIDFetcher(userNamesSection).call());
}
catch (Exception e) {
} catch (Exception e) {
// Handle 429
if(e.getMessage() != null)
{
if (e.getMessage() != null) {
if (e.getMessage().contains("429")) {
size += userNamesSection.size();
try {

View File

@ -26,6 +26,7 @@ public class AcrobaticsManager extends SkillManager {
private long rollXPInterval;
private long rollXPIntervalLengthen = (1000 * 10); //10 Seconds
private LimitedSizeList fallLocationMap;
public AcrobaticsManager(McMMOPlayer mcMMOPlayer) {
super(mcMMOPlayer, PrimarySkillType.ACROBATICS);
rollXPInterval = (1000 * mcMMO.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().getRollXPGainCooldownSeconds());

View File

@ -171,6 +171,7 @@ public final class BlockUtils {
/**
* Whether or not a block is gathered via Pickaxes
*
* @param material target blocks material
* @return
*/

View File

@ -7,9 +7,8 @@ import java.util.HashSet;
/**
* Stores hash tables for item and block names
* This allows for better support across multiple versions of Minecraft
*
* <p>
* This is a temporary class, mcMMO is spaghetti and I'l clean it up later
*
*/
public class MaterialMapStore {
@ -22,8 +21,7 @@ public class MaterialMapStore {
private HashSet<String> canMakeShroomyWhiteList;
private HashSet<String> multiBlockEntities;
public MaterialMapStore()
{
public MaterialMapStore() {
abilityBlackList = new HashSet<>();
toolBlackList = new HashSet<>();
mossyWhiteList = new HashSet<>();
@ -36,48 +34,39 @@ public class MaterialMapStore {
fillHardcodedHashSets();
}
public boolean isMultiBlock(Material material)
{
public boolean isMultiBlock(Material material) {
return multiBlockEntities.contains(material.getKey().getKey());
}
public boolean isAbilityActivationBlackListed(Material material)
{
public boolean isAbilityActivationBlackListed(Material material) {
return abilityBlackList.contains(material.getKey().getKey());
}
public boolean isToolActivationBlackListed(Material material)
{
public boolean isToolActivationBlackListed(Material material) {
return toolBlackList.contains(material.getKey().getKey());
}
public boolean isMossyWhiteListed(Material material)
{
public boolean isMossyWhiteListed(Material material) {
return mossyWhiteList.contains(material.getKey().getKey());
}
public boolean isLeavesWhiteListed(Material material)
{
public boolean isLeavesWhiteListed(Material material) {
return leavesWhiteList.contains(material.getKey().getKey());
}
public boolean isHerbalismAbilityWhiteListed(Material material)
{
public boolean isHerbalismAbilityWhiteListed(Material material) {
return herbalismAbilityBlackList.contains(material.getKey().getKey());
}
public boolean isBlockCrackerWhiteListed(Material material)
{
public boolean isBlockCrackerWhiteListed(Material material) {
return blockCrackerWhiteList.contains(material.getKey().getKey());
}
public boolean isShroomyWhiteListed(Material material)
{
public boolean isShroomyWhiteListed(Material material) {
return canMakeShroomyWhiteList.contains(material.getKey().getKey());
}
private void fillHardcodedHashSets()
{
private void fillHardcodedHashSets() {
fillAbilityBlackList();
filltoolBlackList();
fillMossyWhiteList();
@ -88,8 +77,7 @@ public class MaterialMapStore {
fillMultiBlockEntitiesList();
}
private void fillMultiBlockEntitiesList()
{
private void fillMultiBlockEntitiesList() {
multiBlockEntities.add("cactus");
multiBlockEntities.add("chorus_plant");
multiBlockEntities.add("sugar_cane");
@ -100,28 +88,24 @@ public class MaterialMapStore {
multiBlockEntities.add("bamboo");
}
private void fillShroomyWhiteList()
{
private void fillShroomyWhiteList() {
canMakeShroomyWhiteList.add("dirt");
canMakeShroomyWhiteList.add("grass");
canMakeShroomyWhiteList.add("grass_path");
}
private void fillBlockCrackerWhiteList()
{
private void fillBlockCrackerWhiteList() {
blockCrackerWhiteList.add("stone_bricks");
}
private void fillHerbalismAbilityBlackList()
{
private void fillHerbalismAbilityBlackList() {
herbalismAbilityBlackList.add("dirt");
herbalismAbilityBlackList.add("grass");
herbalismAbilityBlackList.add("grass_path");
herbalismAbilityBlackList.add("farmland");
}
private void fillLeavesWhiteList()
{
private void fillLeavesWhiteList() {
leavesWhiteList.add("oak_leaves");
leavesWhiteList.add("acacia_leaves");
leavesWhiteList.add("birch_leaves");
@ -130,8 +114,7 @@ public class MaterialMapStore {
leavesWhiteList.add("spruce_leaves");
}
private void fillMossyWhiteList()
{
private void fillMossyWhiteList() {
mossyWhiteList.add("cobblestone");
mossyWhiteList.add("dirt");
mossyWhiteList.add("grass_path");
@ -139,8 +122,7 @@ public class MaterialMapStore {
mossyWhiteList.add("cobblestone_wall");
}
private void fillAbilityBlackList()
{
private void fillAbilityBlackList() {
abilityBlackList.add("black_bed");
abilityBlackList.add("blue_bed");
abilityBlackList.add("brown_bed");
@ -239,9 +221,8 @@ public class MaterialMapStore {
abilityBlackList.add("wall_sign"); //1.13 and lower?
abilityBlackList.add("sign"); //1.13 and lower?
}
private void filltoolBlackList()
{
private void filltoolBlackList() {
//TODO: Add anvils / missing logs
toolBlackList.add("black_bed");
toolBlackList.add("blue_bed");
@ -364,8 +345,7 @@ public class MaterialMapStore {
toolBlackList.add("spruce_wood");
}
private void addToHashSet(String string, HashSet<String> stringHashSet)
{
private void addToHashSet(String string, HashSet<String> stringHashSet) {
stringHashSet.add(string.toLowerCase());
}
}

View File

@ -1,6 +1,7 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.commands.party.PartySubcommandType;
import com.gmail.nossr50.datatypes.experience.CustomXPPerk;
import com.gmail.nossr50.datatypes.skills.ItemMaterialCategory;
import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@ -233,7 +234,9 @@ public final class Permissions {
return permissible.hasPermission("mcmmo.commands.mmoupdate");
}
public static boolean reloadlocale(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.reloadlocale"); }
public static boolean reloadlocale(Permissible permissible) {
return permissible.hasPermission("mcmmo.commands.reloadlocale");
}
/*
* PERKS
@ -278,8 +281,8 @@ public final class Permissions {
return permissible.hasPermission("mcmmo.perks.xp.10percentboost." + skill.toString().toLowerCase());
}
public static boolean customXpBoost(Permissible permissible, PrimarySkillType skill) {
return permissible.hasPermission("mcmmo.perks.xp.customboost." + skill.toString().toLowerCase());
public static boolean hasCustomXPPerk(Permissible permissible, CustomXPPerk customXPPerk) {
return permissible.hasPermission(customXPPerk.getPerkPermissionAddress());
}
/* ACTIVATION PERKS */
@ -515,6 +518,22 @@ public final class Permissions {
}
}
/**
* XP Perks are defined by user config files and are not known until runtime
* This method registers Permissions with the server software as needed
*/
public static void addCustomXPPerks() {
mcMMO.p.getLogger().info("Registering custom XP perks with server software...");
PluginManager pluginManager = mcMMO.p.getServer().getPluginManager();
for (CustomXPPerk customXPPerk : mcMMO.getConfigManager().getConfigExperience().getCustomXPBoosts()) {
Permission permission = new Permission(customXPPerk.getPerkPermissionAddress());
permission.setDefault(PermissionDefault.FALSE);
pluginManager.addPermission(permission);
}
}
private static void addDynamicPermission(String permissionName, PluginManager pluginManager) {
Permission permission = new Permission(permissionName);
permission.setDefault(PermissionDefault.OP);

View File

@ -38,9 +38,8 @@ public class ExperienceMapManager implements Unload {
* This method servers two purposes
* 1) It adds user config values to a hash table
* 2) It converts user config values into their fully qualified names
*
* <p>
* This is done to avoid namespace conflicts, which don't happen in Bukkit but could easily happen in Sponge
*
*/
public void buildBlockXPMaps() {
buildMiningBlockXPMap();
@ -53,33 +52,27 @@ public class ExperienceMapManager implements Unload {
/**
* Taming entries in the config are case insensitive, but for faster lookups we convert them to ENUMs
*/
private void buildTamingXPMap()
{
private void buildTamingXPMap() {
mcMMO.p.getLogger().info("Building Taming XP list...");
HashMap<String, Integer> userTamingConfigMap = mcMMO.getConfigManager().getConfigExperience().getTamingExperienceMap();
for(String s : userTamingConfigMap.keySet())
{
for (String s : userTamingConfigMap.keySet()) {
boolean matchFound = false;
for(EntityType entityType : EntityType.values())
{
if(entityType.toString().equalsIgnoreCase(s))
{
for (EntityType entityType : EntityType.values()) {
if (entityType.toString().equalsIgnoreCase(s)) {
//Match!
matchFound = true;
tamingExperienceMap.put(entityType, (float) userTamingConfigMap.get(s));
}
}
if(!matchFound)
{
mcMMO.p.getLogger().info("Unable to find entity with matching name - "+s);
if (!matchFound) {
mcMMO.p.getLogger().info("Unable to find entity with matching name - " + s);
}
}
}
private void fillBlockXPMap(HashMap<String, Integer> userConfigMap, HashMap<String, Integer> fullyQualifiedBlockXPMap)
{
for(String string : userConfigMap.keySet()) {
private void fillBlockXPMap(HashMap<String, Integer> userConfigMap, HashMap<String, Integer> fullyQualifiedBlockXPMap) {
for (String string : userConfigMap.keySet()) {
//matchMaterial can match fully qualified names and names without domain
Material matchingMaterial = Material.matchMaterial(string);
@ -87,7 +80,7 @@ public class ExperienceMapManager implements Unload {
//Map the fully qualified name
fullyQualifiedBlockXPMap.put(matchingMaterial.getKey().getKey(), userConfigMap.get(string));
} else {
mcMMO.p.getLogger().info("Could not find a match for the block named '"+string+"' among vanilla block registers");
mcMMO.p.getLogger().info("Could not find a match for the block named '" + string + "' among vanilla block registers");
}
}
}
@ -115,6 +108,7 @@ public class ExperienceMapManager implements Unload {
/**
* Change the gloabl xp multiplier, this is temporary and will not be serialiized
*
* @param newGlobalXpMult new global xp multiplier value
*/
public void setGlobalXpMult(double newGlobalXpMult) {
@ -123,7 +117,7 @@ public class ExperienceMapManager implements Unload {
}
public void resetGlobalXpMult() {
mcMMO.p.getLogger().info("Resetting the global XP multiplier "+globalXpMult+" -> "+getOriginalGlobalXpMult());
mcMMO.p.getLogger().info("Resetting the global XP multiplier " + globalXpMult + " -> " + getOriginalGlobalXpMult());
globalXpMult = getOriginalGlobalXpMult();
}
@ -150,6 +144,7 @@ public class ExperienceMapManager implements Unload {
/**
* Gets the current global xp multiplier value
* This value can be changed by the xprate command
*
* @return
*/
public double getGlobalXpMult() {
@ -158,16 +153,16 @@ public class ExperienceMapManager implements Unload {
/**
* Gets the block break XP value for a specific skill
*
* @param primarySkillType target skill
* @param material target material
* @param material target material
* @return XP value for breaking this block for said skill
* @throws InvalidSkillException for skills that don't give block break experience
* @deprecated its faster to use direct calls to get XP, for example getMiningXP(Material material) instead of using this method
*/
@Deprecated
public float getBlockBreakXpValue(PrimarySkillType primarySkillType, Material material) throws InvalidSkillException {
switch(primarySkillType)
{
switch (primarySkillType) {
case MINING:
return getMiningXp(material);
case HERBALISM:
@ -183,6 +178,7 @@ public class ExperienceMapManager implements Unload {
/**
* Gets the taming XP for this entity
*
* @param entityType target entity
* @return value of XP for this entity
*/
@ -194,6 +190,7 @@ public class ExperienceMapManager implements Unload {
* Gets the original value of the global XP multiplier
* This is defined by the users config
* This value can be different from the current working value (due to xprate etc)
*
* @return the original global xp multiplier value from the user config file
*/
public double getOriginalGlobalXpMult() {

View File

@ -1,29 +1,58 @@
package com.gmail.nossr50.util.player;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.experience.CustomXPPerk;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Permissions;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
public class PlayerLevelUtils {
HashMap<PrimarySkillType, Integer> earlyGameBoostCutoffs;
private HashMap<PrimarySkillType, Integer> earlyGameBoostCutoffs;
private HashSet<CustomXPPerk> customXpPerkNodes;
public PlayerLevelUtils()
{
public PlayerLevelUtils() {
registerCustomPerkPermissions();
earlyGameBoostCutoffs = new HashMap<>();
calculateEarlyGameBoostCutoffs();
applyConfigPerks();
}
private void calculateEarlyGameBoostCutoffs()
{
for(PrimarySkillType primarySkillType : PrimarySkillType.values())
{
/**
* Register our custom permission perks with bukkit
*/
private void registerCustomPerkPermissions() {
Permissions.addCustomXPPerks();
}
/**
* Updates our custom XP boost map
*/
private void applyConfigPerks() {
//Make a copy
customXpPerkNodes = new HashSet<>(mcMMO.getConfigManager().getConfigExperience().getCustomXPBoosts());
}
/**
* Get the the final level at which players will still receive an early game XP boost
* Note: This doesn't mean early game boosts are enabled on the server, as that is a config toggle
*
* @param primarySkillType target skill
* @return this skills maximum early game boost level
*/
public int getEarlyGameCutoff(PrimarySkillType primarySkillType) {
return earlyGameBoostCutoffs.get(primarySkillType);
}
private void calculateEarlyGameBoostCutoffs() {
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
int levelCap = mcMMO.getConfigManager().getConfigLeveling().getLevelCap(primarySkillType);
int cap;
if(levelCap == Integer.MAX_VALUE || levelCap <= 0)
{
if (levelCap == Integer.MAX_VALUE || levelCap <= 0) {
cap = mcMMO.isRetroModeEnabled() ? 50 : 5;
} else {
cap = (int) (levelCap * mcMMO.getConfigManager().getConfigLeveling().getEarlyGameBoostMultiplier());
@ -33,8 +62,73 @@ public class PlayerLevelUtils {
}
}
public int getEarlyGameCutoff(PrimarySkillType primarySkillType)
{
return earlyGameBoostCutoffs.get(primarySkillType);
/**
* Finds all custom XP perks that a player currently qualifies for
* Used in figuring out which XP boost to give the player
*
* @param player target player
* @return a set of all CustomXPPerk that a player has positive permissions for
*/
public HashSet<CustomXPPerk> findCustomXPPerks(Player player) {
HashSet<CustomXPPerk> enabledXPPerks = new HashSet<>();
//Check all registered XP Perk nodes for this player
for (CustomXPPerk customXPPerk : customXpPerkNodes) {
if (Permissions.hasCustomXPPerk(player, customXPPerk)) {
enabledXPPerks.add(customXPPerk);
}
}
return enabledXPPerks;
}
/**
* Determines a players XP boost in a specific skill
* If a player has no custom XP perks or other boosts this value should always return 1.0
* Since a player can have multiple XP perks and boosts, this method only returns the highest that a player qualifies for
*
* @param player target player
* @param skill target skill
* @return the highest XP boost that this player qualifies for through perks or otherwise for target skill
*/
public float determineXpPerkValue(Player player, PrimarySkillType skill) {
HashSet<CustomXPPerk> enabledCustomXPPerks = findCustomXPPerks(player);
//A player can have multiple overlapping perks at a time, we need to compile a list and then sort it for the highest value
HashSet<Float> xpPerkValues = new HashSet<>();
if (enabledCustomXPPerks.size() >= 1) {
//Player has custom XP perks
for (CustomXPPerk customXPPerk : enabledCustomXPPerks) {
//Note: This returns 1.0 on skills with unset values
//Only add results that are not equal to 1.0
if (customXPPerk.getXPMultiplierValue(skill) != 1.0F)
xpPerkValues.add(customXPPerk.getXPMultiplierValue(skill));
}
}
//Disgusting legacy support start
if (Permissions.quadrupleXp(player, skill)) {
xpPerkValues.add(4f);
} else if (Permissions.tripleXp(player, skill)) {
xpPerkValues.add(3f);
} else if (Permissions.doubleAndOneHalfXp(player, skill)) {
xpPerkValues.add(2.5f);
} else if (Permissions.doubleXp(player, skill)) {
xpPerkValues.add(2.0f);
} else if (Permissions.oneAndOneHalfXp(player, skill)) {
xpPerkValues.add(1.5f);
} else if (Permissions.oneAndOneTenthXp(player, skill)) {
xpPerkValues.add(1.1f);
}
//Disgusting legacy support end
//Return
if (xpPerkValues.size() >= 1)
return Collections.max(xpPerkValues);
else
return 1.0F;
}
}

View File

@ -1,6 +1,5 @@
package com.gmail.nossr50.util.skills;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.util.Permissions;
import org.bukkit.entity.Player;
@ -40,26 +39,6 @@ public final class PerksUtils {
return ticks;
}
public static float handleXpPerks(Player player, float xp, PrimarySkillType skill) {
if (Permissions.customXpBoost(player, skill)) {
xp *= ExperienceConfig.getInstance().getCustomXpPerkBoost();
} else if (Permissions.quadrupleXp(player, skill)) {
xp *= 4;
} else if (Permissions.tripleXp(player, skill)) {
xp *= 3;
} else if (Permissions.doubleAndOneHalfXp(player, skill)) {
xp *= 2.5;
} else if (Permissions.doubleXp(player, skill)) {
xp *= 2;
} else if (Permissions.oneAndOneHalfXp(player, skill)) {
xp *= 1.5;
} else if (Permissions.oneAndOneTenthXp(player, skill)) {
xp *= 1.1;
}
return xp;
}
/**
* Calculate activation chance for a skill.
*

View File

@ -39,8 +39,7 @@ public class UUIDFetcher implements Callable<Map<String, UUID>> {
List<String> nameSubList = names.subList(i * PROFILES_PER_REQUEST, Math.min((i + 1) * PROFILES_PER_REQUEST, names.size()));
JsonArray array = new JsonArray();
for(String name : nameSubList)
{
for (String name : nameSubList) {
JsonPrimitive element = new JsonPrimitive(name);
array.add(element);
}