mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2025-11-18 06:24:17 +01:00
Merge branch 'master' into sao
This commit is contained in:
commit
a803716bec
@ -94,17 +94,18 @@
|
||||
<url>https://maven.enginehub.org/repo/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>https://repo.dmulloy2.net/repository/public/</url>
|
||||
</repository>
|
||||
|
||||
<!-- Party and Friends Repository -->
|
||||
<repository>
|
||||
<id>simonsators Repo</id>
|
||||
<url>https://simonsator.de/repo</url>
|
||||
</repository>
|
||||
|
||||
<!-- Quests (plugin) -->
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<!-- Heroes Repository
|
||||
<repository>
|
||||
<id>herocraft</id>
|
||||
@ -227,9 +228,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<groupId>net.dmulloy2</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<version>5.4.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@ -325,9 +326,9 @@
|
||||
|
||||
<!-- Quest Plugins -->
|
||||
<dependency>
|
||||
<groupId>me.blackvein</groupId>
|
||||
<artifactId>Quests</artifactId>
|
||||
<version>4.4.1-b340</version>
|
||||
<groupId>me.pikamug.quests</groupId>
|
||||
<artifactId>quests-core</artifactId>
|
||||
<version>5.2.7</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@ -725,7 +725,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
||||
* @return Experience needed in order to reach next level
|
||||
*/
|
||||
public long getLevelUpExperience() {
|
||||
return getProfess().getExpCurve().getExperience(getLevel() + 1);
|
||||
return getProfess().getExpCurve().getExperience(this, getLevel());
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
@ -752,7 +752,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
||||
|
||||
public void giveLevels(int value, @NotNull EXPSource source) {
|
||||
long equivalentExp = 0;
|
||||
while (value-- > 0) equivalentExp += getProfess().getExpCurve().getExperience(getLevel() + value + 1);
|
||||
while (value-- > 0) equivalentExp += getProfess().getExpCurve().getExperience(this, getLevel() + value);
|
||||
giveExperience(equivalentExp, source);
|
||||
}
|
||||
|
||||
@ -1088,7 +1088,7 @@ public class PlayerData extends SynchronizedDataHolder implements OfflinePlayerD
|
||||
* Loop for exp overload when leveling up, will continue
|
||||
* looping until exp is 0 or max currentLevel has been reached
|
||||
*/
|
||||
while (experience >= (experienceNeeded = getProfess().getExpCurve().getExperience(newLevel + 1))) {
|
||||
while (experience >= (experienceNeeded = getProfess().getExpCurve().getExperience(this, newLevel))) {
|
||||
|
||||
if (maxLevel > 0 && newLevel >= maxLevel) {
|
||||
experience = 0;
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
package net.Indyuce.mmocore.api.player.attribute;
|
||||
|
||||
import io.lumine.mythic.lib.api.stat.StatInstance;
|
||||
import io.lumine.mythic.lib.api.stat.handler.StatHandler;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
/**
|
||||
* This fixes an issue where registering new stat modifiers in ML
|
||||
* to add extra attribute points does NOT update the stats granted
|
||||
* by the attribute.
|
||||
* <p>
|
||||
* This stat handler MAY call subsequent stat handlers. There might
|
||||
* be infinite recursion problems if another attr. grants extra attribute pts.
|
||||
*/
|
||||
public class MMOCoreAttributeStatHandler extends StatHandler {
|
||||
private final PlayerAttribute attr;
|
||||
|
||||
public MMOCoreAttributeStatHandler(ConfigurationSection config, PlayerAttribute attr) {
|
||||
super(config, "ADDITIONAL_" + attr.getId().toUpperCase().replace("-", "_"));
|
||||
|
||||
this.attr = attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called on login but the MMOCore playerData
|
||||
* is not loaded yet, hence the try/catch clause
|
||||
*/
|
||||
@Override
|
||||
public void runUpdate(StatInstance instance) {
|
||||
try {
|
||||
final PlayerData playerData = PlayerData.get(instance.getMap().getPlayerData());
|
||||
playerData.getAttributes().getInstance(attr).updateStats();
|
||||
} catch (NullPointerException exception) {
|
||||
// Player data is not loaded yet so there's nothing to update.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import org.bukkit.Location;
|
||||
@ -84,7 +84,7 @@ public class PlayerAttribute implements ExperienceObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
public @NotNull String getKey() {
|
||||
return "attribute:" + getId().replace("-", "_");
|
||||
}
|
||||
|
||||
@ -99,9 +99,9 @@ public class PlayerAttribute implements ExperienceObject {
|
||||
return expTable != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ExpCurve getExpCurve() {
|
||||
public ExperienceCurve getExpCurve() {
|
||||
throw new RuntimeException("Attributes don't have experience");
|
||||
}
|
||||
|
||||
|
||||
@ -25,8 +25,8 @@ import net.Indyuce.mmocore.api.player.profess.resource.ResourceRegeneration;
|
||||
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
|
||||
import net.Indyuce.mmocore.player.stats.StatInfo;
|
||||
@ -59,7 +59,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
||||
private final ManaDisplayOptions manaDisplay;
|
||||
|
||||
@NotNull
|
||||
private final ExpCurve expCurve;
|
||||
private final ExperienceCurve expCurve;
|
||||
|
||||
@Nullable
|
||||
private final ExperienceTable expTable;
|
||||
@ -111,10 +111,14 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
||||
actionBarFormat = config.contains("action-bar") ? config.getString("action-bar") : null;
|
||||
|
||||
// Exp curve
|
||||
expCurve = config.contains("exp-curve")
|
||||
? MMOCore.plugin.experience.getCurveOrThrow(
|
||||
config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
|
||||
: ExpCurve.DEFAULT;
|
||||
ExperienceCurve expCurve = ExperienceCurve.DEFAULT;
|
||||
try {
|
||||
expCurve = ExperienceCurve.fromConfig(config.getString("exp-curve"));
|
||||
} catch (Throwable exception) {
|
||||
MMOCore.log(Level.WARNING, "Could not load exp curve from class '" + id + "': " + exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
this.expCurve = expCurve;
|
||||
|
||||
// Main exp table
|
||||
ExperienceTable expTable = null;
|
||||
@ -261,7 +265,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
||||
manaDisplay = ManaDisplayOptions.DEFAULT;
|
||||
maxLevel = 0;
|
||||
displayOrder = 0;
|
||||
expCurve = ExpCurve.DEFAULT;
|
||||
expCurve = ExperienceCurve.DEFAULT;
|
||||
expTable = null;
|
||||
comboMap = null;
|
||||
castParticle = new CastingParticle(VParticle.INSTANT_EFFECT.get());
|
||||
@ -282,7 +286,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
public @NotNull String getKey() {
|
||||
return "class_" + getId();
|
||||
}
|
||||
|
||||
@ -315,7 +319,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ExpCurve getExpCurve() {
|
||||
public @NotNull ExperienceCurve getExpCurve() {
|
||||
return expCurve;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ public class InfoCommandTreeNode extends CommandTreeNode {
|
||||
for (Profession profession : MMOCore.plugin.professionManager.getAll())
|
||||
sender.sendMessage(
|
||||
ChatColor.YELLOW + profession.getName() + ": Lvl " + ChatColor.GOLD + playerData.getCollectionSkills().getLevel(profession)
|
||||
+ ChatColor.YELLOW + " - " + ChatColor.GOLD + playerData.getCollectionSkills().getExperience(profession)
|
||||
+ ChatColor.YELLOW + " - " + ChatColor.GOLD + MythicLib.plugin.getMMOConfig().decimal.format(playerData.getCollectionSkills().getExperience(profession))
|
||||
+ ChatColor.YELLOW + " / " + ChatColor.GOLD + playerData.getCollectionSkills().getLevelUpExperience(profession));
|
||||
sender.sendMessage(ChatColor.YELLOW + "----------------------------------------------------");
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
@ -200,14 +200,24 @@ public class RPGPlaceholders extends PlaceholderExpansion {
|
||||
if (playerData.hasSkillBound(slot))
|
||||
return Double.toString(playerData.getCooldownMap().getCooldown(playerData.getBoundSkill(slot)));
|
||||
else return MMOCore.plugin.configManager.noSkillBoundPlaceholder;
|
||||
} else if (identifier.startsWith("profession_experience_"))
|
||||
}
|
||||
|
||||
// Current exp in profession
|
||||
else if (identifier.startsWith("profession_experience_")) {
|
||||
return MythicLib.plugin.getMMOConfig().decimal.format(
|
||||
playerData.getCollectionSkills().getExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
|
||||
}
|
||||
|
||||
else if (identifier.startsWith("profession_next_level_"))
|
||||
return String.valueOf(PlayerData.get(player).getCollectionSkills()
|
||||
.getLevelUpExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
|
||||
// Exp needed to level up profession
|
||||
else if (identifier.startsWith("profession_next_level_")) {
|
||||
final var professionId = identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase();
|
||||
final @Nullable var profession = MMOCore.plugin.professionManager.get(professionId);
|
||||
if (profession == null) return "{profession_not_found}";
|
||||
final var professionLevel = playerData.getCollectionSkills().getLevel(profession);
|
||||
return String.valueOf(profession.getExpCurve().getExperience(playerData, professionLevel));
|
||||
}
|
||||
|
||||
// Number of online members in party
|
||||
else if (identifier.startsWith("party_count")) {
|
||||
final @Nullable AbstractParty party = playerData.getParty();
|
||||
return party == null ? "0" : String.valueOf(party.countMembers());
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
package net.Indyuce.mmocore.experience;
|
||||
|
||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ExpCurve {
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Experience needed to level up. Different professions or classes can have
|
||||
* different exp curves so that it is easier to balance.
|
||||
*/
|
||||
private final List<Long> experience = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Purely arbitrary but MMOCore needs a default exp curve for everything
|
||||
* otherwise there might be divisions by 0 when trying to update the vanilla
|
||||
* exp bar which requires a 0.0 -> 1.0 float as parameter.
|
||||
*
|
||||
* See {@link PlayerData#refreshVanillaExp()}
|
||||
*/
|
||||
public static final ExpCurve DEFAULT = new ExpCurve("default", 100, 200, 300, 400, 500);
|
||||
|
||||
/**
|
||||
* Reads an exp curve from a text file, one line after the other. Each exp
|
||||
* value has to be the only thing written on every line
|
||||
*
|
||||
* @param file Text file to read data from
|
||||
*/
|
||||
public ExpCurve(File file) {
|
||||
this.id = file.getName().replace(".txt", "").toLowerCase().replace("_", "-").replace(" ", "-");
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String readLine;
|
||||
while ((readLine = reader.readLine()) != null)
|
||||
experience.add(Long.valueOf(readLine));
|
||||
reader.close();
|
||||
|
||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||
} catch(Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor for external plugins
|
||||
*
|
||||
* @param id Some unique identifier to let other plugin features refer
|
||||
* to your exp curve.
|
||||
* @param values The exp values, at to be at least one or the constructor
|
||||
* will throw an error
|
||||
*/
|
||||
public ExpCurve(String id, long... values) {
|
||||
this.id = id;
|
||||
for (long value : values)
|
||||
experience.add(value);
|
||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param level Level being reached by some player
|
||||
* @return Experience needed to reach provided level. The level serves
|
||||
* an index for a list checkup. If the level is higher than
|
||||
* the list size, it just returns the last value of the list
|
||||
*/
|
||||
public long getExperience(int level) {
|
||||
Validate.isTrue(level > 0, "Level must be stricly positive");
|
||||
return experience.get(Math.min(level, experience.size()) - 1);
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
package net.Indyuce.mmocore.experience;
|
||||
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* General implementation for professions, classes and attributes.
|
||||
@ -17,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public interface ExperienceObject extends ExperienceDispenser {
|
||||
|
||||
@NotNull
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
@ -24,14 +25,14 @@ public interface ExperienceObject extends ExperienceDispenser {
|
||||
*
|
||||
* @return Exp curve of that object
|
||||
*/
|
||||
@Nullable
|
||||
ExpCurve getExpCurve();
|
||||
@NotNull
|
||||
ExperienceCurve getExpCurve();
|
||||
|
||||
/**
|
||||
* Should throw an error if called when
|
||||
* {@link #hasExperienceTable()} returns false
|
||||
* Throws an exception no experience table
|
||||
*
|
||||
* @return Table read when leveling up
|
||||
* @see #hasExperienceTable()
|
||||
*/
|
||||
@NotNull
|
||||
ExperienceTable getExperienceTable();
|
||||
|
||||
@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
|
||||
public class PlayerProfessions {
|
||||
private final Map<String, Double> exp = new HashMap<>();
|
||||
@ -120,11 +121,14 @@ public class PlayerProfessions {
|
||||
}
|
||||
|
||||
public long getLevelUpExperience(Profession profession) {
|
||||
return profession.getExpCurve().getExperience(getLevel(profession) + 1);
|
||||
return profession.getExpCurve().getExperience(playerData, getLevel(profession));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long getLevelUpExperience(String id) {
|
||||
return MMOCore.plugin.professionManager.has(id) ? MMOCore.plugin.professionManager.get(id).getExpCurve().getExperience(getLevel(id) + 1) : 0;
|
||||
final var prof = MMOCore.plugin.professionManager.get(id);
|
||||
if (prof == null) return 0;
|
||||
return prof.getExpCurve().getExperience(null, getLevel(id));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ -132,6 +136,12 @@ public class PlayerProfessions {
|
||||
setLevel(profession, value, PlayerLevelChangeEvent.Reason.UNKNOWN);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void takeLevels(@NotNull Profession profession, int value) {
|
||||
int current = Math.max(1, level.getOrDefault(profession.getId(), 1));
|
||||
level.put(profession.getId(), Math.max(1, current - value));
|
||||
}
|
||||
|
||||
public void setLevel(@NotNull Profession profession, int newLevel, @NotNull PlayerLevelChangeEvent.Reason reason) {
|
||||
if (profession.hasMaxLevel()) newLevel = Math.min(profession.getMaxLevel(), newLevel);
|
||||
final var previousValue = level.put(profession.getId(), Math.max(1, newLevel));
|
||||
@ -146,12 +156,6 @@ public class PlayerProfessions {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void takeLevels(@NotNull Profession profession, int value) {
|
||||
int current = Math.max(1, level.getOrDefault(profession.getId(), 1));
|
||||
level.put(profession.getId(), Math.max(1, current - value));
|
||||
}
|
||||
|
||||
public void setExperience(Profession profession, double value) {
|
||||
exp.put(profession.getId(), value);
|
||||
}
|
||||
@ -159,7 +163,8 @@ public class PlayerProfessions {
|
||||
public void giveLevels(Profession profession, int value, EXPSource source) {
|
||||
long equivalentExp = 0;
|
||||
final var currentLevel = getLevel(profession);
|
||||
while (value-- > 0) equivalentExp += profession.getExpCurve().getExperience(currentLevel + value + 1);
|
||||
while (value-- > 0)
|
||||
equivalentExp += profession.getExpCurve().getExperience(playerData, currentLevel + value);
|
||||
giveExperience(profession, equivalentExp, source);
|
||||
}
|
||||
|
||||
@ -171,6 +176,8 @@ public class PlayerProfessions {
|
||||
giveExperience(profession, value, source, null, true);
|
||||
}
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
public void giveExperience(@NotNull Profession profession, double value, @NotNull EXPSource source, @Nullable Location hologramLocation, boolean splitExp) {
|
||||
Validate.isTrue(playerData.isOnline(), "Cannot give experience to offline player");
|
||||
if (value <= 0) {
|
||||
@ -200,8 +207,11 @@ public class PlayerProfessions {
|
||||
if (event.isCancelled()) return;
|
||||
|
||||
// Display hologram
|
||||
if (hologramLocation != null && profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS))
|
||||
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
|
||||
if (hologramLocation != null && profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS)) {
|
||||
// TODO custom location per profession/exp source.
|
||||
hologramLocation.add(.5 + .7 * RANDOM.nextDouble(), 1.3 + RANDOM.nextDouble() / 3, .5 + .7 * RANDOM.nextDouble());
|
||||
MMOCoreUtils.displayIndicator(hologramLocation, Language.EXP_HOLOGRAM.getFormat().replace("{exp}", MythicLib.plugin.getMMOConfig().decimal.format(event.getExperience())));
|
||||
}
|
||||
|
||||
final var maxLevel = profession.getMaxLevel();
|
||||
var currentExp = Math.max(0d, exp.getOrDefault(profession.getId(), 0d) + event.getExperience());
|
||||
@ -213,7 +223,7 @@ public class PlayerProfessions {
|
||||
* Loop for exp overload when leveling up, will continue
|
||||
* looping until exp is 0 or max newLevel has been reached
|
||||
*/
|
||||
while (currentExp >= (experienceNeeded = profession.getExpCurve().getExperience(newLevel))) {
|
||||
while (currentExp >= (experienceNeeded = profession.getExpCurve().getExperience(playerData, newLevel))) {
|
||||
|
||||
if (maxLevel > 0 && newLevel >= maxLevel) {
|
||||
currentExp = 0;
|
||||
|
||||
@ -6,6 +6,7 @@ import io.lumine.mythic.lib.util.PreloadedObject;
|
||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.util.formula.ScalingFormula;
|
||||
import org.bukkit.Location;
|
||||
@ -22,7 +23,8 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
||||
private final String id, name;
|
||||
private final int maxLevel;
|
||||
private final Map<ProfessionOption, Boolean> options = new HashMap<>();
|
||||
private final ExpCurve expCurve;
|
||||
@NotNull
|
||||
private final ExperienceCurve expCurve;
|
||||
private final ExperienceTable expTable;
|
||||
|
||||
/**
|
||||
@ -44,9 +46,7 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
||||
this.name = config.getString("name");
|
||||
Validate.notNull(name, "Could not load name");
|
||||
|
||||
expCurve = config.contains("exp-curve")
|
||||
? MMOCore.plugin.experience.getCurveOrThrow(config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
|
||||
: ExpCurve.DEFAULT;
|
||||
expCurve = ExperienceCurve.fromConfig(config.getString("exp-curve"));
|
||||
experience = ScalingFormula.fromConfig(config.get("experience"));
|
||||
|
||||
ExperienceTable expTable = null;
|
||||
@ -99,12 +99,12 @@ public class Profession implements ExperienceObject, PreloadedObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
public @NotNull String getKey() {
|
||||
return "profession_" + getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpCurve getExpCurve() {
|
||||
public @NotNull ExperienceCurve getExpCurve() {
|
||||
return expCurve;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package net.Indyuce.mmocore.experience.curve;
|
||||
|
||||
import io.lumine.mythic.lib.util.FileUtils;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ExperienceCurve {
|
||||
|
||||
/**
|
||||
* Arbitrary values. MMOCore needs a default exp curve for everything otherwise
|
||||
* it would be swarming be divisions by 0 when trying to update the vanilla
|
||||
* exp bar which requires a 0.0 -> 1.0 float as parameter.
|
||||
* <p>
|
||||
* See {@link PlayerData#refreshVanillaExp()}
|
||||
*/
|
||||
public static final ExperienceCurve DEFAULT = new ListExperienceCurve(100, 200, 300, 400, 500);
|
||||
|
||||
/**
|
||||
* If 1 is provided as level, this method returns the experience needed
|
||||
* to reach level 2. If the exp curve is a formula, it will provide 1 to the formula.
|
||||
* If the exp curve is a list, it will return the first element of the list.
|
||||
*
|
||||
* @param player Player leveling up
|
||||
* @param level Current level of the player.
|
||||
* @return Experience needed to reach the next level.
|
||||
*/
|
||||
public long getExperience(@NotNull PlayerData player, int level);
|
||||
|
||||
@NotNull
|
||||
public static ExperienceCurve fromConfig(@Nullable String configInput) {
|
||||
|
||||
// [BACKWARDS COMPATIBILITY] Load from predefined file
|
||||
try {
|
||||
if (configInput == null) throw new RuntimeException();
|
||||
final var expCurveFile = FileUtils.getFile(MMOCore.plugin, "expcurves/" + configInput + ".txt");
|
||||
return new ListExperienceCurve(expCurveFile);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
if (configInput == null) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
// Load from file
|
||||
else if (configInput.endsWith(".txt")) {
|
||||
final var expCurveFile = FileUtils.getFile(MMOCore.plugin, configInput);
|
||||
return new ListExperienceCurve(expCurveFile);
|
||||
}
|
||||
|
||||
// Load as formula
|
||||
else {
|
||||
return new FormulaExperienceCurve(configInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package net.Indyuce.mmocore.experience.curve;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.util.formula.NumericalExpression;
|
||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FormulaExperienceCurve implements ExperienceCurve {
|
||||
private final String formula;
|
||||
|
||||
public FormulaExperienceCurve(@NotNull String formula) {
|
||||
this.formula = formula;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExperience(@NotNull PlayerData player, int level) {
|
||||
try {
|
||||
Validate.isTrue(level > 0, "Level must be stricly positive, got " + level);
|
||||
final var parsed = MythicLib.plugin.getPlaceholderParser().parse(player.getPlayer(), this.formula);
|
||||
final var value = (int) NumericalExpression.eval(parsed.replace("{level}", String.valueOf(level)));
|
||||
Validate.isTrue(value > 0, "Exp curve must return a positive value, got " + value);
|
||||
return value;
|
||||
|
||||
} catch (Exception e) {
|
||||
MythicLib.plugin.getLogger().warning("Error parsing exp formula '" + this.formula + "' for player " + player.getPlayer().getName() + ", using 100: " + e.getMessage());
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package net.Indyuce.mmocore.experience.curve;
|
||||
|
||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ListExperienceCurve implements ExperienceCurve {
|
||||
|
||||
/**
|
||||
* Experience needed to level up. At index i, experience needed
|
||||
* to level up from level N to (N + 1).
|
||||
*/
|
||||
private final List<Long> experience;
|
||||
|
||||
/**
|
||||
* Reads an exp curve from a text file, one line after the other. Each
|
||||
* exp value has to be the only thing written on every line
|
||||
*
|
||||
* @param file Text file to read data from
|
||||
*/
|
||||
public ListExperienceCurve(@NotNull File file) {
|
||||
this.experience = new ArrayList<>();
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String readLine;
|
||||
while ((readLine = reader.readLine()) != null)
|
||||
experience.add(Long.valueOf(readLine));
|
||||
reader.close();
|
||||
|
||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exp curve with specific level up exp values
|
||||
*
|
||||
* @param values The exp values. There has to be at least one
|
||||
*/
|
||||
public ListExperienceCurve(long... values) {
|
||||
this.experience = new ArrayList<>(values.length);
|
||||
for (long value : values) experience.add(value);
|
||||
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExperience(@NotNull PlayerData player, int level) {
|
||||
Validate.isTrue(level > 0, "Level must be stricly positive");
|
||||
return experience.get(Math.min(level, experience.size()));
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.inventory.CraftItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CraftItemExperienceSource extends SpecificExperienceSource<Material> {
|
||||
@ -45,7 +46,7 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
|
||||
|
||||
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
|
||||
|
||||
/**
|
||||
/*
|
||||
* This makes sure that the crafting recipe was performed correctly.
|
||||
*
|
||||
* In some scenarii, the CraftItemEvent (which is only a click event
|
||||
@ -62,27 +63,32 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
|
||||
* - https://git.lumine.io/mythiccraft/mmocore/-/issues/102
|
||||
* - https://www.spigotmc.org/threads/how-to-get-amount-of-item-crafted.377598/
|
||||
*/
|
||||
final int index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
|
||||
final int oldAmount = event.getInventory().getMatrix()[index].getAmount();
|
||||
final int itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
|
||||
final Material resultType = event.getInventory().getResult().getType();
|
||||
final var index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
|
||||
final var oldItem = event.getInventory().getMatrix()[index];
|
||||
final var oldAmount = oldItem.getAmount();
|
||||
final var itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
|
||||
final var resultType = event.getInventory().getResult().getType();
|
||||
|
||||
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
|
||||
|
||||
// First check
|
||||
int newAmount = getAmount(event.getInventory().getMatrix()[index]);
|
||||
final var newItem = event.getInventory().getMatrix()[index];
|
||||
final var newAmount = getEffectiveNewAmount(newItem, oldItem);
|
||||
|
||||
if (newAmount >= oldAmount) return;
|
||||
|
||||
// Deduce amount crafted
|
||||
int amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
|
||||
final var amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
|
||||
for (CraftItemExperienceSource source : getSources())
|
||||
if (source.matches(data, resultType))
|
||||
source.giveExperience(data, amountCrafted, event.getInventory().getLocation());
|
||||
});
|
||||
}
|
||||
|
||||
private int getAmount(@Nullable ItemStack item) {
|
||||
return item == null || item.getType() == Material.AIR ? 0 : item.getAmount();
|
||||
private int getEffectiveNewAmount(@Nullable ItemStack item, @NotNull ItemStack oldItem) {
|
||||
// Some items are consumed and leave behind a different type (e.g. buckets)
|
||||
// If that's the case just say all items were crafted
|
||||
// Fixes https://gitlab.com/phoenix-dvpmt/mmocore/-/issues/1165
|
||||
return item == null || item.getType() == Material.AIR || item.getType() != oldItem.getType() ? 0 : item.getAmount();
|
||||
}
|
||||
|
||||
private int getLowerAmountIngredientIndex(ItemStack[] matrix) {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.stat.StatInstance;
|
||||
import io.lumine.mythic.lib.util.FileUtils;
|
||||
import io.lumine.mythic.lib.util.config.YamlFile;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.attribute.MMOCoreAttributeStatHandler;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -40,20 +40,23 @@ public class AttributeManager implements MMOCoreManager {
|
||||
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore) {
|
||||
if (clearBefore)
|
||||
map.clear();
|
||||
MythicLib.plugin.getStats().clearRegisteredStats(handler -> handler instanceof MMOCoreAttributeStatHandler);
|
||||
}
|
||||
|
||||
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "attributes", false, (key, config) -> {
|
||||
final String path = key.toLowerCase().replace("_", "-").replace(" ", "-");
|
||||
map.put(path, new PlayerAttribute(config));
|
||||
}, "Could not load attribute '%s' from file '%s': %s");
|
||||
|
||||
final var statsConfig = new YamlFile(MythicLib.plugin, "stats").getContent();
|
||||
// MythicLib stat handlers
|
||||
for (PlayerAttribute attr : getAll()) {
|
||||
final MMOCoreAttributeStatHandler handler = new MMOCoreAttributeStatHandler(statsConfig, attr);
|
||||
MythicLib.plugin.getStats().registerStat(handler, handler.getStat() + "_PERCENT");
|
||||
final var statId = attr.getId().toUpperCase().replace("-", "_") + "_PERCENT";
|
||||
MythicLib.plugin.getStats().computeStat(statId).addUpdateListener(ins -> this.updateMMOCoreStatAttributeValue(ins, attr));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMMOCoreStatAttributeValue(@NotNull StatInstance instance, PlayerAttribute attribute) {
|
||||
final var playerData = PlayerData.get(instance.getMap().getPlayerData());
|
||||
playerData.getAttributes().getInstance(attribute).updateStats();
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,12 +69,6 @@ public class ConfigManager {
|
||||
if (!FileUtils.getFile(MMOCore.plugin, "exp-tables").exists())
|
||||
copyDefaultFile("exp-tables/default_exp_tables.yml");
|
||||
|
||||
if (!FileUtils.getFile(MMOCore.plugin, "expcurves").exists()) {
|
||||
copyDefaultFile("expcurves/levels.txt");
|
||||
copyDefaultFile("expcurves/mining.txt");
|
||||
copyDefaultFile("expcurves/skill-tree-node.txt");
|
||||
}
|
||||
|
||||
if (!FileUtils.getFile(MMOCore.plugin, "loot-chests").exists())
|
||||
copyDefaultFile("loot-chests/default_loot_chests.yml");
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
package net.Indyuce.mmocore.manager;
|
||||
|
||||
import io.lumine.mythic.lib.util.FileUtils;
|
||||
import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
|
||||
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
|
||||
@ -14,7 +13,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
public class ExperienceManager implements MMOCoreManager {
|
||||
private final Map<String, ExpCurve> expCurves = new HashMap<>();
|
||||
private final Map<String, ExperienceTable> expTables = new HashMap<>();
|
||||
|
||||
/**
|
||||
@ -45,14 +43,29 @@ public class ExperienceManager implements MMOCoreManager {
|
||||
getManager(path).registerSource(source);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean hasCurve(String id) {
|
||||
return expCurves.containsKey(id);
|
||||
try {
|
||||
ExperienceCurve.fromConfig("expcurves/" + id + ".txt");
|
||||
return true;
|
||||
} catch (Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@NotNull
|
||||
public ExpCurve getCurveOrThrow(String id) {
|
||||
Validate.isTrue(hasCurve(id), "Could not find exp curve with ID '" + id + "'");
|
||||
return expCurves.get(id);
|
||||
public ExperienceCurve getCurveOrThrow(String id) {
|
||||
try {
|
||||
return ExperienceCurve.fromConfig(id + ".txt");
|
||||
} catch (Exception ignored) {
|
||||
throw new IllegalArgumentException("Could not find exp curve with ID '" + id + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Collection<ExperienceCurve> getCurves() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ -82,10 +95,6 @@ public class ExperienceManager implements MMOCoreManager {
|
||||
throw new IllegalArgumentException("Please provide either a string (exp table name) or a config section (locally define an exp table)");
|
||||
}
|
||||
|
||||
public Collection<ExpCurve> getCurves() {
|
||||
return expCurves.values();
|
||||
}
|
||||
|
||||
public Collection<ExperienceTable> getTables() {
|
||||
return expTables.values();
|
||||
}
|
||||
@ -100,21 +109,15 @@ public class ExperienceManager implements MMOCoreManager {
|
||||
@Override
|
||||
public void initialize(boolean clearBefore) {
|
||||
if (clearBefore) {
|
||||
expCurves.clear();
|
||||
expTables.clear();
|
||||
|
||||
managers.forEach((c, manager) -> manager.close());
|
||||
managers.clear();
|
||||
}
|
||||
|
||||
// Exp curves
|
||||
FileUtils.loadObjectsFromFolderRaw(MMOCore.plugin, "expcurves", file -> {
|
||||
final ExpCurve curve = new ExpCurve(file);
|
||||
expCurves.put(curve.getId(), curve);
|
||||
}, "Could not load exp curve from file '%s': %s");
|
||||
|
||||
// Exp tables
|
||||
FileUtils.loadObjectsFromFolder(MMOCore.plugin ,"exp-tables", false, (key, config) -> {
|
||||
FileUtils.loadObjectsFromFolder(MMOCore.plugin, "exp-tables", false, (key, config) -> {
|
||||
final ExperienceTable table = new ExperienceTable(config);
|
||||
expTables.put(table.getId(), table);
|
||||
}, "Could not load exp table '%s' from file '%s': %s");
|
||||
|
||||
@ -161,7 +161,11 @@ public class YAMLDatabaseImpl extends YAMLFlatDatabase<PlayerData, OfflinePlayer
|
||||
|
||||
// Saves the nodes levels
|
||||
config.set("skill-tree-level", null);
|
||||
MMOCore.plugin.skillTreeManager.getAllNodes().forEach(node -> config.set("skill-tree-level." + node.getFullId(), data.getNodeLevel(node)));
|
||||
config.createSection("skill-tree-level");
|
||||
for (var node : MMOCore.plugin.skillTreeManager.getAllNodes()) {
|
||||
final var nodeLevel = data.getNodeLevel(node);
|
||||
if (nodeLevel > 0) config.set("skill-tree-level." + node.getFullId(), nodeLevel);
|
||||
}
|
||||
|
||||
// Skill levels
|
||||
config.set("skill", null);
|
||||
|
||||
@ -205,12 +205,15 @@ public class CustomBlockManager extends SpecificProfessionManager {
|
||||
this.protectVanillaBlocks = config.getBoolean("protect-vanilla-blocks");
|
||||
this.enableToolRestrictions = config.getBoolean("enable-tool-restrictions");
|
||||
|
||||
for (String key : config.getStringList("conditions"))
|
||||
try {
|
||||
customMineConditions.add(MMOCore.plugin.loadManager.loadCondition(new MMOLineConfig(key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load custom mining condition '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
// Avoid warnings if disabled
|
||||
if (enabled)
|
||||
for (String key : config.getStringList("conditions"))
|
||||
try {
|
||||
customMineConditions.add(MMOCore.plugin.loadManager.loadCondition(new MMOLineConfig(key)));
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load custom mining condition '" + key + "': " + exception.getMessage());
|
||||
}
|
||||
else customMineConditions.clear();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package net.Indyuce.mmocore.quest;
|
||||
|
||||
import net.Indyuce.mmocore.quest.compat.BeautyQuestModule;
|
||||
import net.Indyuce.mmocore.quest.compat.BlackVeinQuestsModule;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestsModule;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestCreatorModule;
|
||||
import net.Indyuce.mmocore.quest.compat.QuestModule;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -10,7 +10,7 @@ import javax.inject.Provider;
|
||||
|
||||
public enum QuestModuleType {
|
||||
MMOCORE("MMOCore", MMOCoreQuestModule::new),
|
||||
QUESTS("Quests", BlackVeinQuestsModule::new),
|
||||
QUESTS("Quests", QuestsModule::new),
|
||||
BEAUTY_QUEST("BeautyQuests", BeautyQuestModule::new),
|
||||
QUEST_CREATOR("QuestCreator", QuestCreatorModule::new);
|
||||
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
package net.Indyuce.mmocore.quest.compat;
|
||||
|
||||
import me.blackvein.quests.Quest;
|
||||
import me.blackvein.quests.Quester;
|
||||
import me.blackvein.quests.Quests;
|
||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
public class BlackVeinQuestsModule implements QuestModule<BlackVeinQuestsModule.BlackVeinQuestQuest> {
|
||||
private final Quests plugin = (Quests) Bukkit.getPluginManager().getPlugin("Quests");
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public BlackVeinQuestQuest getQuestOrThrow(String id) {
|
||||
Quests plugin = (Quests) Bukkit.getPluginManager().getPlugin("Quests");
|
||||
return plugin.getQuestById(id)==null?null:new BlackVeinQuestQuest(plugin.getQuestById(id));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasCompletedQuest(String questId, Player player) {
|
||||
Quester quester = plugin.getQuester(player.getUniqueId());
|
||||
if(quester==null)
|
||||
return false;
|
||||
for(Quest quest:quester.getCompletedQuests()) {
|
||||
if(quest.getId().equals(questId))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public class BlackVeinQuestQuest implements AbstractQuest {
|
||||
private final Quest quest;
|
||||
|
||||
public BlackVeinQuestQuest(Quest quest) {
|
||||
this.quest = quest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return quest.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return quest.getId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package net.Indyuce.mmocore.quest.compat;
|
||||
|
||||
import me.pikamug.quests.BukkitQuestsPlugin;
|
||||
import me.pikamug.quests.player.Quester;
|
||||
import me.pikamug.quests.quests.Quest;
|
||||
import net.Indyuce.mmocore.quest.AbstractQuest;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class QuestsModule implements QuestModule<QuestsModule.QuestImpl> {
|
||||
private final BukkitQuestsPlugin plugin;
|
||||
|
||||
public QuestsModule() {
|
||||
plugin = (BukkitQuestsPlugin) Bukkit.getPluginManager().getPlugin("Quests");
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuestImpl getQuestOrThrow(String id) {
|
||||
final var found = plugin.getQuest(id);
|
||||
return found == null ? null : new QuestImpl(found);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasCompletedQuest(String questId, Player player) {
|
||||
Quester quester = plugin.getQuester(player.getUniqueId());
|
||||
if (quester == null) return false;
|
||||
|
||||
for (var quest : quester.getCompletedQuests())
|
||||
if (quest.getId().equals(questId)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class QuestImpl implements AbstractQuest {
|
||||
private final Quest quest;
|
||||
|
||||
public QuestImpl(Quest quest) {
|
||||
this.quest = quest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return quest.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return quest.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ import io.lumine.mythic.lib.util.lang3.Validate;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.experience.EXPSource;
|
||||
import net.Indyuce.mmocore.experience.ExpCurve;
|
||||
import net.Indyuce.mmocore.experience.curve.ExperienceCurve;
|
||||
import net.Indyuce.mmocore.experience.ExperienceObject;
|
||||
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
|
||||
import net.Indyuce.mmocore.skilltree.display.DisplayMap;
|
||||
@ -204,7 +204,7 @@ public class SkillTreeNode implements ExperienceObject {
|
||||
public static final String KEY_PREFIX = "node";
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
public @NotNull String getKey() {
|
||||
return KEY_PREFIX + ":" + getFullId().replace("-", "_");
|
||||
}
|
||||
|
||||
@ -269,9 +269,9 @@ public class SkillTreeNode implements ExperienceObject {
|
||||
throw new RuntimeException("Skill trees don't have experience");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public ExpCurve getExpCurve() {
|
||||
public ExperienceCurve getExpCurve() {
|
||||
throw new RuntimeException("Skill trees don't have experience");
|
||||
}
|
||||
|
||||
|
||||
@ -20,8 +20,14 @@ options:
|
||||
off-combat-health-regen: false
|
||||
off-combat-mana-regen: false
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
exp-table: class_exp_table
|
||||
|
||||
|
||||
@ -36,8 +36,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
skill-slots:
|
||||
1:
|
||||
|
||||
@ -36,8 +36,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
# The maximum level players can reach
|
||||
max-level: 100
|
||||
|
||||
@ -35,8 +35,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
# The maximum level players can reach
|
||||
max-level: 100
|
||||
|
||||
@ -35,8 +35,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
skill-slots:
|
||||
1:
|
||||
|
||||
@ -36,8 +36,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
# The maximum level players can reach
|
||||
max-level: 100
|
||||
|
||||
@ -39,8 +39,14 @@ display:
|
||||
# item-model: 'minecraft:dirt'
|
||||
# texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD')
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/class_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current class level.
|
||||
# | Example: '{level} * 200'
|
||||
exp-curve: '{level} * 200'
|
||||
|
||||
# The maximum level players can reach
|
||||
max-level: 100
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
200
|
||||
400
|
||||
600
|
||||
800
|
||||
1000
|
||||
1200
|
||||
1400
|
||||
1600
|
||||
1800
|
||||
2000
|
||||
2200
|
||||
2400
|
||||
2600
|
||||
2800
|
||||
3000
|
||||
3200
|
||||
3400
|
||||
3600
|
||||
3800
|
||||
4000
|
||||
4200
|
||||
4400
|
||||
4600
|
||||
4800
|
||||
5000
|
||||
@ -1,25 +0,0 @@
|
||||
100
|
||||
200
|
||||
300
|
||||
400
|
||||
500
|
||||
600
|
||||
700
|
||||
800
|
||||
900
|
||||
1000
|
||||
1100
|
||||
1200
|
||||
1300
|
||||
1400
|
||||
1500
|
||||
1600
|
||||
1700
|
||||
1800
|
||||
1900
|
||||
2000
|
||||
2100
|
||||
2200
|
||||
2300
|
||||
2400
|
||||
2500
|
||||
@ -1,25 +0,0 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 20
|
||||
per-level: 3
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources:
|
||||
- 'brewpotion{effect=SPEED}'
|
||||
@ -20,31 +26,31 @@ exp-sources:
|
||||
alchemy-experience:
|
||||
|
||||
special:
|
||||
|
||||
|
||||
# When brewing a potion into a splash potion,
|
||||
# only 40% of the base EXP is earned.
|
||||
splash: 40
|
||||
|
||||
|
||||
# When brewing a potion into a splash potion,
|
||||
# only 40% of the base EXP is earned.
|
||||
lingering: 40
|
||||
|
||||
|
||||
# When extending a pot duration,
|
||||
# only 40% of base EXP is earned.
|
||||
extend: 40
|
||||
|
||||
|
||||
# When upgrading a potion level,
|
||||
# only 40% of base EXP is earned.
|
||||
upgrade: 40
|
||||
|
||||
# Base EXP of potions
|
||||
effects:
|
||||
|
||||
|
||||
# Water bottles
|
||||
AWKWARD: 5
|
||||
MUNDANE: 5
|
||||
THICK: 5
|
||||
|
||||
|
||||
# Potion effects
|
||||
NIGHT_VISION: 10
|
||||
INVISIBILITY: 10
|
||||
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 10
|
||||
per-level: 2
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
# Remove the 'enchant' parameter from the line config
|
||||
# to make the profession get EXP with ANY enchant.
|
||||
|
||||
@ -7,8 +7,14 @@ experience:
|
||||
base: 10
|
||||
per-level: 2
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources:
|
||||
- 'mineblock{type=WHEAT;amount=1-3;crop=true;player-placed=true;silk-touch=false}'
|
||||
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 20
|
||||
per-level: 3
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources: {}
|
||||
|
||||
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 20
|
||||
per-level: 3
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: mining
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
# This part of the config is ONLY for custom mining.
|
||||
# Custom Mining must be setup in config.yml and it
|
||||
|
||||
@ -7,8 +7,14 @@ experience:
|
||||
base: 20
|
||||
per-level: 3
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources:
|
||||
- 'craftitem{type=BLAST_FURNACE;amount=1}'
|
||||
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 20
|
||||
per-level: 3
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources:
|
||||
- 'repairitem{}'
|
||||
|
||||
@ -8,8 +8,14 @@ experience:
|
||||
base: 13
|
||||
per-level: 2.5
|
||||
|
||||
# Must match an existing exp curve filename from the 'expcurves' folder
|
||||
exp-curve: levels
|
||||
# Can be a file path to an existing .txt file inside the MMOCore/ folder.
|
||||
# | The TXT files contains only the experience required per level, one per line.
|
||||
# | Example: 'expcurves/profession_exp_curve.txt'
|
||||
# Or a formula using the {level} and PAPI placeholders.
|
||||
# | The formula should return the total experience required to reach the next
|
||||
# | level if {level} is the player's current profession level.
|
||||
# | Example: '{level} * 150'
|
||||
exp-curve: '{level} * 150'
|
||||
|
||||
exp-sources:
|
||||
- 'mineblock{type=OAK_LOG;amount=1-3}'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user