Spears update (#5236)

Spears update
This commit is contained in:
Robert Alan Chapton
2025-12-14 14:23:25 -08:00
committed by GitHub
parent a907bfd624
commit b15365e978
55 changed files with 5927 additions and 3090 deletions

View File

@@ -1,3 +1,33 @@
Version 2.2.046
Added Spears combat skill
Added Spears to repair.vanilla.yml and salvage.vanilla.yml (see notes)
Added various permissions related to Spears
Added /spears skill command
Added Nautilus to taming XP in experience.yml
Added Camel_Husk to taming XP in experience.yml
Added Camel_Husk to combat XP in experience.yml
Added Parched to combat XP in experience.yml
Fixed bug where converting from SQL to FlatFile would not copy data for tridents, crossbows, maces, or spears
(Codebase) Added docker-based unit tests for SQL databases (see notes)
(Codebase) Large refactor to both SQLDatabaseManager and FlatFileDatabaseManager
(Codebase) Database related errors are now more descriptive and have had their logging improved
NOTES:
This update had a lot of changes behind the scenes, please report any bugs you find to our GitHub issues page!
You will need to manually update repair.vanilla.yml and salvage.vanilla.yml to get support for Spears, or...
If you want to update salvage/repair configs the easy way, you simply can delete these config files to have mcMMO regenerate them with the new entries.
If you don't want to delete them, you can find the default values for these config files in the defaults folder at plugins\mcMMO\defaults after running this mcMMO update at least once.
You can use this default file to copy paste if you please.
Docker is ONLY required for developers compiling mcMMO from source code and ONLY for running SQL-related unit tests.
mcMMO itself does NOT require Docker to run, and servers using prebuilt releases are completely unaffected.
New SQL database unit tests use Testcontainers to spin up temporary MySQL/MariaDB instances for testing purposes.
These containers are created at test time and are never used at runtime.
If you compile mcMMO locally and do not have Docker installed, SQL-related unit tests may fail.
In this case, you can safely compile with -DskipTests to skip unit tests entirely.
Skipping tests has no impact on mcMMO functionality when running on a server.
Known Issues:
I ran into an issue where having a spear in the offhand while the main hand is empty causes attacks to be incorrectly classified as unarmed. This allows unarmed abilities to apply to spear damage. As a temporary measure, Ive disabled unarmed skills from applying to combat when a spear is equipped in the offhand while I investigate a more robust solution.
Version 2.2.045 Version 2.2.045
Green Thumb now replants some crops it was failing to replant before (see notes) Green Thumb now replants some crops it was failing to replant before (see notes)
Green Thumb now replants harvested plants faster Green Thumb now replants harvested plants faster

113
pom.xml
View File

@@ -1,8 +1,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.nossr50.mcMMO</groupId> <groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId> <artifactId>mcMMO</artifactId>
<version>2.2.046-SNAPSHOT</version> <version>2.2.046</version>
<name>mcMMO</name> <name>mcMMO</name>
<url>https://github.com/mcMMO-Dev/mcMMO</url> <url>https://github.com/mcMMO-Dev/mcMMO</url>
<scm> <scm>
@@ -13,8 +15,8 @@
</scm> </scm>
<properties> <properties>
<!-- <spigot.version>1.19-R0.1-SNAPSHOT</spigot.version>--> <!-- <spigot.version>1.19-R0.1-SNAPSHOT</spigot.version>-->
<spigot.version>1.21.10-R0.1-SNAPSHOT</spigot.version> <spigot.version>1.21.11-R0.1-SNAPSHOT</spigot.version>
<kyori.adventure.version>4.23.0</kyori.adventure.version> <kyori.adventure.version>4.23.0</kyori.adventure.version>
<kyori.adventure.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.version> <kyori.adventure.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.version>
<kyori.option.version>1.1.0</kyori.option.version> <kyori.option.version>1.1.0</kyori.option.version>
@@ -182,11 +184,13 @@
</relocation> </relocation>
<relocation> <relocation>
<pattern>co.aikar.commands</pattern> <pattern>co.aikar.commands</pattern>
<shadedPattern>com.gmail.nossr50.mcmmo.acf</shadedPattern> <!-- Replace this --> <shadedPattern>com.gmail.nossr50.mcmmo.acf
</shadedPattern> <!-- Replace this -->
</relocation> </relocation>
<relocation> <relocation>
<pattern>co.aikar.locales</pattern> <pattern>co.aikar.locales</pattern>
<shadedPattern>com.gmail.nossr50.mcmmo.locales</shadedPattern> <!-- Replace this --> <shadedPattern>com.gmail.nossr50.mcmmo.locales
</shadedPattern> <!-- Replace this -->
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.apache.commons.logging</pattern> <pattern>org.apache.commons.logging</pattern>
@@ -194,7 +198,8 @@
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.apache.juli</pattern> <pattern>org.apache.juli</pattern>
<shadedPattern>com.gmail.nossr50.mcmmo.database.tomcat.juli</shadedPattern> <shadedPattern>com.gmail.nossr50.mcmmo.database.tomcat.juli
</shadedPattern>
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.apache.tomcat</pattern> <pattern>org.apache.tomcat</pattern>
@@ -385,11 +390,11 @@
<version>3.0.2</version> <version>3.0.2</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- <dependency>--> <!-- <dependency>-->
<!-- <groupId>io.papermc.paper</groupId>--> <!-- <groupId>io.papermc.paper</groupId>-->
<!-- <artifactId>paper-api</artifactId>--> <!-- <artifactId>paper-api</artifactId>-->
<!-- <version>1.21.8-R0.1-SNAPSHOT</version>--> <!-- <version>1.21.8-R0.1-SNAPSHOT</version>-->
<!-- </dependency>--> <!-- </dependency>-->
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
@@ -426,10 +431,76 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<!-- JUnit 5 -->
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>5.11.0-M2</version> <version>5.11.0</version>
<scope>test</scope>
</dependency>
<!-- Testcontainers core -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<!-- Testcontainers JUnit Jupiter integration -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-junit-jupiter</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<!-- Log4j core for tests -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.25.2</version>
<scope>test</scope>
</dependency>
<!-- Log4j API -->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.25.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.25.2</version>
<scope>test</scope>
</dependency>
<!-- MySQL Testcontainers module -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-mysql</artifactId>
<scope>test</scope>
</dependency>
<!-- MariaDB Testcontainers module -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-mariadb</artifactId>
<scope>test</scope>
</dependency>
<!-- MySQL JDBC driver -->
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.5.0</version>
<scope>test</scope>
</dependency>
<!-- MariaDB JDBC driver -->
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.5.6</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -447,7 +518,7 @@
<dependency> <dependency>
<groupId>org.apache.tomcat</groupId> <groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId> <artifactId>tomcat-jdbc</artifactId>
<version>10.1.24</version> <version>11.0.14</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -458,7 +529,8 @@
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>33.2.0-jre</version> <!-- At this time Spigot is including 29.0 Guava classes that we are using --> <version>33.2.0-jre
</version> <!-- At this time Spigot is including 29.0 Guava classes that we are using -->
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -468,4 +540,15 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>2.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project> </project>

View File

@@ -73,7 +73,7 @@ public class AcrobaticsCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.ACROBATICS); PrimarySkillType.ACROBATICS);
return textComponents; return textComponents;

View File

@@ -92,7 +92,7 @@ public class AlchemyCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.ALCHEMY); PrimarySkillType.ALCHEMY);
return textComponents; return textComponents;

View File

@@ -93,7 +93,7 @@ public class ArcheryCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.ARCHERY); PrimarySkillType.ARCHERY);
return textComponents; return textComponents;

View File

@@ -119,7 +119,7 @@ public class AxesCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
final List<Component> textComponents = new ArrayList<>(); final List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.AXES); PrimarySkillType.AXES);
return textComponents; return textComponents;

View File

@@ -68,7 +68,7 @@ public class CrossbowsCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.CROSSBOWS); PrimarySkillType.CROSSBOWS);
return textComponents; return textComponents;

View File

@@ -71,7 +71,7 @@ public class ExcavationCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.EXCAVATION); PrimarySkillType.EXCAVATION);
return textComponents; return textComponents;

View File

@@ -185,7 +185,7 @@ public class FishingCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.FISHING); PrimarySkillType.FISHING);
return textComponents; return textComponents;

View File

@@ -187,7 +187,7 @@ public class HerbalismCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.HERBALISM); PrimarySkillType.HERBALISM);
return textComponents; return textComponents;

View File

@@ -23,7 +23,8 @@ public class MacesCommand extends SkillCommand {
super(PrimarySkillType.MACES); super(PrimarySkillType.MACES);
} }
String crippleChanceToApply, crippleChanceToApplyLucky, crippleLengthAgainstPlayers, crippleLengthAgainstMobs; String crippleChanceToApply, crippleChanceToApplyLucky, crippleLengthAgainstPlayers,
crippleLengthAgainstMobs;
@Override @Override
protected void dataCalculations(Player player, float skillValue) { protected void dataCalculations(Player player, float skillValue) {
@@ -33,7 +34,6 @@ public class MacesCommand extends SkillCommand {
MacesManager.getCrippleTickDuration(true) / 20.0D); MacesManager.getCrippleTickDuration(true) / 20.0D);
crippleLengthAgainstMobs = String.valueOf( crippleLengthAgainstMobs = String.valueOf(
MacesManager.getCrippleTickDuration(false) / 20.0D); MacesManager.getCrippleTickDuration(false) / 20.0D);
crippleChanceToApply = crippleChanceToApply =
mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) + "%"; mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) + "%";
crippleChanceToApplyLucky = String.valueOf( crippleChanceToApplyLucky = String.valueOf(
@@ -77,7 +77,7 @@ public class MacesCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.MACES); PrimarySkillType.MACES);
return textComponents; return textComponents;

View File

@@ -144,7 +144,7 @@ public class MiningCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.MINING); PrimarySkillType.MINING);
return textComponents; return textComponents;

View File

@@ -134,7 +134,7 @@ public class RepairCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.REPAIR); PrimarySkillType.REPAIR);
return textComponents; return textComponents;

View File

@@ -72,7 +72,7 @@ public class SalvageCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.SALVAGE); PrimarySkillType.SALVAGE);
return textComponents; return textComponents;

View File

@@ -97,7 +97,7 @@ public class SmeltingCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.SMELTING); PrimarySkillType.SMELTING);
return textComponents; return textComponents;

View File

@@ -0,0 +1,85 @@
package com.gmail.nossr50.commands.skills;
import static com.gmail.nossr50.datatypes.skills.SubSkillType.SPEARS_MOMENTUM;
import static com.gmail.nossr50.datatypes.skills.SubSkillType.SPEARS_SPEARS_LIMIT_BREAK;
import static com.gmail.nossr50.datatypes.skills.SubSkillType.SPEARS_SPEAR_MASTERY;
import static com.gmail.nossr50.util.skills.SkillUtils.canUseSubskill;
import static com.gmail.nossr50.util.text.TextComponentFactory.appendSubSkillTextComponents;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.spears.SpearsManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import java.util.ArrayList;
import java.util.List;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
public class SpearsCommand extends SkillCommand {
public SpearsCommand() {
super(PrimarySkillType.SPEARS);
}
String momentumChanceToApply, momentumChanceToApplyLucky, momentumDuration;
@Override
protected void dataCalculations(Player player, float skillValue) {
if (SkillUtils.canUseSubskill(player, SPEARS_MOMENTUM)) {
int momentumRank = RankUtils.getRank(player, SPEARS_MOMENTUM);
momentumDuration = String.valueOf(
SpearsManager.getMomentumTickDuration(momentumRank) / 20.0D);
momentumChanceToApply =
mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank) + "%";
momentumChanceToApplyLucky = String.valueOf(
mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank) * 1.33);
}
}
@Override
protected void permissionsCheck(Player player) {
}
@Override
protected List<String> statsDisplay(Player player, float skillValue, boolean hasEndurance,
boolean isLucky) {
final SpearsManager spearsManager = UserManager.getPlayer(player).getSpearsManager();
final double spearMasteryBonusDmg = spearsManager.getSpearMasteryBonusDamage();
List<String> messages = new ArrayList<>();
if (canUseSubskill(player, SPEARS_SPEARS_LIMIT_BREAK)) {
messages.add(getStatMessage(SPEARS_SPEARS_LIMIT_BREAK,
String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player,
SPEARS_SPEARS_LIMIT_BREAK, 1000))));
}
if (canUseSubskill(player, SPEARS_SPEAR_MASTERY)) {
messages.add(getStatMessage(SPEARS_SPEAR_MASTERY,
String.valueOf(spearMasteryBonusDmg)));
}
if (SkillUtils.canUseSubskill(player, SPEARS_MOMENTUM)) {
messages.add(getStatMessage(SPEARS_MOMENTUM, momentumChanceToApply)
+ (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus",
momentumChanceToApplyLucky) : ""));
messages.add(getStatMessage(true, true, SPEARS_MOMENTUM, momentumDuration));
}
return messages;
}
@Override
protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>();
appendSubSkillTextComponents(player, textComponents, PrimarySkillType.SPEARS);
return textComponents;
}
}

View File

@@ -22,8 +22,8 @@ public class SwordsCommand extends SkillCommand {
private String serratedStrikesLengthEndurance; private String serratedStrikesLengthEndurance;
private String rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs, private String rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs,
ruptureExplosionDamageAgainstPlayers, ruptureExplosionDamageAgainstMobs, ruptureLengthSecondsAgainstPlayers, ruptureLengthSecondsAgainstMobs,
ruptureLengthSecondsAgainstPlayers, ruptureLengthSecondsAgainstMobs, ruptureChanceToApply, ruptureChanceToApplyLucky; ruptureChanceToApply, ruptureChanceToApplyLucky;
private boolean canCounter; private boolean canCounter;
private boolean canSerratedStrike; private boolean canSerratedStrike;
@@ -56,11 +56,6 @@ public class SwordsCommand extends SkillCommand {
rupturePureTickDamageAgainstMobs = String.valueOf( rupturePureTickDamageAgainstMobs = String.valueOf(
mcMMO.p.getAdvancedConfig().getRuptureTickDamage(false, ruptureRank)); mcMMO.p.getAdvancedConfig().getRuptureTickDamage(false, ruptureRank));
ruptureExplosionDamageAgainstPlayers = String.valueOf(
mcMMO.p.getAdvancedConfig().getRuptureExplosionDamage(true, ruptureRank));
ruptureExplosionDamageAgainstMobs = String.valueOf(
mcMMO.p.getAdvancedConfig().getRuptureExplosionDamage(false, ruptureRank));
ruptureChanceToApply = ruptureChanceToApply =
mcMMO.p.getAdvancedConfig().getRuptureChanceToApplyOnHit(ruptureRank) + "%"; mcMMO.p.getAdvancedConfig().getRuptureChanceToApplyOnHit(ruptureRank) + "%";
ruptureChanceToApplyLucky = String.valueOf( ruptureChanceToApplyLucky = String.valueOf(
@@ -105,7 +100,6 @@ public class SwordsCommand extends SkillCommand {
messages.add(LocaleLoader.getString("Swords.SubSkill.Rupture.Stat.TickDamage", messages.add(LocaleLoader.getString("Swords.SubSkill.Rupture.Stat.TickDamage",
rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs)); rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs));
// messages.add(LocaleLoader.getString("Swords.SubSkill.Rupture.Stat.ExplosionDamage", ruptureExplosionDamageAgainstPlayers, ruptureExplosionDamageAgainstMobs));
messages.add(LocaleLoader.getString("Swords.Combat.Rupture.Note.Update.One")); messages.add(LocaleLoader.getString("Swords.Combat.Rupture.Note.Update.One"));
} }
@@ -134,7 +128,7 @@ public class SwordsCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.SWORDS); PrimarySkillType.SWORDS);
return textComponents; return textComponents;

View File

@@ -115,7 +115,7 @@ public class TamingCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, this.skill); TextComponentFactory.appendSubSkillTextComponents(player, textComponents, this.skill);
return textComponents; return textComponents;
} }

View File

@@ -50,7 +50,7 @@ public class TridentsCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.TRIDENTS); PrimarySkillType.TRIDENTS);
return textComponents; return textComponents;

View File

@@ -136,7 +136,7 @@ public class UnarmedCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.UNARMED); PrimarySkillType.UNARMED);
return textComponents; return textComponents;

View File

@@ -123,7 +123,7 @@ public class WoodcuttingCommand extends SkillCommand {
protected List<Component> getTextComponents(Player player) { protected List<Component> getTextComponents(Player player) {
List<Component> textComponents = new ArrayList<>(); List<Component> textComponents = new ArrayList<>();
TextComponentFactory.getSubSkillTextComponents(player, textComponents, TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
PrimarySkillType.WOODCUTTING); PrimarySkillType.WOODCUTTING);
return textComponents; return textComponents;

View File

@@ -11,6 +11,7 @@ import net.md_5.bungee.api.ChatColor;
public class AdvancedConfig extends BukkitConfig { public class AdvancedConfig extends BukkitConfig {
int[] defaultCrippleValues = new int[]{10, 15, 20, 25}; int[] defaultCrippleValues = new int[]{10, 15, 20, 25};
int[] defaultMomentumValues = new int[]{5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
public AdvancedConfig(File dataFolder) { public AdvancedConfig(File dataFolder) {
super("advanced.yml", dataFolder); super("advanced.yml", dataFolder);
@@ -884,7 +885,17 @@ public class AdvancedConfig extends BukkitConfig {
/* MACES */ /* MACES */
public double getCrippleChanceToApplyOnHit(int rank) { public double getCrippleChanceToApplyOnHit(int rank) {
String root = "Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_"; return config.getDouble("Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_" + rank,
return config.getDouble(root + rank, defaultCrippleValues[rank - 1]); defaultCrippleValues[rank - 1]);
}
/* SPEARS */
public double getMomentumChanceToApplyOnHit(int rank) {
return config.getDouble("Skills.Spears.Momentum.Chance_To_Apply_On_Hit.Rank_" + rank,
defaultMomentumValues[rank - 1]);
}
public double getSpearMasteryRankDamageMultiplier() {
return config.getDouble("Skills.Spears.SpearMastery.Rank_Damage_Multiplier", 0.4D);
} }
} }

View File

@@ -424,10 +424,6 @@ public class GeneralConfig extends BukkitConfig {
return config.getBoolean("MySQL.Server.SSL", true); return config.getBoolean("MySQL.Server.SSL", true);
} }
public boolean getMySQLDebug() {
return config.getBoolean("MySQL.Debug", false);
}
public boolean getMySQLPublicKeyRetrieval() { public boolean getMySQLPublicKeyRetrieval() {
return config.getBoolean("MySQL.Server.allowPublicKeyRetrieval", true); return config.getBoolean("MySQL.Server.allowPublicKeyRetrieval", true);
} }

View File

@@ -28,8 +28,8 @@ public class DatabaseManagerFactory {
: "Flatfile") + " database"); : "Flatfile") + " database");
} }
return mcMMO.p.getGeneralConfig().getUseMySQL() ? new SQLDatabaseManager(logger, return mcMMO.p.getGeneralConfig().getUseMySQL()
MYSQL_DRIVER) ? new SQLDatabaseManager(logger, MYSQL_DRIVER)
: new FlatFileDatabaseManager(userFilePath, logger, purgeTime, startingLevel); : new FlatFileDatabaseManager(userFilePath, logger, purgeTime, startingLevel);
} }

View File

@@ -9,6 +9,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_GREEN_
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SERRATED_STRIKES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SERRATED_STRIKES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SKULL_SPLITTER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SKULL_SPLITTER;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_BREAKER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_BREAKER;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_SHOTGUN; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_SHOTGUN;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_TREE_FELLER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_TREE_FELLER;
@@ -25,6 +26,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_HERBALISM;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MINING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MINING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_REPAIR; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_REPAIR;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SWORDS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SWORDS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TAMING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TAMING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TRIDENTS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TRIDENTS;
@@ -45,6 +47,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_HERBALIS
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MINING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MINING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_REPAIR; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_REPAIR;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SWORDS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SWORDS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TAMING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TAMING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS;
@@ -318,27 +321,26 @@ public class FlatFileDataProcessor {
throws IndexOutOfBoundsException { throws IndexOutOfBoundsException {
return switch (dataIndex) { return switch (dataIndex) {
case USERNAME_INDEX -> case USERNAME_INDEX ->
ExpectedType.STRING; //Assumption: Used to be for something, no longer used ExpectedType.STRING;
//Assumption: Used to be for something, no longer used
//Assumption: Used to be used for something, no longer used
//Assumption: Used to be used for something, no longer used //Assumption: Used to be used for something, no longer used
case 2, 3, 23, 33, HEALTHBAR, LEGACY_LAST_LOGIN -> ExpectedType.IGNORED; case 2, 3, 23, 33, HEALTHBAR, LEGACY_LAST_LOGIN -> ExpectedType.IGNORED;
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION, case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION,
SKILLS_ARCHERY, SKILLS_ARCHERY,
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING, SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING,
SKILLS_FISHING, SKILLS_FISHING,
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES, COOLDOWN_BERSERK, SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES, SKILLS_SPEARS,
COOLDOWN_BERSERK,
COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER, COOLDOWN_GREEN_TERRA, COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER, COOLDOWN_GREEN_TERRA,
COOLDOWN_SERRATED_STRIKES, COOLDOWN_SERRATED_STRIKES,
COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_BLAST_MINING, COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_BLAST_MINING,
SCOREBOARD_TIPS, SCOREBOARD_TIPS,
COOLDOWN_CHIMAERA_WING, COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS, COOLDOWN_CHIMAERA_WING, COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS,
COOLDOWN_ARCHERY, COOLDOWN_MACES -> ExpectedType.INTEGER; COOLDOWN_ARCHERY, COOLDOWN_MACES, COOLDOWN_SPEARS -> ExpectedType.INTEGER;
case EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM, case EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM,
EXP_EXCAVATION, EXP_ARCHERY, EXP_EXCAVATION, EXP_ARCHERY,
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY, EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY,
EXP_CROSSBOWS, EXP_CROSSBOWS,
EXP_TRIDENTS, EXP_MACES -> ExpectedType.FLOAT; EXP_TRIDENTS, EXP_MACES, EXP_SPEARS -> ExpectedType.FLOAT;
case UUID_INDEX -> ExpectedType.UUID; case UUID_INDEX -> ExpectedType.UUID;
case OVERHAUL_LAST_LOGIN -> ExpectedType.LONG; case OVERHAUL_LAST_LOGIN -> ExpectedType.LONG;
default -> throw new IndexOutOfBoundsException(); default -> throw new IndexOutOfBoundsException();

View File

@@ -9,6 +9,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_GREEN_
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SERRATED_STRIKES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SERRATED_STRIKES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SKULL_SPLITTER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SKULL_SPLITTER;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_BREAKER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_BREAKER;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_SHOTGUN; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_SUPER_SHOTGUN;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_TREE_FELLER; import static com.gmail.nossr50.database.FlatFileDatabaseManager.COOLDOWN_TREE_FELLER;
@@ -24,6 +25,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_HERBALISM;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MINING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_MINING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_REPAIR; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_REPAIR;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SWORDS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_SWORDS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TAMING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TAMING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TRIDENTS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.EXP_TRIDENTS;
@@ -45,6 +47,7 @@ import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_HERBALIS
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MACES; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MACES;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MINING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_MINING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_REPAIR; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_REPAIR;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SPEARS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SWORDS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_SWORDS;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TAMING; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TAMING;
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS; import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS;
@@ -114,18 +117,16 @@ public class FlatFileDataUtil {
throws IndexOutOfBoundsException { throws IndexOutOfBoundsException {
//TODO: Add UUID recovery? Might not even be worth it. //TODO: Add UUID recovery? Might not even be worth it.
return switch (index) { return switch (index) {
//We'll keep using this value for legacy compatibility reasons (not sure if needed but don't care)
case USERNAME_INDEX -> case USERNAME_INDEX ->
LEGACY_INVALID_OLD_USERNAME; //We'll keep using this value for legacy compatibility reasons (not sure if needed but don't care) LEGACY_INVALID_OLD_USERNAME;
//Assumption: Used to be for something, no longer used
//Assumption: Used to be for something, no longer used
//Assumption: Used to be used for something, no longer used
//Assumption: Used to be used for something, no longer used //Assumption: Used to be used for something, no longer used
case 2, 3, 23, 33, LEGACY_LAST_LOGIN, HEALTHBAR -> "IGNORED"; case 2, 3, 23, 33, LEGACY_LAST_LOGIN, HEALTHBAR -> "IGNORED";
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION, case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION,
SKILLS_ARCHERY, SKILLS_ARCHERY,
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING, SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING,
SKILLS_FISHING, SKILLS_FISHING,
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES -> SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES, SKILLS_SPEARS ->
String.valueOf(startingLevel); String.valueOf(startingLevel);
case OVERHAUL_LAST_LOGIN -> String.valueOf(-1L); case OVERHAUL_LAST_LOGIN -> String.valueOf(-1L);
case COOLDOWN_BERSERK, COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER, case COOLDOWN_BERSERK, COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER,
@@ -133,12 +134,12 @@ public class FlatFileDataUtil {
COOLDOWN_SERRATED_STRIKES, COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_SERRATED_STRIKES, COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER,
COOLDOWN_BLAST_MINING, COOLDOWN_BLAST_MINING,
COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS, COOLDOWN_ARCHERY, COOLDOWN_MACES, COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS, COOLDOWN_ARCHERY, COOLDOWN_MACES,
SCOREBOARD_TIPS, COOLDOWN_CHIMAERA_WING, COOLDOWN_SPEARS, SCOREBOARD_TIPS, COOLDOWN_CHIMAERA_WING,
EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM, EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM,
EXP_EXCAVATION, EXP_ARCHERY, EXP_EXCAVATION, EXP_ARCHERY,
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY, EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY,
EXP_CROSSBOWS, EXP_CROSSBOWS,
EXP_TRIDENTS, EXP_MACES -> "0"; EXP_TRIDENTS, EXP_MACES, EXP_SPEARS -> "0";
case UUID_INDEX -> case UUID_INDEX ->
throw new IndexOutOfBoundsException(); //TODO: Add UUID recovery? Might not even be worth it. throw new IndexOutOfBoundsException(); //TODO: Add UUID recovery? Might not even be worth it.
default -> throw new IndexOutOfBoundsException(); default -> throw new IndexOutOfBoundsException();

View File

@@ -3,7 +3,6 @@ package com.gmail.nossr50.datatypes.database;
public enum UpgradeType { public enum UpgradeType {
ADD_FISHING, ADD_FISHING,
ADD_BLAST_MINING_COOLDOWN, ADD_BLAST_MINING_COOLDOWN,
ADD_SQL_INDEXES,
ADD_MOB_HEALTHBARS, ADD_MOB_HEALTHBARS,
DROP_SQL_PARTY_NAMES, DROP_SQL_PARTY_NAMES,
DROP_SPOUT, DROP_SPOUT,

View File

@@ -40,6 +40,7 @@ import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.repair.RepairManager; import com.gmail.nossr50.skills.repair.RepairManager;
import com.gmail.nossr50.skills.salvage.SalvageManager; import com.gmail.nossr50.skills.salvage.SalvageManager;
import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.smelting.SmeltingManager;
import com.gmail.nossr50.skills.spears.SpearsManager;
import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.swords.SwordsManager;
import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.tridents.TridentsManager; import com.gmail.nossr50.skills.tridents.TridentsManager;
@@ -63,6 +64,7 @@ import com.gmail.nossr50.util.sounds.SoundType;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level;
import net.kyori.adventure.identity.Identified; import net.kyori.adventure.identity.Identified;
import net.kyori.adventure.identity.Identity; import net.kyori.adventure.identity.Identity;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -171,73 +173,50 @@ public class McMMOPlayer implements Identified {
try { try {
initManager(primarySkillType); initManager(primarySkillType);
} catch (InvalidSkillException e) { } catch (InvalidSkillException e) {
e.printStackTrace(); mcMMO.p.getLogger().log(Level.SEVERE,
"Invalid skill while initializing skill managers for player "
+ player.getName()
+ ". Contact the plugin developers.", e);
} }
} }
} }
//TODO: Add test //TODO: Add test
private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException { private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException {
switch (primarySkillType) { final var version = mcMMO.getCompatibilityManager().getMinecraftGameVersion();
case ACROBATICS:
skillManagers.put(primarySkillType, new AcrobaticsManager(this)); final SkillManager manager = switch (primarySkillType) {
break; case ACROBATICS -> new AcrobaticsManager(this);
case ALCHEMY: case ALCHEMY -> new AlchemyManager(this);
skillManagers.put(primarySkillType, new AlchemyManager(this)); case ARCHERY -> new ArcheryManager(this);
break; case AXES -> new AxesManager(this);
case ARCHERY: case CROSSBOWS -> new CrossbowsManager(this);
skillManagers.put(primarySkillType, new ArcheryManager(this)); case EXCAVATION -> new ExcavationManager(this);
break; case FISHING -> new FishingManager(this);
case AXES: case HERBALISM -> new HerbalismManager(this);
skillManagers.put(primarySkillType, new AxesManager(this)); case MINING -> new MiningManager(this);
break; case REPAIR -> new RepairManager(this);
case CROSSBOWS: case SALVAGE -> new SalvageManager(this);
skillManagers.put(primarySkillType, new CrossbowsManager(this)); case SMELTING -> new SmeltingManager(this);
break; case SWORDS -> new SwordsManager(this);
case EXCAVATION: case TAMING -> new TamingManager(this);
skillManagers.put(primarySkillType, new ExcavationManager(this)); case TRIDENTS -> new TridentsManager(this);
break; case UNARMED -> new UnarmedManager(this);
case FISHING: case WOODCUTTING -> new WoodcuttingManager(this);
skillManagers.put(primarySkillType, new FishingManager(this));
break; case MACES -> version.isAtLeast(1, 21, 0)
case HERBALISM: ? new MacesManager(this)
skillManagers.put(primarySkillType, new HerbalismManager(this)); : null; // keep current behavior: no manager on older versions
break;
case MINING: case SPEARS -> version.isAtLeast(1, 21, 11)
skillManagers.put(primarySkillType, new MiningManager(this)); ? new SpearsManager(this)
break; : null; // same here
case REPAIR: };
skillManagers.put(primarySkillType, new RepairManager(this));
break; if (manager != null) {
case SALVAGE: skillManagers.put(primarySkillType, manager);
skillManagers.put(primarySkillType, new SalvageManager(this)); } else {
break; throw new InvalidSkillException("No valid skill manager for skill: " + primarySkillType);
case SMELTING:
skillManagers.put(primarySkillType, new SmeltingManager(this));
break;
case SWORDS:
skillManagers.put(primarySkillType, new SwordsManager(this));
break;
case TAMING:
skillManagers.put(primarySkillType, new TamingManager(this));
break;
case TRIDENTS:
skillManagers.put(primarySkillType, new TridentsManager(this));
break;
case UNARMED:
skillManagers.put(primarySkillType, new UnarmedManager(this));
break;
case WOODCUTTING:
skillManagers.put(primarySkillType, new WoodcuttingManager(this));
break;
case MACES:
if (mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
skillManagers.put(primarySkillType, new MacesManager(this));
}
break;
default:
throw new InvalidSkillException(
"The skill named has no manager! Contact the devs!");
} }
} }
@@ -369,6 +348,10 @@ public class McMMOPlayer implements Identified {
return (SmeltingManager) skillManagers.get(PrimarySkillType.SMELTING); return (SmeltingManager) skillManagers.get(PrimarySkillType.SMELTING);
} }
public SpearsManager getSpearsManager() {
return (SpearsManager) skillManagers.get(PrimarySkillType.SPEARS);
}
public SwordsManager getSwordsManager() { public SwordsManager getSwordsManager() {
return (SwordsManager) skillManagers.get(PrimarySkillType.SWORDS); return (SwordsManager) skillManagers.get(PrimarySkillType.SWORDS);
} }

View File

@@ -87,7 +87,7 @@ public class PlayerProfile {
this.loaded = isLoaded; this.loaded = isLoaded;
} }
public PlayerProfile(@NotNull String playerName, UUID uuid, boolean isLoaded, int startingLvl) { public PlayerProfile(@NotNull String playerName, @Nullable UUID uuid, boolean isLoaded, int startingLvl) {
this(playerName, uuid, startingLvl); this(playerName, uuid, startingLvl);
this.loaded = isLoaded; this.loaded = isLoaded;
} }

View File

@@ -24,6 +24,7 @@ public enum PrimarySkillType {
REPAIR, REPAIR,
SALVAGE, SALVAGE,
SMELTING, SMELTING,
SPEARS,
SWORDS, SWORDS,
TAMING, TAMING,
TRIDENTS, TRIDENTS,

View File

@@ -83,6 +83,11 @@ public enum SubSkillType {
SMELTING_SECOND_SMELT, SMELTING_SECOND_SMELT,
SMELTING_UNDERSTANDING_THE_ART(8), SMELTING_UNDERSTANDING_THE_ART(8),
/* Spears */
SPEARS_SPEARS_LIMIT_BREAK(10),
SPEARS_MOMENTUM(10),
SPEARS_SPEAR_MASTERY(8),
/* Swords */ /* Swords */
SWORDS_COUNTER_ATTACK(1), SWORDS_COUNTER_ATTACK(1),
SWORDS_RUPTURE(4), SWORDS_RUPTURE(4),

View File

@@ -93,6 +93,13 @@ public enum SuperAbilityType {
"Placeholder", "Placeholder",
"Placeholder", "Placeholder",
"Placeholder"), "Placeholder"),
SPEARS_SUPER_ABILITY(
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder"),
/** /**
* Has cooldown - but has to share a skill with Super Breaker, so needs special treatment * Has cooldown - but has to share a skill with Super Breaker, so needs special treatment
@@ -216,8 +223,8 @@ public enum SuperAbilityType {
case SUPER_BREAKER -> Permissions.superBreaker(player); case SUPER_BREAKER -> Permissions.superBreaker(player);
case TREE_FELLER -> Permissions.treeFeller(player); case TREE_FELLER -> Permissions.treeFeller(player);
// TODO: once implemented, return permissions for the following abilities // TODO: once implemented, return permissions for the following abilities
case EXPLOSIVE_SHOT, TRIDENTS_SUPER_ABILITY, SUPER_SHOTGUN, MACES_SUPER_ABILITY -> case EXPLOSIVE_SHOT, TRIDENTS_SUPER_ABILITY, SUPER_SHOTGUN, MACES_SUPER_ABILITY,
false; SPEARS_SUPER_ABILITY -> false;
}; };
} }

View File

@@ -168,6 +168,7 @@ public class PlayerListener implements Listener {
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) {
return; return;
} }
// world guard main flag check // world guard main flag check
if (WorldGuardUtils.isWorldGuardLoaded() && !WorldGuardManager.getInstance() if (WorldGuardUtils.isWorldGuardLoaded() && !WorldGuardManager.getInstance()
.hasMainFlag((Player) event.getEntity())) { .hasMainFlag((Player) event.getEntity())) {
@@ -342,8 +343,8 @@ public class PlayerListener implements Listener {
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager(); FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
switch (event.getState()) { switch (event.getState()) {
// CAUGHT_FISH happens for any item caught (including junk and treasure)
case CAUGHT_FISH: case CAUGHT_FISH:
//TODO Update to new API once available! Waiting for case CAUGHT_TREASURE
if (event.getCaught() != null) { if (event.getCaught() != null) {
Item fishingCatch = (Item) event.getCaught(); Item fishingCatch = (Item) event.getCaught();
@@ -675,6 +676,10 @@ public class PlayerListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteractLowest(PlayerInteractEvent event) { public void onPlayerInteractLowest(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL) {
return;
}
/* WORLD BLACKLIST CHECK */ /* WORLD BLACKLIST CHECK */
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
return; return;
@@ -817,6 +822,10 @@ public class PlayerListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerInteractMonitor(PlayerInteractEvent event) { public void onPlayerInteractMonitor(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL) {
return;
}
/* WORLD BLACKLIST CHECK */ /* WORLD BLACKLIST CHECK */
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
return; return;

View File

@@ -0,0 +1,121 @@
package com.gmail.nossr50.skills.spears;
import static com.gmail.nossr50.util.random.ProbabilityUtil.isStaticSkillRNGSuccessful;
import static com.gmail.nossr50.util.skills.RankUtils.getRank;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import java.util.Locale;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class SpearsManager extends SkillManager {
private static @Nullable PotionEffectType swiftnessEffectType;
public SpearsManager(McMMOPlayer mmoPlayer) {
super(mmoPlayer, PrimarySkillType.SPEARS);
}
private static @Nullable PotionEffectType mockSpigotMatch(@NotNull String input) {
// Replicates match() behaviour for older versions lacking this API
final String filtered = input.toLowerCase(Locale.ROOT).replaceAll("\\s+", "_");
final NamespacedKey namespacedKey = NamespacedKey.fromString(filtered);
return (namespacedKey != null) ? Registry.EFFECT.get(namespacedKey) : null;
}
/**
* Process Momentum activation.
*/
public void potentiallyApplyMomentum() {
// Lazy initialized to avoid some backwards compatibility issues
if (swiftnessEffectType == null) {
if (mockSpigotMatch("speed") == null) {
mcMMO.p.getLogger().severe("Unable to find the Speed PotionEffectType, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Speed PotionEffectType!");
} else {
swiftnessEffectType = mockSpigotMatch("speed");
}
}
if (!canMomentumBeApplied()) {
return;
}
int momentumRank = getRank(getPlayer(), SubSkillType.SPEARS_MOMENTUM);
// Chance to activate on hit is influence by the CD
double momentumOdds = (mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank)
* Math.min(mmoPlayer.getAttackStrength(), 1.0D));
if (isStaticSkillRNGSuccessful(PrimarySkillType.SPEARS, mmoPlayer, momentumOdds)) {
if (mmoPlayer.useChatNotifications()) {
NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(),
NotificationType.SUBSKILL_MESSAGE, "Spears.SubSkill.Momentum.Activated");
}
// Momentum is success, Momentum the target
getPlayer().addPotionEffect(swiftnessEffectType.createEffect(
getMomentumTickDuration(momentumRank),
getMomentumStrength()));
// TODO: Consider adding an effect here
// ParticleEffectUtils.playMomentumEffect(target);
}
}
public static int getMomentumTickDuration(int momentumRank) {
return 20 * (momentumRank * 2);
}
public static int getMomentumStrength() {
return 2;
}
private boolean canMomentumBeApplied() {
// TODO: Potentially it should overwrite the effect if we are providing a stronger one
if (swiftnessEffectType == null) {
return false;
}
final PotionEffect currentlyAppliedPotion = getPlayer()
.getPotionEffect(swiftnessEffectType);
if (currentlyAppliedPotion != null) {
if (isCurrentPotionEffectStronger(currentlyAppliedPotion)) {
return false;
}
}
if (!Permissions.canUseSubSkill(mmoPlayer.getPlayer(), SubSkillType.SPEARS_MOMENTUM)) {
return false;
}
return true;
}
private boolean isCurrentPotionEffectStronger(@NotNull PotionEffect potionEffect) {
if (potionEffect.getAmplifier() > getMomentumStrength()) {
return true;
}
if (potionEffect.getDuration() > getMomentumTickDuration(getRank(getPlayer(),
SubSkillType.SPEARS_MOMENTUM))) {
return true;
}
return false;
}
public double getSpearMasteryBonusDamage() {
return mcMMO.p.getAdvancedConfig().getSpearMasteryRankDamageMultiplier()
* getRank(getPlayer(), SubSkillType.SPEARS_SPEAR_MASTERY);
}
}

View File

@@ -166,20 +166,6 @@ public final class ItemUtils {
} }
} }
// TODO: Unit tests
public static boolean isCrossbow(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());
}
// TODO: Unit tests
public static boolean isTrident(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey());
}
public static boolean isMace(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isMace(item.getType().getKey().getKey());
}
public static boolean hasItemInEitherHand(@NotNull Player player, Material material) { public static boolean hasItemInEitherHand(@NotNull Player player, Material material) {
return player.getInventory().getItemInMainHand().getType() == material return player.getInventory().getItemInMainHand().getType() == material
|| player.getInventory().getItemInOffHand().getType() == material; || player.getInventory().getItemInOffHand().getType() == material;
@@ -276,6 +262,46 @@ public final class ItemUtils {
return null; return null;
} }
/**
* Checks if the item is a crossbow.
*
* @param item Item to check
* @return true if the item is a crossbow, false otherwise
*/
public static boolean isCrossbow(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());
}
/**
* Checks if the item is a trident.
*
* @param item Item to check
* @return true if the item is a trident, false otherwise
*/
public static boolean isTrident(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey());
}
/**
* Checks if the item is a mace.
*
* @param item Item to check
* @return true if the item is a mace, false otherwise
*/
public static boolean isMace(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isMace(item.getType().getKey().getKey());
}
/**
* Checks if the item is a spear.
* @param item Item to check
*
* @return true if the item is a spear, false otherwise
*/
public static boolean isSpear(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isSpear(item.getType().getKey().getKey());
}
/** /**
* Checks if the item is a sword. * Checks if the item is a sword.
* *

View File

@@ -8,6 +8,7 @@ public class LogUtils {
public static final String DEBUG_STR = "[D] "; public static final String DEBUG_STR = "[D] ";
public static void debug(@NotNull Logger logger, @NotNull String message) { public static void debug(@NotNull Logger logger, @NotNull String message) {
// Messages here will get filtered based on config settings via LogFilter
logger.info(DEBUG_STR + message); logger.info(DEBUG_STR + message);
} }
} }

View File

@@ -51,9 +51,10 @@ public class MaterialMapStore {
private final @NotNull HashSet<String> tridents; private final @NotNull HashSet<String> tridents;
private final @NotNull HashSet<String> bows; private final @NotNull HashSet<String> bows;
private final @NotNull HashSet<String> crossbows; private final @NotNull HashSet<String> crossbows;
private final @NotNull HashSet<String> tools;
private final @NotNull HashSet<String> enchantables;
private final @NotNull HashSet<String> maces; private final @NotNull HashSet<String> maces;
private final @NotNull HashSet<String> spears;
private final @NotNull HashSet<String> enchantables;
private final @NotNull HashSet<String> tools;
private final @NotNull HashSet<String> ores; private final @NotNull HashSet<String> ores;
private final @NotNull HashSet<String> intendedToolPickAxe; private final @NotNull HashSet<String> intendedToolPickAxe;
@@ -95,15 +96,15 @@ public class MaterialMapStore {
crossbows = new HashSet<>(); crossbows = new HashSet<>();
stringTools = new HashSet<>(); stringTools = new HashSet<>();
prismarineTools = new HashSet<>(); prismarineTools = new HashSet<>();
tools = new HashSet<>();
swords = new HashSet<>(); swords = new HashSet<>();
axes = new HashSet<>(); axes = new HashSet<>();
pickAxes = new HashSet<>(); pickAxes = new HashSet<>();
shovels = new HashSet<>(); shovels = new HashSet<>();
hoes = new HashSet<>(); hoes = new HashSet<>();
tridents = new HashSet<>(); tridents = new HashSet<>();
spears = new HashSet<>();
maces = new HashSet<>(); maces = new HashSet<>();
tools = new HashSet<>();
enchantables = new HashSet<>(); enchantables = new HashSet<>();
@@ -459,6 +460,7 @@ public class MaterialMapStore {
enchantables.addAll(bows); enchantables.addAll(bows);
enchantables.addAll(crossbows); enchantables.addAll(crossbows);
enchantables.addAll(maces); enchantables.addAll(maces);
enchantables.addAll(spears);
enchantables.add("shears"); enchantables.add("shears");
enchantables.add("fishing_rod"); enchantables.add("fishing_rod");
@@ -484,6 +486,7 @@ public class MaterialMapStore {
fillShovels(); fillShovels();
fillTridents(); fillTridents();
fillMaces(); fillMaces();
fillSpears();
fillStringTools(); fillStringTools();
fillPrismarineTools(); fillPrismarineTools();
fillBows(); fillBows();
@@ -502,6 +505,7 @@ public class MaterialMapStore {
tools.addAll(bows); tools.addAll(bows);
tools.addAll(crossbows); tools.addAll(crossbows);
tools.addAll(maces); tools.addAll(maces);
tools.addAll(spears);
} }
private void fillBows() { private void fillBows() {
@@ -527,6 +531,16 @@ public class MaterialMapStore {
maces.add("mace"); maces.add("mace");
} }
private void fillSpears() {
spears.add("wooden_spear");
spears.add("stone_spear");
spears.add("copper_spear");
spears.add("iron_spear");
spears.add("golden_spear");
spears.add("diamond_spear");
spears.add("netherite_spear");
}
private void fillTridents() { private void fillTridents() {
tridents.add("trident"); tridents.add("trident");
} }
@@ -874,6 +888,14 @@ public class MaterialMapStore {
return maces.contains(id); return maces.contains(id);
} }
public boolean isSpear(@NotNull Material material) {
return isSpear(material.getKey().getKey());
}
public boolean isSpear(@NotNull String id) {
return spears.contains(id);
}
public boolean isLeatherArmor(@NotNull Material material) { public boolean isLeatherArmor(@NotNull Material material) {
return isLeatherArmor(material.getKey().getKey()); return isLeatherArmor(material.getKey().getKey());
} }

View File

@@ -41,6 +41,7 @@ import com.gmail.nossr50.commands.skills.MmoInfoCommand;
import com.gmail.nossr50.commands.skills.RepairCommand; import com.gmail.nossr50.commands.skills.RepairCommand;
import com.gmail.nossr50.commands.skills.SalvageCommand; import com.gmail.nossr50.commands.skills.SalvageCommand;
import com.gmail.nossr50.commands.skills.SmeltingCommand; import com.gmail.nossr50.commands.skills.SmeltingCommand;
import com.gmail.nossr50.commands.skills.SpearsCommand;
import com.gmail.nossr50.commands.skills.SwordsCommand; import com.gmail.nossr50.commands.skills.SwordsCommand;
import com.gmail.nossr50.commands.skills.TamingCommand; import com.gmail.nossr50.commands.skills.TamingCommand;
import com.gmail.nossr50.commands.skills.TridentsCommand; import com.gmail.nossr50.commands.skills.TridentsCommand;
@@ -101,6 +102,7 @@ public final class CommandRegistrationManager {
case REPAIR -> command.setExecutor(new RepairCommand()); case REPAIR -> command.setExecutor(new RepairCommand());
case SALVAGE -> command.setExecutor(new SalvageCommand()); case SALVAGE -> command.setExecutor(new SalvageCommand());
case SMELTING -> command.setExecutor(new SmeltingCommand()); case SMELTING -> command.setExecutor(new SmeltingCommand());
case SPEARS -> command.setExecutor(new SpearsCommand());
case SWORDS -> command.setExecutor(new SwordsCommand()); case SWORDS -> command.setExecutor(new SwordsCommand());
case TAMING -> command.setExecutor(new TamingCommand()); case TAMING -> command.setExecutor(new TamingCommand());
case TRIDENTS -> command.setExecutor(new TridentsCommand()); case TRIDENTS -> command.setExecutor(new TridentsCommand());

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.util.skills;
import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP; import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP;
import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED; import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED;
import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag; import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag;
import static com.gmail.nossr50.util.Permissions.canUseSubSkill;
import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile; import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
@@ -19,6 +20,7 @@ import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.archery.ArcheryManager; import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager; import com.gmail.nossr50.skills.axes.AxesManager;
import com.gmail.nossr50.skills.maces.MacesManager; import com.gmail.nossr50.skills.maces.MacesManager;
import com.gmail.nossr50.skills.spears.SpearsManager;
import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.swords.SwordsManager;
import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.tridents.TridentsManager; import com.gmail.nossr50.skills.tridents.TridentsManager;
@@ -331,6 +333,46 @@ public final class CombatUtils {
printFinalDamageDebug(player, event, mmoPlayer); printFinalDamageDebug(player, event, mmoPlayer);
} }
private static void processSpearsCombat(@NotNull LivingEntity target,
@NotNull Player player,
@NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
}
double boostedDamage = event.getDamage();
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if (mmoPlayer == null) {
return;
}
final SpearsManager spearsManager = mmoPlayer.getSpearsManager();
if (canUseSubSkill(player, SubSkillType.SPEARS_SPEAR_MASTERY)) {
boostedDamage += spearsManager.getSpearMasteryBonusDamage()
* mmoPlayer.getAttackStrength();
}
// Apply Limit Break DMG
if (canUseLimitBreak(player, target, SubSkillType.SPEARS_SPEARS_LIMIT_BREAK)) {
boostedDamage += (getLimitBreakDamage(
player, target, SubSkillType.SPEARS_SPEARS_LIMIT_BREAK)
* mmoPlayer.getAttackStrength());
}
event.setDamage(boostedDamage);
// Apply any non-damage effects here
spearsManager.potentiallyApplyMomentum();
processCombatXP(mmoPlayer, target, PrimarySkillType.SPEARS);
printFinalDamageDebug(player, event, mmoPlayer);
}
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player,
@NotNull EntityDamageByEntityEvent event) { @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) { if (event.getCause() == DamageCause.THORNS) {
@@ -391,6 +433,11 @@ public final class CombatUtils {
double boostedDamage = event.getDamage(); double boostedDamage = event.getDamage();
// TODO: Temporary hack to avoid unintended spear / unarmed interactions
if (ItemUtils.isSpear(player.getInventory().getItemInOffHand())) {
return;
}
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player); final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded //Make sure the profiles been loaded
@@ -642,6 +689,15 @@ public final class CombatUtils {
.doesPlayerHaveSkillPermission(player, PrimarySkillType.MACES)) { .doesPlayerHaveSkillPermission(player, PrimarySkillType.MACES)) {
processMacesCombat(target, player, event); processMacesCombat(target, player, event);
} }
} else if (ItemUtils.isSpear(heldItem)) {
if (!mcMMO.p.getSkillTools()
.canCombatSkillsTrigger(PrimarySkillType.SPEARS, target)) {
return;
}
if (mcMMO.p.getSkillTools()
.doesPlayerHaveSkillPermission(player, PrimarySkillType.SPEARS)) {
processSpearsCombat(target, player, event);
}
} }
} else if (entityType == EntityType.WOLF) { } else if (entityType == EntityType.WOLF) {
Wolf wolf = (Wolf) painSource; Wolf wolf = (Wolf) painSource;

View File

@@ -1,6 +1,5 @@
package com.gmail.nossr50.util.skills; package com.gmail.nossr50.util.skills;
import com.gmail.nossr50.api.exceptions.InvalidSkillException;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType;
@@ -18,6 +17,7 @@ import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -27,15 +27,16 @@ import org.jetbrains.annotations.VisibleForTesting;
public class SkillTools { public class SkillTools {
private final mcMMO pluginRef; private final mcMMO pluginRef;
// TODO: Java has immutable types now, switch to those // TODO: Java has immutable types now, switch to those
// TODO: Figure out which ones we don't need, this was copy pasted from a diff branch // TODO: Figure out which ones we don't need, this was copy pasted from a diff branch
public final @NotNull ImmutableList<String> LOCALIZED_SKILL_NAMES; public final @NotNull ImmutableList<String> LOCALIZED_SKILL_NAMES;
public final @NotNull ImmutableList<String> FORMATTED_SUBSKILL_NAMES; public final @NotNull ImmutableList<String> FORMATTED_SUBSKILL_NAMES;
public final @NotNull ImmutableSet<String> EXACT_SUBSKILL_NAMES; public final @NotNull ImmutableSet<String> EXACT_SUBSKILL_NAMES;
public final @NotNull ImmutableList<PrimarySkillType> CHILD_SKILLS; public final @NotNull ImmutableList<PrimarySkillType> CHILD_SKILLS;
public final static @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS; public static final @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
public final static @NotNull ImmutableList<PrimarySkillType> SALVAGE_PARENTS; public static final @NotNull ImmutableList<PrimarySkillType> SALVAGE_PARENTS;
public final static @NotNull ImmutableList<PrimarySkillType> SMELTING_PARENTS; public static final @NotNull ImmutableList<PrimarySkillType> SMELTING_PARENTS;
public final @NotNull ImmutableList<PrimarySkillType> COMBAT_SKILLS; public final @NotNull ImmutableList<PrimarySkillType> COMBAT_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> GATHERING_SKILLS; public final @NotNull ImmutableList<PrimarySkillType> GATHERING_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> MISC_SKILLS; public final @NotNull ImmutableList<PrimarySkillType> MISC_SKILLS;
@@ -44,73 +45,141 @@ public class SkillTools {
private final @NotNull ImmutableMap<SuperAbilityType, PrimarySkillType> superAbilityParentRelationshipMap; private final @NotNull ImmutableMap<SuperAbilityType, PrimarySkillType> superAbilityParentRelationshipMap;
private final @NotNull ImmutableMap<PrimarySkillType, Set<SubSkillType>> primarySkillChildrenMap; private final @NotNull ImmutableMap<PrimarySkillType, Set<SubSkillType>> primarySkillChildrenMap;
// The map below is for the super abilities which require readying a tool, its everything except blast mining
private final ImmutableMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap; private final ImmutableMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap;
private final ImmutableMap<PrimarySkillType, ToolType> primarySkillToolMap; private final ImmutableMap<PrimarySkillType, ToolType> primarySkillToolMap;
static { static {
// Build NON_CHILD_SKILLS once from the enum values
ArrayList<PrimarySkillType> tempNonChildSkills = new ArrayList<>(); ArrayList<PrimarySkillType> tempNonChildSkills = new ArrayList<>();
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) { for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType != PrimarySkillType.SALVAGE if (!isChildSkill(primarySkillType)) {
&& primarySkillType != PrimarySkillType.SMELTING) {
tempNonChildSkills.add(primarySkillType); tempNonChildSkills.add(primarySkillType);
} }
} }
NON_CHILD_SKILLS = ImmutableList.copyOf(tempNonChildSkills); NON_CHILD_SKILLS = ImmutableList.copyOf(tempNonChildSkills);
SALVAGE_PARENTS = ImmutableList.of(PrimarySkillType.REPAIR, PrimarySkillType.FISHING);
SMELTING_PARENTS = ImmutableList.of(PrimarySkillType.MINING, PrimarySkillType.REPAIR); SALVAGE_PARENTS = ImmutableList.of(
PrimarySkillType.REPAIR,
PrimarySkillType.FISHING
);
SMELTING_PARENTS = ImmutableList.of(
PrimarySkillType.MINING,
PrimarySkillType.REPAIR
);
} }
public SkillTools(@NotNull mcMMO pluginRef) throws InvalidSkillException { public SkillTools(@NotNull mcMMO pluginRef) {
this.pluginRef = pluginRef; this.pluginRef = pluginRef;
/* /*
* Setup subskill -> parent relationship map * Setup subskill -> parent relationship map
*/ */
EnumMap<SubSkillType, PrimarySkillType> tempSubParentMap = new EnumMap<>( this.subSkillParentRelationshipMap = buildSubSkillParentMap();
SubSkillType.class);
//Super hacky and disgusting
for (PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
String[] splitSubSkillName = subSkillType.toString().split("_");
if (primarySkillType1.toString().equalsIgnoreCase(splitSubSkillName[0])) {
//Parent Skill Found
tempSubParentMap.put(subSkillType, primarySkillType1);
}
}
}
subSkillParentRelationshipMap = ImmutableMap.copyOf(tempSubParentMap);
/* /*
* Setup primary -> (collection) subskill map * Setup primary -> (collection) subskill map
*/ */
this.primarySkillChildrenMap = buildPrimarySkillChildrenMap(subSkillParentRelationshipMap);
EnumMap<PrimarySkillType, Set<SubSkillType>> tempPrimaryChildMap = new EnumMap<>(
PrimarySkillType.class);
//Init the empty Hash Sets
for (PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
tempPrimaryChildMap.put(primarySkillType1, new HashSet<>());
}
//Fill in the hash sets
for (SubSkillType subSkillType : SubSkillType.values()) {
PrimarySkillType parentSkill = subSkillParentRelationshipMap.get(subSkillType);
//Add this subskill as a child
tempPrimaryChildMap.get(parentSkill).add(subSkillType);
}
primarySkillChildrenMap = ImmutableMap.copyOf(tempPrimaryChildMap);
/* /*
* Setup primary -> tooltype map * Setup primary -> tooltype map
*/ */
EnumMap<PrimarySkillType, ToolType> tempToolMap = new EnumMap<>(PrimarySkillType.class); this.primarySkillToolMap = buildPrimarySkillToolMap();
/*
* Setup ability -> primary map
* Setup primary -> ability map
*/
var abilityMaps = buildSuperAbilityMaps();
this.superAbilityParentRelationshipMap = abilityMaps.superAbilityParentRelationshipMap();
this.mainActivatedAbilityChildMap = abilityMaps.mainActivatedAbilityChildMap();
/*
* Build child skill list
*/
this.CHILD_SKILLS = buildChildSkills();
/*
* Build categorized skill lists
*/
this.COMBAT_SKILLS = buildCombatSkills();
this.GATHERING_SKILLS = ImmutableList.of(
PrimarySkillType.EXCAVATION,
PrimarySkillType.FISHING,
PrimarySkillType.HERBALISM,
PrimarySkillType.MINING,
PrimarySkillType.WOODCUTTING
);
this.MISC_SKILLS = ImmutableList.of(
PrimarySkillType.ACROBATICS,
PrimarySkillType.ALCHEMY,
PrimarySkillType.REPAIR,
PrimarySkillType.SALVAGE,
PrimarySkillType.SMELTING
);
/*
* Build formatted/localized/etc string lists
*/
this.LOCALIZED_SKILL_NAMES = ImmutableList.copyOf(buildLocalizedPrimarySkillNames());
this.FORMATTED_SUBSKILL_NAMES = ImmutableList.copyOf(buildFormattedSubSkillNameList());
this.EXACT_SUBSKILL_NAMES = ImmutableSet.copyOf(buildExactSubSkillNameList());
}
@VisibleForTesting
@NotNull
ImmutableMap<SubSkillType, PrimarySkillType> buildSubSkillParentMap() {
EnumMap<SubSkillType, PrimarySkillType> tempSubParentMap =
new EnumMap<>(SubSkillType.class);
// SubSkillType names use a convention: <PRIMARY>_SOMETHING
for (SubSkillType subSkillType : SubSkillType.values()) {
String enumName = subSkillType.name();
int underscoreIndex = enumName.indexOf('_');
String parentPrefix = underscoreIndex == -1
? enumName
: enumName.substring(0, underscoreIndex);
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType.name().equalsIgnoreCase(parentPrefix)) {
tempSubParentMap.put(subSkillType, primarySkillType);
break;
}
}
}
return ImmutableMap.copyOf(tempSubParentMap);
}
@VisibleForTesting
@NotNull
ImmutableMap<PrimarySkillType, Set<SubSkillType>> buildPrimarySkillChildrenMap(
ImmutableMap<SubSkillType, PrimarySkillType> subParentMap) {
EnumMap<PrimarySkillType, Set<SubSkillType>> tempPrimaryChildMap =
new EnumMap<>(PrimarySkillType.class);
// Initialize empty sets
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
tempPrimaryChildMap.put(primarySkillType, new HashSet<>());
}
// Fill sets
for (SubSkillType subSkillType : SubSkillType.values()) {
PrimarySkillType parentSkill = subParentMap.get(subSkillType);
if (parentSkill != null) {
tempPrimaryChildMap.get(parentSkill).add(subSkillType);
}
}
return ImmutableMap.copyOf(tempPrimaryChildMap);
}
@VisibleForTesting
@NotNull
ImmutableMap<PrimarySkillType, ToolType> buildPrimarySkillToolMap() {
EnumMap<PrimarySkillType, ToolType> tempToolMap =
new EnumMap<>(PrimarySkillType.class);
tempToolMap.put(PrimarySkillType.AXES, ToolType.AXE); tempToolMap.put(PrimarySkillType.AXES, ToolType.AXE);
tempToolMap.put(PrimarySkillType.WOODCUTTING, ToolType.AXE); tempToolMap.put(PrimarySkillType.WOODCUTTING, ToolType.AXE);
@@ -120,56 +189,76 @@ public class SkillTools {
tempToolMap.put(PrimarySkillType.HERBALISM, ToolType.HOE); tempToolMap.put(PrimarySkillType.HERBALISM, ToolType.HOE);
tempToolMap.put(PrimarySkillType.MINING, ToolType.PICKAXE); tempToolMap.put(PrimarySkillType.MINING, ToolType.PICKAXE);
primarySkillToolMap = ImmutableMap.copyOf(tempToolMap); return ImmutableMap.copyOf(tempToolMap);
}
/* /**
* Setup ability -> primary map * Holder for the two super ability maps, so we can build them in one pass.
* Setup primary -> ability map */
*/ @VisibleForTesting
record SuperAbilityMaps(
@NotNull ImmutableMap<SuperAbilityType, PrimarySkillType> superAbilityParentRelationshipMap,
@NotNull ImmutableMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap) {
}
EnumMap<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap = new EnumMap<>( @VisibleForTesting
SuperAbilityType.class); @NotNull
EnumMap<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap = new EnumMap<>( SuperAbilityMaps buildSuperAbilityMaps() {
PrimarySkillType.class); final Map<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap =
new EnumMap<>(SuperAbilityType.class);
final Map<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap =
new EnumMap<>(PrimarySkillType.class);
for (SuperAbilityType superAbilityType : SuperAbilityType.values()) { for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {
try { final PrimarySkillType parent = getSuperAbilityParent(superAbilityType);
PrimarySkillType parent = getSuperAbilityParent(superAbilityType); tempAbilityParentRelationshipMap.put(superAbilityType, parent);
tempAbilityParentRelationshipMap.put(superAbilityType, parent);
if (superAbilityType != SuperAbilityType.BLAST_MINING) { // This map is used only for abilities that have a tool readying phase,
//This map is used only for abilities that have a tool readying phase, so blast mining is ignored // so Blast Mining is ignored.
tempMainActivatedAbilityChildMap.put(parent, superAbilityType); if (superAbilityType != SuperAbilityType.BLAST_MINING) {
} tempMainActivatedAbilityChildMap.put(parent, superAbilityType);
} catch (InvalidSkillException e) {
e.printStackTrace();
} }
} }
superAbilityParentRelationshipMap = ImmutableMap.copyOf(tempAbilityParentRelationshipMap); return new SuperAbilityMaps(
mainActivatedAbilityChildMap = ImmutableMap.copyOf(tempMainActivatedAbilityChildMap); ImmutableMap.copyOf(tempAbilityParentRelationshipMap),
ImmutableMap.copyOf(tempMainActivatedAbilityChildMap)
/* );
* Build child skill and nonchild skill lists }
*/
@VisibleForTesting
@NotNull
ImmutableList<PrimarySkillType> buildChildSkills() {
List<PrimarySkillType> childSkills = new ArrayList<>(); List<PrimarySkillType> childSkills = new ArrayList<>();
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) { for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (isChildSkill(primarySkillType)) { if (isChildSkill(primarySkillType)) {
childSkills.add(primarySkillType); childSkills.add(primarySkillType);
} }
} }
return ImmutableList.copyOf(childSkills);
}
CHILD_SKILLS = ImmutableList.copyOf(childSkills); @VisibleForTesting
@NotNull
ImmutableList<PrimarySkillType> buildCombatSkills() {
var gameVersion = mcMMO.getCompatibilityManager().getMinecraftGameVersion();
/* if (gameVersion.isAtLeast(1, 21, 11)) {
* Build categorized skill lists // We are in a game version with Spears and Maces
*/ return ImmutableList.of(
PrimarySkillType.ARCHERY,
// We are in a game version with Maces PrimarySkillType.AXES,
if (mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { PrimarySkillType.CROSSBOWS,
COMBAT_SKILLS = ImmutableList.of( PrimarySkillType.MACES,
PrimarySkillType.SWORDS,
PrimarySkillType.SPEARS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED
);
} else if (gameVersion.isAtLeast(1, 21, 0)) {
// We are in a game version with Maces
return ImmutableList.of(
PrimarySkillType.ARCHERY, PrimarySkillType.ARCHERY,
PrimarySkillType.AXES, PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS, PrimarySkillType.CROSSBOWS,
@@ -177,42 +266,23 @@ public class SkillTools {
PrimarySkillType.SWORDS, PrimarySkillType.SWORDS,
PrimarySkillType.TAMING, PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS, PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED); PrimarySkillType.UNARMED
);
} else { } else {
// No Maces in this version // No Maces in this version
COMBAT_SKILLS = ImmutableList.of( return ImmutableList.of(
PrimarySkillType.ARCHERY, PrimarySkillType.ARCHERY,
PrimarySkillType.AXES, PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS, PrimarySkillType.CROSSBOWS,
PrimarySkillType.SWORDS, PrimarySkillType.SWORDS,
PrimarySkillType.TAMING, PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS, PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED); PrimarySkillType.UNARMED
);
} }
GATHERING_SKILLS = ImmutableList.of(
PrimarySkillType.EXCAVATION,
PrimarySkillType.FISHING,
PrimarySkillType.HERBALISM,
PrimarySkillType.MINING,
PrimarySkillType.WOODCUTTING);
MISC_SKILLS = ImmutableList.of(
PrimarySkillType.ACROBATICS,
PrimarySkillType.ALCHEMY,
PrimarySkillType.REPAIR,
PrimarySkillType.SALVAGE,
PrimarySkillType.SMELTING);
/*
* Build formatted/localized/etc string lists
*/
LOCALIZED_SKILL_NAMES = ImmutableList.copyOf(buildLocalizedPrimarySkillNames());
FORMATTED_SUBSKILL_NAMES = ImmutableList.copyOf(buildFormattedSubSkillNameList());
EXACT_SUBSKILL_NAMES = ImmutableSet.copyOf(buildExactSubSkillNameList());
} }
private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) {
throws InvalidSkillException {
return switch (superAbilityType) { return switch (superAbilityType) {
case BERSERK -> PrimarySkillType.UNARMED; case BERSERK -> PrimarySkillType.UNARMED;
case GREEN_TERRA -> PrimarySkillType.HERBALISM; case GREEN_TERRA -> PrimarySkillType.HERBALISM;
@@ -225,11 +295,12 @@ public class SkillTools {
case TRIDENTS_SUPER_ABILITY -> PrimarySkillType.TRIDENTS; case TRIDENTS_SUPER_ABILITY -> PrimarySkillType.TRIDENTS;
case EXPLOSIVE_SHOT -> PrimarySkillType.ARCHERY; case EXPLOSIVE_SHOT -> PrimarySkillType.ARCHERY;
case MACES_SUPER_ABILITY -> PrimarySkillType.MACES; case MACES_SUPER_ABILITY -> PrimarySkillType.MACES;
case SPEARS_SUPER_ABILITY -> PrimarySkillType.SPEARS;
}; };
} }
/** /**
* Makes a list of the "nice" version of sub skill names Used in tab completion mostly * Makes a list of the "nice" version of sub skill names. Used in tab completion mostly.
* *
* @return a list of formatted sub skill names * @return a list of formatted sub skill names
*/ */
@@ -272,9 +343,12 @@ public class SkillTools {
} }
/** /**
* Matches a string of a skill to a skill This is NOT case sensitive First it checks the locale * Matches a string of a skill to a skill.
* file and tries to match by the localized name of the skill Then if nothing is found it checks * This is NOT case-sensitive.
* against the hard coded "name" of the skill, which is just its name in English * <p>
* First it checks the locale file and tries to match by the localized name of the skill.
* Then if nothing is found it checks against the hard coded "name" of the skill,
* which is just its name in English.
* *
* @param skillName target skill name * @param skillName target skill name
* @return the matching PrimarySkillType if one is found, otherwise null * @return the matching PrimarySkillType if one is found, otherwise null
@@ -282,8 +356,9 @@ public class SkillTools {
public PrimarySkillType matchSkill(String skillName) { public PrimarySkillType matchSkill(String skillName) {
if (!pluginRef.getGeneralConfig().getLocale().equalsIgnoreCase("en_US")) { if (!pluginRef.getGeneralConfig().getLocale().equalsIgnoreCase("en_US")) {
for (PrimarySkillType type : PrimarySkillType.values()) { for (PrimarySkillType type : PrimarySkillType.values()) {
if (skillName.equalsIgnoreCase(LocaleLoader.getString( String localized = LocaleLoader.getString(
StringUtils.getCapitalized(type.name()) + ".SkillName"))) { StringUtils.getCapitalized(type.name()) + ".SkillName");
if (skillName.equalsIgnoreCase(localized)) {
return type; return type;
} }
} }
@@ -297,15 +372,15 @@ public class SkillTools {
if (!skillName.equalsIgnoreCase("all")) { if (!skillName.equalsIgnoreCase("all")) {
pluginRef.getLogger() pluginRef.getLogger()
.warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize .warning("Invalid mcMMO skill (" + skillName + ")"); // TODO: Localize
} }
return null; return null;
} }
/** /**
* Gets the PrimarySkillStype to which a SubSkillType belongs Return null if it does not belong * Gets the PrimarySkillType to which a SubSkillType belongs.
* to one.. which should be impossible in most circumstances * Returns null if it does not belong to one (which should be impossible in most circumstances).
* *
* @param subSkillType target subskill * @param subSkillType target subskill
* @return the PrimarySkillType of this SubSkill, null if it doesn't exist * @return the PrimarySkillType of this SubSkill, null if it doesn't exist
@@ -315,8 +390,8 @@ public class SkillTools {
} }
/** /**
* Gets the PrimarySkillStype to which a SuperAbilityType belongs Return null if it does not * Gets the PrimarySkillType to which a SuperAbilityType belongs.
* belong to one.. which should be impossible in most circumstances * Returns null if it does not belong to one (which should be impossible in most circumstances).
* *
* @param superAbilityType target super ability * @param superAbilityType target super ability
* @return the PrimarySkillType of this SuperAbilityType, null if it doesn't exist * @return the PrimarySkillType of this SuperAbilityType, null if it doesn't exist
@@ -326,16 +401,15 @@ public class SkillTools {
} }
public SuperAbilityType getSuperAbility(PrimarySkillType primarySkillType) { public SuperAbilityType getSuperAbility(PrimarySkillType primarySkillType) {
if (mainActivatedAbilityChildMap.get(primarySkillType) == null) {
return null;
}
return mainActivatedAbilityChildMap.get(primarySkillType); return mainActivatedAbilityChildMap.get(primarySkillType);
} }
public boolean isSuperAbilityUnlocked(PrimarySkillType primarySkillType, Player player) { public boolean isSuperAbilityUnlocked(PrimarySkillType primarySkillType, Player player) {
SuperAbilityType superAbilityType = mcMMO.p.getSkillTools() SuperAbilityType superAbilityType = getSuperAbility(primarySkillType);
.getSuperAbility(primarySkillType); if (superAbilityType == null) {
return false;
}
SubSkillType subSkillType = superAbilityType.getSubSkillTypeDefinition(); SubSkillType subSkillType = superAbilityType.getSubSkillTypeDefinition();
return RankUtils.hasUnlockedSubskill(player, subSkillType); return RankUtils.hasUnlockedSubskill(player, subSkillType);
} }
@@ -368,7 +442,6 @@ public class SkillTools {
return ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType); return ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType);
} }
// TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
public static boolean isChildSkill(PrimarySkillType primarySkillType) { public static boolean isChildSkill(PrimarySkillType primarySkillType) {
return switch (primarySkillType) { return switch (primarySkillType) {
case SALVAGE, SMELTING -> true; case SALVAGE, SMELTING -> true;
@@ -392,8 +465,10 @@ public class SkillTools {
} }
public boolean canCombatSkillsTrigger(PrimarySkillType primarySkillType, Entity target) { public boolean canCombatSkillsTrigger(PrimarySkillType primarySkillType, Entity target) {
return (target instanceof Player || (target instanceof Tameable boolean isPlayerOrTamed = (target instanceof Player)
&& ((Tameable) target).isTamed())) ? getPVPEnabled(primarySkillType) || (target instanceof Tameable && ((Tameable) target).isTamed());
return isPlayerOrTamed
? getPVPEnabled(primarySkillType)
: getPVEEnabled(primarySkillType); : getPVEEnabled(primarySkillType);
} }
@@ -410,7 +485,7 @@ public class SkillTools {
} }
public int getLevelCap(@NotNull PrimarySkillType primarySkillType) { public int getLevelCap(@NotNull PrimarySkillType primarySkillType) {
return mcMMO.p.getGeneralConfig().getLevelCap(primarySkillType); return pluginRef.getGeneralConfig().getLevelCap(primarySkillType);
} }
/** /**
@@ -445,17 +520,12 @@ public class SkillTools {
} }
public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents( public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents(
PrimarySkillType childSkill) PrimarySkillType childSkill) throws IllegalArgumentException {
throws IllegalArgumentException { return switch (childSkill) {
switch (childSkill) { case SALVAGE -> SALVAGE_PARENTS;
case SALVAGE -> { case SMELTING -> SMELTING_PARENTS;
return SALVAGE_PARENTS;
}
case SMELTING -> {
return SMELTING_PARENTS;
}
default -> throw new IllegalArgumentException( default -> throw new IllegalArgumentException(
"Skill " + childSkill + " is not a child skill"); "Skill " + childSkill + " is not a child skill");
} };
} }
} }

View File

@@ -544,7 +544,25 @@ public class TextComponentFactory {
componentBuilder.append(Component.newline()); componentBuilder.append(Component.newline());
} }
/**
* @deprecated use appendSubSkillTextComponents(Player, List<Component>, PrimarySkillType)
* @param player target player
* @param textComponents list to append to
* @param parentSkill the parent skill
*/
@Deprecated(since = "2.2.046", forRemoval = true)
public static void getSubSkillTextComponents(Player player, List<Component> textComponents, public static void getSubSkillTextComponents(Player player, List<Component> textComponents,
PrimarySkillType parentSkill) {
appendSubSkillTextComponents(player, textComponents, parentSkill);
}
/**
* Appends sub-skill text components to a list for a given parent skill
* @param player target player
* @param textComponents list to append to
* @param parentSkill the parent skill
*/
public static void appendSubSkillTextComponents(Player player, List<Component> textComponents,
PrimarySkillType parentSkill) { PrimarySkillType parentSkill) {
for (SubSkillType subSkillType : SubSkillType.values()) { for (SubSkillType subSkillType : SubSkillType.values()) {
if (subSkillType.getParentSkill() == parentSkill) { if (subSkillType.getParentSkill() == parentSkill) {

View File

@@ -648,3 +648,18 @@ Skills:
Rank_2: 15 Rank_2: 15
Rank_3: 20 Rank_3: 20
Rank_4: 33 Rank_4: 33
Spears:
SpearMastery:
Rank_Damage_Multiplier: 0.4
Momentum:
Chance_To_Apply_On_Hit:
Rank_1: 5
Rank_2: 10
Rank_3: 15
Rank_4: 20
Rank_5: 25
Rank_6: 30
Rank_7: 35
Rank_8: 40
Rank_9: 45
Rank_10: 50

View File

@@ -229,6 +229,7 @@ Hardcore:
Tridents: false Tridents: false
Crossbows: false Crossbows: false
Maces: false Maces: false
Spears: false
Vampirism: Vampirism:
Leech_Percentage: 5.0 Leech_Percentage: 5.0
Level_Threshold: 0 Level_Threshold: 0
@@ -249,6 +250,7 @@ Hardcore:
Tridents: false Tridents: false
Crossbows: false Crossbows: false
Maces: false Maces: false
Spears: false
# #
# Settings for SMP Mods # Settings for SMP Mods
@@ -427,6 +429,10 @@ Skills:
Enabled_For_PVP: true Enabled_For_PVP: true
Enabled_For_PVE: true Enabled_For_PVE: true
Level_Cap: 0 Level_Cap: 0
Spears:
Enabled_For_PVP: true
Enabled_For_PVE: true
Level_Cap: 0
Taming: Taming:
Enabled_For_PVP: true Enabled_For_PVP: true
Enabled_For_PVE: true Enabled_For_PVE: true

View File

@@ -95,6 +95,10 @@ Experience_Bars:
Enable: true Enable: true
Color: BLUE Color: BLUE
BarStyle: SEGMENTED_6 BarStyle: SEGMENTED_6
Spears:
Enable: true
Color: BLUE
BarStyle: SEGMENTED_6
Repair: Repair:
Enable: true Enable: true
Color: PURPLE Color: PURPLE
@@ -167,6 +171,7 @@ Experience_Formula:
# Experience gained will get multiplied by these values. 1.0 by default, 0.5 means half XP gained. This happens right before multiplying the XP by the global multiplier. # Experience gained will get multiplied by these values. 1.0 by default, 0.5 means half XP gained. This happens right before multiplying the XP by the global multiplier.
Skill_Multiplier: Skill_Multiplier:
Spears: 1.0
Maces: 1.0 Maces: 1.0
Crossbows: 1.0 Crossbows: 1.0
Tridents: 1.0 Tridents: 1.0
@@ -218,6 +223,7 @@ Diminished_Returns:
Crossbows: 20000 Crossbows: 20000
Tridents: 20000 Tridents: 20000
Maces: 20000 Maces: 20000
Spears: 20000
Time_Interval: 10 Time_Interval: 10
@@ -582,6 +588,7 @@ Experience_Values:
Taming: Taming:
Animal_Taming: Animal_Taming:
Camel: 1300 Camel: 1300
Camel_Husk: 1300
Sniffer: 1500 Sniffer: 1500
Snifflet: 900 Snifflet: 900
Llama: 1200 Llama: 1200
@@ -600,12 +607,15 @@ Experience_Values:
Goat: 250 Goat: 250
Axolotl: 600 Axolotl: 600
Frog: 900 Frog: 900
Nautilus: 1700
Zombie_Nautilus: 1700
Combat: Combat:
Multiplier: Multiplier:
Animals: 1.0 Animals: 1.0
Armadillo: 1.1 Armadillo: 1.1
Creeper: 4.0 Creeper: 4.0
Skeleton: 3.0 Skeleton: 3.0
Parched: 2.5
Spider: 2.0 Spider: 2.0
Giant: 4.0 Giant: 4.0
Zombie: 2.0 Zombie: 2.0
@@ -683,6 +693,7 @@ Experience_Values:
Sniffer: 1.1 Sniffer: 1.1
Snifflet: 1.1 Snifflet: 1.1
Camel: 1.2 Camel: 1.2
Camel_Husk: 1.25
Bogged: 2.0 Bogged: 2.0
Breeze: 4.0 Breeze: 4.0
Armor_Stand: 0.0 Armor_Stand: 0.0

View File

@@ -27,6 +27,7 @@ JSON.Salvage=Salvage
JSON.Swords=Swords JSON.Swords=Swords
JSON.Taming=Taming JSON.Taming=Taming
JSON.Tridents=Tridents JSON.Tridents=Tridents
JSON.Spears=Spears
JSON.Maces=Maces JSON.Maces=Maces
JSON.Unarmed=Unarmed JSON.Unarmed=Unarmed
JSON.Woodcutting=Woodcutting JSON.Woodcutting=Woodcutting
@@ -98,6 +99,7 @@ Overhaul.Name.Smelting=Smelting
Overhaul.Name.Swords=Swords Overhaul.Name.Swords=Swords
Overhaul.Name.Taming=Taming Overhaul.Name.Taming=Taming
Overhaul.Name.Tridents=Tridents Overhaul.Name.Tridents=Tridents
Overhaul.Name.Spears=Spears
Overhaul.Name.Maces=Maces Overhaul.Name.Maces=Maces
Overhaul.Name.Unarmed=Unarmed Overhaul.Name.Unarmed=Unarmed
Overhaul.Name.Woodcutting=Woodcutting Overhaul.Name.Woodcutting=Woodcutting
@@ -125,6 +127,7 @@ XPBar.Smelting=Smelting Lv.&6{0}
XPBar.Swords=Swords Lv.&6{0} XPBar.Swords=Swords Lv.&6{0}
XPBar.Taming=Taming Lv.&6{0} XPBar.Taming=Taming Lv.&6{0}
XPBar.Tridents=Tridents Lv.&6{0} XPBar.Tridents=Tridents Lv.&6{0}
XPBar.Spears=Spears Lv.&6{0}
XPBar.Maces=Maces Lv.&6{0} XPBar.Maces=Maces Lv.&6{0}
XPBar.Unarmed=Unarmed Lv.&6{0} XPBar.Unarmed=Unarmed Lv.&6{0}
XPBar.Woodcutting=Woodcutting Lv.&6{0} XPBar.Woodcutting=Woodcutting Lv.&6{0}
@@ -474,6 +477,24 @@ Maces.SubSkill.Cripple.Stat=Cripple Chance
Maces.SubSkill.Cripple.Stat.Extra=[[DARK_AQUA]]Cripple Duration: &e{0}s&a vs Players, &e{1}s&a vs Mobs. Maces.SubSkill.Cripple.Stat.Extra=[[DARK_AQUA]]Cripple Duration: &e{0}s&a vs Players, &e{1}s&a vs Mobs.
Maces.Listener=Maces: Maces.Listener=Maces:
#SPEARS
Spears.SkillName=SPEARS
Spears.Ability.Lower=&7You lower your spear.
Spears.Ability.Ready=&3You &6ready&3 your spear.
Spears.SubSkill.SpearsLimitBreak.Name=Spears Limit Break
Spears.SubSkill.SpearsLimitBreak.Description=Breaking your limits. Increased damage against tough opponents. Intended for PVP, up to server settings for whether it will boost damage in PVE.
Spears.SubSkill.SpearsLimitBreak.Stat=Limit Break Max DMG
Spears.SubSkill.SpearAbility.Name=WIP
Spears.SubSkill.Momentum.Name=Momentum
Spears.SubSkill.Momentum.Description=Adds a chance to increase movement speed for a short duration when attacking.
Spears.SubSkill.Momentum.Stat=Momentum Chance
Spears.SubSkill.Momentum.Stat.Extra=[[DARK_AQUA]]Momentum Duration: &e{0}s
Spears.SubSkill.Momentum.Activated=MOMENTUM ACTIVATED!
Spears.SubSkill.SpearMastery.Name=Spear Mastery
Spears.SubSkill.SpearMastery.Description=Adds bonus damage to your attacks.
Spears.SubSkill.SpearMastery.Stat=Spear Mastery Bonus DMG
Spears.Listener=Spears:
#SWORDS #SWORDS
Swords.Ability.Lower=&7You lower your sword. Swords.Ability.Lower=&7You lower your sword.
Swords.Ability.Ready=&3You &6ready&3 your Sword. Swords.Ability.Ready=&3You &6ready&3 your Sword.
@@ -913,6 +934,7 @@ Commands.XPGain.Repair=Repairing
Commands.XPGain.Swords=Attacking Monsters Commands.XPGain.Swords=Attacking Monsters
Commands.XPGain.Taming=Animal Taming, or combat w/ your wolves Commands.XPGain.Taming=Animal Taming, or combat w/ your wolves
Commands.XPGain.Tridents=Attacking Monsters Commands.XPGain.Tridents=Attacking Monsters
Commands.XPGain.Spears=Attacking Monsters
Commands.XPGain.Unarmed=Attacking Monsters Commands.XPGain.Unarmed=Attacking Monsters
Commands.XPGain.Woodcutting=Chopping down trees Commands.XPGain.Woodcutting=Chopping down trees
Commands.XPGain=&8XP GAIN: &f{0} Commands.XPGain=&8XP GAIN: &f{0}
@@ -1047,12 +1069,12 @@ Guides.Woodcutting.Section.1=&3How does Tree Feller work?\n&eTree Feller is an a
Guides.Woodcutting.Section.2=&3How does Leaf Blower work?\n&eLeaf Blower is a passive ability that will cause leaf\n&eblocks to break instantly when hit with an axe. By default,\n&ethis ability unlocks at level 100. Guides.Woodcutting.Section.2=&3How does Leaf Blower work?\n&eLeaf Blower is a passive ability that will cause leaf\n&eblocks to break instantly when hit with an axe. By default,\n&ethis ability unlocks at level 100.
Guides.Woodcutting.Section.3=&3How do Double Drops work?\n&eThis passive ability gives you a chance to obtain an extra\n&eblock for every log you chop. Guides.Woodcutting.Section.3=&3How do Double Drops work?\n&eThis passive ability gives you a chance to obtain an extra\n&eblock for every log you chop.
# Crossbows # Crossbows
Guides.Crossbows.Section.0=&3About Crossbows:\n&eCrossbows is all about shooting with your crossbow.\n\n&3XP GAIN:\n&eXP is gained whenever you shoot mobs with a crossbow.\nThis is a WIP skill and more information will be added soon. Guides.Crossbows.Section.0=&3About Crossbows:\n&eCrossbows is all about shooting with your crossbow.\n\n&3XP GAIN:\n&eXP is gained whenever you shoot mobs with a crossbow.
Guides.Crossbows.Section.1=&3How does Trickshot work?\n&eTrickshot is an passive ability, you shoot your bolts at a shallow angle with a crossbow to attempt a Trickshot. This will cause the arrow to ricochet off of blocks and potentially hit a target. The number of potential bounces from a ricochet depend on the rank of Trickshot. Guides.Crossbows.Section.1=&3How does Trickshot work?\n&eTrickshot is an passive ability, you shoot your bolts at a shallow angle with a crossbow to attempt a Trickshot. This will cause the arrow to ricochet off of blocks and potentially hit a target. The number of potential bounces from a ricochet depend on the rank of Trickshot.
# Tridents # Tridents
Guides.Tridents.Section.0=&3About Tridents:\n&eTridents skill involves impaling foes with your trident.\n\n&3XP GAIN:\n&eXP is gained whenever you hit mobs with a trident.\nThis is a WIP skill and more information will be added soon. Guides.Tridents.Section.0=&3About Tridents:\n&eTridents skill involves impaling foes with your trident.\n\n&3XP GAIN:\n&eXP is gained whenever you hit mobs with a trident.
Guides.Maces.Section.0=&3About Maces:\n&eMaces is all about smashing your foes with a mace.\n\n&3XP GAIN:\n&eXP is gained whenever you hit mobs with a mace.\nThis is a WIP skill and more information will be added soon. Guides.Maces.Section.0=&3About Maces:\n&eMaces is all about smashing your foes with a mace.\n\n&3XP GAIN:\n&eXP is gained whenever you hit mobs with a mace.
Guides.Spears.Section.0=&3About Spears:\n&eSpears is all about impaling your foes with a spear.\n\n&3XP GAIN:\n&eXP is gained whenever you hit mobs with a spear.
#INSPECT #INSPECT
Inspect.Offline= &cYou do not have permission to inspect offline players! Inspect.Offline= &cYou do not have permission to inspect offline players!
Inspect.OfflineStats=mcMMO Stats for Offline Player &e{0} Inspect.OfflineStats=mcMMO Stats for Offline Player &e{0}

View File

@@ -1,20 +1,20 @@
name: mcMMO name: mcMMO
version: ${project.version} version: ${project.version}
description: > description: >
The goal of mcMMO is to take core Minecraft game mechanics and expand them into The goal of mcMMO is to take core Minecraft game mechanics and expand them into
add an extensive and quality RPG experience. Everything in mcMMO has been carefully add an extensive and quality RPG experience. Everything in mcMMO has been carefully
thought out and is constantly being improved upon. Currently, mcMMO adds thirteen thought out and is constantly being improved upon. Currently, mcMMO adds thirteen
unique skills to train and level in. Each of these skills is highly customizable unique skills to train and level in. Each of these skills is highly customizable
through our configuration files, allowing server admins to tweak mcMMO to best suit through our configuration files, allowing server admins to tweak mcMMO to best suit
the needs of his or her server. Know that the mcMMO team is dedicated to providing the needs of his or her server. Know that the mcMMO team is dedicated to providing
an ever-evolving experience, and that we carefully read all feedback and bug reports an ever-evolving experience, and that we carefully read all feedback and bug reports
in order to evaluate and balance the mechanics of mcMMO in every update. in order to evaluate and balance the mechanics of mcMMO in every update.
author: nossr50 author: nossr50
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, electronicboy, kashike] authors: [ GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, electronicboy, kashike ]
website: https://www.mcmmo.org website: https://www.mcmmo.org
main: com.gmail.nossr50.mcMMO main: com.gmail.nossr50.mcMMO
softdepend: [WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib] softdepend: [ WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib ]
load: POSTWORLD load: POSTWORLD
folia-supported: true folia-supported: true
api-version: 1.13 api-version: 1.13
@@ -26,14 +26,14 @@ commands:
mmocompat: mmocompat:
description: Information about the server and whether its considered fully compatible or running in compatibility mode description: Information about the server and whether its considered fully compatible or running in compatibility mode
mmodebug: mmodebug:
aliases: [mcmmodebugmode] aliases: [ mcmmodebugmode ]
description: Toggles a debug mode which will print useful information to chat description: Toggles a debug mode which will print useful information to chat
mmoinfo: mmoinfo:
aliases: [mcinfo] aliases: [ mcinfo ]
description: Info pages for mcMMO description: Info pages for mcMMO
permission: mcmmo.commands.mmoinfo permission: mcmmo.commands.mmoinfo
xprate: xprate:
aliases: [mcxprate] aliases: [ mcxprate ]
description: Modify the xp rate or start an event description: Modify the xp rate or start an event
permission: mcmmo.commands.xprate permission: mcmmo.commands.xprate
mcmmo: mcmmo:
@@ -59,7 +59,7 @@ commands:
permission: mcmmo.commands.mcrefresh permission: mcmmo.commands.mcrefresh
mccooldown: mccooldown:
description: Show the cooldowns on all your mcMMO abilities description: Show the cooldowns on all your mcMMO abilities
aliases: [mccooldowns] aliases: [ mccooldowns ]
permission: mcmmo.commands.mccooldown permission: mcmmo.commands.mccooldown
mcchatspy: mcchatspy:
description: Toggle mcMMO Party Chat spying on/off description: Toggle mcMMO Party Chat spying on/off
@@ -68,7 +68,7 @@ commands:
description: Toggle mcMMO god-mode on/off description: Toggle mcMMO god-mode on/off
permission: mcmmo.commands.mcgod permission: mcmmo.commands.mcgod
mcstats: mcstats:
aliases: [stats] aliases: [ stats ]
description: Shows your mcMMO stats and xp description: Shows your mcMMO stats and xp
permission: mcmmo.commands.mcstats permission: mcmmo.commands.mcstats
mcremove: mcremove:
@@ -84,7 +84,7 @@ commands:
description: Create/join a party description: Create/join a party
permission: mcmmo.commands.party permission: mcmmo.commands.party
inspect: inspect:
aliases: [mcinspect, mmoinspect] aliases: [ mcinspect, mmoinspect ]
description: View detailed mcMMO info on another player description: View detailed mcMMO info on another player
permission: mcmmo.commands.inspect permission: mcmmo.commands.inspect
mmoshowdb: mmoshowdb:
@@ -94,7 +94,7 @@ commands:
description: Convert between different database and formula types description: Convert between different database and formula types
permission: mcmmo.commands.mcconvert permission: mcmmo.commands.mcconvert
partychat: partychat:
aliases: [pc, p] aliases: [ pc, p ]
description: Toggle Party chat or send party chat messages description: Toggle Party chat or send party chat messages
permission: mcmmo.chat.partychat permission: mcmmo.chat.partychat
skillreset: skillreset:
@@ -145,6 +145,9 @@ commands:
smelting: smelting:
description: Detailed mcMMO skill info description: Detailed mcMMO skill info
permission: mcmmo.commands.smelting permission: mcmmo.commands.smelting
spears:
description: Detailed mcMMO skill info
permission: mcmmo.commands.spears
alchemy: alchemy:
description: Detailed mcMMO skill info description: Detailed mcMMO skill info
permission: mcmmo.commands.alchemy permission: mcmmo.commands.alchemy
@@ -157,24 +160,24 @@ commands:
mmopower: mmopower:
description: Shows skill mastery and power level info description: Shows skill mastery and power level info
permission: mcmmo.commands.mmopower permission: mcmmo.commands.mmopower
aliases: [mmopowerlevel, powerlevel] aliases: [ mmopowerlevel, powerlevel ]
adminchat: adminchat:
aliases: [ac, a] aliases: [ ac, a ]
description: Toggle Admin chat or send admin chat messages description: Toggle Admin chat or send admin chat messages
permission: mcmmo.chat.adminchat permission: mcmmo.chat.adminchat
mcpurge: mcpurge:
description: Purge users with 0 powerlevel and/or who haven't connected in several months from the server DB. description: Purge users with 0 powerlevel and/or who haven't connected in several months from the server DB.
permission: mcmmo.commands.mcpurge permission: mcmmo.commands.mcpurge
mcnotify: mcnotify:
aliases: [notify] aliases: [ notify ]
description: Toggle mcMMO abilities chat display notifications on/off description: Toggle mcMMO abilities chat display notifications on/off
permission: mcmmo.commands.mcnotify permission: mcmmo.commands.mcnotify
mcscoreboard: mcscoreboard:
aliases: [mcsb] aliases: [ mcsb ]
description: Manage your mcMMO Scoreboard description: Manage your mcMMO Scoreboard
permission: mcmmo.commands.mcscoreboard permission: mcmmo.commands.mcscoreboard
mcmmoreloadlocale: mcmmoreloadlocale:
aliases: [mcreloadlocale] aliases: [ mcreloadlocale ]
description: Reloads locale description: Reloads locale
permission: mcmmo.commands.reloadlocale permission: mcmmo.commands.reloadlocale
permissions: permissions:
@@ -237,6 +240,7 @@ permissions:
mcmmo.ability.repair.all: true mcmmo.ability.repair.all: true
mcmmo.ability.salvage.all: true mcmmo.ability.salvage.all: true
mcmmo.ability.smelting.all: true mcmmo.ability.smelting.all: true
mcmmo.ability.spears.all: true
mcmmo.ability.swords.all: true mcmmo.ability.swords.all: true
mcmmo.ability.taming.all: true mcmmo.ability.taming.all: true
mcmmo.ability.tridents.all: true mcmmo.ability.tridents.all: true
@@ -320,19 +324,19 @@ permissions:
mcmmo.ability.axes.skullsplitter: mcmmo.ability.axes.skullsplitter:
description: Allows access to the Skull Splitter ability description: Allows access to the Skull Splitter ability
mcmmo.ability.crossbows.*: mcmmo.ability.crossbows.*:
description: Allows access to all Crossbows abilities description: Allows access to all Crossbows abilities
children: children:
mcmmo.ability.crossbows.all: true mcmmo.ability.crossbows.all: true
mcmmo.ability.crossbows.all: mcmmo.ability.crossbows.all:
description: Allows access to all Crossbows abilities description: Allows access to all Crossbows abilities
children: children:
mcmmo.ability.crossbows.trickshot: true mcmmo.ability.crossbows.trickshot: true
mcmmo.ability.crossbows.poweredshot: true mcmmo.ability.crossbows.poweredshot: true
mcmmo.ability.crossbows.crossbowslimitbreak: true mcmmo.ability.crossbows.crossbowslimitbreak: true
mcmmo.ability.crossbows.crossbowslimitbreak: mcmmo.ability.crossbows.crossbowslimitbreak:
description: Adds damage to crossbows description: Adds damage to crossbows
mcmmo.ability.crossbows.trickshot: mcmmo.ability.crossbows.trickshot:
description: Allows access to the Trick Shot ability description: Allows access to the Trick Shot ability
mcmmo.ability.crossbows.poweredshot: mcmmo.ability.crossbows.poweredshot:
description: Allows access to the Powered Shot ability description: Allows access to the Powered Shot ability
mcmmo.ability.excavation.*: mcmmo.ability.excavation.*:
@@ -646,6 +650,23 @@ permissions:
description: Allows access to the Second Smelt ability description: Allows access to the Second Smelt ability
mcmmo.ability.smelting.vanillaxpboost: mcmmo.ability.smelting.vanillaxpboost:
description: Allows vanilla XP boost from Smelting description: Allows vanilla XP boost from Smelting
mcmmo.ability.spears.*:
default: false
description: Allows access to all Spear abilities
children:
mcmmo.ability.spears.all: true
mcmmo.ability.spears.all:
description: Allows access to all Spear abilities
children:
mcmmo.ability.spears.spearslimitbreak: true
mcmmo.ability.spears.momentum: true
mcmmo.ability.spears.spearmastery: true
mcmmo.ability.spears.spearslimitbreak:
description: Adds damage to spears
mcmmo.ability.spears.momentum:
description: Allows access to the Spear Momentum ability
mcmmo.ability.spears.spearmastery:
description: Allows access to the Spear Mastery ability
mcmmo.ability.swords.*: mcmmo.ability.swords.*:
default: false default: false
description: Allows access to all Swords abilities description: Allows access to all Swords abilities
@@ -885,6 +906,7 @@ permissions:
mcmmo.commands.repair: true mcmmo.commands.repair: true
mcmmo.commands.salvage: true mcmmo.commands.salvage: true
mcmmo.commands.smelting: true mcmmo.commands.smelting: true
mcmmo.commands.spears: true
mcmmo.commands.swords: true mcmmo.commands.swords: true
mcmmo.commands.taming: true mcmmo.commands.taming: true
mcmmo.commands.unarmed: true mcmmo.commands.unarmed: true
@@ -898,7 +920,7 @@ permissions:
mcmmo.commands.addxp: true mcmmo.commands.addxp: true
mcmmo.commands.addxp.others: true mcmmo.commands.addxp.others: true
mcmmo.commands.defaults: true mcmmo.commands.defaults: true
# mcmmo.commands.hardcore.all: true # mcmmo.commands.hardcore.all: true
mcmmo.commands.inspect.far: true mcmmo.commands.inspect.far: true
mcmmo.commands.inspect.hidden: true mcmmo.commands.inspect.hidden: true
mcmmo.commands.mcability.others: true mcmmo.commands.mcability.others: true
@@ -918,7 +940,7 @@ permissions:
mcmmo.commands.ptp.world.all: true mcmmo.commands.ptp.world.all: true
mcmmo.commands.reloadlocale: true mcmmo.commands.reloadlocale: true
mcmmo.commands.skillreset.all: true mcmmo.commands.skillreset.all: true
# mcmmo.commands.vampirism.all: true # mcmmo.commands.vampirism.all: true
mcmmo.commands.xprate.all: true mcmmo.commands.xprate.all: true
mcmmo.commands.acrobatics: mcmmo.commands.acrobatics:
description: Allows access to the acrobatics command description: Allows access to the acrobatics command
@@ -1058,6 +1080,7 @@ permissions:
mcmmo.commands.mctop.repair: true mcmmo.commands.mctop.repair: true
mcmmo.commands.mctop.salvage: true mcmmo.commands.mctop.salvage: true
mcmmo.commands.mctop.smelting: true mcmmo.commands.mctop.smelting: true
mcmmo.commands.mctop.spears: true
mcmmo.commands.mctop.swords: true mcmmo.commands.mctop.swords: true
mcmmo.commands.mctop.taming: true mcmmo.commands.mctop.taming: true
mcmmo.commands.mctop.tridents: true mcmmo.commands.mctop.tridents: true
@@ -1091,6 +1114,8 @@ permissions:
description: Allows access to the mctop command for salvage description: Allows access to the mctop command for salvage
mcmmo.commands.mctop.smelting: mcmmo.commands.mctop.smelting:
description: Allows access to the mctop command for smelting description: Allows access to the mctop command for smelting
mcmmo.commands.mctop.spears:
description: Allows access to the mctop command for spears
mcmmo.commands.mctop.swords: mcmmo.commands.mctop.swords:
description: Allows access to the mctop command for swords description: Allows access to the mctop command for swords
mcmmo.commands.mctop.taming: mcmmo.commands.mctop.taming:
@@ -1239,6 +1264,7 @@ permissions:
mcmmo.commands.skillreset.repair: true mcmmo.commands.skillreset.repair: true
mcmmo.commands.skillreset.salvage: true mcmmo.commands.skillreset.salvage: true
mcmmo.commands.skillreset.smelting: true mcmmo.commands.skillreset.smelting: true
mcmmo.commands.skillreset.spears: true
mcmmo.commands.skillreset.swords: true mcmmo.commands.skillreset.swords: true
mcmmo.commands.skillreset.taming: true mcmmo.commands.skillreset.taming: true
mcmmo.commands.skillreset.unarmed: true mcmmo.commands.skillreset.unarmed: true
@@ -1268,6 +1294,8 @@ permissions:
description: Allows access to the skillreset command for crossbows description: Allows access to the skillreset command for crossbows
mcmmo.commands.skillreset.tridents: mcmmo.commands.skillreset.tridents:
description: Allows access to the skillreset command for tridents description: Allows access to the skillreset command for tridents
mcmmo.commands.skillreset.spears:
description: Allows access to the skillreset command for spears
mcmmo.commands.skillreset.maces: mcmmo.commands.skillreset.maces:
description: Allows access to the skillreset command for maces description: Allows access to the skillreset command for maces
mcmmo.commands.skillreset.others.*: mcmmo.commands.skillreset.others.*:
@@ -1290,6 +1318,7 @@ permissions:
mcmmo.commands.skillreset.others.repair: true mcmmo.commands.skillreset.others.repair: true
mcmmo.commands.skillreset.others.salvage: true mcmmo.commands.skillreset.others.salvage: true
mcmmo.commands.skillreset.others.smelting: true mcmmo.commands.skillreset.others.smelting: true
mcmmo.commands.skillreset.others.spears: true
mcmmo.commands.skillreset.others.swords: true mcmmo.commands.skillreset.others.swords: true
mcmmo.commands.skillreset.others.taming: true mcmmo.commands.skillreset.others.taming: true
mcmmo.commands.skillreset.others.unarmed: true mcmmo.commands.skillreset.others.unarmed: true
@@ -1321,6 +1350,8 @@ permissions:
description: Allows access to the skillreset command for salvage for other players description: Allows access to the skillreset command for salvage for other players
mcmmo.commands.skillreset.others.smelting: mcmmo.commands.skillreset.others.smelting:
description: Allows access to the skillreset command for smelting for other players description: Allows access to the skillreset command for smelting for other players
mcmmo.commands.skillreset.others.spears:
description: Allows access to the skillreset command for spears for other players
mcmmo.commands.skillreset.others.swords: mcmmo.commands.skillreset.others.swords:
description: Allows access to the skillreset command for swords for other players description: Allows access to the skillreset command for swords for other players
mcmmo.commands.skillreset.others.taming: mcmmo.commands.skillreset.others.taming:
@@ -1497,6 +1528,7 @@ permissions:
mcmmo.perks.lucky.repair: true mcmmo.perks.lucky.repair: true
mcmmo.perks.lucky.salvage: true mcmmo.perks.lucky.salvage: true
mcmmo.perks.lucky.smelting: true mcmmo.perks.lucky.smelting: true
mcmmo.perks.lucky.spears: true
mcmmo.perks.lucky.swords: true mcmmo.perks.lucky.swords: true
mcmmo.perks.lucky.taming: true mcmmo.perks.lucky.taming: true
mcmmo.perks.lucky.unarmed: true mcmmo.perks.lucky.unarmed: true
@@ -1539,6 +1571,9 @@ permissions:
mcmmo.perks.lucky.salvage: mcmmo.perks.lucky.salvage:
default: false default: false
description: Gives Salvage abilities & skills a 33.3% better chance to activate. description: Gives Salvage abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.spears:
default: false
description: Gives Spears abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.smelting: mcmmo.perks.lucky.smelting:
default: false default: false
description: Gives Smelting abilities & skills a 33.3% better chance to activate. description: Gives Smelting abilities & skills a 33.3% better chance to activate.
@@ -1600,6 +1635,7 @@ permissions:
mcmmo.perks.xp.150percentboost.mining: true mcmmo.perks.xp.150percentboost.mining: true
mcmmo.perks.xp.150percentboost.repair: true mcmmo.perks.xp.150percentboost.repair: true
mcmmo.perks.xp.150percentboost.smelting: true mcmmo.perks.xp.150percentboost.smelting: true
mcmmo.perks.xp.150percentboost.spears: true
mcmmo.perks.xp.150percentboost.swords: true mcmmo.perks.xp.150percentboost.swords: true
mcmmo.perks.xp.150percentboost.taming: true mcmmo.perks.xp.150percentboost.taming: true
mcmmo.perks.xp.150percentboost.tridents: true mcmmo.perks.xp.150percentboost.tridents: true
@@ -1641,6 +1677,9 @@ permissions:
mcmmo.perks.xp.150percentboost.smelting: mcmmo.perks.xp.150percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 2.5 description: Multiplies incoming Smelting XP by 2.5
mcmmo.perks.xp.150percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 2.5
mcmmo.perks.xp.150percentboost.swords: mcmmo.perks.xp.150percentboost.swords:
default: false default: false
description: Multiplies incoming Swords XP by 2.5 description: Multiplies incoming Swords XP by 2.5
@@ -1682,6 +1721,7 @@ permissions:
mcmmo.perks.xp.50percentboost.mining: true mcmmo.perks.xp.50percentboost.mining: true
mcmmo.perks.xp.50percentboost.repair: true mcmmo.perks.xp.50percentboost.repair: true
mcmmo.perks.xp.50percentboost.smelting: true mcmmo.perks.xp.50percentboost.smelting: true
mcmmo.perks.xp.50percentboost.spears: true
mcmmo.perks.xp.50percentboost.swords: true mcmmo.perks.xp.50percentboost.swords: true
mcmmo.perks.xp.50percentboost.taming: true mcmmo.perks.xp.50percentboost.taming: true
mcmmo.perks.xp.50percentboost.tridents: true mcmmo.perks.xp.50percentboost.tridents: true
@@ -1720,6 +1760,9 @@ permissions:
mcmmo.perks.xp.50percentboost.repair: mcmmo.perks.xp.50percentboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by 1.5 description: Multiplies incoming Repair XP by 1.5
mcmmo.perks.xp.50percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 1.5
mcmmo.perks.xp.50percentboost.smelting: mcmmo.perks.xp.50percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 1.5 description: Multiplies incoming Smelting XP by 1.5
@@ -1739,87 +1782,91 @@ permissions:
default: false default: false
description: Multiplies incoming Woodcutting XP by 1.5 description: Multiplies incoming Woodcutting XP by 1.5
mcmmo.perks.xp.25percentboost.*: mcmmo.perks.xp.25percentboost.*:
default: false
description: Multiplies incoming XP by 1.25
children:
mcmmo.perks.xp.25percentboost.all: true
mcmmo.perks.xp.25percentboost:
default: false default: false
description: Multiplies incoming XP by 1.25 description: Multiplies incoming XP by 1.25
children: children:
mcmmo.perks.xp.25percentboost.all: true mcmmo.perks.xp.25percentboost.all: true
mcmmo.perks.xp.25percentboost.all: mcmmo.perks.xp.25percentboost:
default: false default: false
description: Multiplies incoming XP by 1.25 description: Multiplies incoming XP by 1.25
children: children:
mcmmo.perks.xp.25percentboost.acrobatics: true mcmmo.perks.xp.25percentboost.all: true
mcmmo.perks.xp.25percentboost.alchemy: true mcmmo.perks.xp.25percentboost.all:
mcmmo.perks.xp.25percentboost.archery: true default: false
mcmmo.perks.xp.25percentboost.axes: true description: Multiplies incoming XP by 1.25
mcmmo.perks.xp.25percentboost.crossbows: true children:
mcmmo.perks.xp.25percentboost.excavation: true mcmmo.perks.xp.25percentboost.acrobatics: true
mcmmo.perks.xp.25percentboost.fishing: true mcmmo.perks.xp.25percentboost.alchemy: true
mcmmo.perks.xp.25percentboost.herbalism: true mcmmo.perks.xp.25percentboost.archery: true
mcmmo.perks.xp.25percentboost.maces: true mcmmo.perks.xp.25percentboost.axes: true
mcmmo.perks.xp.25percentboost.mining: true mcmmo.perks.xp.25percentboost.crossbows: true
mcmmo.perks.xp.25percentboost.repair: true mcmmo.perks.xp.25percentboost.excavation: true
mcmmo.perks.xp.25percentboost.smelting: true mcmmo.perks.xp.25percentboost.fishing: true
mcmmo.perks.xp.25percentboost.swords: true mcmmo.perks.xp.25percentboost.herbalism: true
mcmmo.perks.xp.25percentboost.taming: true mcmmo.perks.xp.25percentboost.maces: true
mcmmo.perks.xp.25percentboost.tridents: true mcmmo.perks.xp.25percentboost.mining: true
mcmmo.perks.xp.25percentboost.unarmed: true mcmmo.perks.xp.25percentboost.repair: true
mcmmo.perks.xp.25percentboost.woodcutting: true mcmmo.perks.xp.25percentboost.smelting: true
mcmmo.perks.xp.25percentboost.acrobatics: mcmmo.perks.xp.25percentboost.spears: true
default: false mcmmo.perks.xp.25percentboost.swords: true
description: Multiplies incoming Acrobatics XP by 1.25 mcmmo.perks.xp.25percentboost.taming: true
mcmmo.perks.xp.25percentboost.alchemy: mcmmo.perks.xp.25percentboost.tridents: true
default: false mcmmo.perks.xp.25percentboost.unarmed: true
description: Multiplies incoming Acrobatics XP by 1.25 mcmmo.perks.xp.25percentboost.woodcutting: true
mcmmo.perks.xp.25percentboost.archery: mcmmo.perks.xp.25percentboost.acrobatics:
default: false default: false
description: Multiplies incoming Archery XP by 1.25 description: Multiplies incoming Acrobatics XP by 1.25
mcmmo.perks.xp.25percentboost.axes: mcmmo.perks.xp.25percentboost.alchemy:
default: false default: false
description: Multiplies incoming Axes XP by 1.25 description: Multiplies incoming Acrobatics XP by 1.25
mcmmo.perks.xp.25percentboost.crossbows: mcmmo.perks.xp.25percentboost.archery:
default: false default: false
description: Multiplies incoming Crossbows XP by 1.25 description: Multiplies incoming Archery XP by 1.25
mcmmo.perks.xp.25percentboost.excavation: mcmmo.perks.xp.25percentboost.axes:
default: false default: false
description: Multiplies incoming Excavation XP by 1.25 description: Multiplies incoming Axes XP by 1.25
mcmmo.perks.xp.25percentboost.fishing: mcmmo.perks.xp.25percentboost.crossbows:
default: false default: false
description: Multiplies incoming Fishing XP by 1.25 description: Multiplies incoming Crossbows XP by 1.25
mcmmo.perks.xp.25percentboost.herbalism: mcmmo.perks.xp.25percentboost.excavation:
default: false default: false
description: Multiplies incoming Herbalism XP by 1.25 description: Multiplies incoming Excavation XP by 1.25
mcmmo.perks.xp.25percentboost.maces: mcmmo.perks.xp.25percentboost.fishing:
default: false default: false
description: Multiplies incoming Maces XP by 1.25 description: Multiplies incoming Fishing XP by 1.25
mcmmo.perks.xp.25percentboost.mining: mcmmo.perks.xp.25percentboost.herbalism:
default: false default: false
description: Multiplies incoming Mining XP by 1.25 description: Multiplies incoming Herbalism XP by 1.25
mcmmo.perks.xp.25percentboost.repair: mcmmo.perks.xp.25percentboost.maces:
default: false default: false
description: Multiplies incoming Repair XP by 1.25 description: Multiplies incoming Maces XP by 1.25
mcmmo.perks.xp.25percentboost.smelting: mcmmo.perks.xp.25percentboost.mining:
default: false default: false
description: Multiplies incoming Smelting XP by 1.25 description: Multiplies incoming Mining XP by 1.25
mcmmo.perks.xp.25percentboost.swords: mcmmo.perks.xp.25percentboost.repair:
default: false default: false
description: Multiplies incoming Swords XP by 1.25 description: Multiplies incoming Repair XP by 1.25
mcmmo.perks.xp.25percentboost.taming: mcmmo.perks.xp.25percentboost.smelting:
default: false default: false
description: Multiplies incoming Taming XP by 1.25 description: Multiplies incoming Smelting XP by 1.25
mcmmo.perks.xp.25percentboost.tridents: mcmmo.perks.xp.25percentboost.spears:
default: false default: false
description: Multiplies incoming Tridents XP by 1.25 description: Multiplies incoming Spears XP by 1.25
mcmmo.perks.xp.25percentboost.unarmed: mcmmo.perks.xp.25percentboost.swords:
default: false default: false
description: Multiplies incoming Unarmed XP by 1.5 description: Multiplies incoming Swords XP by 1.25
mcmmo.perks.xp.25percentboost.woodcutting: mcmmo.perks.xp.25percentboost.taming:
default: false default: false
description: Multiplies incoming Woodcutting XP by 1.25 description: Multiplies incoming Taming XP by 1.25
mcmmo.perks.xp.25percentboost.tridents:
default: false
description: Multiplies incoming Tridents XP by 1.25
mcmmo.perks.xp.25percentboost.unarmed:
default: false
description: Multiplies incoming Unarmed XP by 1.5
mcmmo.perks.xp.25percentboost.woodcutting:
default: false
description: Multiplies incoming Woodcutting XP by 1.25
mcmmo.perks.xp.10percentboost.*: mcmmo.perks.xp.10percentboost.*:
default: false default: false
description: Multiplies incoming XP by 1.1 description: Multiplies incoming XP by 1.1
@@ -1846,6 +1893,7 @@ permissions:
mcmmo.perks.xp.10percentboost.mining: true mcmmo.perks.xp.10percentboost.mining: true
mcmmo.perks.xp.10percentboost.repair: true mcmmo.perks.xp.10percentboost.repair: true
mcmmo.perks.xp.10percentboost.smelting: true mcmmo.perks.xp.10percentboost.smelting: true
mcmmo.perks.xp.10percentboost.spears: true
mcmmo.perks.xp.10percentboost.swords: true mcmmo.perks.xp.10percentboost.swords: true
mcmmo.perks.xp.10percentboost.taming: true mcmmo.perks.xp.10percentboost.taming: true
mcmmo.perks.xp.10percentboost.tridents: true mcmmo.perks.xp.10percentboost.tridents: true
@@ -1884,6 +1932,9 @@ permissions:
mcmmo.perks.xp.10percentboost.repair: mcmmo.perks.xp.10percentboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by 1.1 description: Multiplies incoming Repair XP by 1.1
mcmmo.perks.xp.10percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 1.1
mcmmo.perks.xp.10percentboost.smelting: mcmmo.perks.xp.10percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 1.1 description: Multiplies incoming Smelting XP by 1.1
@@ -1928,6 +1979,7 @@ permissions:
mcmmo.perks.xp.customboost.mining: true mcmmo.perks.xp.customboost.mining: true
mcmmo.perks.xp.customboost.repair: true mcmmo.perks.xp.customboost.repair: true
mcmmo.perks.xp.customboost.smelting: true mcmmo.perks.xp.customboost.smelting: true
mcmmo.perks.xp.customboost.spears: true
mcmmo.perks.xp.customboost.swords: true mcmmo.perks.xp.customboost.swords: true
mcmmo.perks.xp.customboost.taming: true mcmmo.perks.xp.customboost.taming: true
mcmmo.perks.xp.customboost.tridents: true mcmmo.perks.xp.customboost.tridents: true
@@ -1966,6 +2018,9 @@ permissions:
mcmmo.perks.xp.customboost.repair: mcmmo.perks.xp.customboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by the boost amount defined in the experience config description: Multiplies incoming Repair XP by the boost amount defined in the experience config
mcmmo.perks.xp.customboost.spears:
default: false
description: Multiplies incoming Smelting XP by the boost amount defined in the experience config
mcmmo.perks.xp.customboost.smelting: mcmmo.perks.xp.customboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by the boost amount defined in the experience config description: Multiplies incoming Smelting XP by the boost amount defined in the experience config
@@ -2010,6 +2065,7 @@ permissions:
mcmmo.perks.xp.double.mining: true mcmmo.perks.xp.double.mining: true
mcmmo.perks.xp.double.repair: true mcmmo.perks.xp.double.repair: true
mcmmo.perks.xp.double.smelting: true mcmmo.perks.xp.double.smelting: true
mcmmo.perks.xp.double.spears: true
mcmmo.perks.xp.double.swords: true mcmmo.perks.xp.double.swords: true
mcmmo.perks.xp.double.taming: true mcmmo.perks.xp.double.taming: true
mcmmo.perks.xp.double.tridents: true mcmmo.perks.xp.double.tridents: true
@@ -2048,6 +2104,9 @@ permissions:
mcmmo.perks.xp.double.repair: mcmmo.perks.xp.double.repair:
default: false default: false
description: Doubles incoming Repair XP description: Doubles incoming Repair XP
mcmmo.perks.xp.double.spears:
default: false
description: Doubles incoming Smelting XP
mcmmo.perks.xp.double.smelting: mcmmo.perks.xp.double.smelting:
default: false default: false
description: Doubles incoming Smelting XP description: Doubles incoming Smelting XP
@@ -2092,6 +2151,7 @@ permissions:
mcmmo.perks.xp.quadruple.mining: true mcmmo.perks.xp.quadruple.mining: true
mcmmo.perks.xp.quadruple.repair: true mcmmo.perks.xp.quadruple.repair: true
mcmmo.perks.xp.quadruple.smelting: true mcmmo.perks.xp.quadruple.smelting: true
mcmmo.perks.xp.quadruple.spears: true
mcmmo.perks.xp.quadruple.swords: true mcmmo.perks.xp.quadruple.swords: true
mcmmo.perks.xp.quadruple.taming: true mcmmo.perks.xp.quadruple.taming: true
mcmmo.perks.xp.quadruple.tridents: true mcmmo.perks.xp.quadruple.tridents: true
@@ -2133,6 +2193,9 @@ permissions:
mcmmo.perks.xp.quadruple.smelting: mcmmo.perks.xp.quadruple.smelting:
default: false default: false
description: Quadruples incoming Smelting XP description: Quadruples incoming Smelting XP
mcmmo.perks.xp.quadruple.spears:
default: false
description: Quadruples incoming Spears XP
mcmmo.perks.xp.quadruple.swords: mcmmo.perks.xp.quadruple.swords:
default: false default: false
description: Quadruples incoming Swords XP description: Quadruples incoming Swords XP
@@ -2174,6 +2237,7 @@ permissions:
mcmmo.perks.xp.triple.maces: true mcmmo.perks.xp.triple.maces: true
mcmmo.perks.xp.triple.repair: true mcmmo.perks.xp.triple.repair: true
mcmmo.perks.xp.triple.smelting: true mcmmo.perks.xp.triple.smelting: true
mcmmo.perks.xp.triple.spears: true
mcmmo.perks.xp.triple.swords: true mcmmo.perks.xp.triple.swords: true
mcmmo.perks.xp.triple.taming: true mcmmo.perks.xp.triple.taming: true
mcmmo.perks.xp.triple.tridents: true mcmmo.perks.xp.triple.tridents: true
@@ -2215,6 +2279,9 @@ permissions:
mcmmo.perks.xp.triple.smelting: mcmmo.perks.xp.triple.smelting:
default: false default: false
description: Triples incoming Smelting XP description: Triples incoming Smelting XP
mcmmo.perks.xp.triple.spears:
default: false
description: Triples incoming Spears XP
mcmmo.perks.xp.triple.swords: mcmmo.perks.xp.triple.swords:
default: false default: false
description: Triples incoming Swords XP description: Triples incoming Swords XP
@@ -2257,6 +2324,7 @@ permissions:
mcmmo.skills.salvage: true mcmmo.skills.salvage: true
mcmmo.skills.swords: true mcmmo.skills.swords: true
mcmmo.skills.smelting: true mcmmo.skills.smelting: true
mcmmo.skills.spears: true
mcmmo.skills.taming: true mcmmo.skills.taming: true
mcmmo.skills.unarmed: true mcmmo.skills.unarmed: true
mcmmo.skills.woodcutting: true mcmmo.skills.woodcutting: true
@@ -2322,6 +2390,11 @@ permissions:
children: children:
mcmmo.ability.smelting.all: true mcmmo.ability.smelting.all: true
mcmmo.commands.smelting: true mcmmo.commands.smelting: true
mcmmo.skills.spears:
description: Allows access to the Spears skill
children:
mcmmo.ability.spears.all: true
mcmmo.commands.spears: true
mcmmo.skills.swords: mcmmo.skills.swords:
description: Allows access to the Swords skill description: Allows access to the Swords skill
children: children:

View File

@@ -55,6 +55,9 @@ Repairables:
WOODEN_SWORD: WOODEN_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
WOODEN_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
WOODEN_SHOVEL: WOODEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -74,6 +77,9 @@ Repairables:
STONE_SWORD: STONE_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
STONE_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
STONE_SHOVEL: STONE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -96,6 +102,12 @@ Repairables:
ItemType: TOOL ItemType: TOOL
ItemMaterialCategory: COPPER ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT RepairMaterial: COPPER_INGOT
COPPER_SPEAR:
MinimumLevel: 0
XpMultiplier: .3
ItemType: TOOL
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_SHOVEL: COPPER_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .2 XpMultiplier: .2
@@ -152,6 +164,9 @@ Repairables:
IRON_SWORD: IRON_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
IRON_SPEAR:
MinimumLevel: 0
XpMultiplier: .5
IRON_SHOVEL: IRON_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -190,6 +205,9 @@ Repairables:
GOLDEN_SWORD: GOLDEN_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 4 XpMultiplier: 4
GOLDEN_SPEAR:
MinimumLevel: 0
XpMultiplier: 4
GOLDEN_SHOVEL: GOLDEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 2.6 XpMultiplier: 2.6
@@ -222,6 +240,9 @@ Repairables:
DIAMOND_SWORD: DIAMOND_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
DIAMOND_SPEAR:
MinimumLevel: 0
XpMultiplier: .5
DIAMOND_SHOVEL: DIAMOND_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -255,6 +276,9 @@ Repairables:
NETHERITE_SWORD: NETHERITE_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .6 XpMultiplier: .6
NETHERITE_SPEAR:
MinimumLevel: 0
XpMultiplier: .6
NETHERITE_SHOVEL: NETHERITE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .4 XpMultiplier: .4

View File

@@ -50,6 +50,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
MaximumQuantity: 2 MaximumQuantity: 2
WOODEN_SPEAR:
MinimumLevel: 0
XpMultiplier: .16
MaximumQuantity: 1
WOODEN_SHOVEL: WOODEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -74,6 +78,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
MaximumQuantity: 2 MaximumQuantity: 2
STONE_SPEAR:
MinimumLevel: 0
XpMultiplier: .16
MaximumQuantity: 1
STONE_SHOVEL: STONE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -98,6 +106,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .4 XpMultiplier: .4
MaximumQuantity: 2 MaximumQuantity: 2
COPPER_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
MaximumQuantity: 1
COPPER_SHOVEL: COPPER_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
@@ -139,6 +151,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 2 MaximumQuantity: 2
IRON_SPEAR:
MinimumLevel: 0
XpMultiplier: .3
MaximumQuantity: 1
IRON_SHOVEL: IRON_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -186,6 +202,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 4 XpMultiplier: 4
MaximumQuantity: 2 MaximumQuantity: 2
GOLDEN_SPEAR:
MinimumLevel: 0
XpMultiplier: 4
MaximumQuantity: 1
GOLDEN_SHOVEL: GOLDEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 2.6 XpMultiplier: 2.6
@@ -227,6 +247,10 @@ Salvageables:
MinimumLevel: 50 MinimumLevel: 50
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 2 MaximumQuantity: 2
DIAMOND_SPEAR:
MinimumLevel: 50
XpMultiplier: .5
MaximumQuantity: 1
DIAMOND_SHOVEL: DIAMOND_SHOVEL:
MinimumLevel: 50 MinimumLevel: 50
XpMultiplier: .3 XpMultiplier: .3
@@ -268,6 +292,10 @@ Salvageables:
MinimumLevel: 100 MinimumLevel: 100
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 4 MaximumQuantity: 4
NETHERITE_SPEAR:
MinimumLevel: 100
XpMultiplier: .3
MaximumQuantity: 4
NETHERITE_SHOVEL: NETHERITE_SHOVEL:
MinimumLevel: 100 MinimumLevel: 100
XpMultiplier: .3 XpMultiplier: .3

View File

@@ -404,6 +404,72 @@ Smelting:
Rank_6: 750 Rank_6: 750
Rank_7: 850 Rank_7: 850
Rank_8: 1000 Rank_8: 1000
Spears:
SpearsLimitBreak:
Standard:
Rank_1: 10
Rank_2: 20
Rank_3: 30
Rank_4: 40
Rank_5: 50
Rank_6: 60
Rank_7: 70
Rank_8: 80
Rank_9: 90
Rank_10: 100
RetroMode:
Rank_1: 100
Rank_2: 200
Rank_3: 300
Rank_4: 400
Rank_5: 500
Rank_6: 600
Rank_7: 700
Rank_8: 800
Rank_9: 900
Rank_10: 1000
SpearMastery:
Standard:
Rank_1: 5
Rank_2: 15
Rank_3: 30
Rank_4: 45
Rank_5: 60
Rank_6: 75
Rank_7: 90
Rank_8: 100
RetroMode:
Rank_1: 50
Rank_2: 150
Rank_3: 300
Rank_4: 450
Rank_5: 600
Rank_6: 750
Rank_7: 900
Rank_8: 1000
Momentum:
Standard:
Rank_1: 1
Rank_2: 10
Rank_3: 15
Rank_4: 20
Rank_5: 25
Rank_6: 40
Rank_7: 50
Rank_8: 60
Rank_9: 80
Rank_10: 95
RetroMode:
Rank_1: 1
Rank_2: 100
Rank_3: 150
Rank_4: 200
Rank_5: 250
Rank_6: 400
Rank_7: 500
Rank_8: 600
Rank_9: 800
Rank_10: 950
Salvage: Salvage:
ScrapCollector: ScrapCollector:
Standard: Standard:

View File

@@ -0,0 +1,371 @@
package com.gmail.nossr50.util.skills;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.gmail.nossr50.config.GeneralConfig;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.CompatibilityManager;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
@TestInstance(Lifecycle.PER_CLASS)
class SkillToolsTest {
private static final @NotNull Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
private static MockedStatic<mcMMO> mockedMcMMO;
private static MockedStatic<LocaleLoader> mockedLocaleLoader;
private GeneralConfig generalConfig;
private CompatibilityManager compatibilityManager;
@BeforeAll
void setUpAll() {
// Static mcMMO + LocaleLoader mocks
mockedMcMMO = Mockito.mockStatic(mcMMO.class);
mockedLocaleLoader = Mockito.mockStatic(LocaleLoader.class);
// Plugin instance
mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
// General config
generalConfig = mock(GeneralConfig.class);
when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
when(generalConfig.getLocale()).thenReturn("en_US");
// Compatibility manager + game version
compatibilityManager = mock(CompatibilityManager.class);
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
// LocaleLoader just echo key back to keep things simple/deterministic
mockedLocaleLoader.when(() -> LocaleLoader.getString(anyString()))
.thenAnswer(invocation -> invocation.getArgument(0));
}
@AfterAll
void tearDownAll() {
mockedLocaleLoader.close();
mockedMcMMO.close();
}
private SkillTools newSkillToolsForVersion(int major, int minor, int patch) throws Exception {
when(compatibilityManager.getMinecraftGameVersion())
.thenReturn(new MinecraftGameVersion(major, minor, patch));
return new SkillTools(mcMMO.p);
}
// ------------------------------------------------------------------------
// NON_CHILD_SKILLS / isChildSkill / CHILD_SKILLS
// ------------------------------------------------------------------------
@Test
void nonChildSkillsShouldContainAllPrimarySkillsExceptSalvageAndSmelting() {
List<PrimarySkillType> expected = Arrays.stream(PrimarySkillType.values())
.filter(t -> t != PrimarySkillType.SALVAGE && t != PrimarySkillType.SMELTING)
.collect(Collectors.toList());
assertThat(SkillTools.NON_CHILD_SKILLS)
.containsExactlyInAnyOrderElementsOf(expected);
}
@Test
void isChildSkillShouldReturnTrueOnlyForSalvageAndSmelting() {
for (PrimarySkillType type : PrimarySkillType.values()) {
boolean isChild = SkillTools.isChildSkill(type);
if (type == PrimarySkillType.SALVAGE || type == PrimarySkillType.SMELTING) {
assertThat(isChild)
.as("%s should be considered a child skill", type)
.isTrue();
} else {
assertThat(isChild)
.as("%s should NOT be considered a child skill", type)
.isFalse();
}
}
}
@Test
void childSkillsListShouldMatchIsChildSkillClassification() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
List<PrimarySkillType> expectedChildren = Arrays.stream(PrimarySkillType.values())
.filter(SkillTools::isChildSkill)
.collect(Collectors.toList());
assertThat(skillTools.getChildSkills())
.containsExactlyInAnyOrderElementsOf(expectedChildren);
}
// ------------------------------------------------------------------------
// Child skill parents (SALVAGE_PARENTS / SMELTING_PARENTS / getChildSkillParents)
// ------------------------------------------------------------------------
@Test
void childSkillParentsShouldMatchStaticParentLists() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
assertThat(skillTools.getChildSkillParents(PrimarySkillType.SALVAGE))
.as("SALVAGE parents")
.containsExactlyElementsOf(SkillTools.SALVAGE_PARENTS);
assertThat(skillTools.getChildSkillParents(PrimarySkillType.SMELTING))
.as("SMELTING parents")
.containsExactlyElementsOf(SkillTools.SMELTING_PARENTS);
}
@Test
void getChildSkillParentsShouldThrowForNonChildSkill() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
assertThatThrownBy(() -> skillTools.getChildSkillParents(PrimarySkillType.MINING))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("is not a child skill");
}
// ------------------------------------------------------------------------
// Super ability ↔ primary skill relationships
// ------------------------------------------------------------------------
@Test
void superAbilityParentMappingShouldMatchDefinedSwitch() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.BERSERK))
.isEqualTo(PrimarySkillType.UNARMED);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.GREEN_TERRA))
.isEqualTo(PrimarySkillType.HERBALISM);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.TREE_FELLER))
.isEqualTo(PrimarySkillType.WOODCUTTING);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.SUPER_BREAKER))
.isEqualTo(PrimarySkillType.MINING);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.BLAST_MINING))
.isEqualTo(PrimarySkillType.MINING);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.SKULL_SPLITTER))
.isEqualTo(PrimarySkillType.AXES);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.SERRATED_STRIKES))
.isEqualTo(PrimarySkillType.SWORDS);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.GIGA_DRILL_BREAKER))
.isEqualTo(PrimarySkillType.EXCAVATION);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.SUPER_SHOTGUN))
.isEqualTo(PrimarySkillType.CROSSBOWS);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.TRIDENTS_SUPER_ABILITY))
.isEqualTo(PrimarySkillType.TRIDENTS);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.EXPLOSIVE_SHOT))
.isEqualTo(PrimarySkillType.ARCHERY);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.MACES_SUPER_ABILITY))
.isEqualTo(PrimarySkillType.MACES);
assertThat(skillTools.getPrimarySkillBySuperAbility(SuperAbilityType.SPEARS_SUPER_ABILITY))
.isEqualTo(PrimarySkillType.SPEARS);
}
@Test
void mainActivatedAbilityChildMapShouldOmitBlastMiningAndMapOthersBackToAbility() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
// All super abilities EXCEPT BLAST_MINING should be discoverable via getSuperAbility()
assertThat(skillTools.getSuperAbility(PrimarySkillType.MINING))
.as("MINING should not expose BLAST_MINING as the 'main' tool-readied ability")
.isEqualTo(SuperAbilityType.SUPER_BREAKER);
assertThat(skillTools.getSuperAbility(PrimarySkillType.UNARMED))
.isEqualTo(SuperAbilityType.BERSERK);
assertThat(skillTools.getSuperAbility(PrimarySkillType.HERBALISM))
.isEqualTo(SuperAbilityType.GREEN_TERRA);
assertThat(skillTools.getSuperAbility(PrimarySkillType.WOODCUTTING))
.isEqualTo(SuperAbilityType.TREE_FELLER);
assertThat(skillTools.getSuperAbility(PrimarySkillType.AXES))
.isEqualTo(SuperAbilityType.SKULL_SPLITTER);
assertThat(skillTools.getSuperAbility(PrimarySkillType.SWORDS))
.isEqualTo(SuperAbilityType.SERRATED_STRIKES);
assertThat(skillTools.getSuperAbility(PrimarySkillType.EXCAVATION))
.isEqualTo(SuperAbilityType.GIGA_DRILL_BREAKER);
assertThat(skillTools.getSuperAbility(PrimarySkillType.CROSSBOWS))
.isEqualTo(SuperAbilityType.SUPER_SHOTGUN);
assertThat(skillTools.getSuperAbility(PrimarySkillType.TRIDENTS))
.isEqualTo(SuperAbilityType.TRIDENTS_SUPER_ABILITY);
assertThat(skillTools.getSuperAbility(PrimarySkillType.ARCHERY))
.isEqualTo(SuperAbilityType.EXPLOSIVE_SHOT);
assertThat(skillTools.getSuperAbility(PrimarySkillType.MACES))
.isEqualTo(SuperAbilityType.MACES_SUPER_ABILITY);
assertThat(skillTools.getSuperAbility(PrimarySkillType.SPEARS))
.isEqualTo(SuperAbilityType.SPEARS_SUPER_ABILITY);
// Skills without a main activated ability should return null
assertThat(skillTools.getSuperAbility(PrimarySkillType.REPAIR)).isNull();
assertThat(skillTools.getSuperAbility(PrimarySkillType.FISHING)).isNull();
}
// ------------------------------------------------------------------------
// Sub-skill → primary-skill mapping (name prefix convention)
// ------------------------------------------------------------------------
@Test
void primarySkillBySubSkillShouldFollowNamePrefixConvention() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
for (SubSkillType sub : SubSkillType.values()) {
PrimarySkillType parent = skillTools.getPrimarySkillBySubSkill(sub);
assertThat(parent)
.as("SubSkill %s should have a parent PrimarySkillType", sub)
.isNotNull();
String subName = sub.name().toUpperCase(Locale.ENGLISH);
String parentPrefix = parent.name().toUpperCase(Locale.ENGLISH);
assertThat(subName.startsWith(parentPrefix))
.as("SubSkill %s should start with its parent skill name %s", subName, parentPrefix)
.isTrue();
}
}
// ------------------------------------------------------------------------
// primarySkillToolMap
// ------------------------------------------------------------------------
@Test
void primarySkillToolTypeMappingShouldMatchDefinition() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.AXES))
.isEqualTo(ToolType.AXE);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.WOODCUTTING))
.isEqualTo(ToolType.AXE);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.UNARMED))
.isEqualTo(ToolType.FISTS);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.SWORDS))
.isEqualTo(ToolType.SWORD);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.EXCAVATION))
.isEqualTo(ToolType.SHOVEL);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.HERBALISM))
.isEqualTo(ToolType.HOE);
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.MINING))
.isEqualTo(ToolType.PICKAXE);
// And any skill not explicitly mapped should currently return null
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.FISHING)).isNull();
assertThat(skillTools.getPrimarySkillToolType(PrimarySkillType.TAMING)).isNull();
}
// ------------------------------------------------------------------------
// Combat / Gathering / Misc groupings by Minecraft version
// ------------------------------------------------------------------------
@Test
void combatGatheringMiscGroupingsShouldMatchDefinitionForModernSpearsAndMacesVersion()
throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
assertThat(skillTools.getCombatSkills())
.containsExactly(
PrimarySkillType.ARCHERY,
PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS,
PrimarySkillType.MACES,
PrimarySkillType.SWORDS,
PrimarySkillType.SPEARS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED
);
assertThat(skillTools.getGatheringSkills())
.containsExactly(
PrimarySkillType.EXCAVATION,
PrimarySkillType.FISHING,
PrimarySkillType.HERBALISM,
PrimarySkillType.MINING,
PrimarySkillType.WOODCUTTING
);
assertThat(skillTools.getMiscSkills())
.containsExactly(
PrimarySkillType.ACROBATICS,
PrimarySkillType.ALCHEMY,
PrimarySkillType.REPAIR,
PrimarySkillType.SALVAGE,
PrimarySkillType.SMELTING
);
}
@Test
void combatSkillsShouldMatchDefinitionForVersionWithMacesButWithoutSpears() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 0);
assertThat(skillTools.getCombatSkills())
.containsExactly(
PrimarySkillType.ARCHERY,
PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS,
PrimarySkillType.MACES,
PrimarySkillType.SWORDS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED
);
}
@Test
void combatSkillsShouldMatchDefinitionForVersionWithoutMacesOrSpears() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 20, 4);
assertThat(skillTools.getCombatSkills())
.containsExactly(
PrimarySkillType.ARCHERY,
PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS,
PrimarySkillType.SWORDS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED
);
}
// ------------------------------------------------------------------------
// LOCALIZED_SKILL_NAMES basic sanity (size + uniqueness, not content)
// ------------------------------------------------------------------------
@Test
void localizedSkillNamesShouldContainOneEntryPerPrimarySkillAndBeSorted() throws Exception {
SkillTools skillTools = newSkillToolsForVersion(1, 21, 11);
List<String> names = new ArrayList<>(skillTools.LOCALIZED_SKILL_NAMES);
// One per PrimarySkillType
assertThat(names).hasSize(PrimarySkillType.values().length);
// No duplicates
assertThat(new HashSet<>(names)).hasSize(names.size());
// Sorted ascending
List<String> sorted = new ArrayList<>(names);
Collections.sort(sorted);
assertThat(names).isEqualTo(sorted);
}
}

View File

@@ -1,3 +1,3 @@
nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:IGNORED:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:2020:140:14:150:15:1111:2222:3333:160:16:4444: nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:IGNORED:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:2020:140:14:150:15:1111:2222:3333:160:16:4444:170:17:5555:
mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:3030:0:0:0:0:0:0:0:0:0:0: mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:3030:0:0:0:0:0:0:0:0:0:0:0:0:0:
powerless:0:::0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0::0:0:0:0:0:0:0:0:0::0:0:0:1337:HEARTS:0:0:e0d07db8-f7e8-43c7-9ded-864dfc6f3b7c:5:1600906906:4040:0:0:0:0:0:0:0:0:0:0: powerless:0:::0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0::0:0:0:0:0:0:0:0:0::0:0:0:1337:HEARTS:0:0:e0d07db8-f7e8-43c7-9ded-864dfc6f3b7c:5:1600906906:4040:0:0:0:0:0:0:0:0:0:0:0:0:0: