mirror of https://github.com/mcMMO-Dev/mcMMO.git
Compare commits
17 Commits
1127dfe553
...
1bcca99c2d
Author | SHA1 | Date |
---|---|---|
Prestley | 1bcca99c2d | |
nossr50 | 4d98d25215 | |
nossr50 | ffc6061f8b | |
nossr50 | 0363ee2e90 | |
nossr50 | b6e512b09e | |
nossr50 | aecf17a2a2 | |
nossr50 | c769813892 | |
nossr50 | e509876658 | |
nossr50 | a047bca94c | |
nossr50 | b5a50da09b | |
nossr50 | 2d79b364db | |
Robert Alan Chapton | 657d7cafa7 | |
nossr50 | d92c60fc84 | |
nossr50 | b56ddebde8 | |
nossr50 | cf49fc7599 | |
cj89898 | 618dfa94fc | |
cj89898 | 6fd4dd1403 |
|
@ -1,3 +1,39 @@
|
|||
Version 2.2.006
|
||||
Updated outdated wiki URLs in commands to point to the new wiki
|
||||
Removed the msg about skills being migrated to a new system when using /mmoinfo command
|
||||
Added new config custom_item_support.yml
|
||||
Added setting to disable repair on items with custom models, this is not on by default
|
||||
Added new locale entry 'Anvil.Repair.Reject.CustomModelData'
|
||||
Added new locale entry 'Anvil.Salvage.Reject.CustomModelData'
|
||||
|
||||
NOTES:
|
||||
Let me know in detail what kind of support you'd like to see in mcMMO regarding custom items, I'm open to suggestions.
|
||||
This update adds a new config file to allow server owners to disable repair or salvage on items with custom models,
|
||||
This prevention mechanism is not enabled by default, change the settings in custom_item_support.yml if you want to enable it.
|
||||
This feature is off by default for now to keep compatibility with existing servers, but it may be enabled by default in the future if feedback suggests it should be.
|
||||
As a reminder, anyone can update the wiki by clicking on the "edit on github" link on various pages, this will take you to the wiki's source code on GitHub, submit a PR to make changes
|
||||
|
||||
Version 2.2.005
|
||||
Fixed a bug where certain skills such as Dodge/Arrow Deflect had no skill cap and would continue improving forever
|
||||
Reduced messages on startup for SQL DB
|
||||
(API) Constructor for ProbabilityImpl now takes a raw value between 0 and 1 instead of an inflated percentage
|
||||
(API) Added some convenience methods to Probability, and ProbabilityUtil classes
|
||||
(Codebase) Added more unit tests revolving around Probability/RNG
|
||||
|
||||
Version 2.2.004
|
||||
Fixed bug where values from Experience_Formula.Skill_Multiplier were not functioning
|
||||
|
||||
NOTES:
|
||||
A reminder that these values are multipliers and no longer divisors, if you want 10x lower XP, a value of .1 would do the job.
|
||||
|
||||
Version 2.2.003
|
||||
(SQLDB) Fixed a bug where lastlogin was using a value that was too large
|
||||
(SQLDB) Fixed bug where crossbows was not getting added to SQL schema for some users
|
||||
|
||||
Version 2.2.002
|
||||
Fixed bug where thrown tridents did not grant XP or benefit from subskills
|
||||
Fixed bug where trickshot marked bounced arrows as being shot from a bow instead of being shot from a crossbow
|
||||
|
||||
Version 2.2.001
|
||||
Fixed Crossbow's Powered shot showing the text for the wrong skill from the locale when using /crossbows command
|
||||
|
||||
|
|
16
README.md
16
README.md
|
@ -10,6 +10,22 @@ Spigot Resource: https://spigot.mcmmo.org
|
|||
|
||||
I plan to post links to our new wiki (its still under development), downloads, and dev blogs there.
|
||||
|
||||
## API
|
||||
If you are using maven, you can add mcMMO API to your plugin by adding it to pom.xml like so...
|
||||
|
||||
```
|
||||
<repository>
|
||||
<id>neetgames</id>
|
||||
<url>https://nexus.neetgames.com/repository/maven-releases/</url>
|
||||
</repository>
|
||||
```
|
||||
```
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.2.004</version>
|
||||
</dependency>
|
||||
```
|
||||
### Builds
|
||||
Currently, you can obtain our builds via the Spigot or Polymart:
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -2,7 +2,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.2.001</version>
|
||||
<version>2.2.006-SNAPSHOT</version>
|
||||
<name>mcMMO</name>
|
||||
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
||||
<scm>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.gmail.nossr50.commands.skills;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.listeners.InteractionManager;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
|
@ -29,14 +28,11 @@ public class MmoInfoCommand implements TabExecutor {
|
|||
*/
|
||||
if(commandSender instanceof Player player)
|
||||
{
|
||||
if(args.length < 1)
|
||||
if(args == null || args.length < 1 || args[0] == null || args[0].isEmpty())
|
||||
return false;
|
||||
|
||||
if(Permissions.mmoinfo(player))
|
||||
{
|
||||
if(args == null || args[0] == null)
|
||||
return false;
|
||||
|
||||
if(args[0].equalsIgnoreCase( "???"))
|
||||
{
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Header"));
|
||||
|
@ -44,14 +40,15 @@ public class MmoInfoCommand implements TabExecutor {
|
|||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.DetailsHeader"));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Mystery"));
|
||||
return true;
|
||||
} else if(InteractionManager.getAbstractByName(args[0]) != null || mcMMO.p.getSkillTools().EXACT_SUBSKILL_NAMES.contains(args[0]))
|
||||
{
|
||||
displayInfo(player, args[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Not a real skill
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.NoMatch"));
|
||||
final SubSkillType subSkillType = matchSubSkill(args[0]);
|
||||
if (subSkillType != null) {
|
||||
displayInfo(player, subSkillType);
|
||||
} else {
|
||||
//Not a real skill
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.NoMatch"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +56,16 @@ public class MmoInfoCommand implements TabExecutor {
|
|||
return false;
|
||||
}
|
||||
|
||||
public SubSkillType matchSubSkill(String name) {
|
||||
for(SubSkillType subSkillType : SubSkillType.values())
|
||||
{
|
||||
if(subSkillType.getNiceNameNoSpaces(subSkillType).equalsIgnoreCase(name)
|
||||
|| subSkillType.name().equalsIgnoreCase(name))
|
||||
return subSkillType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
if (args.length == 1) {
|
||||
|
@ -67,20 +74,13 @@ public class MmoInfoCommand implements TabExecutor {
|
|||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
private void displayInfo(Player player, String subSkillName)
|
||||
private void displayInfo(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Header"));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.SubSkillHeader", subSkillName));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.SubSkillHeader", subSkillType.getLocaleName()));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.DetailsHeader"));
|
||||
player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.OldSkill"));
|
||||
|
||||
for(SubSkillType subSkillType : SubSkillType.values())
|
||||
{
|
||||
if(subSkillType.getNiceNameNoSpaces(subSkillType).equalsIgnoreCase(subSkillName))
|
||||
subSkillName = subSkillType.getWikiName(subSkillType.toString());
|
||||
}
|
||||
|
||||
//Send Player Wiki Link
|
||||
TextComponentFactory.sendPlayerSubSkillWikiLink(player, subSkillName);
|
||||
TextComponentFactory.sendPlayerSubSkillWikiLink(player, subSkillType.getLocaleName(), subSkillType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.gmail.nossr50.config;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CustomItemSupportConfig extends BukkitConfig {
|
||||
public CustomItemSupportConfig(File dataFolder) {
|
||||
super("custom_item_support.yml", dataFolder);
|
||||
validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadKeys() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isCustomRepairAllowed() {
|
||||
return config.getBoolean("Custom_Item_Support.Repair.Allow_Repair_On_Items_With_Custom_Model_Data", true);
|
||||
}
|
||||
|
||||
public boolean isCustomSalvageAllowed() {
|
||||
return config.getBoolean("Custom_Item_Support.Salvage.Allow_Salvage_On_Items_With_Custom_Model_Data", true);
|
||||
}
|
||||
}
|
|
@ -260,7 +260,7 @@ public class ExperienceConfig extends BukkitConfig {
|
|||
|
||||
/* Skill modifiers */
|
||||
public double getFormulaSkillModifier(PrimarySkillType skill) {
|
||||
return config.getDouble("Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString()), 1);
|
||||
return config.getDouble("Experience_Formula.Skill_Multiplier." + StringUtils.getCapitalized(skill.toString()), 1);
|
||||
}
|
||||
|
||||
/* Custom XP perk */
|
||||
|
|
|
@ -578,13 +578,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
|
|||
statement.executeUpdate();
|
||||
statement.close();
|
||||
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
|
||||
String sql = "INSERT INTO " + tablePrefix + "users (`user`, uuid, lastlogin) VALUES (?, ?, ?)";
|
||||
statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
statement = connection.prepareStatement("INSERT INTO " + tablePrefix + "users (user, uuid, lastlogin) VALUES (?, ?, UNIX_TIMESTAMP())", Statement.RETURN_GENERATED_KEYS);
|
||||
statement.setString(1, playerName);
|
||||
statement.setString(2, uuid != null ? uuid.toString() : null);
|
||||
statement.setLong(3, currentTimeMillis);
|
||||
statement.executeUpdate();
|
||||
|
||||
resultSet = statement.getGeneratedKeys();
|
||||
|
@ -1038,19 +1034,41 @@ public final class SQLDatabaseManager implements DatabaseManager {
|
|||
}
|
||||
|
||||
private void updateStructure(String tableName, String columnName, String columnSize) {
|
||||
try (Connection connection = getConnection(PoolIdentifier.MISC);
|
||||
Statement createStatement = connection.createStatement()) {
|
||||
|
||||
String startingLevel = "'" + mcMMO.p.getAdvancedConfig().getStartingLevel() + "'";
|
||||
createStatement.executeUpdate("ALTER TABLE `" + tablePrefix + tableName + "` "
|
||||
+ "ADD COLUMN IF NOT EXISTS `" + columnName + "` int(" + columnSize + ") unsigned NOT NULL DEFAULT " + startingLevel);
|
||||
|
||||
try (Connection connection = getConnection(PoolIdentifier.MISC)) {
|
||||
if (!columnExists(connection, mcMMO.p.getGeneralConfig().getMySQLDatabaseName(), tablePrefix+tableName, columnName)) {
|
||||
try (Statement createStatement = connection.createStatement()) {
|
||||
// logger.info("[SQLDB Check] Adding column '" + columnName + "' to table '" + tablePrefix + tableName + "'...");
|
||||
String startingLevel = "'" + mcMMO.p.getAdvancedConfig().getStartingLevel() + "'";
|
||||
createStatement.executeUpdate("ALTER TABLE `" + tablePrefix + tableName + "` "
|
||||
+ "ADD COLUMN `" + columnName + "` int(" + columnSize + ") unsigned NOT NULL DEFAULT " + startingLevel);
|
||||
}
|
||||
} else {
|
||||
// logger.info("[SQLDB Check] Column '" + columnName + "' already exists in table '" + tablePrefix + tableName + "', looks good!");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace(); // Consider more robust logging
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean columnExists(Connection connection, String database, String tableName, String columnName) throws SQLException {
|
||||
// logger.info("[SQLDB Check] Checking if column '" + columnName + "' exists in table '" + tableName + "'");
|
||||
try (Statement createStatement = connection.createStatement()) {
|
||||
String sql = "SELECT `COLUMN_NAME`\n" +
|
||||
"FROM `INFORMATION_SCHEMA`.`COLUMNS`\n" +
|
||||
"WHERE `TABLE_SCHEMA`='" + database + "'\n" +
|
||||
" AND `TABLE_NAME`='" + tableName + "'\n" +
|
||||
" AND `COLUMN_NAME`='" + columnName + "'";
|
||||
var resultSet = createStatement.executeQuery(sql);
|
||||
return resultSet.next();
|
||||
} catch (SQLException e) {
|
||||
logger.info("Failed to check if column exists in table " + tableName + " for column " + columnName);
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setStatementQuery(PreparedStatement statement, String tableName) throws SQLException {
|
||||
if (!this.h2) {
|
||||
// Set schema name for MySQL
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.bukkit.plugin.Plugin;
|
|||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
@ -840,14 +841,15 @@ public class McMMOPlayer implements Identified {
|
|||
* @param xp Experience amount to process
|
||||
* @return Modified experience
|
||||
*/
|
||||
private float modifyXpGain(PrimarySkillType primarySkillType, float xp) {
|
||||
@VisibleForTesting
|
||||
float modifyXpGain(PrimarySkillType primarySkillType, float xp) {
|
||||
//TODO: A rare situation can occur where the default Power Level cap can prevent a player with one skill edited to something silly like Integer.MAX_VALUE from gaining XP in any skill, we may need to represent power level with another data type
|
||||
if ((mcMMO.p.getSkillTools().getLevelCap(primarySkillType) <= getSkillLevel(primarySkillType))
|
||||
|| (mcMMO.p.getGeneralConfig().getPowerLevelCap() <= getPowerLevel())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
xp = (float) (xp * ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType) * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
|
||||
xp = (float) ((xp * ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType)) * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
|
||||
|
||||
if (mcMMO.p.getGeneralConfig().getToolModsEnabled()) {
|
||||
CustomTool tool = mcMMO.getModManager().getTool(player.getInventory().getItemInMainHand());
|
||||
|
|
|
@ -132,12 +132,12 @@ public enum PrimarySkillType {
|
|||
/**
|
||||
* WARNING: Being removed in an upcoming update, you should be using mcMMO.getSkillTools() instead
|
||||
* @return the max level of this skill
|
||||
* @see SkillTools#getXpModifier(com.gmail.nossr50.datatypes.skills.PrimarySkillType)
|
||||
* @see SkillTools#getXpMultiplier(com.gmail.nossr50.datatypes.skills.PrimarySkillType)
|
||||
* @deprecated this is being removed in an upcoming update, you should be using mcMMO.getSkillTools() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public double getXpModifier() {
|
||||
return mcMMO.p.getSkillTools().getXpModifier(this);
|
||||
return mcMMO.p.getSkillTools().getXpMultiplier(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -213,35 +213,12 @@ public enum SubSkillType {
|
|||
return endResult.toString();
|
||||
}
|
||||
|
||||
public String getWikiName(String subSkillName) {
|
||||
/*
|
||||
* Find where to begin our substring (after the prefix)
|
||||
*/
|
||||
StringBuilder endResult = new StringBuilder();
|
||||
int subStringIndex = getSubStringIndex(subSkillName);
|
||||
|
||||
/*
|
||||
* Split the string up so we can capitalize each part
|
||||
*/
|
||||
String subskillNameWithoutPrefix = subSkillName.substring(subStringIndex);
|
||||
if(subskillNameWithoutPrefix.contains("_"))
|
||||
{
|
||||
String[] splitStrings = subskillNameWithoutPrefix.split("_");
|
||||
|
||||
for(int i = 0; i < splitStrings.length; i++)
|
||||
{
|
||||
if(i+1 >= splitStrings.length)
|
||||
endResult.append(StringUtils.getCapitalized(splitStrings[i]));
|
||||
else {
|
||||
endResult.append(StringUtils.getCapitalized(splitStrings[i]));
|
||||
endResult.append("_");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
endResult.append(StringUtils.getCapitalized(subskillNameWithoutPrefix));
|
||||
}
|
||||
|
||||
return endResult.toString();
|
||||
public String getWikiUrl() {
|
||||
// remove the text before the first underscore
|
||||
int subStringIndex = getSubStringIndex(name());
|
||||
String afterPrefix = name().substring(subStringIndex);
|
||||
// replace _ or spaces with -
|
||||
return afterPrefix.replace("_", "-").replace(" ", "-").toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -140,6 +140,7 @@ public class mcMMO extends JavaPlugin {
|
|||
private GeneralConfig generalConfig;
|
||||
private AdvancedConfig advancedConfig;
|
||||
private PartyConfig partyConfig;
|
||||
private CustomItemSupportConfig customItemSupportConfig;
|
||||
|
||||
private FoliaLib foliaLib;
|
||||
private PartyManager partyManager;
|
||||
|
@ -185,6 +186,7 @@ public class mcMMO extends JavaPlugin {
|
|||
//Init configs
|
||||
advancedConfig = new AdvancedConfig(getDataFolder());
|
||||
partyConfig = new PartyConfig(getDataFolder());
|
||||
customItemSupportConfig = new CustomItemSupportConfig(getDataFolder());
|
||||
|
||||
//Store this value so other plugins can check it
|
||||
isRetroModeEnabled = generalConfig.getIsRetroMode();
|
||||
|
@ -806,6 +808,10 @@ public class mcMMO extends JavaPlugin {
|
|||
return partyManager;
|
||||
}
|
||||
|
||||
public CustomItemSupportConfig getCustomItemSupportConfig() {
|
||||
return customItemSupportConfig;
|
||||
}
|
||||
|
||||
public @NotNull FoliaLib getFoliaLib() {
|
||||
return foliaLib;
|
||||
}
|
||||
|
|
|
@ -15,14 +15,26 @@ import org.bukkit.entity.Player;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class PapiExpansion extends PlaceholderExpansion {
|
||||
private final Map<String, Placeholder> placeholders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
public static final String SKILL_LEVEL = "level_";
|
||||
public static final String SKILL_EXP_NEEDED = "xp_needed_";
|
||||
public static final String SKILL_EXP_REMAINING = "xp_remaining_";
|
||||
public static final String SKILL_EXP = "xp_";
|
||||
public static final String SKILL_RANK = "rank_";
|
||||
public static final String SKILL_EXP_RATE = "xprate_";
|
||||
public static final String POWER_LEVEL = "power_level";
|
||||
public static final String POWER_LEVEL_CAP = "power_level_cap";
|
||||
public static final String IN_PARTY = "in_party";
|
||||
public static final String PARTY_NAME = "party_name";
|
||||
public static final String IS_PARTY_LEADER = "is_party_leader";
|
||||
public static final String PARTY_LEADER = "party_leader";
|
||||
public static final String PARTY_SIZE = "party_size";
|
||||
public static final String EXP_RATE = "xprate";
|
||||
public static final String IS_EXP_EVENT_ACTIVE = "is_xp_event_active";
|
||||
|
||||
public PapiExpansion() {
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,8 +49,7 @@ public class PapiExpansion extends PlaceholderExpansion {
|
|||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
//grab version from pom.xml
|
||||
return "1.0,0";
|
||||
return mcMMO.p.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,105 +65,41 @@ public class PapiExpansion extends PlaceholderExpansion {
|
|||
@Override
|
||||
@Nullable
|
||||
public String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
||||
String token;
|
||||
String data = null;
|
||||
int dataPosition = params.indexOf(":");
|
||||
|
||||
if (dataPosition != -1) {
|
||||
token = params.substring(0, dataPosition);
|
||||
data = params.substring(dataPosition + 1);
|
||||
} else {
|
||||
token = params;
|
||||
}
|
||||
|
||||
Placeholder placeholder = placeholders.get(token);
|
||||
|
||||
if (placeholder != null) {
|
||||
return placeholder.process(player, data);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getSkillLevel(PrimarySkillType skill, Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
return user.getSkillLevel(skill);
|
||||
}
|
||||
|
||||
public Integer getExpNeeded(PrimarySkillType skill, Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
return user.getXpToLevel(skill);
|
||||
}
|
||||
|
||||
public Integer getExp(PrimarySkillType skill, Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
|
||||
return user.getSkillXpLevel(skill);
|
||||
}
|
||||
|
||||
|
||||
public Integer getExpRemaining(PrimarySkillType skill, Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
int current = user.getSkillXpLevel(skill);
|
||||
int needed = user.getXpToLevel(skill);
|
||||
|
||||
return needed - current;
|
||||
}
|
||||
|
||||
public Integer getRank(PrimarySkillType skill, Player player) {
|
||||
try {
|
||||
return ExperienceAPI.getPlayerRankSkill(player.getUniqueId(), StringUtils.getCapitalized(skill.toString()));
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getPowerLevel(Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
return user.getPowerLevel();
|
||||
}
|
||||
|
||||
public Integer getPowerCap(Player player) {
|
||||
return mcMMO.p.getGeneralConfig().getPowerLevelCap();
|
||||
}
|
||||
|
||||
public String getPartyName(Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
final Party party = user.getParty();
|
||||
|
||||
return (party == null) ? null : party.getName();
|
||||
}
|
||||
|
||||
public String getPartyLeader(Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
final Party party = user.getParty();
|
||||
return (party == null) ? null : party.getLeader().getPlayerName();
|
||||
}
|
||||
|
||||
public Integer getPartySize(Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
final Party party = user.getParty();
|
||||
return (party == null) ? null : party.getMembers().size();
|
||||
}
|
||||
|
||||
public String getXpRate(Player player) {
|
||||
|
||||
// Non player-specific placeholders
|
||||
if (params.equalsIgnoreCase(IS_EXP_EVENT_ACTIVE)) {
|
||||
return mcMMO.p.isXPEventEnabled() ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
} else if (params.equalsIgnoreCase(EXP_RATE)) {
|
||||
return String.valueOf(ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
|
||||
}
|
||||
|
||||
public String getSkillXpRate(PrimarySkillType skill, Player player) {
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
|
||||
} else if (params.equalsIgnoreCase(POWER_LEVEL_CAP)) {
|
||||
return String.valueOf(mcMMO.p.getGeneralConfig().getPowerLevelCap());
|
||||
}
|
||||
|
||||
final McMMOPlayer user = UserManager.getPlayer(player);
|
||||
if (user == null) return null;
|
||||
|
||||
if (params.startsWith(SKILL_LEVEL)) {
|
||||
PrimarySkillType skill = PrimarySkillType.valueOf(params.substring(SKILL_LEVEL.length()).toUpperCase());
|
||||
return skill == null ? null : String.valueOf(user.getSkillLevel(skill));
|
||||
} else if (params.startsWith(SKILL_EXP_NEEDED)) {
|
||||
PrimarySkillType skill = PrimarySkillType.valueOf(params.substring(SKILL_EXP_NEEDED.length()).toUpperCase());
|
||||
return skill == null ? null : String.valueOf(user.getXpToLevel(skill));
|
||||
} else if (params.startsWith(SKILL_EXP_REMAINING)) {
|
||||
PrimarySkillType skill = PrimarySkillType.valueOf(params.substring(SKILL_EXP_REMAINING.length()).toUpperCase());
|
||||
return skill == null ? null : String.valueOf(user.getXpToLevel(skill) - user.getSkillXpLevel(skill));
|
||||
} else if (params.startsWith(SKILL_EXP)) {
|
||||
PrimarySkillType skill = PrimarySkillType.valueOf(params.substring(SKILL_EXP.length()).toUpperCase());
|
||||
return skill == null ? null : String.valueOf(user.getSkillXpLevel(skill));
|
||||
} else if (params.startsWith(SKILL_RANK)) {
|
||||
try {
|
||||
return String.valueOf(ExperienceAPI.getPlayerRankSkill(player.getUniqueId(), StringUtils.getCapitalized(params.substring(SKILL_RANK.length()))));
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
} else if (params.startsWith(SKILL_EXP_RATE)) {
|
||||
PrimarySkillType skill = PrimarySkillType.valueOf(params.substring(SKILL_EXP_RATE.length()).toUpperCase());
|
||||
if (skill == null) return null;
|
||||
double modifier = 1.0F;
|
||||
|
||||
if (Permissions.customXpBoost(player, skill))
|
||||
modifier = ExperienceConfig.getInstance().getCustomXpPerkBoost();
|
||||
else if (Permissions.quadrupleXp(player, skill))
|
||||
|
@ -167,69 +114,29 @@ public class PapiExpansion extends PlaceholderExpansion {
|
|||
modifier = 1.5;
|
||||
else if (Permissions.oneAndOneTenthXp(player, skill))
|
||||
modifier = 1.1;
|
||||
|
||||
return String.valueOf(modifier);
|
||||
} else if (params.equalsIgnoreCase(POWER_LEVEL)) {
|
||||
return String.valueOf(user.getPowerLevel());
|
||||
}
|
||||
|
||||
|
||||
//Party placeholders
|
||||
final Party party = user.getParty();
|
||||
|
||||
if (params.equalsIgnoreCase(IN_PARTY)) {
|
||||
return (party==null) ? PlaceholderAPIPlugin.booleanFalse() : PlaceholderAPIPlugin.booleanTrue();
|
||||
} else if (params.equalsIgnoreCase(PARTY_NAME)) {
|
||||
return (party == null) ? "" : party.getName();
|
||||
} else if (params.equalsIgnoreCase(IS_PARTY_LEADER)) {
|
||||
if (party == null) return "";
|
||||
return party.getLeader().getPlayerName().equals(player.getName()) ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
} else if (params.equalsIgnoreCase(PARTY_LEADER)) {
|
||||
return (party == null) ? "" : party.getLeader().getPlayerName();
|
||||
} else if (params.equalsIgnoreCase(PARTY_SIZE)) {
|
||||
return (party == null) ? "" : String.valueOf(party.getMembers().size());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String isExpEventActive(Player player) {
|
||||
return mcMMO.p.isXPEventEnabled() ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
}
|
||||
|
||||
public void registerPlaceholder(Placeholder placeholder) {
|
||||
final Placeholder registered = placeholders.get(placeholder.getName());
|
||||
if (registered != null)
|
||||
throw new IllegalStateException("Placeholder " + placeholder.getName() + " is already registered!");
|
||||
|
||||
placeholders.put(placeholder.getName(), placeholder);
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
|
||||
for (PrimarySkillType skill : PrimarySkillType.values()) {
|
||||
// %mcmmo_level_<skillname>%
|
||||
registerPlaceholder(new SkillLevelPlaceholder(this, skill));
|
||||
|
||||
//%mcmmo_xp_needed_<skillname>%
|
||||
registerPlaceholder(new SkillExpNeededPlaceholder(this, skill));
|
||||
|
||||
//%mcmmo_xp_<skillname>%
|
||||
registerPlaceholder(new SkillExpPlaceholder(this, skill));
|
||||
|
||||
//%mcmmo_xp_remaining_<skillname>%
|
||||
registerPlaceholder(new SkillExpRemainingPlaceholder(this, skill));
|
||||
|
||||
//%mcmmo_rank_<skillname>%
|
||||
registerPlaceholder(new SkillRankPlaceholder(this, skill));
|
||||
|
||||
//%mcmmo_xprate_<skillname>%
|
||||
registerPlaceholder(new SkillXpRatePlaceholder(this, skill));
|
||||
}
|
||||
|
||||
|
||||
//%mcmmo_power_level%
|
||||
registerPlaceholder(new PowerLevelPlaceholder(this));
|
||||
|
||||
// %mcmmo_power_level_cap%
|
||||
registerPlaceholder(new PowerLevelCapPlaceholder(this));
|
||||
|
||||
// %mcmmo_in_party%
|
||||
registerPlaceholder(new PartyIsMemberPlaceholder(this));
|
||||
|
||||
/// %mcmmo_party_name%
|
||||
registerPlaceholder(new PartyNamePlaceholder(this));
|
||||
|
||||
// %mcmmo_is_party_leader%
|
||||
registerPlaceholder(new PartyIsLeaderPlaceholder(this));
|
||||
|
||||
// %mcmmo_party_leader%
|
||||
registerPlaceholder(new PartyLeaderPlaceholder(this));
|
||||
|
||||
// %mcmmo_party_size%
|
||||
registerPlaceholder(new PartySizePlaceholder(this));
|
||||
|
||||
// %mcmmo_is_xp_event_active%
|
||||
registerPlaceholder(new XpEventActivePlaceholder(this));
|
||||
// %mcmmo_xprate%
|
||||
registerPlaceholder(new XpRatePlaceholder(this));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PartyIsLeaderPlaceholder implements Placeholder {
|
||||
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PartyIsLeaderPlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
String leader = papiExpansion.getPartyLeader(player);
|
||||
return (leader.equals(player.getName())) ? "true" : "false";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "is_party_leader";
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PartyIsMemberPlaceholder implements Placeholder {
|
||||
|
||||
private final PapiExpansion papiExpansion;
|
||||
public PartyIsMemberPlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
return (papiExpansion.getPartyName(player) == null) ? "false" : "true";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "in_party";
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PartyLeaderPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PartyLeaderPlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
return StringUtils.stripToEmpty(papiExpansion.getPartyLeader(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "party_leader";
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PartyNamePlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PartyNamePlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
return StringUtils.stripToEmpty(papiExpansion.getPartyName(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "party_name";
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PartySizePlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PartySizePlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
Integer partySize = papiExpansion.getPartySize(player);
|
||||
return (partySize == null) ? "" : partySize.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "party_size";
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface Placeholder {
|
||||
|
||||
/**
|
||||
* @param player the player to process the placeholder for
|
||||
* @param params the paramaters to be passed to the placeholder
|
||||
* @return the value of the placeholder
|
||||
*/
|
||||
String process(Player player, String params);
|
||||
|
||||
/**
|
||||
* @return the name of the placeholder
|
||||
*/
|
||||
String getName();
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PowerLevelCapPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PowerLevelCapPlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
Integer cap = papiExpansion.getPowerCap(player);
|
||||
return (cap == null) ? "" : cap.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "power_level_cap";
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PowerLevelPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public PowerLevelPlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
Integer powerLevel = papiExpansion.getPowerLevel(player);
|
||||
return (powerLevel == null) ? "" : powerLevel.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "power_level";
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillExpNeededPlaceholder implements Placeholder {
|
||||
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skillType;
|
||||
|
||||
public SkillExpNeededPlaceholder(PapiExpansion papiExpansion, PrimarySkillType skillType) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skillType = skillType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
final Integer expNeeded = papiExpansion.getExpNeeded(skillType, player);
|
||||
return (expNeeded == null) ? "" : expNeeded.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xp_needed_" + skillType.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillExpPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skill;
|
||||
|
||||
public SkillExpPlaceholder(PapiExpansion papiExpansion, PrimarySkillType skill) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
Integer exp = papiExpansion.getExp(skill, player);
|
||||
return (exp == null) ? "" : exp.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xp_" + skill.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillExpRemainingPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skill;
|
||||
|
||||
public SkillExpRemainingPlaceholder(PapiExpansion papiExpansion, PrimarySkillType skill) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
final Integer expRemaining = papiExpansion.getExpRemaining(skill, player);
|
||||
return (expRemaining == null) ? "" : expRemaining.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xp_remaining_" + skill.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillLevelPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skillType;
|
||||
|
||||
public SkillLevelPlaceholder(PapiExpansion papiExpansion, PrimarySkillType skillType) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skillType = skillType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player p, String params) {
|
||||
final Integer skillLevel = papiExpansion.getSkillLevel(skillType, p);
|
||||
return (skillLevel == null) ? "" : skillLevel.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "level_" + skillType.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillRankPlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skill;
|
||||
|
||||
public SkillRankPlaceholder(PapiExpansion papiExpansion, PrimarySkillType skill) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
Integer rank = papiExpansion.getRank(skill, player);
|
||||
return (rank == null) ? "" : rank.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "rank_" + skill.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SkillXpRatePlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
private final PrimarySkillType skillType;
|
||||
|
||||
public SkillXpRatePlaceholder(PapiExpansion papiExpansion, PrimarySkillType skillType) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
this.skillType = skillType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player p, String params) {
|
||||
final String skillLevel = papiExpansion.getSkillXpRate(skillType, p);
|
||||
return (skillLevel == null) ? "" : skillLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xprate_" + skillType.toString().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class XpEventActivePlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public <S extends PrimarySkillType> XpEventActivePlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
return papiExpansion.isExpEventActive(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "is_xp_event_active";
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.gmail.nossr50.placeholders;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class XpRatePlaceholder implements Placeholder {
|
||||
private final PapiExpansion papiExpansion;
|
||||
|
||||
public <S extends PrimarySkillType> XpRatePlaceholder(PapiExpansion papiExpansion) {
|
||||
this.papiExpansion = papiExpansion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process(Player player, String params) {
|
||||
return papiExpansion.getXpRate(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "xprate";
|
||||
}
|
||||
}
|
|
@ -72,6 +72,7 @@ public class CrossbowsManager extends SkillManager {
|
|||
new FixedMetadataValue(pluginRef, bounceCount + 1));
|
||||
spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
|
||||
new FixedMetadataValue(pluginRef, originalArrowShooter));
|
||||
spawnedArrow.setShotFromCrossbow(true);
|
||||
|
||||
// Don't allow multi-shot or infinite arrows to be picked up
|
||||
if (spawnedArrow.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)
|
||||
|
|
|
@ -65,10 +65,19 @@ public class RepairManager extends SkillManager {
|
|||
public void handleRepair(ItemStack item) {
|
||||
Player player = getPlayer();
|
||||
Repairable repairable = mcMMO.getRepairableManager().getRepairable(item.getType());
|
||||
if (item.getItemMeta() != null) {
|
||||
if(item.getItemMeta().hasCustomModelData()) {
|
||||
if(!mcMMO.p.getCustomItemSupportConfig().isCustomRepairAllowed()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED,
|
||||
"Anvil.Repair.Reject.CustomModelData");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getItemMeta().isUnbreakable()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
|
||||
return;
|
||||
if (item.getItemMeta().isUnbreakable()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Permissions checks on material and item types
|
||||
|
|
|
@ -62,14 +62,19 @@ public class SalvageManager extends SkillManager {
|
|||
}
|
||||
|
||||
public void handleSalvage(Location location, ItemStack item) {
|
||||
Player player = getPlayer();
|
||||
final Player player = getPlayer();
|
||||
|
||||
Salvageable salvageable = mcMMO.getSalvageableManager().getSalvageable(item.getType());
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null && meta.isUnbreakable()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
|
||||
return;
|
||||
final Salvageable salvageable = mcMMO.getSalvageableManager().getSalvageable(item.getType());
|
||||
final ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
if (meta.hasCustomModelData() && !mcMMO.p.getCustomItemSupportConfig().isCustomSalvageAllowed()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Salvage.Reject.CustomModelData");
|
||||
return;
|
||||
}
|
||||
if (meta.isUnbreakable()) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Permissions checks on material and item types
|
||||
|
@ -190,30 +195,6 @@ public class SalvageManager extends SkillManager {
|
|||
return RankUtils.getRank(getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE);
|
||||
}
|
||||
|
||||
/*public double getExtractFullEnchantChance() {
|
||||
int skillLevel = getSkillLevel();
|
||||
|
||||
for (Tier tier : Tier.values()) {
|
||||
if (skillLevel >= tier.getLevel()) {
|
||||
return tier.getExtractFullEnchantChance();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double getExtractPartialEnchantChance() {
|
||||
int skillLevel = getSkillLevel();
|
||||
|
||||
for (Tier tier : Tier.values()) {
|
||||
if (skillLevel >= tier.getLevel()) {
|
||||
return tier.getExtractPartialEnchantChance();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
public double getExtractFullEnchantChance() {
|
||||
if(Permissions.hasSalvageEnchantBypassPerk(getPlayer()))
|
||||
return 100.0D;
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.api.exceptions.ValueOutOfBoundsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public interface Probability {
|
||||
/**
|
||||
* A Probability that always fails.
|
||||
*/
|
||||
Probability ALWAYS_FAILS = () -> 0;
|
||||
|
||||
/**
|
||||
* A Probability that always succeeds.
|
||||
*/
|
||||
Probability ALWAYS_SUCCEEDS = () -> 1;
|
||||
|
||||
/**
|
||||
* The value of this Probability
|
||||
* Should return a result between 0 and 1 (inclusive)
|
||||
|
@ -17,19 +28,40 @@ public interface Probability {
|
|||
double getValue();
|
||||
|
||||
/**
|
||||
* Create a new Probability with the given value
|
||||
* A value of 100 would represent 100% chance of success
|
||||
* A value of 50 would represent 50% chance of success
|
||||
* A value of 0 would represent 0% chance of success
|
||||
* A value of 1 would represent 1% chance of success
|
||||
* A value of 0.5 would represent 0.5% chance of success
|
||||
* A value of 0.01 would represent 0.01% chance of success
|
||||
* Create a new Probability of a percentage.
|
||||
* This method takes a percentage and creates a Probability of equivalent odds.
|
||||
*
|
||||
* A value of 100 would represent 100% chance of success,
|
||||
* A value of 50 would represent 50% chance of success,
|
||||
* A value of 0 would represent 0% chance of success,
|
||||
* A value of 1 would represent 1% chance of success,
|
||||
* A value of 0.5 would represent 0.5% chance of success,
|
||||
* A value of 0.01 would represent 0.01% chance of success.
|
||||
*
|
||||
* @param percentage the value of the probability
|
||||
* @return a new Probability with the given value
|
||||
*/
|
||||
static @NotNull Probability ofPercent(double percentage) {
|
||||
return new ProbabilityImpl(percentage);
|
||||
if (percentage < 0) {
|
||||
throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
|
||||
}
|
||||
|
||||
// Convert to a 0-1 floating point representation
|
||||
double probabilityValue = percentage / 100.0D;
|
||||
return new ProbabilityImpl(probabilityValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Probability of a value.
|
||||
* This method takes a value between 0 and 1 and creates a Probability of equivalent odds.
|
||||
* A value of 1 or greater represents something that will always succeed.
|
||||
* A value of around 0.5 represents something that succeeds around half the time.
|
||||
* A value of 0 represents something that will always fail.
|
||||
* @param value the value of the probability
|
||||
* @return a new Probability with the given value
|
||||
*/
|
||||
static @NotNull Probability ofValue(double value) {
|
||||
return new ProbabilityImpl(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,31 +8,22 @@ public class ProbabilityImpl implements Probability {
|
|||
private final double probabilityValue;
|
||||
|
||||
/**
|
||||
* Create a probability with a static value
|
||||
* Create a probability from a static value.
|
||||
* A value of 0 represents a 0% chance of success,
|
||||
* A value of 1 represents a 100% chance of success.
|
||||
* A value of 0.5 represents a 50% chance of success.
|
||||
* A value of 0.01 represents a 1% chance of success.
|
||||
* And so on.
|
||||
*
|
||||
* @param percentage the percentage value of the probability
|
||||
* @param value the value of the probability between 0 and 100
|
||||
*/
|
||||
ProbabilityImpl(double percentage) throws ValueOutOfBoundsException {
|
||||
if (percentage < 0) {
|
||||
throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
|
||||
public ProbabilityImpl(double value) throws ValueOutOfBoundsException {
|
||||
if (value < 0) {
|
||||
throw new ValueOutOfBoundsException("Value should never be negative for Probability!" +
|
||||
" This suggests a coding mistake, contact the devs!");
|
||||
}
|
||||
|
||||
// Convert to a 0-1 floating point representation
|
||||
probabilityValue = percentage / 100.0D;
|
||||
}
|
||||
|
||||
ProbabilityImpl(double xPos, double xCeiling, double probabilityCeiling) throws ValueOutOfBoundsException {
|
||||
if(probabilityCeiling > 100) {
|
||||
throw new ValueOutOfBoundsException("Probability Ceiling should never be above 100!");
|
||||
} else if (probabilityCeiling < 0) {
|
||||
throw new ValueOutOfBoundsException("Probability Ceiling should never be below 0!");
|
||||
}
|
||||
|
||||
//Get the percent success, this will be from 0-100
|
||||
double probabilityPercent = (probabilityCeiling * (xPos / xCeiling));
|
||||
|
||||
//Convert to a 0-1 floating point representation
|
||||
this.probabilityValue = probabilityPercent / 100.0D;
|
||||
probabilityValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -79,24 +79,24 @@ public class ProbabilityUtil {
|
|||
switch (getProbabilityType(subSkillType)) {
|
||||
case DYNAMIC_CONFIGURABLE:
|
||||
double probabilityCeiling;
|
||||
double xCeiling;
|
||||
double xPos;
|
||||
double skillLevel;
|
||||
double maxBonusLevel; // If a skill level is equal to the cap, it has the full probability
|
||||
|
||||
if (player != null) {
|
||||
McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
|
||||
if (mmoPlayer == null) {
|
||||
return Probability.ofPercent(0);
|
||||
}
|
||||
xPos = mmoPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
skillLevel = mmoPlayer.getSkillLevel(subSkillType.getParentSkill());
|
||||
} else {
|
||||
xPos = 0;
|
||||
skillLevel = 0;
|
||||
}
|
||||
|
||||
//Probability ceiling is configurable in this type
|
||||
probabilityCeiling = mcMMO.p.getAdvancedConfig().getMaximumProbability(subSkillType);
|
||||
//The xCeiling is configurable in this type
|
||||
xCeiling = mcMMO.p.getAdvancedConfig().getMaxBonusLevel(subSkillType);
|
||||
return new ProbabilityImpl(xPos, xCeiling, probabilityCeiling);
|
||||
maxBonusLevel = mcMMO.p.getAdvancedConfig().getMaxBonusLevel(subSkillType);
|
||||
return calculateCurrentSkillProbability(skillLevel, 0, probabilityCeiling, maxBonusLevel);
|
||||
case STATIC_CONFIGURABLE:
|
||||
try {
|
||||
return getStaticRandomChance(subSkillType);
|
||||
|
@ -127,22 +127,7 @@ public class ProbabilityUtil {
|
|||
* @return true if the Skill RNG succeeds, false if it fails
|
||||
*/
|
||||
public static boolean isSkillRNGSuccessful(@NotNull SubSkillType subSkillType, @NotNull Player player) {
|
||||
//Process probability
|
||||
Probability probability = getSubSkillProbability(subSkillType, player);
|
||||
|
||||
//Send out event
|
||||
SubSkillEvent subSkillEvent = EventUtils.callSubSkillEvent(player, subSkillType);
|
||||
|
||||
if(subSkillEvent.isCancelled()) {
|
||||
return false; //Event got cancelled so this doesn't succeed
|
||||
}
|
||||
|
||||
//Result modifier
|
||||
double resultModifier = subSkillEvent.getResultModifier();
|
||||
|
||||
//Mutate probability
|
||||
if(resultModifier != 1.0D)
|
||||
probability = Probability.ofPercent(probability.getValue() * resultModifier);
|
||||
final Probability probability = getSkillProbability(subSkillType, player);
|
||||
|
||||
//Luck
|
||||
boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
||||
|
@ -154,12 +139,42 @@ public class ProbabilityUtil {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Probability} for a specific {@link SubSkillType} for a specific {@link Player}.
|
||||
* This does not take into account perks such as lucky for the player.
|
||||
* This is affected by other plugins who can listen to the {@link SubSkillEvent} and cancel it or mutate it.
|
||||
*
|
||||
* @param subSkillType the target subskill
|
||||
* @param player the target player
|
||||
* @return the probability for this skill
|
||||
*/
|
||||
public static Probability getSkillProbability(@NotNull SubSkillType subSkillType, @NotNull Player player) {
|
||||
//Process probability
|
||||
Probability probability = getSubSkillProbability(subSkillType, player);
|
||||
|
||||
//Send out event
|
||||
SubSkillEvent subSkillEvent = EventUtils.callSubSkillEvent(player, subSkillType);
|
||||
|
||||
if(subSkillEvent.isCancelled()) {
|
||||
return Probability.ALWAYS_FAILS;
|
||||
}
|
||||
|
||||
//Result modifier
|
||||
double resultModifier = subSkillEvent.getResultModifier();
|
||||
|
||||
//Mutate probability
|
||||
if(resultModifier != 1.0D)
|
||||
probability = Probability.ofPercent(probability.getValue() * resultModifier);
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is one of several Skill RNG check methods
|
||||
* This helper method is specific to static value RNG, which can be influenced by a player's Luck
|
||||
*
|
||||
* @param primarySkillType the related primary skill
|
||||
* @param player the target player, can be null (null players have the worst odds)
|
||||
* @param player the target player can be null (null players have the worst odds)
|
||||
* @param probabilityPercentage the probability of this player succeeding in "percentage" format (0-100 inclusive)
|
||||
* @return true if the RNG succeeds, false if it fails
|
||||
*/
|
||||
|
@ -223,4 +238,31 @@ public class ProbabilityUtil {
|
|||
|
||||
return new String[]{percent.format(firstValue), percent.format(secondValue)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to calculate what probability a given skill has at a certain level
|
||||
* @param skillLevel the skill level currently between the floor and the ceiling
|
||||
* @param floor the minimum odds this skill can have
|
||||
* @param ceiling the maximum odds this skill can have
|
||||
* @param maxBonusLevel the maximum level this skill can have to reach the ceiling
|
||||
*
|
||||
* @return the probability of success for this skill at this level
|
||||
*/
|
||||
public static Probability calculateCurrentSkillProbability(double skillLevel, double floor,
|
||||
double ceiling, double maxBonusLevel) {
|
||||
// The odds of success are between the value of the floor and the value of the ceiling.
|
||||
// If the skill has a maxBonusLevel of 500 on this skill, then at skill level 500 you would have the full odds,
|
||||
// at skill level 250 it would be half odds.
|
||||
|
||||
if (skillLevel >= maxBonusLevel || maxBonusLevel <= 0) {
|
||||
// Avoid divide by zero bugs
|
||||
// Max benefit has been reached, should always succeed
|
||||
return Probability.ofPercent(ceiling);
|
||||
}
|
||||
|
||||
double odds = (skillLevel / maxBonusLevel) * 100D;
|
||||
|
||||
// make sure the odds aren't lower or higher than the floor or ceiling
|
||||
return Probability.ofPercent(Math.min(Math.max(floor, odds), ceiling));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public final class CombatUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
private static void processTridentCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
||||
private static void processTridentCombatMelee(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
||||
if (event.getCause() == DamageCause.THORNS) {
|
||||
return;
|
||||
}
|
||||
|
@ -127,10 +127,40 @@ public final class CombatUtils {
|
|||
|
||||
TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager();
|
||||
|
||||
if (tridentsManager.canActivateAbility()) {
|
||||
mcMMOPlayer.checkAbilityActivation(PrimarySkillType.TRIDENTS);
|
||||
// if (tridentsManager.canActivateAbility()) {
|
||||
// mcMMOPlayer.checkAbilityActivation(PrimarySkillType.TRIDENTS);
|
||||
// }
|
||||
|
||||
if (SkillUtils.canUseSubskill(player, SubSkillType.TRIDENTS_IMPALE)) {
|
||||
boostedDamage += (tridentsManager.impaleDamageBonus() * mcMMOPlayer.getAttackStrength());
|
||||
}
|
||||
|
||||
if(canUseLimitBreak(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK)) {
|
||||
boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength());
|
||||
}
|
||||
|
||||
event.setDamage(boostedDamage);
|
||||
processCombatXP(mcMMOPlayer, target, PrimarySkillType.TRIDENTS);
|
||||
|
||||
printFinalDamageDebug(player, event, mcMMOPlayer);
|
||||
}
|
||||
|
||||
private static void processTridentCombatRanged(@NotNull Trident trident, @NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
||||
if (event.getCause() == DamageCause.THORNS) {
|
||||
return;
|
||||
}
|
||||
|
||||
double boostedDamage = event.getDamage();
|
||||
|
||||
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||
|
||||
//Make sure the profiles been loaded
|
||||
if(mcMMOPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager();
|
||||
|
||||
if (SkillUtils.canUseSubskill(player, SubSkillType.TRIDENTS_IMPALE)) {
|
||||
boostedDamage += (tridentsManager.impaleDamageBonus() * mcMMOPlayer.getAttackStrength());
|
||||
}
|
||||
|
@ -465,7 +495,7 @@ public final class CombatUtils {
|
|||
}
|
||||
|
||||
if (mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.TRIDENTS)) {
|
||||
processTridentCombat(target, player, event);
|
||||
processTridentCombatMelee(target, player, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,6 +511,17 @@ public final class CombatUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (painSource instanceof Trident trident) {
|
||||
ProjectileSource projectileSource = trident.getShooter();
|
||||
|
||||
if (projectileSource instanceof Player player) {
|
||||
if (!Misc.isNPCEntityExcludingVillagers(player)) {
|
||||
if(mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.TRIDENTS, target)) {
|
||||
processTridentCombatRanged(trident, target, player, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (painSource instanceof Arrow arrow) {
|
||||
ProjectileSource projectileSource = arrow.getShooter();
|
||||
boolean isCrossbow = arrow.isShotFromCrossbow();
|
||||
|
|
|
@ -331,7 +331,7 @@ public class SkillTools {
|
|||
return primarySkillChildrenMap.get(primarySkillType);
|
||||
}
|
||||
|
||||
public double getXpModifier(PrimarySkillType primarySkillType) {
|
||||
public double getXpMultiplier(PrimarySkillType primarySkillType) {
|
||||
return ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.Iterator;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class SkillUtils {
|
||||
/**
|
||||
* This is a static utility class, therefore we don't want any instances of
|
||||
|
|
|
@ -56,18 +56,23 @@ public class TextComponentFactory {
|
|||
return Component.text(text);
|
||||
}
|
||||
|
||||
public static void sendPlayerSubSkillWikiLink(Player player, String subskillformatted) {
|
||||
public static String getSubSkillWikiLink(SubSkillType subSkillType) {
|
||||
return "https://wiki.mcmmo.org/en/skills/"
|
||||
+ subSkillType.getParentSkill().toString().toLowerCase(Locale.ENGLISH) + "#"
|
||||
+ subSkillType.getWikiUrl().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
public static void sendPlayerSubSkillWikiLink(Player player, String subskillformatted, SubSkillType subSkillType) {
|
||||
if (!mcMMO.p.getGeneralConfig().getUrlLinksEnabled())
|
||||
return;
|
||||
|
||||
TextComponent.Builder wikiLinkComponent = Component.text().content(LocaleLoader.getString("Overhaul.mcMMO.MmoInfo.Wiki"));
|
||||
wikiLinkComponent.decoration(TextDecoration.UNDERLINED, true);
|
||||
|
||||
String wikiUrl = "https://wiki.mcmmo.org/" + subskillformatted;
|
||||
final String subSkillWikiLink = getSubSkillWikiLink(subSkillType);
|
||||
wikiLinkComponent.clickEvent(ClickEvent.openUrl(subSkillWikiLink));
|
||||
|
||||
wikiLinkComponent.clickEvent(ClickEvent.openUrl(wikiUrl));
|
||||
|
||||
TextComponent.Builder componentBuilder = Component.text().content(subskillformatted).append(Component.newline()).append(Component.text(wikiUrl)).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true);
|
||||
TextComponent.Builder componentBuilder = Component.text().content(subskillformatted).append(Component.newline()).append(Component.text(subSkillWikiLink)).color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, true);
|
||||
|
||||
wikiLinkComponent.hoverEvent(HoverEvent.showText(componentBuilder.build()));
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# This is meant to be a general config for allowing mcMMO to allow interaction with custom items.
|
||||
# In the future, I would like to add configs to be specific about certain custom items.
|
||||
# For now, support is generalized to whether the custom item has a custom model.
|
||||
# This is an easy solution to implement for now, but not the most ideal.
|
||||
Custom_Item_Support:
|
||||
Repair:
|
||||
# Turn this off to disable repair on any items with custom model data
|
||||
Allow_Repair_On_Items_With_Custom_Model_Data: true
|
||||
Salvage:
|
||||
# Turn this off to disable salvage on any items with custom model data
|
||||
Allow_Salvage_On_Items_With_Custom_Model_Data: true
|
|
@ -423,6 +423,8 @@ Salvage.Skills.Lottery.Perfect=&a&lPerfect!&r&6 You salvaged &3{1}&6 effortlessl
|
|||
Salvage.Skills.Lottery.Untrained=&7You aren't properly trained in salvaging. You were only able to recover &c{0}&7 materials from &a{1}&7.
|
||||
#Anvil (Shared between SALVAGE and REPAIR)
|
||||
Anvil.Unbreakable=This item is unbreakable!
|
||||
Anvil.Repair.Reject.CustomModelData=A mysterious force prevents you from repairing this item...
|
||||
Anvil.Salvage.Reject.CustomModelData=A mysterious force prevents you from salvaging this item...
|
||||
#CROSSBOWS
|
||||
Crossbows.SkillName=CROSSBOWS
|
||||
Crossbows.Ability.Lower=&7You lower your crossbow.
|
||||
|
|
|
@ -1,245 +1,245 @@
|
|||
package com.gmail.nossr50.database;
|
||||
|
||||
import com.gmail.nossr50.config.AdvancedConfig;
|
||||
import com.gmail.nossr50.config.GeneralConfig;
|
||||
import com.gmail.nossr50.datatypes.MobHealthbarType;
|
||||
import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import com.gmail.nossr50.util.skills.SkillTools;
|
||||
import com.gmail.nossr50.util.upgrade.UpgradeManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class SQLDatabaseManagerTest {
|
||||
private final static @NotNull Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||
static MockedStatic<mcMMO> mockedMcMMO;
|
||||
SQLDatabaseManager sqlDatabaseManager;
|
||||
static GeneralConfig generalConfig;
|
||||
static AdvancedConfig advancedConfig;
|
||||
static UpgradeManager upgradeManager;
|
||||
static CompatibilityManager compatibilityManager;
|
||||
static SkillTools skillTools;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpAll() {
|
||||
// stub mcMMO.p
|
||||
mockedMcMMO = Mockito.mockStatic(mcMMO.class);
|
||||
mcMMO.p = Mockito.mock(mcMMO.class);
|
||||
when(mcMMO.p.getLogger()).thenReturn(logger);
|
||||
|
||||
// general config mock
|
||||
mockGeneralConfig();
|
||||
|
||||
// advanced config mock
|
||||
advancedConfig = Mockito.mock(AdvancedConfig.class);
|
||||
when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
|
||||
|
||||
// starting level
|
||||
when(mcMMO.p.getAdvancedConfig().getStartingLevel()).thenReturn(0);
|
||||
|
||||
// wire skill tools
|
||||
skillTools = new SkillTools(mcMMO.p);
|
||||
when(mcMMO.p.getSkillTools()).thenReturn(skillTools);
|
||||
|
||||
// compatibility manager mock
|
||||
compatibilityManager = Mockito.mock(CompatibilityManager.class);
|
||||
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(new MinecraftGameVersion(1, 20, 4));
|
||||
|
||||
// upgrade manager mock
|
||||
upgradeManager = Mockito.mock(UpgradeManager.class);
|
||||
when(mcMMO.getUpgradeManager()).thenReturn(upgradeManager);
|
||||
|
||||
// don't trigger upgrades
|
||||
when(mcMMO.getUpgradeManager().shouldUpgrade(any())).thenReturn(false);
|
||||
}
|
||||
|
||||
private static void mockGeneralConfig() {
|
||||
generalConfig = Mockito.mock(GeneralConfig.class);
|
||||
when(generalConfig.getLocale()).thenReturn("en_US");
|
||||
when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
|
||||
|
||||
// max pool size
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.MISC))
|
||||
.thenReturn(10);
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.LOAD))
|
||||
.thenReturn(20);
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.SAVE))
|
||||
.thenReturn(20);
|
||||
|
||||
// max connections
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.MISC))
|
||||
.thenReturn(30);
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.LOAD))
|
||||
.thenReturn(30);
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.SAVE))
|
||||
.thenReturn(30);
|
||||
|
||||
// table prefix
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLTablePrefix()).thenReturn("mcmmo_");
|
||||
|
||||
// public key retrieval
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLPublicKeyRetrieval()).thenReturn(true);
|
||||
|
||||
// debug
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLDebug()).thenReturn(true);
|
||||
|
||||
// use mysql
|
||||
when(mcMMO.p.getGeneralConfig().getUseMySQL()).thenReturn(true);
|
||||
|
||||
// use ssl
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLSSL()).thenReturn(true);
|
||||
|
||||
// username
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLUserName()).thenReturn("sa");
|
||||
|
||||
// password
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLUserPassword()).thenReturn("");
|
||||
|
||||
// host
|
||||
when(mcMMO.p.getGeneralConfig().getMySQLServerName()).thenReturn("localhost");
|
||||
|
||||
// unused mob health bar thingy
|
||||
when(mcMMO.p.getGeneralConfig().getMobHealthbarDefault()).thenReturn(MobHealthbarType.HEARTS);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
assertNull(sqlDatabaseManager);
|
||||
sqlDatabaseManager = new SQLDatabaseManager(logger, "org.h2.Driver", true);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
sqlDatabaseManager = null;
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDownAll() {
|
||||
mockedMcMMO.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetConnectionMisc() throws Exception {
|
||||
assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.MISC));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetConnectionLoad() throws Exception {
|
||||
assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.LOAD));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetConnectionSave() throws Exception {
|
||||
assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.SAVE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewUser() {
|
||||
Player player = Mockito.mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
when(player.getName()).thenReturn("nossr50");
|
||||
sqlDatabaseManager.newUser(player);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewUserGetSkillLevel() {
|
||||
Player player = Mockito.mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
when(player.getName()).thenReturn("nossr50");
|
||||
PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
assertEquals(0, playerProfile.getSkillLevel(primarySkillType));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewUserGetSkillXpLevel() {
|
||||
Player player = Mockito.mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
when(player.getName()).thenReturn("nossr50");
|
||||
PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveSkillLevelValues() {
|
||||
Player player = Mockito.mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
when(player.getName()).thenReturn("nossr50");
|
||||
PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
|
||||
// Validate values are starting from zero
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
}
|
||||
|
||||
// Change values
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
playerProfile.modifySkill(primarySkillType, 1 + primarySkillType.ordinal());
|
||||
}
|
||||
|
||||
boolean saveSuccess = sqlDatabaseManager.saveUser(playerProfile);
|
||||
assertTrue(saveSuccess);
|
||||
|
||||
PlayerProfile retrievedUser = sqlDatabaseManager.loadPlayerProfile(player.getName());
|
||||
|
||||
// Check that values got saved
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
if (primarySkillType == PrimarySkillType.SALVAGE || primarySkillType == PrimarySkillType.SMELTING) {
|
||||
// Child skills are not saved, but calculated
|
||||
continue;
|
||||
}
|
||||
|
||||
assertEquals(1 + primarySkillType.ordinal(), retrievedUser.getSkillLevel(primarySkillType));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveSkillXpValues() {
|
||||
Player player = Mockito.mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
when(player.getName()).thenReturn("nossr50");
|
||||
PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
|
||||
// Validate values are starting from zero
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
}
|
||||
|
||||
// Change values
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
playerProfile.setSkillXpLevel(primarySkillType, 1 + primarySkillType.ordinal());
|
||||
}
|
||||
|
||||
sqlDatabaseManager.saveUser(playerProfile);
|
||||
|
||||
PlayerProfile retrievedUser = sqlDatabaseManager.loadPlayerProfile(player.getName());
|
||||
|
||||
// Check that values got saved
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
if (primarySkillType == PrimarySkillType.SALVAGE || primarySkillType == PrimarySkillType.SMELTING) {
|
||||
// Child skills are not saved, but calculated
|
||||
continue;
|
||||
}
|
||||
|
||||
assertEquals(1 + primarySkillType.ordinal(), retrievedUser.getSkillXpLevel(primarySkillType));
|
||||
}
|
||||
}
|
||||
}
|
||||
//package com.gmail.nossr50.database;
|
||||
//
|
||||
//import com.gmail.nossr50.config.AdvancedConfig;
|
||||
//import com.gmail.nossr50.config.GeneralConfig;
|
||||
//import com.gmail.nossr50.datatypes.MobHealthbarType;
|
||||
//import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||
//import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
//import com.gmail.nossr50.mcMMO;
|
||||
//import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
//import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
//import com.gmail.nossr50.util.skills.SkillTools;
|
||||
//import com.gmail.nossr50.util.upgrade.UpgradeManager;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.junit.jupiter.api.*;
|
||||
//import org.mockito.MockedStatic;
|
||||
//import org.mockito.Mockito;
|
||||
//
|
||||
//import java.util.logging.Logger;
|
||||
//
|
||||
//import static org.junit.jupiter.api.Assertions.*;
|
||||
//import static org.mockito.ArgumentMatchers.any;
|
||||
//import static org.mockito.Mockito.when;
|
||||
//
|
||||
//class SQLDatabaseManagerTest {
|
||||
// private final static @NotNull Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
||||
// static MockedStatic<mcMMO> mockedMcMMO;
|
||||
// SQLDatabaseManager sqlDatabaseManager;
|
||||
// static GeneralConfig generalConfig;
|
||||
// static AdvancedConfig advancedConfig;
|
||||
// static UpgradeManager upgradeManager;
|
||||
// static CompatibilityManager compatibilityManager;
|
||||
// static SkillTools skillTools;
|
||||
//
|
||||
// @BeforeAll
|
||||
// static void setUpAll() {
|
||||
// // stub mcMMO.p
|
||||
// mockedMcMMO = Mockito.mockStatic(mcMMO.class);
|
||||
// mcMMO.p = Mockito.mock(mcMMO.class);
|
||||
// when(mcMMO.p.getLogger()).thenReturn(logger);
|
||||
//
|
||||
// // general config mock
|
||||
// mockGeneralConfig();
|
||||
//
|
||||
// // advanced config mock
|
||||
// advancedConfig = Mockito.mock(AdvancedConfig.class);
|
||||
// when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
|
||||
//
|
||||
// // starting level
|
||||
// when(mcMMO.p.getAdvancedConfig().getStartingLevel()).thenReturn(0);
|
||||
//
|
||||
// // wire skill tools
|
||||
// skillTools = new SkillTools(mcMMO.p);
|
||||
// when(mcMMO.p.getSkillTools()).thenReturn(skillTools);
|
||||
//
|
||||
// // compatibility manager mock
|
||||
// compatibilityManager = Mockito.mock(CompatibilityManager.class);
|
||||
// when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
// when(compatibilityManager.getMinecraftGameVersion()).thenReturn(new MinecraftGameVersion(1, 20, 4));
|
||||
//
|
||||
// // upgrade manager mock
|
||||
// upgradeManager = Mockito.mock(UpgradeManager.class);
|
||||
// when(mcMMO.getUpgradeManager()).thenReturn(upgradeManager);
|
||||
//
|
||||
// // don't trigger upgrades
|
||||
// when(mcMMO.getUpgradeManager().shouldUpgrade(any())).thenReturn(false);
|
||||
// }
|
||||
//
|
||||
// private static void mockGeneralConfig() {
|
||||
// generalConfig = Mockito.mock(GeneralConfig.class);
|
||||
// when(generalConfig.getLocale()).thenReturn("en_US");
|
||||
// when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
|
||||
//
|
||||
// // max pool size
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.MISC))
|
||||
// .thenReturn(10);
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.LOAD))
|
||||
// .thenReturn(20);
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier.SAVE))
|
||||
// .thenReturn(20);
|
||||
//
|
||||
// // max connections
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.MISC))
|
||||
// .thenReturn(30);
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.LOAD))
|
||||
// .thenReturn(30);
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier.SAVE))
|
||||
// .thenReturn(30);
|
||||
//
|
||||
// // table prefix
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLTablePrefix()).thenReturn("mcmmo_");
|
||||
//
|
||||
// // public key retrieval
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLPublicKeyRetrieval()).thenReturn(true);
|
||||
//
|
||||
// // debug
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLDebug()).thenReturn(true);
|
||||
//
|
||||
// // use mysql
|
||||
// when(mcMMO.p.getGeneralConfig().getUseMySQL()).thenReturn(true);
|
||||
//
|
||||
// // use ssl
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLSSL()).thenReturn(true);
|
||||
//
|
||||
// // username
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLUserName()).thenReturn("sa");
|
||||
//
|
||||
// // password
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLUserPassword()).thenReturn("");
|
||||
//
|
||||
// // host
|
||||
// when(mcMMO.p.getGeneralConfig().getMySQLServerName()).thenReturn("localhost");
|
||||
//
|
||||
// // unused mob health bar thingy
|
||||
// when(mcMMO.p.getGeneralConfig().getMobHealthbarDefault()).thenReturn(MobHealthbarType.HEARTS);
|
||||
// }
|
||||
//
|
||||
// @BeforeEach
|
||||
// void setUp() {
|
||||
// assertNull(sqlDatabaseManager);
|
||||
// sqlDatabaseManager = new SQLDatabaseManager(logger, "org.h2.Driver", true);
|
||||
// }
|
||||
//
|
||||
// @AfterEach
|
||||
// void tearDown() {
|
||||
// sqlDatabaseManager = null;
|
||||
// }
|
||||
//
|
||||
// @AfterAll
|
||||
// static void tearDownAll() {
|
||||
// mockedMcMMO.close();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetConnectionMisc() throws Exception {
|
||||
// assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.MISC));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetConnectionLoad() throws Exception {
|
||||
// assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.LOAD));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetConnectionSave() throws Exception {
|
||||
// assertNotNull(sqlDatabaseManager.getConnection(SQLDatabaseManager.PoolIdentifier.SAVE));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testNewUser() {
|
||||
// Player player = Mockito.mock(Player.class);
|
||||
// when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
// when(player.getName()).thenReturn("nossr50");
|
||||
// sqlDatabaseManager.newUser(player);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testNewUserGetSkillLevel() {
|
||||
// Player player = Mockito.mock(Player.class);
|
||||
// when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
// when(player.getName()).thenReturn("nossr50");
|
||||
// PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
//
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// assertEquals(0, playerProfile.getSkillLevel(primarySkillType));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testNewUserGetSkillXpLevel() {
|
||||
// Player player = Mockito.mock(Player.class);
|
||||
// when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
// when(player.getName()).thenReturn("nossr50");
|
||||
// PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
//
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testSaveSkillLevelValues() {
|
||||
// Player player = Mockito.mock(Player.class);
|
||||
// when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
// when(player.getName()).thenReturn("nossr50");
|
||||
// PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
//
|
||||
// // Validate values are starting from zero
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
// }
|
||||
//
|
||||
// // Change values
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// playerProfile.modifySkill(primarySkillType, 1 + primarySkillType.ordinal());
|
||||
// }
|
||||
//
|
||||
// boolean saveSuccess = sqlDatabaseManager.saveUser(playerProfile);
|
||||
// assertTrue(saveSuccess);
|
||||
//
|
||||
// PlayerProfile retrievedUser = sqlDatabaseManager.loadPlayerProfile(player.getName());
|
||||
//
|
||||
// // Check that values got saved
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// if (primarySkillType == PrimarySkillType.SALVAGE || primarySkillType == PrimarySkillType.SMELTING) {
|
||||
// // Child skills are not saved, but calculated
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// assertEquals(1 + primarySkillType.ordinal(), retrievedUser.getSkillLevel(primarySkillType));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testSaveSkillXpValues() {
|
||||
// Player player = Mockito.mock(Player.class);
|
||||
// when(player.getUniqueId()).thenReturn(java.util.UUID.randomUUID());
|
||||
// when(player.getName()).thenReturn("nossr50");
|
||||
// PlayerProfile playerProfile = sqlDatabaseManager.newUser(player);
|
||||
//
|
||||
// // Validate values are starting from zero
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// assertEquals(0, playerProfile.getSkillXpLevel(primarySkillType));
|
||||
// }
|
||||
//
|
||||
// // Change values
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// playerProfile.setSkillXpLevel(primarySkillType, 1 + primarySkillType.ordinal());
|
||||
// }
|
||||
//
|
||||
// sqlDatabaseManager.saveUser(playerProfile);
|
||||
//
|
||||
// PlayerProfile retrievedUser = sqlDatabaseManager.loadPlayerProfile(player.getName());
|
||||
//
|
||||
// // Check that values got saved
|
||||
// for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
// if (primarySkillType == PrimarySkillType.SALVAGE || primarySkillType == PrimarySkillType.SMELTING) {
|
||||
// // Child skills are not saved, but calculated
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// assertEquals(1 + primarySkillType.ordinal(), retrievedUser.getSkillXpLevel(primarySkillType));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
|
@ -73,8 +73,9 @@ class WoodcuttingTest extends MMOTestEnvironment {
|
|||
woodcuttingManager.processBonusDropCheck(blockState);
|
||||
|
||||
// verify bonus drops were spawned
|
||||
// TODO: Can fail if triple drops happen, need to update test
|
||||
Mockito.verify(woodcuttingManager, Mockito.times(1)).spawnHarvestLumberBonusDrops(blockState);
|
||||
// TODO: using at least once since triple drops can also happen
|
||||
// TODO: Change the test env to disallow triple drop in the future
|
||||
Mockito.verify(woodcuttingManager, Mockito.atLeastOnce()).spawnHarvestLumberBonusDrops(blockState);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -14,19 +14,19 @@ class ProbabilityTest {
|
|||
private static Stream<Arguments> provideProbabilitiesForWithinExpectations() {
|
||||
return Stream.of(
|
||||
// static probability, % of time for success
|
||||
Arguments.of(new ProbabilityImpl(5), 5),
|
||||
Arguments.of(new ProbabilityImpl(10), 10),
|
||||
Arguments.of(new ProbabilityImpl(15), 15),
|
||||
Arguments.of(new ProbabilityImpl(20), 20),
|
||||
Arguments.of(new ProbabilityImpl(25), 25),
|
||||
Arguments.of(new ProbabilityImpl(50), 50),
|
||||
Arguments.of(new ProbabilityImpl(75), 75),
|
||||
Arguments.of(new ProbabilityImpl(90), 90),
|
||||
Arguments.of(new ProbabilityImpl(99.9), 99.9),
|
||||
Arguments.of(new ProbabilityImpl(0.05), 0.05),
|
||||
Arguments.of(new ProbabilityImpl(0.1), 0.1),
|
||||
Arguments.of(new ProbabilityImpl(500), 100),
|
||||
Arguments.of(new ProbabilityImpl(1000), 100)
|
||||
Arguments.of(new ProbabilityImpl(.05), 5),
|
||||
Arguments.of(new ProbabilityImpl(.10), 10),
|
||||
Arguments.of(new ProbabilityImpl(.15), 15),
|
||||
Arguments.of(new ProbabilityImpl(.20), 20),
|
||||
Arguments.of(new ProbabilityImpl(.25), 25),
|
||||
Arguments.of(new ProbabilityImpl(.50), 50),
|
||||
Arguments.of(new ProbabilityImpl(.75), 75),
|
||||
Arguments.of(new ProbabilityImpl(.90), 90),
|
||||
Arguments.of(new ProbabilityImpl(.999), 99.9),
|
||||
Arguments.of(new ProbabilityImpl(0.0005), 0.05),
|
||||
Arguments.of(new ProbabilityImpl(0.001), 0.1),
|
||||
Arguments.of(new ProbabilityImpl(50.0), 100),
|
||||
Arguments.of(new ProbabilityImpl(100.0), 100)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ProbabilityTestUtils {
|
||||
public static void assertProbabilityExpectations(double expectedWinPercent, Probability probability) {
|
||||
double iterations = 2.0e7; //20 million
|
||||
double winCount = 0;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if(probability.evaluate()) {
|
||||
winCount++;
|
||||
}
|
||||
}
|
||||
|
||||
double successPercent = (winCount / iterations) * 100;
|
||||
System.out.println("Wins: " + winCount);
|
||||
System.out.println("Fails: " + (iterations - winCount));
|
||||
System.out.println("Percentage succeeded: " + successPercent + ", Expected: " + expectedWinPercent);
|
||||
assertEquals(expectedWinPercent, successPercent, 0.025D);
|
||||
System.out.println("Variance is within tolerance levels!");
|
||||
}
|
||||
}
|
|
@ -1,39 +1,44 @@
|
|||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.config.AdvancedConfig;
|
||||
import com.gmail.nossr50.MMOTestEnvironment;
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gmail.nossr50.datatypes.skills.SubSkillType.*;
|
||||
import static com.gmail.nossr50.util.random.ProbabilityTestUtils.assertProbabilityExpectations;
|
||||
import static com.gmail.nossr50.util.random.ProbabilityUtil.calculateCurrentSkillProbability;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class ProbabilityUtilTest {
|
||||
mcMMO mmoInstance;
|
||||
AdvancedConfig advancedConfig;
|
||||
class ProbabilityUtilTest extends MMOTestEnvironment {
|
||||
private static final Logger logger = getLogger(ProbabilityUtilTest.class.getName());
|
||||
|
||||
final static double impactChance = 11D;
|
||||
final static double greaterImpactChance = 0.007D;
|
||||
final static double fastFoodChance = 45.5D;
|
||||
|
||||
@BeforeEach
|
||||
public void setupMocks() throws NoSuchFieldException, IllegalAccessException {
|
||||
this.mmoInstance = mock(mcMMO.class);
|
||||
mcMMO.class.getField("p").set(null, mmoInstance);
|
||||
this.advancedConfig = mock(AdvancedConfig.class);
|
||||
when(mmoInstance.getAdvancedConfig()).thenReturn(advancedConfig);
|
||||
public void setupMocks() {
|
||||
mockBaseEnvironment(logger);
|
||||
when(advancedConfig.getImpactChance()).thenReturn(impactChance);
|
||||
when(advancedConfig.getGreaterImpactChance()).thenReturn(greaterImpactChance);
|
||||
when(advancedConfig.getFastFoodChance()).thenReturn(fastFoodChance);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
cleanupBaseEnvironment();
|
||||
}
|
||||
|
||||
private static Stream<Arguments> staticChanceSkills() {
|
||||
return Stream.of(
|
||||
// static probability, % of time for success
|
||||
|
@ -45,22 +50,26 @@ class ProbabilityUtilTest {
|
|||
|
||||
@ParameterizedTest
|
||||
@MethodSource("staticChanceSkills")
|
||||
void testStaticChanceSkills(SubSkillType subSkillType, double expectedWinPercent) throws InvalidStaticChance {
|
||||
void staticChanceSkillsShouldSucceedAsExpected(SubSkillType subSkillType, double expectedWinPercent)
|
||||
throws InvalidStaticChance {
|
||||
Probability staticRandomChance = ProbabilityUtil.getStaticRandomChance(subSkillType);
|
||||
assertProbabilityExpectations(expectedWinPercent, staticRandomChance);
|
||||
}
|
||||
|
||||
private static void assertProbabilityExpectations(double expectedWinPercent, Probability probability) {
|
||||
double iterations = 2.0e7;
|
||||
double winCount = 0;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
if(probability.evaluate()) {
|
||||
winCount++;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void isSkillRNGSuccessfulShouldBehaveAsExpected() {
|
||||
// Given
|
||||
when(advancedConfig.getMaximumProbability(UNARMED_ARROW_DEFLECT)).thenReturn(20D);
|
||||
when(advancedConfig.getMaxBonusLevel(UNARMED_ARROW_DEFLECT)).thenReturn(0);
|
||||
|
||||
double successPercent = (winCount / iterations) * 100;
|
||||
System.out.println(successPercent + ", " + expectedWinPercent);
|
||||
assertEquals(expectedWinPercent, successPercent, 0.05D);
|
||||
final Probability probability = ProbabilityUtil.getSkillProbability(UNARMED_ARROW_DEFLECT, player);
|
||||
assertEquals(0.2D, probability.getValue());
|
||||
assertProbabilityExpectations(20, probability);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateCurrentSkillProbabilityShouldBeTwenty() {
|
||||
final Probability probability = calculateCurrentSkillProbability(1000, 0, 20, 1000);
|
||||
assertEquals(0.2D, probability.getValue());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue