mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2026-02-20 10:43:12 +01:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be613bc9b6 | ||
|
|
99c2ec2959 | ||
|
|
3a7d605450 | ||
|
|
0e0e2efb6d | ||
|
|
a6e12c4cc1 | ||
|
|
33597e1db1 | ||
|
|
c94f10568d | ||
|
|
db985bcc52 | ||
|
|
1b8897b8ab | ||
|
|
95026e6016 | ||
|
|
7738c45b72 | ||
|
|
080d407c14 | ||
|
|
8f8d7756ca | ||
|
|
e24b5b0b75 | ||
|
|
8ac3198386 | ||
|
|
4c33f76404 | ||
|
|
77dac78bec | ||
|
|
9c9e5313ca | ||
|
|
db5654dbe6 | ||
|
|
c14b82fff1 | ||
|
|
5a9390f88f | ||
|
|
4a890a28a1 | ||
|
|
8b7cffbe49 | ||
|
|
921fa713b8 | ||
|
|
ebe49154b4 | ||
|
|
1036aabc32 | ||
|
|
e2f18a9e89 | ||
|
|
694de2ff5f | ||
|
|
cc1a581192 | ||
|
|
b15365e978 |
@@ -1,3 +1,75 @@
|
||||
Version 2.2.050
|
||||
Minimum supported Minecraft version raised to 1.20.5 (see notes)
|
||||
Improved Spears damage detection (see notes)
|
||||
Spear abilities can now trigger from off-hand attacks with the Spear
|
||||
Further improved compatibility with Excellent Enchants (fixed more errors)
|
||||
Fixed Spears command showing too many decimal places in some circumstances (Thanks Momshroom)
|
||||
(Codebase) Updated Recipe API to use alternative methods (Thanks Warriorrrr)
|
||||
(Codebase) Removed a bunch of unused code
|
||||
(Codebase) Refactored code around evaluating Minecraft server version
|
||||
|
||||
|
||||
NOTES:
|
||||
From 2.2.050 onwards, mcMMO will require Minecraft versions 1.20.5 or newer.
|
||||
Every now and then I raise the minimum supported Minecraft version to reduce maintenance burden of supporting older versions.
|
||||
mcMMO no longer monitors PlayerAnimationEvent, it turns out Spigot has a DamageType just for Spear damage, avoiding the need to track player arm swings.
|
||||
I changed how mcMMO detects the game version slightly, now if it fails to determine the game version it will make the assumption you are on the minimum supported version and print an error, this is just a failsafe in case the version detection mechanism ever fails.
|
||||
|
||||
Version 2.2.049
|
||||
Combat abilities work with spear in off-hand again (see notes)
|
||||
Sweet berry bushes now work with Herbalism (thanks dnocturne)
|
||||
Fixed copper items not giving XP for Repair (thanks Remski01)
|
||||
Fixed rare edge case where mcMMO could drop items with stack size set outside normal bounds
|
||||
Fixed a bug where tamed wolves could cause errors on Folia (thanks Warriorrrr)
|
||||
Improved compatibility with Excellent Enchants (fixed error spam from Flame Walker)
|
||||
(Codebase) Fixed unit tests when building mcMMO with Java 25 (thanks Warriorrrr)
|
||||
|
||||
NOTES:
|
||||
As a semi-permanent work around, mcMMO keeps track of when players swing their weapon, if they have swung it recently enough combat skills will work even if you have a spear in your off-hand.
|
||||
Prior to this patch, mcMMO disabled combat abilities when spear was in off-hand to prevent the off-hand spear charge from applying combat abilities from other skills, as mcMMO was unable to determine which item (mainhand vs offhand) caused the damage from the event information alone.
|
||||
|
||||
Version 2.2.048
|
||||
Fixed error when loading Spears skill manager on older Minecraft versions
|
||||
Fixed error when using /spears command on an older Minecraft version
|
||||
|
||||
Version 2.2.047
|
||||
Fix bug where off-hand spears damage could be attributed to various combat skills and trigger their abilities
|
||||
|
||||
NOTE:
|
||||
Sorry guys, noticed this right after pushing 2.2.046, for now melee combat skills won't trigger if you have a spear in your off-hand as a temporary work around to mcMMO being unable to differentiate between main hand and off hand damage.
|
||||
I'm working on a more robust solution to this issue, so stay tuned.
|
||||
What this means in laymen's terms is if you are using a sword main hand, and you have a spear off hand, mcMMO has temporarily disabled your main hand abilities from triggering to avoid issues where off hand spear damage benefits from it and triggers abilities belonging to other weapons.
|
||||
|
||||
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, I’ve 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
|
||||
Green Thumb now replants some crops it was failing to replant before (see notes)
|
||||
Green Thumb now replants harvested plants faster
|
||||
|
||||
150
pom.xml
150
pom.xml
@@ -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>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.2.046-SNAPSHOT</version>
|
||||
<version>2.2.050-SNAPSHOT</version>
|
||||
<name>mcMMO</name>
|
||||
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
||||
<scm>
|
||||
@@ -13,8 +15,8 @@
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<!-- <spigot.version>1.19-R0.1-SNAPSHOT</spigot.version>-->
|
||||
<spigot.version>1.21.10-R0.1-SNAPSHOT</spigot.version>
|
||||
<spigot.version>1.20.5-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.platform.version>4.4.1-SNAPSHOT</kyori.adventure.platform.version>
|
||||
<kyori.option.version>1.1.0</kyori.option.version>
|
||||
@@ -87,6 +89,17 @@
|
||||
<propertiesEncoding>UTF-8</propertiesEncoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>properties</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.2.5</version>
|
||||
@@ -95,6 +108,8 @@
|
||||
<junitArtifactName>org.junit.jupiter:junit-jupiter</junitArtifactName>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<excludedGroups>skip</excludedGroups>
|
||||
<!-- https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3 -->
|
||||
<argLine>-javaagent:${org.mockito:mockito-core:jar}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -182,11 +197,13 @@
|
||||
</relocation>
|
||||
<relocation>
|
||||
<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>
|
||||
<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>
|
||||
<pattern>org.apache.commons.logging</pattern>
|
||||
@@ -194,7 +211,8 @@
|
||||
</relocation>
|
||||
<relocation>
|
||||
<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>
|
||||
<pattern>org.apache.tomcat</pattern>
|
||||
@@ -283,14 +301,28 @@
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.25.3</version>
|
||||
<version>3.27.7</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<!-- Exclude bytebuddy, messes with tests on java 25+ -->
|
||||
<exclusion>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.dmulloy2</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<!-- Exclude bytebuddy, messes with tests on java 25+ -->
|
||||
<exclusion>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
@@ -385,11 +417,11 @@
|
||||
<version>3.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.papermc.paper</groupId>-->
|
||||
<!-- <artifactId>paper-api</artifactId>-->
|
||||
<!-- <version>1.21.8-R0.1-SNAPSHOT</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.papermc.paper</groupId>-->
|
||||
<!-- <artifactId>paper-api</artifactId>-->
|
||||
<!-- <version>1.21.11-R0.1-SNAPSHOT</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
@@ -426,28 +458,88 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- JUnit 5 -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>5.12.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>5.2.0</version>
|
||||
<version>5.21.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-jdbc</artifactId>
|
||||
<version>10.1.24</version>
|
||||
<version>11.0.14</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -458,7 +550,8 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -468,4 +561,15 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</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>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.gmail.nossr50.commands.admin;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CompatibilityCommand implements CommandExecutor {
|
||||
|
||||
/**
|
||||
* Executes the given command, returning its success.
|
||||
* <br>
|
||||
* If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be
|
||||
* sent to the player.
|
||||
*
|
||||
* @param commandSender Source of the command
|
||||
* @param command Command which was executed
|
||||
* @param s Alias of the command which was used
|
||||
* @param strings Passed command arguments
|
||||
* @return true if a valid command, otherwise false
|
||||
*/
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command,
|
||||
@NotNull String s,
|
||||
@NotNull String[] strings) {
|
||||
mcMMO.getCompatibilityManager().reportCompatibilityStatus(commandSender);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -44,13 +44,6 @@ public class McTopCommand implements TabExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the command is for Maces but the MC version is not correct
|
||||
if (skill == PrimarySkillType.MACES
|
||||
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
display(1, skill, sender, command);
|
||||
return true;
|
||||
|
||||
@@ -65,13 +58,6 @@ public class McTopCommand implements TabExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the command is for Maces but the MC version is not correct
|
||||
if (skill == PrimarySkillType.MACES
|
||||
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
display(Math.abs(Integer.parseInt(args[1])), skill, sender, command);
|
||||
return true;
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AcrobaticsCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.ACROBATICS);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -92,7 +92,7 @@ public class AlchemyCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.ALCHEMY);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ArcheryCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.ARCHERY);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -119,7 +119,7 @@ public class AxesCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
final List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.AXES);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -68,7 +68,7 @@ public class CrossbowsCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.CROSSBOWS);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ExcavationCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.EXCAVATION);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.gmail.nossr50.commands.skills;
|
||||
|
||||
import static com.gmail.nossr50.util.Permissions.canUseSubSkill;
|
||||
|
||||
import com.gmail.nossr50.config.treasure.FishingTreasureConfig;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.datatypes.treasure.Rarity;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.skills.fishing.FishingManager;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.random.Probability;
|
||||
import com.gmail.nossr50.util.random.ProbabilityUtil;
|
||||
import com.gmail.nossr50.util.skills.RankUtils;
|
||||
@@ -118,16 +118,14 @@ public class FishingCommand extends SkillCommand {
|
||||
|
||||
@Override
|
||||
protected void permissionsCheck(Player player) {
|
||||
canTreasureHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
|
||||
canMagicHunt = Permissions.canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER)
|
||||
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
|
||||
canShake = Permissions.canUseSubSkill(player, SubSkillType.FISHING_SHAKE);
|
||||
canFishermansDiet = Permissions.canUseSubSkill(player,
|
||||
canTreasureHunt = canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
|
||||
canMagicHunt = canUseSubSkill(player, SubSkillType.FISHING_MAGIC_HUNTER)
|
||||
&& canUseSubSkill(player, SubSkillType.FISHING_TREASURE_HUNTER);
|
||||
canShake = canUseSubSkill(player, SubSkillType.FISHING_SHAKE);
|
||||
canFishermansDiet = canUseSubSkill(player,
|
||||
SubSkillType.FISHING_FISHERMANS_DIET);
|
||||
canMasterAngler =
|
||||
mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null
|
||||
&& Permissions.canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
|
||||
canIceFish = Permissions.canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
|
||||
canMasterAngler = canUseSubSkill(player, SubSkillType.FISHING_MASTER_ANGLER);
|
||||
canIceFish = canUseSubSkill(player, SubSkillType.FISHING_ICE_FISHING);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,7 +183,7 @@ public class FishingCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.FISHING);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -187,7 +187,7 @@ public class HerbalismCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.HERBALISM);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -23,7 +23,8 @@ public class MacesCommand extends SkillCommand {
|
||||
super(PrimarySkillType.MACES);
|
||||
}
|
||||
|
||||
String crippleChanceToApply, crippleChanceToApplyLucky, crippleLengthAgainstPlayers, crippleLengthAgainstMobs;
|
||||
String crippleChanceToApply, crippleChanceToApplyLucky, crippleLengthAgainstPlayers,
|
||||
crippleLengthAgainstMobs;
|
||||
|
||||
@Override
|
||||
protected void dataCalculations(Player player, float skillValue) {
|
||||
@@ -33,7 +34,6 @@ public class MacesCommand extends SkillCommand {
|
||||
MacesManager.getCrippleTickDuration(true) / 20.0D);
|
||||
crippleLengthAgainstMobs = String.valueOf(
|
||||
MacesManager.getCrippleTickDuration(false) / 20.0D);
|
||||
|
||||
crippleChanceToApply =
|
||||
mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) + "%";
|
||||
crippleChanceToApplyLucky = String.valueOf(
|
||||
@@ -77,7 +77,7 @@ public class MacesCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.MACES);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -144,7 +144,7 @@ public class MiningCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.MINING);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class RepairCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.REPAIR);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SalvageCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.SALVAGE);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -97,7 +97,7 @@ public class SmeltingCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.SMELTING);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -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.format("%.2f", 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;
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ public class SwordsCommand extends SkillCommand {
|
||||
private String serratedStrikesLengthEndurance;
|
||||
|
||||
private String rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs,
|
||||
ruptureExplosionDamageAgainstPlayers, ruptureExplosionDamageAgainstMobs,
|
||||
ruptureLengthSecondsAgainstPlayers, ruptureLengthSecondsAgainstMobs, ruptureChanceToApply, ruptureChanceToApplyLucky;
|
||||
ruptureLengthSecondsAgainstPlayers, ruptureLengthSecondsAgainstMobs,
|
||||
ruptureChanceToApply, ruptureChanceToApplyLucky;
|
||||
|
||||
private boolean canCounter;
|
||||
private boolean canSerratedStrike;
|
||||
@@ -56,11 +56,6 @@ public class SwordsCommand extends SkillCommand {
|
||||
rupturePureTickDamageAgainstMobs = String.valueOf(
|
||||
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 =
|
||||
mcMMO.p.getAdvancedConfig().getRuptureChanceToApplyOnHit(ruptureRank) + "%";
|
||||
ruptureChanceToApplyLucky = String.valueOf(
|
||||
@@ -105,7 +100,6 @@ public class SwordsCommand extends SkillCommand {
|
||||
|
||||
messages.add(LocaleLoader.getString("Swords.SubSkill.Rupture.Stat.TickDamage",
|
||||
rupturePureTickDamageAgainstPlayers, rupturePureTickDamageAgainstMobs));
|
||||
// messages.add(LocaleLoader.getString("Swords.SubSkill.Rupture.Stat.ExplosionDamage", ruptureExplosionDamageAgainstPlayers, ruptureExplosionDamageAgainstMobs));
|
||||
|
||||
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) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.SWORDS);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -115,7 +115,7 @@ public class TamingCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents, this.skill);
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents, this.skill);
|
||||
|
||||
return textComponents;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class TridentsCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.TRIDENTS);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -136,7 +136,7 @@ public class UnarmedCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.UNARMED);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -123,7 +123,7 @@ public class WoodcuttingCommand extends SkillCommand {
|
||||
protected List<Component> getTextComponents(Player player) {
|
||||
List<Component> textComponents = new ArrayList<>();
|
||||
|
||||
TextComponentFactory.getSubSkillTextComponents(player, textComponents,
|
||||
TextComponentFactory.appendSubSkillTextComponents(player, textComponents,
|
||||
PrimarySkillType.WOODCUTTING);
|
||||
|
||||
return textComponents;
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class AdvancedConfig extends BukkitConfig {
|
||||
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) {
|
||||
super("advanced.yml", dataFolder);
|
||||
@@ -884,7 +885,17 @@ public class AdvancedConfig extends BukkitConfig {
|
||||
|
||||
/* MACES */
|
||||
public double getCrippleChanceToApplyOnHit(int rank) {
|
||||
String root = "Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_";
|
||||
return config.getDouble(root + rank, defaultCrippleValues[rank - 1]);
|
||||
return config.getDouble("Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_" + rank,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,10 +424,6 @@ public class GeneralConfig extends BukkitConfig {
|
||||
return config.getBoolean("MySQL.Server.SSL", true);
|
||||
}
|
||||
|
||||
public boolean getMySQLDebug() {
|
||||
return config.getBoolean("MySQL.Debug", false);
|
||||
}
|
||||
|
||||
public boolean getMySQLPublicKeyRetrieval() {
|
||||
return config.getBoolean("MySQL.Server.allowPublicKeyRetrieval", true);
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ package com.gmail.nossr50.config.skills.alchemy;
|
||||
import static com.gmail.nossr50.util.ItemUtils.customName;
|
||||
import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
|
||||
import static com.gmail.nossr50.util.PotionUtil.setBasePotionType;
|
||||
import static com.gmail.nossr50.util.PotionUtil.setUpgradedAndExtendedProperties;
|
||||
|
||||
import com.gmail.nossr50.config.LegacyConfigLoader;
|
||||
import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.ItemUtils;
|
||||
import com.gmail.nossr50.util.LogUtils;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -49,9 +47,6 @@ public class PotionConfig extends LegacyConfigLoader {
|
||||
private final List<ItemStack> concoctionsIngredientsTierSix = new ArrayList<>();
|
||||
private final List<ItemStack> concoctionsIngredientsTierSeven = new ArrayList<>();
|
||||
private final List<ItemStack> concoctionsIngredientsTierEight = new ArrayList<>();
|
||||
private final AlchemyPotionConfigResult INCOMPATIBLE_POTION_RESULT = new AlchemyPotionConfigResult(
|
||||
null,
|
||||
AlchemyPotionConfigResultType.INCOMPATIBLE);
|
||||
private final AlchemyPotionConfigResult ERROR_POTION_RESULT = new AlchemyPotionConfigResult(
|
||||
null,
|
||||
AlchemyPotionConfigResultType.ERROR);
|
||||
@@ -258,15 +253,15 @@ public class PotionConfig extends LegacyConfigLoader {
|
||||
if (potion_section.contains("Effects")) {
|
||||
for (String effect : potion_section.getStringList("Effects")) {
|
||||
String[] parts = effect.split(" ");
|
||||
if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager()
|
||||
.getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
LogUtils.debug(
|
||||
mcMMO.p.getLogger(),
|
||||
"Skipping potion effect " + effect + " because it is not"
|
||||
+ " compatible with the current Minecraft game version.");
|
||||
return INCOMPATIBLE_POTION_RESULT;
|
||||
}
|
||||
// if (isTrickyTrialsPotionEffect(parts[0]) && !mcMMO.getCompatibilityManager()
|
||||
// .minecraftGameVersion()
|
||||
// .isAtLeast(1, 21, 0)) {
|
||||
// LogUtils.debug(
|
||||
// mcMMO.p.getLogger(),
|
||||
// "Skipping potion effect " + effect + " because it is not"
|
||||
// + " compatible with the current Minecraft game version.");
|
||||
// return INCOMPATIBLE_POTION_RESULT;
|
||||
// }
|
||||
|
||||
PotionEffectType type =
|
||||
parts.length > 0 ? PotionEffectType.getByName(parts[0]) : null;
|
||||
@@ -298,9 +293,7 @@ public class PotionConfig extends LegacyConfigLoader {
|
||||
.getKeys(false)) {
|
||||
// Breeze Rod was only for potions after 1.21.0
|
||||
if (isTrickyTrialsIngredient(childIngredient)
|
||||
&& !mcMMO.getCompatibilityManager()
|
||||
.getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
&& !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
|
||||
continue;
|
||||
}
|
||||
ItemStack ingredient = loadIngredient(childIngredient);
|
||||
@@ -359,8 +352,6 @@ public class PotionConfig extends LegacyConfigLoader {
|
||||
// set base
|
||||
setBasePotionType(potionMeta, potionType, extended, upgraded);
|
||||
|
||||
// Legacy only
|
||||
setUpgradedAndExtendedProperties(potionType, potionMeta, upgraded, extended);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ public class DatabaseManagerFactory {
|
||||
: "Flatfile") + " database");
|
||||
}
|
||||
|
||||
return mcMMO.p.getGeneralConfig().getUseMySQL() ? new SQLDatabaseManager(logger,
|
||||
MYSQL_DRIVER)
|
||||
return mcMMO.p.getGeneralConfig().getUseMySQL()
|
||||
? new SQLDatabaseManager(logger, MYSQL_DRIVER)
|
||||
: new FlatFileDatabaseManager(userFilePath, logger, purgeTime, startingLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_SERRATED_STRIKES;
|
||||
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_SHOTGUN;
|
||||
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_MINING;
|
||||
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_TAMING;
|
||||
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_MINING;
|
||||
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_TAMING;
|
||||
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS;
|
||||
@@ -318,27 +321,26 @@ public class FlatFileDataProcessor {
|
||||
throws IndexOutOfBoundsException {
|
||||
return switch (dataIndex) {
|
||||
case USERNAME_INDEX ->
|
||||
ExpectedType.STRING; //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
|
||||
ExpectedType.STRING;
|
||||
//Assumption: Used to be used for something, no longer used
|
||||
case 2, 3, 23, 33, HEALTHBAR, LEGACY_LAST_LOGIN -> ExpectedType.IGNORED;
|
||||
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION,
|
||||
SKILLS_ARCHERY,
|
||||
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING,
|
||||
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_SERRATED_STRIKES,
|
||||
COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_BLAST_MINING,
|
||||
SCOREBOARD_TIPS,
|
||||
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,
|
||||
EXP_EXCAVATION, EXP_ARCHERY,
|
||||
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY,
|
||||
EXP_CROSSBOWS,
|
||||
EXP_TRIDENTS, EXP_MACES -> ExpectedType.FLOAT;
|
||||
EXP_TRIDENTS, EXP_MACES, EXP_SPEARS -> ExpectedType.FLOAT;
|
||||
case UUID_INDEX -> ExpectedType.UUID;
|
||||
case OVERHAUL_LAST_LOGIN -> ExpectedType.LONG;
|
||||
default -> throw new IndexOutOfBoundsException();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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_SERRATED_STRIKES;
|
||||
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_SHOTGUN;
|
||||
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_MINING;
|
||||
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_TAMING;
|
||||
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_MINING;
|
||||
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_TAMING;
|
||||
import static com.gmail.nossr50.database.FlatFileDatabaseManager.SKILLS_TRIDENTS;
|
||||
@@ -114,18 +117,16 @@ public class FlatFileDataUtil {
|
||||
throws IndexOutOfBoundsException {
|
||||
//TODO: Add UUID recovery? Might not even be worth it.
|
||||
return switch (index) {
|
||||
//We'll keep using this value for legacy compatibility reasons (not sure if needed but don't care)
|
||||
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)
|
||||
//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
|
||||
LEGACY_INVALID_OLD_USERNAME;
|
||||
//Assumption: Used to be used for something, no longer used
|
||||
case 2, 3, 23, 33, LEGACY_LAST_LOGIN, HEALTHBAR -> "IGNORED";
|
||||
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION,
|
||||
SKILLS_ARCHERY,
|
||||
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING,
|
||||
SKILLS_FISHING,
|
||||
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES ->
|
||||
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES, SKILLS_SPEARS ->
|
||||
String.valueOf(startingLevel);
|
||||
case OVERHAUL_LAST_LOGIN -> String.valueOf(-1L);
|
||||
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_BLAST_MINING,
|
||||
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_EXCAVATION, EXP_ARCHERY,
|
||||
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY,
|
||||
EXP_CROSSBOWS,
|
||||
EXP_TRIDENTS, EXP_MACES -> "0";
|
||||
EXP_TRIDENTS, EXP_MACES, EXP_SPEARS -> "0";
|
||||
case UUID_INDEX ->
|
||||
throw new IndexOutOfBoundsException(); //TODO: Add UUID recovery? Might not even be worth it.
|
||||
default -> throw new IndexOutOfBoundsException();
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.gmail.nossr50.datatypes.database;
|
||||
public enum UpgradeType {
|
||||
ADD_FISHING,
|
||||
ADD_BLAST_MINING_COOLDOWN,
|
||||
ADD_SQL_INDEXES,
|
||||
ADD_MOB_HEALTHBARS,
|
||||
DROP_SQL_PARTY_NAMES,
|
||||
DROP_SPOUT,
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.gmail.nossr50.skills.mining.MiningManager;
|
||||
import com.gmail.nossr50.skills.repair.RepairManager;
|
||||
import com.gmail.nossr50.skills.salvage.SalvageManager;
|
||||
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.taming.TamingManager;
|
||||
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.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import net.kyori.adventure.identity.Identified;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -171,73 +173,41 @@ public class McMMOPlayer implements Identified {
|
||||
try {
|
||||
initManager(primarySkillType);
|
||||
} 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
|
||||
private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException {
|
||||
switch (primarySkillType) {
|
||||
case ACROBATICS:
|
||||
skillManagers.put(primarySkillType, new AcrobaticsManager(this));
|
||||
break;
|
||||
case ALCHEMY:
|
||||
skillManagers.put(primarySkillType, new AlchemyManager(this));
|
||||
break;
|
||||
case ARCHERY:
|
||||
skillManagers.put(primarySkillType, new ArcheryManager(this));
|
||||
break;
|
||||
case AXES:
|
||||
skillManagers.put(primarySkillType, new AxesManager(this));
|
||||
break;
|
||||
case CROSSBOWS:
|
||||
skillManagers.put(primarySkillType, new CrossbowsManager(this));
|
||||
break;
|
||||
case EXCAVATION:
|
||||
skillManagers.put(primarySkillType, new ExcavationManager(this));
|
||||
break;
|
||||
case FISHING:
|
||||
skillManagers.put(primarySkillType, new FishingManager(this));
|
||||
break;
|
||||
case HERBALISM:
|
||||
skillManagers.put(primarySkillType, new HerbalismManager(this));
|
||||
break;
|
||||
case MINING:
|
||||
skillManagers.put(primarySkillType, new MiningManager(this));
|
||||
break;
|
||||
case REPAIR:
|
||||
skillManagers.put(primarySkillType, new RepairManager(this));
|
||||
break;
|
||||
case SALVAGE:
|
||||
skillManagers.put(primarySkillType, new SalvageManager(this));
|
||||
break;
|
||||
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!");
|
||||
final SkillManager manager = switch (primarySkillType) {
|
||||
case ACROBATICS -> new AcrobaticsManager(this);
|
||||
case ALCHEMY -> new AlchemyManager(this);
|
||||
case ARCHERY -> new ArcheryManager(this);
|
||||
case AXES -> new AxesManager(this);
|
||||
case CROSSBOWS -> new CrossbowsManager(this);
|
||||
case EXCAVATION -> new ExcavationManager(this);
|
||||
case FISHING -> new FishingManager(this);
|
||||
case HERBALISM -> new HerbalismManager(this);
|
||||
case MINING -> new MiningManager(this);
|
||||
case REPAIR -> new RepairManager(this);
|
||||
case SALVAGE -> new SalvageManager(this);
|
||||
case SMELTING -> new SmeltingManager(this);
|
||||
case SWORDS -> new SwordsManager(this);
|
||||
case TAMING -> new TamingManager(this);
|
||||
case TRIDENTS -> new TridentsManager(this);
|
||||
case UNARMED -> new UnarmedManager(this);
|
||||
case WOODCUTTING -> new WoodcuttingManager(this);
|
||||
case MACES -> new MacesManager(this);
|
||||
case SPEARS -> mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)
|
||||
? new SpearsManager(this)
|
||||
: null;
|
||||
};
|
||||
|
||||
if (manager != null) {
|
||||
skillManagers.put(primarySkillType, manager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,6 +339,10 @@ public class McMMOPlayer implements Identified {
|
||||
return (SmeltingManager) skillManagers.get(PrimarySkillType.SMELTING);
|
||||
}
|
||||
|
||||
public SpearsManager getSpearsManager() {
|
||||
return (SpearsManager) skillManagers.get(PrimarySkillType.SPEARS);
|
||||
}
|
||||
|
||||
public SwordsManager getSwordsManager() {
|
||||
return (SwordsManager) skillManagers.get(PrimarySkillType.SWORDS);
|
||||
}
|
||||
@@ -1304,4 +1278,5 @@ public class McMMOPlayer implements Identified {
|
||||
public void setChatMode(@NotNull ChatChannel chatChannel) {
|
||||
this.chatChannel = chatChannel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class PlayerProfile {
|
||||
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.loaded = isLoaded;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ public enum PrimarySkillType {
|
||||
REPAIR,
|
||||
SALVAGE,
|
||||
SMELTING,
|
||||
SPEARS,
|
||||
SWORDS,
|
||||
TAMING,
|
||||
TRIDENTS,
|
||||
|
||||
@@ -83,6 +83,11 @@ public enum SubSkillType {
|
||||
SMELTING_SECOND_SMELT,
|
||||
SMELTING_UNDERSTANDING_THE_ART(8),
|
||||
|
||||
/* Spears */
|
||||
SPEARS_SPEARS_LIMIT_BREAK(10),
|
||||
SPEARS_MOMENTUM(10),
|
||||
SPEARS_SPEAR_MASTERY(8),
|
||||
|
||||
/* Swords */
|
||||
SWORDS_COUNTER_ATTACK(1),
|
||||
SWORDS_RUPTURE(4),
|
||||
|
||||
@@ -93,6 +93,13 @@ public enum SuperAbilityType {
|
||||
"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
|
||||
@@ -216,8 +223,8 @@ public enum SuperAbilityType {
|
||||
case SUPER_BREAKER -> Permissions.superBreaker(player);
|
||||
case TREE_FELLER -> Permissions.treeFeller(player);
|
||||
// TODO: once implemented, return permissions for the following abilities
|
||||
case EXPLOSIVE_SHOT, TRIDENTS_SUPER_ABILITY, SUPER_SHOTGUN, MACES_SUPER_ABILITY ->
|
||||
false;
|
||||
case EXPLOSIVE_SHOT, TRIDENTS_SUPER_ABILITY, SUPER_SHOTGUN, MACES_SUPER_ABILITY,
|
||||
SPEARS_SUPER_ABILITY -> false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.gmail.nossr50.datatypes.skills.alchemy;
|
||||
|
||||
import static com.gmail.nossr50.util.PotionUtil.samePotionType;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.PotionUtil;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
@@ -80,12 +78,14 @@ public class AlchemyPotion {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!samePotionType(getAlchemyPotionMeta(), otherPotionMeta)) {
|
||||
@NotNull PotionMeta potionMeta = getAlchemyPotionMeta();
|
||||
if (!(potionMeta.getBasePotionType() == otherPotionMeta.getBasePotionType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Legacy only comparison, compare PotionData
|
||||
if (!PotionUtil.isPotionDataEqual(getAlchemyPotionMeta(), otherPotionMeta)) {
|
||||
@NotNull PotionMeta potionMeta1 = getAlchemyPotionMeta();
|
||||
if (!(potionMeta1.getBasePotionType() == otherPotionMeta.getBasePotionType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,12 +147,14 @@ public class BlockListener implements Listener {
|
||||
}
|
||||
|
||||
int amountToAddFromBonus = bonusDropMeta.asInt();
|
||||
final McMMOModifyBlockDropItemEvent modifyBlockDropItemEvent
|
||||
final McMMOModifyBlockDropItemEvent modifyDropEvent
|
||||
= new McMMOModifyBlockDropItemEvent(event, item, amountToAddFromBonus);
|
||||
plugin.getServer().getPluginManager().callEvent(modifyBlockDropItemEvent);
|
||||
if (!modifyBlockDropItemEvent.isCancelled()
|
||||
&& modifyBlockDropItemEvent.getModifiedItemStackQuantity() > originalAmount) {
|
||||
eventItemStack.setAmount(modifyBlockDropItemEvent.getModifiedItemStackQuantity());
|
||||
plugin.getServer().getPluginManager().callEvent(modifyDropEvent);
|
||||
if (!modifyDropEvent.isCancelled()
|
||||
&& modifyDropEvent.getModifiedItemStackQuantity() > originalAmount) {
|
||||
eventItemStack.setAmount(
|
||||
Math.min(modifyDropEvent.getModifiedItemStackQuantity(),
|
||||
item.getItemStack().getMaxStackSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,11 +242,16 @@ public class BlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockState blockState = event.getNewState();
|
||||
final BlockState newState = event.getNewState();
|
||||
|
||||
if (!newState.isPlaced()) {
|
||||
// not backed by a real block
|
||||
return;
|
||||
}
|
||||
|
||||
if (ExperienceConfig.getInstance().isSnowExploitPrevented() && BlockUtils.shouldBeWatched(
|
||||
blockState)) {
|
||||
Block block = blockState.getBlock();
|
||||
newState)) {
|
||||
final Block block = newState.getBlock();
|
||||
|
||||
if (BlockUtils.isWithinWorldBounds(block)) {
|
||||
BlockUtils.setUnnaturalBlock(block);
|
||||
@@ -257,7 +264,7 @@ public class BlockListener implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onBlockFormEvent(BlockFormEvent event) {
|
||||
World world = event.getBlock().getWorld();
|
||||
final World world = event.getBlock().getWorld();
|
||||
|
||||
/* WORLD BLACKLIST CHECK */
|
||||
if (WorldBlacklist.isWorldBlacklisted(world)) {
|
||||
@@ -265,12 +272,16 @@ public class BlockListener implements Listener {
|
||||
}
|
||||
|
||||
if (ExperienceConfig.getInstance().preventStoneLavaFarming()) {
|
||||
BlockState newState = event.getNewState();
|
||||
final BlockState newState = event.getNewState();
|
||||
if (!newState.isPlaced()) {
|
||||
// not backed by a real block
|
||||
return;
|
||||
}
|
||||
|
||||
if (newState.getType() != Material.OBSIDIAN
|
||||
&& ExperienceConfig.getInstance().doesBlockGiveSkillXP(
|
||||
PrimarySkillType.MINING, newState.getType())) {
|
||||
Block block = newState.getBlock();
|
||||
final Block block = newState.getBlock();
|
||||
if (BlockUtils.isWithinWorldBounds(block)) {
|
||||
BlockUtils.setUnnaturalBlock(block);
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ public class PlayerListener implements Listener {
|
||||
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// world guard main flag check
|
||||
if (WorldGuardUtils.isWorldGuardLoaded() && !WorldGuardManager.getInstance()
|
||||
.hasMainFlag((Player) event.getEntity())) {
|
||||
@@ -342,8 +343,8 @@ public class PlayerListener implements Listener {
|
||||
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
|
||||
|
||||
switch (event.getState()) {
|
||||
// CAUGHT_FISH happens for any item caught (including junk and treasure)
|
||||
case CAUGHT_FISH:
|
||||
//TODO Update to new API once available! Waiting for case CAUGHT_TREASURE
|
||||
if (event.getCaught() != null) {
|
||||
Item fishingCatch = (Item) event.getCaught();
|
||||
|
||||
@@ -488,8 +489,7 @@ public class PlayerListener implements Listener {
|
||||
|
||||
fishingManager.processExploiting(event.getHook().getLocation().toVector());
|
||||
|
||||
if (fishingManager.isExploitingFishing(
|
||||
event.getHook().getLocation().toVector())) {
|
||||
if (fishingManager.isExploitingFishing()) {
|
||||
player.sendMessage(LocaleLoader.getString("Fishing.ScarcityTip",
|
||||
ExperienceConfig.getInstance()
|
||||
.getFishingExploitingOptionMoveRange()));
|
||||
@@ -675,6 +675,10 @@ public class PlayerListener implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onPlayerInteractLowest(PlayerInteractEvent event) {
|
||||
if (event.getAction() == Action.PHYSICAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* WORLD BLACKLIST CHECK */
|
||||
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
|
||||
return;
|
||||
@@ -817,6 +821,10 @@ public class PlayerListener implements Listener {
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerInteractMonitor(PlayerInteractEvent event) {
|
||||
if (event.getAction() == Action.PHYSICAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* WORLD BLACKLIST CHECK */
|
||||
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
|
||||
return;
|
||||
@@ -900,7 +908,6 @@ public class PlayerListener implements Listener {
|
||||
|
||||
HerbalismManager herbalismManager = mmoPlayer.getHerbalismManager();
|
||||
|
||||
// FakePlayerAnimationEvent fakeSwing = new FakePlayerAnimationEvent(event.getPlayer(), PlayerAnimationType.ARM_SWING); //PlayerAnimationEvent compat
|
||||
if (!event.isCancelled() || event.useInteractedBlock() != Event.Result.DENY) {
|
||||
//TODO: Is this code to set false from bone meal even needed? I'll have to double check later.
|
||||
if (heldItem.getType() == Material.BONE_MEAL) {
|
||||
|
||||
@@ -56,14 +56,13 @@ import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.TransientEntityTracker;
|
||||
import com.gmail.nossr50.util.TransientMetadataTools;
|
||||
import com.gmail.nossr50.util.MinecraftGameVersionFactory;
|
||||
import com.gmail.nossr50.util.blockmeta.ChunkManager;
|
||||
import com.gmail.nossr50.util.blockmeta.ChunkManagerFactory;
|
||||
import com.gmail.nossr50.util.blockmeta.UserBlockTracker;
|
||||
import com.gmail.nossr50.util.commands.CommandRegistrationManager;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.experience.FormulaManager;
|
||||
import com.gmail.nossr50.util.platform.PlatformManager;
|
||||
import com.gmail.nossr50.util.platform.ServerSoftwareType;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import com.gmail.nossr50.util.player.PlayerLevelUtils;
|
||||
import com.gmail.nossr50.util.player.UserManager;
|
||||
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
|
||||
@@ -94,7 +93,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class mcMMO extends JavaPlugin {
|
||||
/* Managers & Services */
|
||||
private static PlatformManager platformManager;
|
||||
private static ChunkManager chunkManager;
|
||||
private static RepairableManager repairableManager;
|
||||
private static SalvageableManager salvageableManager;
|
||||
@@ -107,6 +105,7 @@ public class mcMMO extends JavaPlugin {
|
||||
private static ChatManager chatManager;
|
||||
private static CommandManager commandManager; //ACF
|
||||
private static TransientEntityTracker transientEntityTracker;
|
||||
private static MinecraftGameVersion minecraftGameVersion;
|
||||
|
||||
private SkillTools skillTools;
|
||||
|
||||
@@ -170,8 +169,19 @@ public class mcMMO extends JavaPlugin {
|
||||
//Filter out any debug messages (if debug/verbose logging is not enabled)
|
||||
getLogger().setFilter(new LogFilter(this));
|
||||
|
||||
//Platform Manager
|
||||
platformManager = new PlatformManager();
|
||||
// Determine game version before moving forward
|
||||
final String versionStr = Bukkit.getVersion();
|
||||
try {
|
||||
minecraftGameVersion = MinecraftGameVersionFactory.calculateGameVersion(versionStr);
|
||||
} catch (Exception e) {
|
||||
// if anything goes wrong with our calculations, assume they are running the minimum
|
||||
// supported version and log the error
|
||||
getLogger().warning("Could not determine Minecraft version from"
|
||||
+ " server software version string: " + versionStr +
|
||||
", Please report this bug to the devs!");
|
||||
e.printStackTrace();
|
||||
minecraftGameVersion = new MinecraftGameVersion(1, 20, 5);
|
||||
}
|
||||
|
||||
//Folia lib plugin instance
|
||||
foliaLib = new FoliaLib(this);
|
||||
@@ -245,15 +255,14 @@ public class mcMMO extends JavaPlugin {
|
||||
if (serverAPIOutdated) {
|
||||
foliaLib.getScheduler().runTimer(
|
||||
() -> getLogger().severe(
|
||||
"You are running an outdated version of "
|
||||
+ platformManager.getServerSoftware()
|
||||
"You are potentially running an outdated version of your server software"
|
||||
+ ", mcMMO will not work unless you update to a newer version!"),
|
||||
20, 20 * 60 * 30);
|
||||
|
||||
if (platformManager.getServerSoftware() == ServerSoftwareType.CRAFT_BUKKIT) {
|
||||
if (!minecraftGameVersion.isAtLeast(1, 20, 4)) {
|
||||
foliaLib.getScheduler().runTimer(
|
||||
() -> getLogger().severe(
|
||||
"We have detected you are using incompatible server software, our best guess is that you are using CraftBukkit. mcMMO requires Spigot or Paper, if you are not using CraftBukkit, you will still need to update your custom server software before mcMMO will work."),
|
||||
"This version of mcMMO requires at least Minecraft 1.20.4 to"
|
||||
+ " function properly, please update your software or use an older version of mcMMO!"),
|
||||
20, 20 * 60 * 30);
|
||||
}
|
||||
} else {
|
||||
@@ -351,15 +360,15 @@ public class mcMMO extends JavaPlugin {
|
||||
|
||||
private void checkForOutdatedAPI() {
|
||||
try {
|
||||
Class<?> checkForClass = Class.forName("org.bukkit.event.block.BlockDropItemEvent");
|
||||
checkForClass.getMethod("getItems");
|
||||
Class<?> blockDropItemEvent = Class.forName("org.bukkit.event.block.BlockDropItemEvent");
|
||||
blockDropItemEvent.getMethod("getItems");
|
||||
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
|
||||
// 1.20.4 checks
|
||||
Class<?> entityDamageEvent = Class.forName("org.bukkit.event.entity.EntityDamageEvent");
|
||||
entityDamageEvent.getMethod("getDamageSource");
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
serverAPIOutdated = true;
|
||||
String software = platformManager.getServerSoftwareStr();
|
||||
getLogger().severe(
|
||||
"You are running an older version of " + software
|
||||
+ " that is not compatible with mcMMO, update your server software!");
|
||||
getLogger().severe("Your server software is missing APIs that mcMMO requires to function properly, please update your server software!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,10 +511,6 @@ public class mcMMO extends JavaPlugin {
|
||||
return upgradeManager;
|
||||
}
|
||||
|
||||
public static @Nullable CompatibilityManager getCompatibilityManager() {
|
||||
return platformManager.getCompatibilityManager();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setDatabaseManager(DatabaseManager databaseManager) {
|
||||
mcMMO.databaseManager = databaseManager;
|
||||
@@ -751,10 +756,6 @@ public class mcMMO extends JavaPlugin {
|
||||
return worldBlacklist;
|
||||
}
|
||||
|
||||
public static PlatformManager getPlatformManager() {
|
||||
return platformManager;
|
||||
}
|
||||
|
||||
public static BukkitAudiences getAudiences() {
|
||||
return audiences;
|
||||
}
|
||||
@@ -835,4 +836,13 @@ public class mcMMO extends JavaPlugin {
|
||||
public @NotNull FoliaLib getFoliaLib() {
|
||||
return foliaLib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link MinecraftGameVersion}
|
||||
*
|
||||
* @return the {@link MinecraftGameVersion}
|
||||
*/
|
||||
public static MinecraftGameVersion getMinecraftGameVersion() {
|
||||
return minecraftGameVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +49,6 @@ public class McRankCommandDisplayTask extends CancellableRunnable {
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName));
|
||||
|
||||
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
|
||||
// Check if the command is for Maces but the MC version is not correct
|
||||
if (skill == PrimarySkillType.MACES
|
||||
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
continue;
|
||||
}
|
||||
rank = skills.get(skill);
|
||||
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill",
|
||||
mcMMO.p.getSkillTools().getLocalizedSkillName(skill),
|
||||
|
||||
@@ -6,9 +6,10 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.ItemUtils;
|
||||
import com.gmail.nossr50.util.skills.RankUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -16,7 +17,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Archery {
|
||||
private static final List<TrackedEntity> trackedEntities = new ArrayList<>();
|
||||
private static final Map<UUID, TrackedEntity> trackedEntities = new ConcurrentHashMap<>();
|
||||
|
||||
public static double skillShotMaxBonusDamage = mcMMO.p.getAdvancedConfig()
|
||||
.getSkillShotDamageMax();
|
||||
@@ -27,25 +28,12 @@ public class Archery {
|
||||
.getArcheryDistanceMultiplier();
|
||||
|
||||
protected static void incrementTrackerValue(LivingEntity livingEntity) {
|
||||
for (TrackedEntity trackedEntity : trackedEntities) {
|
||||
if (trackedEntity.getLivingEntity().getEntityId() == livingEntity.getEntityId()) {
|
||||
trackedEntity.incrementArrowCount();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addToTracker(livingEntity); // If the entity isn't tracked yet
|
||||
}
|
||||
|
||||
protected static void addToTracker(LivingEntity livingEntity) {
|
||||
TrackedEntity trackedEntity = new TrackedEntity(livingEntity);
|
||||
|
||||
final TrackedEntity trackedEntity = trackedEntities.computeIfAbsent(livingEntity.getUniqueId(), k -> new TrackedEntity(livingEntity));
|
||||
trackedEntity.incrementArrowCount();
|
||||
trackedEntities.add(trackedEntity);
|
||||
}
|
||||
|
||||
protected static void removeFromTracker(TrackedEntity trackedEntity) {
|
||||
trackedEntities.remove(trackedEntity);
|
||||
trackedEntities.remove(trackedEntity.getID());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,17 +42,11 @@ public class Archery {
|
||||
* @param livingEntity The entity hit by the arrows
|
||||
*/
|
||||
public static void arrowRetrievalCheck(@NotNull LivingEntity livingEntity) {
|
||||
for (Iterator<TrackedEntity> entityIterator = trackedEntities.iterator();
|
||||
entityIterator.hasNext(); ) {
|
||||
TrackedEntity trackedEntity = entityIterator.next();
|
||||
|
||||
if (trackedEntity.getID() == livingEntity.getUniqueId()) {
|
||||
ItemUtils.spawnItems(null, livingEntity.getLocation(),
|
||||
new ItemStack(Material.ARROW), trackedEntity.getArrowCount(),
|
||||
ItemSpawnReason.ARROW_RETRIEVAL_ACTIVATED);
|
||||
entityIterator.remove();
|
||||
return;
|
||||
}
|
||||
final TrackedEntity trackedEntity = trackedEntities.remove(livingEntity.getUniqueId());
|
||||
if (trackedEntity != null) {
|
||||
ItemUtils.spawnItems(null, livingEntity.getLocation(),
|
||||
new ItemStack(Material.ARROW), trackedEntity.getArrowCount(),
|
||||
ItemSpawnReason.ARROW_RETRIEVAL_ACTIVATED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.gmail.nossr50.util.MetadataConstants;
|
||||
import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.adapter.BiomeAdapter;
|
||||
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.player.NotificationManager;
|
||||
import com.gmail.nossr50.util.random.ProbabilityUtil;
|
||||
import com.gmail.nossr50.util.skills.CombatUtils;
|
||||
@@ -40,7 +39,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -55,31 +53,24 @@ import org.bukkit.entity.Sheep;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FishingManager extends SkillManager {
|
||||
public static final int FISHING_ROD_CAST_CD_MILLISECONDS = 100;
|
||||
private final long FISHING_COOLDOWN_SECONDS = 1000L;
|
||||
|
||||
private long fishingRodCastTimestamp = 0L;
|
||||
private long fishHookSpawnTimestamp = 0L;
|
||||
private long lastWarned = 0L;
|
||||
private final long lastWarnedExhaust = 0L;
|
||||
private FishHook fishHookReference;
|
||||
private BoundingBox lastFishingBoundingBox;
|
||||
private boolean sameTarget;
|
||||
private Item fishingCatch;
|
||||
private Location hookLocation;
|
||||
private int fishCaughtCounter = 1;
|
||||
private final int masterAnglerMinWaitLowerBound;
|
||||
private final int masterAnglerMaxWaitLowerBound;
|
||||
|
||||
public FishingManager(McMMOPlayer mmoPlayer) {
|
||||
super(mmoPlayer, PrimarySkillType.FISHING);
|
||||
//Ticks for minWait and maxWait never go below this value
|
||||
// Ticks for minWait and maxWait never go below this value
|
||||
int bonusCapMin = mcMMO.p.getAdvancedConfig().getFishingReductionMinWaitCap();
|
||||
int bonusCapMax = mcMMO.p.getAdvancedConfig().getFishingReductionMaxWaitCap();
|
||||
|
||||
@@ -95,53 +86,18 @@ public class FishingManager extends SkillManager {
|
||||
}
|
||||
|
||||
public boolean canMasterAngler() {
|
||||
return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null
|
||||
&& getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
|
||||
return getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
|
||||
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
|
||||
}
|
||||
|
||||
// public void setFishingRodCastTimestamp()
|
||||
// {
|
||||
// long currentTime = System.currentTimeMillis();
|
||||
// //Only track spam casting if the fishing hook is fresh
|
||||
// if (currentTime > fishHookSpawnTimestamp + 1000)
|
||||
// return;
|
||||
//
|
||||
// if (currentTime < fishingRodCastTimestamp + FISHING_ROD_CAST_CD_MILLISECONDS)
|
||||
// {
|
||||
// ItemStack fishingRod = getPlayer().getInventory().getItemInMainHand();
|
||||
//
|
||||
// //Ensure correct hand item is damaged
|
||||
// if (fishingRod.getType() != Material.FISHING_ROD) {
|
||||
// fishingRod = getPlayer().getInventory().getItemInOffHand();
|
||||
// }
|
||||
//
|
||||
// getPlayer().setFoodLevel(Math.max(getPlayer().getFoodLevel() - 1, 0));
|
||||
// fishingRod.setDurability((short) (fishingRod.getDurability() + 5));
|
||||
// getPlayer().updateInventory();
|
||||
//
|
||||
// if (lastWarnedExhaust + (1000) < currentTime)
|
||||
// {
|
||||
// getPlayer().sendMessage(LocaleLoader.getString("Fishing.Exhausting"));
|
||||
// lastWarnedExhaust = currentTime;
|
||||
// SoundManager.sendSound(getPlayer(), getPlayer().getLocation(), SoundType.TIRED);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fishingRodCastTimestamp = System.currentTimeMillis();
|
||||
// }
|
||||
|
||||
public void setFishHookReference(FishHook fishHook) {
|
||||
if (fishHook.getMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF).size() > 0) {
|
||||
public void setFishHookReference(Metadatable fishHook) {
|
||||
if (!fishHook.getMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fishHook.setMetadata(MetadataConstants.METADATA_KEY_FISH_HOOK_REF,
|
||||
MetadataConstants.MCMMO_METADATA_VALUE);
|
||||
this.fishHookReference = fishHook;
|
||||
fishHookSpawnTimestamp = System.currentTimeMillis();
|
||||
fishingRodCastTimestamp = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
public boolean isFishingTooOften() {
|
||||
@@ -180,21 +136,41 @@ public class FishingManager extends SkillManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the player is exploiting fishing by checking if they have caught
|
||||
* more fish than the configured limit without moving their fishing spot.
|
||||
* This method relies on internal state to determine if the player is exploiting fishing,
|
||||
* and the centerOfCastVector parameter is no longer used and will be removed in
|
||||
* a future version.
|
||||
*
|
||||
* @param centerOfCastVector unused
|
||||
* @deprecated since 2.2.050, the parameter is no longer used and will be removed in
|
||||
* a future version. The method now relies on internal state to determine if the player
|
||||
* is exploiting fishing.
|
||||
* @return true if the player is exploiting fishing, false otherwise
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.2.050")
|
||||
public boolean isExploitingFishing(Vector centerOfCastVector) {
|
||||
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
|
||||
.getFishingExploitingOptionOverFishLimit();
|
||||
}
|
||||
|
||||
/*Block targetBlock = getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100);
|
||||
|
||||
if (!targetBlock.isLiquid()) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Determines if the player is exploiting fishing by checking if they have caught
|
||||
* more fish than the configured limit without moving their fishing spot.
|
||||
*
|
||||
* @return true if the player is exploiting fishing, false otherwise
|
||||
*/
|
||||
public boolean isExploitingFishing() {
|
||||
return this.sameTarget && fishCaughtCounter >= ExperienceConfig.getInstance()
|
||||
.getFishingExploitingOptionOverFishLimit();
|
||||
}
|
||||
|
||||
public static BoundingBox makeBoundingBox(Vector centerOfCastVector) {
|
||||
int exploitingRange = ExperienceConfig.getInstance().getFishingExploitingOptionMoveRange();
|
||||
return BoundingBox.of(centerOfCastVector, exploitingRange / 2, 1, exploitingRange / 2);
|
||||
return BoundingBox.of(centerOfCastVector,
|
||||
(double) exploitingRange / 2, 1,
|
||||
(double) exploitingRange / 2);
|
||||
}
|
||||
|
||||
public void setFishingTarget() {
|
||||
@@ -243,15 +219,6 @@ public class FishingManager extends SkillManager {
|
||||
return mcMMO.p.getAdvancedConfig().getFishingVanillaXPModifier(getLootTier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Shake Mob probability
|
||||
*
|
||||
* @return Shake Mob probability
|
||||
*/
|
||||
public double getShakeProbability() {
|
||||
return getShakeChance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Fisherman's Diet ability
|
||||
*
|
||||
@@ -293,102 +260,95 @@ public class FishingManager extends SkillManager {
|
||||
* @param fishHook target fish hook
|
||||
*/
|
||||
public void processMasterAngler(@NotNull FishHook fishHook, int lureLevel) {
|
||||
MasterAnglerCompatibilityLayer masterAnglerCompatibilityLayer = (MasterAnglerCompatibilityLayer) mcMMO.getCompatibilityManager()
|
||||
.getMasterAnglerCompatibilityLayer();
|
||||
int maxWaitTicks = fishHook.getMaxWaitTime();
|
||||
int minWaitTicks = fishHook.getMinWaitTime();
|
||||
|
||||
if (masterAnglerCompatibilityLayer != null) {
|
||||
int maxWaitTicks = masterAnglerCompatibilityLayer.getMaxWaitTime(fishHook);
|
||||
int minWaitTicks = masterAnglerCompatibilityLayer.getMinWaitTime(fishHook);
|
||||
int masterAnglerRank = RankUtils.getRank(mmoPlayer, SubSkillType.FISHING_MASTER_ANGLER);
|
||||
int convertedLureBonus = 0;
|
||||
|
||||
int masterAnglerRank = RankUtils.getRank(mmoPlayer, SubSkillType.FISHING_MASTER_ANGLER);
|
||||
int convertedLureBonus = 0;
|
||||
|
||||
//This avoids a Minecraft bug where lure levels above 3 break fishing
|
||||
if (lureLevel > 0) {
|
||||
masterAnglerCompatibilityLayer.setApplyLure(fishHook, false);
|
||||
convertedLureBonus = lureLevel * 100;
|
||||
}
|
||||
|
||||
boolean boatBonus = isInBoat();
|
||||
int minWaitReduction = getMasterAnglerTickMinWaitReduction(masterAnglerRank, boatBonus);
|
||||
int maxWaitReduction = getMasterAnglerTickMaxWaitReduction(masterAnglerRank, boatBonus,
|
||||
convertedLureBonus);
|
||||
|
||||
int reducedMinWaitTime = getReducedTicks(minWaitTicks, minWaitReduction,
|
||||
masterAnglerMinWaitLowerBound);
|
||||
int reducedMaxWaitTime = getReducedTicks(maxWaitTicks, maxWaitReduction,
|
||||
masterAnglerMaxWaitLowerBound);
|
||||
|
||||
boolean badValuesFix = false;
|
||||
|
||||
//If we find bad values correct it
|
||||
if (reducedMaxWaitTime < reducedMinWaitTime) {
|
||||
reducedMaxWaitTime = reducedMinWaitTime + 100;
|
||||
badValuesFix = true;
|
||||
}
|
||||
|
||||
final McMMOPlayerMasterAnglerEvent event =
|
||||
new McMMOPlayerMasterAnglerEvent(mmoPlayer, reducedMinWaitTime,
|
||||
reducedMaxWaitTime, this);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reducedMaxWaitTime = event.getReducedMaxWaitTime();
|
||||
reducedMinWaitTime = event.getReducedMinWaitTime();
|
||||
|
||||
if (mmoPlayer.isDebugMode()) {
|
||||
mmoPlayer.getPlayer().sendMessage(ChatColor.GOLD + "Master Angler Debug");
|
||||
|
||||
if (badValuesFix) {
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.RED + "Bad values were applied and corrected," +
|
||||
" check your configs, minWaitLowerBound wait should never be lower than min wait.");
|
||||
}
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage(
|
||||
"ALLOW STACK WITH LURE: " + masterAnglerCompatibilityLayer.getApplyLure(
|
||||
fishHook));
|
||||
mmoPlayer.getPlayer().sendMessage("MIN TICK REDUCTION: " + minWaitReduction);
|
||||
mmoPlayer.getPlayer().sendMessage("MAX TICK REDUCTION: " + maxWaitReduction);
|
||||
mmoPlayer.getPlayer().sendMessage("BOAT BONUS: " + boatBonus);
|
||||
|
||||
if (boatBonus) {
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage("BOAT MAX TICK REDUCTION: " + maxWaitReduction);
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage("BOAT MIN TICK REDUCTION: " + maxWaitReduction);
|
||||
}
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "BEFORE MASTER ANGLER WAS APPLIED");
|
||||
mmoPlayer.getPlayer().sendMessage("Original Max Wait Ticks: " + maxWaitTicks);
|
||||
mmoPlayer.getPlayer().sendMessage("Original Min Wait Ticks: " + minWaitTicks);
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "AFTER MASTER ANGLER WAS APPLIED");
|
||||
mmoPlayer.getPlayer().sendMessage("Current Max Wait Ticks: " + reducedMaxWaitTime);
|
||||
mmoPlayer.getPlayer().sendMessage("Current Min Wait Ticks: " + reducedMinWaitTime);
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "Caps / Limits (edit in advanced.yml)");
|
||||
mmoPlayer.getPlayer().sendMessage("Lowest possible minWaitLowerBound wait ticks "
|
||||
+ masterAnglerMinWaitLowerBound);
|
||||
mmoPlayer.getPlayer().sendMessage(
|
||||
"Lowest possible min wait ticks " + masterAnglerMaxWaitLowerBound);
|
||||
}
|
||||
|
||||
masterAnglerCompatibilityLayer.setMaxWaitTime(fishHook, reducedMaxWaitTime);
|
||||
masterAnglerCompatibilityLayer.setMinWaitTime(fishHook, reducedMinWaitTime);
|
||||
//This avoids a Minecraft bug where lure levels above 3 break fishing
|
||||
if (lureLevel > 0) {
|
||||
fishHook.setApplyLure(false);
|
||||
convertedLureBonus = lureLevel * 100;
|
||||
}
|
||||
|
||||
boolean boatBonus = isInBoat();
|
||||
int minWaitReduction = getMasterAnglerTickMinWaitReduction(masterAnglerRank, boatBonus);
|
||||
int maxWaitReduction = getMasterAnglerTickMaxWaitReduction(masterAnglerRank, boatBonus,
|
||||
convertedLureBonus);
|
||||
|
||||
int reducedMinWaitTime = getReducedTicks(minWaitTicks, minWaitReduction,
|
||||
masterAnglerMinWaitLowerBound);
|
||||
int reducedMaxWaitTime = getReducedTicks(maxWaitTicks, maxWaitReduction,
|
||||
masterAnglerMaxWaitLowerBound);
|
||||
|
||||
boolean badValuesFix = false;
|
||||
|
||||
//If we find bad values correct it
|
||||
if (reducedMaxWaitTime < reducedMinWaitTime) {
|
||||
reducedMaxWaitTime = reducedMinWaitTime + 100;
|
||||
badValuesFix = true;
|
||||
}
|
||||
|
||||
final McMMOPlayerMasterAnglerEvent event =
|
||||
new McMMOPlayerMasterAnglerEvent(mmoPlayer, reducedMinWaitTime,
|
||||
reducedMaxWaitTime, this);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reducedMaxWaitTime = event.getReducedMaxWaitTime();
|
||||
reducedMinWaitTime = event.getReducedMinWaitTime();
|
||||
|
||||
if (mmoPlayer.isDebugMode()) {
|
||||
mmoPlayer.getPlayer().sendMessage(ChatColor.GOLD + "Master Angler Debug");
|
||||
|
||||
if (badValuesFix) {
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.RED + "Bad values were applied and corrected," +
|
||||
" check your configs, minWaitLowerBound wait should never be lower than min wait.");
|
||||
}
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage(
|
||||
"ALLOW STACK WITH LURE: " + fishHook.getApplyLure());
|
||||
mmoPlayer.getPlayer().sendMessage("MIN TICK REDUCTION: " + minWaitReduction);
|
||||
mmoPlayer.getPlayer().sendMessage("MAX TICK REDUCTION: " + maxWaitReduction);
|
||||
mmoPlayer.getPlayer().sendMessage("BOAT BONUS: " + boatBonus);
|
||||
|
||||
if (boatBonus) {
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage("BOAT MAX TICK REDUCTION: " + maxWaitReduction);
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage("BOAT MIN TICK REDUCTION: " + maxWaitReduction);
|
||||
}
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "BEFORE MASTER ANGLER WAS APPLIED");
|
||||
mmoPlayer.getPlayer().sendMessage("Original Max Wait Ticks: " + maxWaitTicks);
|
||||
mmoPlayer.getPlayer().sendMessage("Original Min Wait Ticks: " + minWaitTicks);
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "AFTER MASTER ANGLER WAS APPLIED");
|
||||
mmoPlayer.getPlayer().sendMessage("Current Max Wait Ticks: " + reducedMaxWaitTime);
|
||||
mmoPlayer.getPlayer().sendMessage("Current Min Wait Ticks: " + reducedMinWaitTime);
|
||||
|
||||
mmoPlayer.getPlayer().sendMessage("");
|
||||
|
||||
mmoPlayer.getPlayer()
|
||||
.sendMessage(ChatColor.DARK_AQUA + "Caps / Limits (edit in advanced.yml)");
|
||||
mmoPlayer.getPlayer().sendMessage("Lowest possible minWaitLowerBound wait ticks "
|
||||
+ masterAnglerMinWaitLowerBound);
|
||||
mmoPlayer.getPlayer().sendMessage(
|
||||
"Lowest possible min wait ticks " + masterAnglerMaxWaitLowerBound);
|
||||
}
|
||||
|
||||
fishHook.setMaxWaitTime(reducedMaxWaitTime);
|
||||
fishHook.setMinWaitTime(reducedMinWaitTime);
|
||||
}
|
||||
|
||||
public int getReducedTicks(int ticks, int totalBonus, int tickBounds) {
|
||||
@@ -446,7 +406,6 @@ public class FishingManager extends SkillManager {
|
||||
* @param fishingCatch The {@link Item} initially caught
|
||||
*/
|
||||
public void processFishing(@NotNull Item fishingCatch) {
|
||||
this.fishingCatch = fishingCatch;
|
||||
int fishXp = ExperienceConfig.getInstance()
|
||||
.getXp(PrimarySkillType.FISHING, fishingCatch.getItemStack().getType());
|
||||
int treasureXp = 0;
|
||||
@@ -458,7 +417,6 @@ public class FishingManager extends SkillManager {
|
||||
if (mcMMO.p.getGeneralConfig().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(
|
||||
player, SubSkillType.FISHING_TREASURE_HUNTER)) {
|
||||
treasure = getFishingTreasure();
|
||||
this.fishingCatch = null;
|
||||
}
|
||||
|
||||
if (treasure != null) {
|
||||
@@ -541,10 +499,6 @@ public class FishingManager extends SkillManager {
|
||||
return experience * getVanillaXpMultiplier();
|
||||
}
|
||||
|
||||
public Location getHookLocation() {
|
||||
return hookLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Shake ability
|
||||
*
|
||||
@@ -692,11 +646,6 @@ public class FishingManager extends SkillManager {
|
||||
treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability)));
|
||||
}
|
||||
|
||||
//TODO: Add option to randomize the amount rewarded
|
||||
/*if (treasureDrop.getAmount() > 1) {
|
||||
treasureDrop.setAmount(Misc.getRandom().nextInt(treasureDrop.getAmount()) + 1);
|
||||
}*/
|
||||
|
||||
treasure.setDrop(treasureDrop);
|
||||
|
||||
return treasure;
|
||||
|
||||
@@ -535,6 +535,10 @@ public class HerbalismManager extends SkillManager {
|
||||
}
|
||||
|
||||
public boolean isAgeableMature(Ageable ageable) {
|
||||
// Sweet berry bush is harvestable at age 2 and 3 (max is 3)
|
||||
if (ageable.getMaterial() == Material.SWEET_BERRY_BUSH) {
|
||||
return ageable.getAge() >= 2;
|
||||
}
|
||||
return ageable.getAge() == ageable.getMaximumAge()
|
||||
&& ageable.getAge() != 0;
|
||||
}
|
||||
@@ -868,6 +872,7 @@ public class HerbalismManager extends SkillManager {
|
||||
case "beetroots" -> replantMaterial = Material.matchMaterial("BEETROOT_SEEDS");
|
||||
case "cocoa" -> replantMaterial = Material.matchMaterial("COCOA_BEANS");
|
||||
case "torchflower" -> replantMaterial = Material.matchMaterial("TORCHFLOWER_SEEDS");
|
||||
case "sweet_berry_bush" -> replantMaterial = Material.matchMaterial("SWEET_BERRIES");
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
@@ -956,6 +961,17 @@ public class HerbalismManager extends SkillManager {
|
||||
}
|
||||
break;
|
||||
|
||||
case "sweet_berry_bush":
|
||||
|
||||
// Sweet berry bush has ages 0-3, where 2+ has berries
|
||||
// Cap at age 1 to prevent instant re-harvest exploit with enough herbalism levels
|
||||
if (greenTerra || greenThumbStage >= 2) {
|
||||
finalAge = 1;
|
||||
} else {
|
||||
finalAge = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
121
src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java
Normal file
121
src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -304,7 +304,7 @@ public class TamingManager extends SkillManager {
|
||||
|
||||
Player owner = getPlayer();
|
||||
|
||||
wolf.teleport(owner);
|
||||
mcMMO.p.getFoliaLib().getScheduler().teleportAsync(wolf, owner.getLocation());
|
||||
NotificationManager.sendPlayerInformation(owner, NotificationType.SUBSKILL_MESSAGE,
|
||||
"Taming.Listener.Wolf");
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
return player.getInventory().getItemInMainHand().getType() == material
|
||||
|| player.getInventory().getItemInOffHand().getType() == material;
|
||||
@@ -276,6 +262,46 @@ public final class ItemUtils {
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -8,6 +8,7 @@ public class LogUtils {
|
||||
public static final String DEBUG_STR = "[D] ";
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,10 @@ public class MaterialMapStore {
|
||||
private final @NotNull HashSet<String> tridents;
|
||||
private final @NotNull HashSet<String> bows;
|
||||
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> spears;
|
||||
private final @NotNull HashSet<String> enchantables;
|
||||
private final @NotNull HashSet<String> tools;
|
||||
|
||||
private final @NotNull HashSet<String> ores;
|
||||
private final @NotNull HashSet<String> intendedToolPickAxe;
|
||||
@@ -95,15 +96,15 @@ public class MaterialMapStore {
|
||||
crossbows = new HashSet<>();
|
||||
stringTools = new HashSet<>();
|
||||
prismarineTools = new HashSet<>();
|
||||
tools = new HashSet<>();
|
||||
|
||||
swords = new HashSet<>();
|
||||
axes = new HashSet<>();
|
||||
pickAxes = new HashSet<>();
|
||||
shovels = new HashSet<>();
|
||||
hoes = new HashSet<>();
|
||||
tridents = new HashSet<>();
|
||||
spears = new HashSet<>();
|
||||
maces = new HashSet<>();
|
||||
tools = new HashSet<>();
|
||||
|
||||
enchantables = new HashSet<>();
|
||||
|
||||
@@ -459,6 +460,7 @@ public class MaterialMapStore {
|
||||
enchantables.addAll(bows);
|
||||
enchantables.addAll(crossbows);
|
||||
enchantables.addAll(maces);
|
||||
enchantables.addAll(spears);
|
||||
|
||||
enchantables.add("shears");
|
||||
enchantables.add("fishing_rod");
|
||||
@@ -484,6 +486,7 @@ public class MaterialMapStore {
|
||||
fillShovels();
|
||||
fillTridents();
|
||||
fillMaces();
|
||||
fillSpears();
|
||||
fillStringTools();
|
||||
fillPrismarineTools();
|
||||
fillBows();
|
||||
@@ -502,6 +505,7 @@ public class MaterialMapStore {
|
||||
tools.addAll(bows);
|
||||
tools.addAll(crossbows);
|
||||
tools.addAll(maces);
|
||||
tools.addAll(spears);
|
||||
}
|
||||
|
||||
private void fillBows() {
|
||||
@@ -527,6 +531,16 @@ public class MaterialMapStore {
|
||||
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() {
|
||||
tridents.add("trident");
|
||||
}
|
||||
@@ -659,6 +673,7 @@ public class MaterialMapStore {
|
||||
woodTools.add("wooden_hoe");
|
||||
woodTools.add("wooden_pickaxe");
|
||||
woodTools.add("wooden_shovel");
|
||||
woodTools.add("wooden_spear");
|
||||
}
|
||||
|
||||
private void fillStoneToolsWhiteList() {
|
||||
@@ -667,6 +682,7 @@ public class MaterialMapStore {
|
||||
stoneTools.add("stone_hoe");
|
||||
stoneTools.add("stone_pickaxe");
|
||||
stoneTools.add("stone_shovel");
|
||||
stoneTools.add("stone_spear");
|
||||
}
|
||||
|
||||
private void fillCopperToolsWhiteList() {
|
||||
@@ -675,6 +691,7 @@ public class MaterialMapStore {
|
||||
copperTools.add("copper_hoe");
|
||||
copperTools.add("copper_pickaxe");
|
||||
copperTools.add("copper_shovel");
|
||||
copperTools.add("copper_spear");
|
||||
}
|
||||
|
||||
private void fillIronToolsWhiteList() {
|
||||
@@ -683,6 +700,7 @@ public class MaterialMapStore {
|
||||
ironTools.add("iron_hoe");
|
||||
ironTools.add("iron_pickaxe");
|
||||
ironTools.add("iron_shovel");
|
||||
ironTools.add("iron_spear");
|
||||
|
||||
//Used for repair, remove in 2.2
|
||||
//TODO: Remove in config update
|
||||
@@ -704,6 +722,7 @@ public class MaterialMapStore {
|
||||
goldTools.add("golden_hoe");
|
||||
goldTools.add("golden_pickaxe");
|
||||
goldTools.add("golden_shovel");
|
||||
goldTools.add("golden_spear");
|
||||
}
|
||||
|
||||
private void fillDiamondToolsWhiteList() {
|
||||
@@ -712,6 +731,7 @@ public class MaterialMapStore {
|
||||
diamondTools.add("diamond_hoe");
|
||||
diamondTools.add("diamond_pickaxe");
|
||||
diamondTools.add("diamond_shovel");
|
||||
diamondTools.add("diamond_spear");
|
||||
}
|
||||
|
||||
private void fillNetheriteToolsWhiteList() {
|
||||
@@ -720,6 +740,7 @@ public class MaterialMapStore {
|
||||
netheriteTools.add("netherite_hoe");
|
||||
netheriteTools.add("netherite_pickaxe");
|
||||
netheriteTools.add("netherite_shovel");
|
||||
netheriteTools.add("netherite_spear");
|
||||
}
|
||||
|
||||
private void fillGlassBlockWhiteList() {
|
||||
@@ -874,6 +895,14 @@ public class MaterialMapStore {
|
||||
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) {
|
||||
return isLeatherArmor(material.getKey().getKey());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gmail.nossr50.util;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MinecraftGameVersionFactory {
|
||||
public static @NotNull MinecraftGameVersion calculateGameVersion(
|
||||
@NotNull String platformVersionString) {
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Platform String: " + platformVersionString);
|
||||
|
||||
// Gets two numbers separated by . and optional third number after next dot. Must end with - or _
|
||||
Matcher versionMatch = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?[-_].*")
|
||||
.matcher(platformVersionString);
|
||||
|
||||
if (versionMatch.find()) {
|
||||
major = Integer.parseInt(versionMatch.group(1));
|
||||
minor = Integer.parseInt(versionMatch.group(2));
|
||||
|
||||
if (versionMatch.group(3) != null) {
|
||||
patch = Integer.parseInt(versionMatch.group(3));
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Minecraft version determined to be - "
|
||||
+ major + "."
|
||||
+ minor + "."
|
||||
+ patch);
|
||||
|
||||
return new MinecraftGameVersion(major, minor, patch);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.gmail.nossr50.util;
|
||||
|
||||
public enum PotionCompatibilityType {
|
||||
PRE_1_20_5,
|
||||
MODERN
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
package com.gmail.nossr50.util;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -10,34 +7,19 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PotionUtil {
|
||||
public final class PotionUtil {
|
||||
// Some of the old potion types got renamed, our configs can still contain these old names
|
||||
private static final Map<String, String> legacyPotionTypes = new HashMap<>();
|
||||
private static final Method methodPotionTypeGetKey;
|
||||
private static final Method methodPotionTypeGetEffectType;
|
||||
private static final Method methodPotionTypeGetPotionEffects;
|
||||
private static final Method methodPotionDataIsUpgraded;
|
||||
private static final Method methodPotionDataIsExtended;
|
||||
private static final Method methodPotionDataGetType;
|
||||
private static final Method methodPotionMetaGetBasePotionData;
|
||||
private static final Method methodPotionMetaSetBasePotionData;
|
||||
private static final Method methodPotionMetaGetBasePotionType;
|
||||
private static final Method methodPotionMetaSetBasePotionType;
|
||||
private static final Class<?> potionDataClass;
|
||||
|
||||
public static final String STRONG = "STRONG";
|
||||
public static final String LONG = "LONG";
|
||||
public static final String WATER_POTION_TYPE_STR = "WATER";
|
||||
|
||||
private static final PotionCompatibilityType COMPATIBILITY_MODE;
|
||||
|
||||
static {
|
||||
potionDataClass = getPotionDataClass();
|
||||
// Uncraftable doesn't exist in modern versions
|
||||
// It served as a potion that didn't craft into anything else so it didn't conflict with vanilla systems
|
||||
// Instead we will use Mundane, which doesn't make anything in vanilla systems
|
||||
@@ -47,199 +29,48 @@ public class PotionUtil {
|
||||
legacyPotionTypes.put("INSTANT_HEAL", "HEALING");
|
||||
legacyPotionTypes.put("INSTANT_DAMAGE", "HARMING");
|
||||
legacyPotionTypes.put("REGEN", "REGENERATION");
|
||||
methodPotionTypeGetKey = getKeyMethod();
|
||||
methodPotionDataIsUpgraded = getPotionDataIsUpgraded();
|
||||
methodPotionDataIsExtended = getPotionDataIsExtended();
|
||||
methodPotionMetaGetBasePotionData = getGetBasePotionDataMethod();
|
||||
methodPotionMetaGetBasePotionType = getGetBasePotionTypeMethod();
|
||||
methodPotionMetaSetBasePotionType = getMethodPotionMetaSetBasePotionType();
|
||||
methodPotionDataGetType = getPotionDataGetTypeMethod();
|
||||
methodPotionTypeGetEffectType = getPotionTypeEffectTypeMethod();
|
||||
methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffectsMethod();
|
||||
methodPotionMetaSetBasePotionData = setBasePotionData();
|
||||
|
||||
if (potionDataClass != null
|
||||
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 5)) {
|
||||
COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5;
|
||||
} else {
|
||||
COMPATIBILITY_MODE = PotionCompatibilityType.MODERN;
|
||||
}
|
||||
}
|
||||
|
||||
private PotionUtil() {}
|
||||
|
||||
/**
|
||||
* Derive a potion from a partial name, and whether it should be upgraded or extended.
|
||||
*
|
||||
* @param partialName potion type as a string, can be a substring of the potion type but must
|
||||
* match exactly
|
||||
* @return The potion type
|
||||
*/
|
||||
public static PotionType matchPotionType(String partialName, boolean isUpgraded,
|
||||
boolean isExtended) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return matchLegacyPotionType(partialName);
|
||||
} else {
|
||||
final String updatedName = convertLegacyNames(partialName).toUpperCase(Locale.ENGLISH);
|
||||
return Arrays.stream(PotionType.values())
|
||||
.filter(potionType -> getKeyGetKey(potionType)
|
||||
.toUpperCase(Locale.ENGLISH).contains(updatedName))
|
||||
.filter(potionType -> isUpgraded == potionType.name()
|
||||
.toUpperCase(Locale.ENGLISH).startsWith(STRONG + "_"))
|
||||
.filter(potionType -> isExtended == potionType.name()
|
||||
.toUpperCase(Locale.ENGLISH).startsWith(LONG + "_"))
|
||||
.findAny().orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy matching for {@link PotionType}
|
||||
* <p>In 1.20.5+, "upgraded" and "extended" are represented by distinct {@link PotionType}
|
||||
* constants (e.g. STRONG_HEALING, LONG_SWIFTNESS), not flags.
|
||||
*
|
||||
* @param name The partial name of the potion
|
||||
* @return The potion type
|
||||
* @param partialName potion type as a string, can be a substring of the potion type but must match
|
||||
* against the potion's key or enum name
|
||||
* @return The potion type, or null if no match
|
||||
*/
|
||||
private static PotionType matchLegacyPotionType(String name) {
|
||||
public static @Nullable PotionType matchPotionType(String partialName, boolean isUpgraded, boolean isExtended) {
|
||||
if (partialName == null || partialName.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String updatedName = convertLegacyNames(partialName).toUpperCase(Locale.ENGLISH);
|
||||
|
||||
return Arrays.stream(PotionType.values())
|
||||
.filter(potionType -> getKeyGetKey(potionType).equalsIgnoreCase(name)
|
||||
|| getKeyGetKey(potionType).equalsIgnoreCase(convertLegacyNames(name))
|
||||
|| potionType.name().equalsIgnoreCase(name)
|
||||
|| potionType.name().equalsIgnoreCase(convertLegacyNames(name)))
|
||||
.findAny().orElse(null);
|
||||
}
|
||||
|
||||
private static String convertUpgradedOrExtended(String potionType, boolean isUpgraded,
|
||||
boolean isExtended) {
|
||||
if (isUpgraded) {
|
||||
potionType = STRONG + "_" + potionType;
|
||||
}
|
||||
if (isExtended) {
|
||||
potionType = LONG + "_" + potionType;
|
||||
}
|
||||
return potionType;
|
||||
}
|
||||
|
||||
public static String getKeyGetKey(PotionType potionType) {
|
||||
try {
|
||||
if (getKeyMethod() != null) {
|
||||
NamespacedKey key = (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
|
||||
return key.getKey();
|
||||
} else {
|
||||
return potionType.name();
|
||||
}
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
mcMMO.p.getLogger().warning("Failed to get potion key for " + potionType.name());
|
||||
return potionType.name();
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getPotionDataClass() {
|
||||
try {
|
||||
return Class.forName("org.bukkit.potion.PotionData");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
// Allow matching by namespace key ("swiftness", "long_swiftness") or enum name
|
||||
.filter(potionType -> {
|
||||
final NamespacedKey key = potionType.getKey();
|
||||
final String keyStr = key != null ? key.getKey() : "";
|
||||
return keyStr.toUpperCase(Locale.ENGLISH).contains(updatedName)
|
||||
|| potionType.name().toUpperCase(Locale.ENGLISH).contains(updatedName);
|
||||
})
|
||||
// Enforce strong/long selection by the enum name prefix convention
|
||||
.filter(potionType -> isUpgraded == potionType.name().startsWith(STRONG + "_"))
|
||||
.filter(potionType -> isExtended == potionType.name().startsWith(LONG + "_"))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Older versions of Spigot do not have getKey() in PotionType We need to check for the
|
||||
* existence of this method before calling it
|
||||
*
|
||||
* @return The getKey method
|
||||
* Returns the NamespacedKey key string portion for this potion type (e.g. "swiftness").
|
||||
*/
|
||||
private static @Nullable Method getKeyMethod() {
|
||||
try {
|
||||
return PotionType.class.getMethod("getKey");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Method setBasePotionData() {
|
||||
try {
|
||||
return PotionMeta.class.getMethod("setBasePotionData", potionDataClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethodPotionMetaSetBasePotionType() {
|
||||
try {
|
||||
return PotionMeta.class.getMethod("setBasePotionType", PotionType.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getSetBasePotionData() {
|
||||
try {
|
||||
return PotionMeta.class.getMethod("setBasePotionData", potionDataClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Method getPotionDataIsUpgraded() {
|
||||
try {
|
||||
// TODO: <?> Needed?
|
||||
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
|
||||
return clazz.getMethod("isUpgraded");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Method getPotionDataIsExtended() {
|
||||
try {
|
||||
// TODO: <?> Needed?
|
||||
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
|
||||
return clazz.getMethod("isExtended");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Newer versions of Spigot do not have getBasePotionData() in PotionMeta
|
||||
*
|
||||
* @return the getBasePotionData method, or null if it does not exist
|
||||
*/
|
||||
private static @Nullable Method getGetBasePotionDataMethod() {
|
||||
try {
|
||||
return PotionMeta.class.getMethod("getBasePotionData");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getGetBasePotionTypeMethod() {
|
||||
try {
|
||||
return PotionMeta.class.getMethod("getBasePotionType");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getPotionDataGetTypeMethod() {
|
||||
try {
|
||||
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
|
||||
return clazz.getMethod("getType");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getPotionTypeEffectTypeMethod() {
|
||||
try {
|
||||
return PotionType.class.getMethod("getEffectType");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getPotionTypeGetPotionEffectsMethod() {
|
||||
try {
|
||||
return PotionType.class.getMethod("getPotionEffects");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
public static @NotNull String getKeyGetKey(@NotNull PotionType potionType) {
|
||||
final NamespacedKey key = potionType.getKey();
|
||||
return key != null ? key.getKey() : potionType.name();
|
||||
}
|
||||
|
||||
public static String convertPotionConfigName(String legacyName) {
|
||||
@@ -252,318 +83,91 @@ public class PotionUtil {
|
||||
|
||||
if (replacementName.contains("_II")) {
|
||||
replacementName = replacementName.replace("_II", "");
|
||||
replacementName = "STRONG_" + replacementName;
|
||||
replacementName = STRONG + "_" + replacementName;
|
||||
} else if (replacementName.contains("_EXTENDED")) {
|
||||
replacementName = replacementName.replace("_EXTENDED", "");
|
||||
replacementName = "LONG_" + replacementName;
|
||||
replacementName = LONG + "_" + replacementName;
|
||||
}
|
||||
|
||||
return replacementName;
|
||||
}
|
||||
|
||||
public static String convertLegacyNames(String legacyPotionType) {
|
||||
String modernized = legacyPotionType;
|
||||
// check for legacy names
|
||||
|
||||
for (var key : legacyPotionTypes.keySet()) {
|
||||
if (modernized.contains(key)) {
|
||||
// Replace the legacy name with the new name
|
||||
modernized = modernized.replace(key, legacyPotionTypes.get(key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return modernized;
|
||||
}
|
||||
|
||||
public static boolean hasLegacyName(String potionType) {
|
||||
for (var key : legacyPotionTypes.keySet()) {
|
||||
if (potionType.contains(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public static boolean isStrong(@NotNull PotionMeta potionMeta) {
|
||||
final PotionType base = potionMeta.getBasePotionType();
|
||||
return base != null && base.name().startsWith(STRONG + "_");
|
||||
}
|
||||
|
||||
public static boolean isStrong(PotionMeta potionMeta) {
|
||||
if (methodPotionMetaGetBasePotionData == null) {
|
||||
return isStrongModern(potionMeta);
|
||||
} else {
|
||||
return isStrongLegacy(potionMeta);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean isLong(PotionMeta potionMeta) {
|
||||
if (methodPotionMetaGetBasePotionData == null) {
|
||||
return isLongModern(potionMeta);
|
||||
} else {
|
||||
return isLongLegacy(potionMeta);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLongLegacy(PotionMeta potionMeta) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
return (boolean) methodPotionDataIsExtended.invoke(potionData);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLongModern(PotionMeta potionMeta) {
|
||||
try {
|
||||
return getModernPotionTypeKey(potionMeta).getKey().startsWith(LONG);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isStrongLegacy(PotionMeta potionMeta) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
return (boolean) methodPotionDataIsUpgraded.invoke(potionData);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isStrongModern(PotionMeta potionMeta) {
|
||||
try {
|
||||
return getModernPotionTypeKey(potionMeta).getKey().startsWith(STRONG);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static NamespacedKey getModernPotionTypeKey(PotionMeta potionMeta)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(potionMeta);
|
||||
return (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
|
||||
}
|
||||
|
||||
public static boolean isPotionJustWater(PotionMeta potionMeta) {
|
||||
return isPotionTypeWater(potionMeta)
|
||||
&& !hasBasePotionEffects(potionMeta)
|
||||
&& potionMeta.getCustomEffects().isEmpty();
|
||||
public static boolean isLong(@NotNull PotionMeta potionMeta) {
|
||||
final PotionType base = potionMeta.getBasePotionType();
|
||||
return base != null && base.name().startsWith(LONG + "_");
|
||||
}
|
||||
|
||||
public static boolean isPotionTypeWater(@NotNull PotionMeta potionMeta) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return isPotionTypeWaterLegacy(potionMeta);
|
||||
} else {
|
||||
return isPotionTypeWaterModern(potionMeta);
|
||||
return potionMeta.getBasePotionType() == PotionType.WATER;
|
||||
}
|
||||
|
||||
public static boolean hasBasePotionEffects(@NotNull PotionMeta potionMeta) {
|
||||
final PotionType base = potionMeta.getBasePotionType();
|
||||
if (base == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPotionType(@NotNull PotionMeta potionMeta, String potionType) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return isPotionTypeLegacy(potionMeta, potionType);
|
||||
} else {
|
||||
return isPotionTypeModern(potionMeta, potionType);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPotionTypeWithoutEffects(@NotNull PotionMeta potionMeta,
|
||||
String potionType) {
|
||||
return isPotionType(potionMeta, potionType)
|
||||
&& !hasBasePotionEffects(potionMeta)
|
||||
&& potionMeta.getCustomEffects().isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isPotionTypeModern(@NotNull PotionMeta potionMeta, String potionType) {
|
||||
try {
|
||||
return getModernPotionTypeKey(potionMeta).getKey().equalsIgnoreCase(potionType);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPotionTypeLegacy(@NotNull PotionMeta potionMeta, String potionType) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
PotionType potionTypeObj = (PotionType) methodPotionDataGetType.invoke(potionData);
|
||||
return potionTypeObj.name().equalsIgnoreCase(potionType);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPotionTypeWaterLegacy(@NotNull PotionMeta potionMeta) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
|
||||
return potionType.name().equalsIgnoreCase(WATER_POTION_TYPE_STR)
|
||||
|| PotionType.valueOf(WATER_POTION_TYPE_STR) == potionType;
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPotionTypeWaterModern(@NotNull PotionMeta potionMeta) {
|
||||
try {
|
||||
return getModernPotionTypeKey(potionMeta).getKey()
|
||||
.equalsIgnoreCase(WATER_POTION_TYPE_STR);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean samePotionType(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return samePotionTypeLegacy(potionMeta, otherPotionMeta);
|
||||
} else {
|
||||
return samePotionTypeModern(potionMeta, otherPotionMeta);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean samePotionTypeLegacy(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
Object otherPotionData = methodPotionMetaGetBasePotionData.invoke(otherPotionMeta);
|
||||
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
|
||||
PotionType otherPotionType = (PotionType) methodPotionDataGetType.invoke(
|
||||
otherPotionData);
|
||||
return potionType == otherPotionType;
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean samePotionTypeModern(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
|
||||
try {
|
||||
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
|
||||
potionMeta);
|
||||
PotionType otherPotionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
|
||||
otherPotionMeta);
|
||||
return potionType == otherPotionType;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean samePotionEffects(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return true;
|
||||
} else {
|
||||
return samePotionEffectsModern(potionMeta, otherPotionMeta);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean samePotionEffectsModern(PotionMeta potionMeta,
|
||||
PotionMeta otherPotionMeta) {
|
||||
return potionMeta.getCustomEffects().equals(otherPotionMeta.getCustomEffects());
|
||||
}
|
||||
|
||||
public static boolean hasBasePotionEffects(PotionMeta potionMeta) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
|
||||
return hasBasePotionEffectsLegacy(potionMeta);
|
||||
} else {
|
||||
return hasBasePotionEffectsModern(potionMeta);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasBasePotionEffectsLegacy(PotionMeta potionMeta) {
|
||||
try {
|
||||
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
|
||||
return methodPotionTypeGetEffectType.invoke(potionType) != null;
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasBasePotionEffectsModern(PotionMeta potionMeta) {
|
||||
try {
|
||||
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(
|
||||
potionMeta);
|
||||
List<PotionEffectType> potionEffectTypeList = (List<PotionEffectType>) methodPotionTypeGetPotionEffects.invoke(
|
||||
potionType);
|
||||
return potionEffectTypeList != null && !potionEffectTypeList.isEmpty();
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
final List<PotionEffect> effects = base.getPotionEffects();
|
||||
return effects != null && !effects.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base potion type of a potion meta. Note that extended/upgraded are ignored in 1.20.5
|
||||
* and later.
|
||||
*
|
||||
* @param potionMeta the potion meta
|
||||
* @param extended true if the potion is extended
|
||||
* @param upgraded true if the potion is upgraded
|
||||
* <p>In 1.20.5+, "extended/upgraded" are encoded into {@link PotionType} variants. This method
|
||||
* attempts to select the appropriate STRONG_/LONG_ variant when requested. If no such variant
|
||||
* exists, it falls back to the provided base type.</p>
|
||||
*/
|
||||
public static void setBasePotionType(PotionMeta potionMeta, PotionType potionType,
|
||||
boolean extended, boolean upgraded) {
|
||||
if (methodPotionMetaSetBasePotionType == null) {
|
||||
setBasePotionTypeLegacy(potionMeta, potionType, extended, upgraded);
|
||||
} else {
|
||||
setBasePotionTypeModern(potionMeta, potionType);
|
||||
}
|
||||
public static void setBasePotionType(@NotNull PotionMeta potionMeta,
|
||||
@NotNull PotionType potionType, boolean extended, boolean upgraded) {
|
||||
final PotionType resolved = resolveVariant(potionType, upgraded, extended);
|
||||
potionMeta.setBasePotionType(resolved);
|
||||
}
|
||||
|
||||
public static void setUpgradedAndExtendedProperties(PotionType potionType,
|
||||
PotionMeta potionMeta,
|
||||
boolean isUpgraded, boolean isExtended) {
|
||||
if (potionDataClass == null || mcMMO.getCompatibilityManager().getMinecraftGameVersion()
|
||||
.isAtLeast(1, 20, 5)) {
|
||||
return;
|
||||
private static @NotNull PotionType resolveVariant(@NotNull PotionType base, boolean upgraded,
|
||||
boolean extended) {
|
||||
// Apply the same prefix scheme your code already expects
|
||||
String name = base.name();
|
||||
|
||||
// Avoid double-prefixing if caller already passed LONG_/STRONG_ variants
|
||||
if (name.startsWith(STRONG + "_")) {
|
||||
upgraded = false;
|
||||
}
|
||||
if (name.startsWith(LONG + "_")) {
|
||||
extended = false;
|
||||
}
|
||||
|
||||
if (upgraded) {
|
||||
name = STRONG + "_" + name;
|
||||
}
|
||||
if (extended) {
|
||||
name = LONG + "_" + name;
|
||||
}
|
||||
|
||||
try {
|
||||
final Object potionData = potionDataClass.getConstructor(PotionType.class,
|
||||
boolean.class, boolean.class)
|
||||
.newInstance(potionType, isExtended, isUpgraded);
|
||||
methodPotionMetaSetBasePotionData.invoke(potionMeta, potionData);
|
||||
} catch (IllegalAccessException | InvocationTargetException | InstantiationException
|
||||
| NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setBasePotionTypeLegacy(PotionMeta potionMeta, PotionType potionType,
|
||||
boolean extended,
|
||||
boolean upgraded) {
|
||||
try {
|
||||
Object potionData = potionDataClass.getConstructor(PotionType.class, boolean.class,
|
||||
boolean.class)
|
||||
.newInstance(potionType, extended, upgraded);
|
||||
methodPotionMetaSetBasePotionData.invoke(potionMeta, potionData);
|
||||
} catch (IllegalAccessException | InvocationTargetException | InstantiationException |
|
||||
NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setBasePotionTypeModern(PotionMeta potionMeta, PotionType potionType) {
|
||||
try {
|
||||
methodPotionMetaSetBasePotionType.invoke(potionMeta, potionType);
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPotionDataEqual(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
|
||||
if (COMPATIBILITY_MODE == PotionCompatibilityType.MODERN) {
|
||||
return true; // we don't compare data on newer versions
|
||||
} else {
|
||||
try {
|
||||
final Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
|
||||
final Object otherPotionData = methodPotionMetaGetBasePotionData.invoke(
|
||||
otherPotionMeta);
|
||||
final PotionType potionType = (PotionType) methodPotionDataGetType.invoke(
|
||||
potionData);
|
||||
final PotionType otherPotionType = (PotionType) methodPotionDataGetType.invoke(
|
||||
otherPotionData);
|
||||
if (potionType != otherPotionType) {
|
||||
return false;
|
||||
}
|
||||
if (methodPotionDataIsExtended.invoke(potionData)
|
||||
!= methodPotionDataIsExtended.invoke(otherPotionData)) {
|
||||
return false;
|
||||
}
|
||||
return methodPotionDataIsUpgraded.invoke(potionData)
|
||||
== methodPotionDataIsUpgraded.invoke(otherPotionData);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return PotionType.valueOf(name);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Not all potion types have strong/long variants; just use the provided base.
|
||||
return base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.gmail.nossr50.commands.McnotifyCommand;
|
||||
import com.gmail.nossr50.commands.McrefreshCommand;
|
||||
import com.gmail.nossr50.commands.McscoreboardCommand;
|
||||
import com.gmail.nossr50.commands.XprateCommand;
|
||||
import com.gmail.nossr50.commands.admin.CompatibilityCommand;
|
||||
import com.gmail.nossr50.commands.admin.McmmoReloadLocaleCommand;
|
||||
import com.gmail.nossr50.commands.admin.PlayerDebugCommand;
|
||||
import com.gmail.nossr50.commands.chat.McChatSpy;
|
||||
@@ -41,6 +40,7 @@ import com.gmail.nossr50.commands.skills.MmoInfoCommand;
|
||||
import com.gmail.nossr50.commands.skills.RepairCommand;
|
||||
import com.gmail.nossr50.commands.skills.SalvageCommand;
|
||||
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.TamingCommand;
|
||||
import com.gmail.nossr50.commands.skills.TridentsCommand;
|
||||
@@ -63,9 +63,8 @@ public final class CommandRegistrationManager {
|
||||
|
||||
private static void registerSkillCommands() {
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
if (primarySkillType == PrimarySkillType.MACES
|
||||
&& !mcMMO.getCompatibilityManager().getMinecraftGameVersion()
|
||||
.isAtLeast(1, 21, 0)) {
|
||||
if (primarySkillType == PrimarySkillType.SPEARS
|
||||
&& !mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -101,6 +100,7 @@ public final class CommandRegistrationManager {
|
||||
case REPAIR -> command.setExecutor(new RepairCommand());
|
||||
case SALVAGE -> command.setExecutor(new SalvageCommand());
|
||||
case SMELTING -> command.setExecutor(new SmeltingCommand());
|
||||
case SPEARS -> command.setExecutor(new SpearsCommand());
|
||||
case SWORDS -> command.setExecutor(new SwordsCommand());
|
||||
case TAMING -> command.setExecutor(new TamingCommand());
|
||||
case TRIDENTS -> command.setExecutor(new TridentsCommand());
|
||||
@@ -403,13 +403,6 @@ public final class CommandRegistrationManager {
|
||||
command.setExecutor(new McmmoReloadLocaleCommand());
|
||||
}
|
||||
|
||||
private static void registerCompatibilityCommand() {
|
||||
PluginCommand command = mcMMO.p.getCommand("mmocompat"); //TODO: Localize
|
||||
command.setDescription(LocaleLoader.getString("Commands.Description.mmocompat"));
|
||||
command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mmocompat"));
|
||||
command.setExecutor(new CompatibilityCommand());
|
||||
}
|
||||
|
||||
private static void registerXPBarCommand() {
|
||||
PluginCommand command = mcMMO.p.getCommand("mmoxpbar"); //TODO: Localize
|
||||
command.setDescription(LocaleLoader.getString("Commands.Description.mmoxpbar"));
|
||||
@@ -465,8 +458,5 @@ public final class CommandRegistrationManager {
|
||||
|
||||
// Admin commands
|
||||
registerReloadLocaleCommand();
|
||||
|
||||
// Misc
|
||||
registerCompatibilityCommand();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat;
|
||||
|
||||
/**
|
||||
* Compatibility Layers should be named after the functionality they serve
|
||||
*/
|
||||
public interface CompatibilityLayer {
|
||||
/**
|
||||
* Whether this CompatibilityLayer successfully initialized and in theory should be functional
|
||||
*
|
||||
* @return true if this CompatibilityLayer is functional
|
||||
*/
|
||||
default boolean noErrorsOnInitialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat;
|
||||
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.LogUtils;
|
||||
import com.gmail.nossr50.util.compat.layers.bungee.AbstractBungeeSerializerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.compat.layers.bungee.BungeeLegacySerializerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.compat.layers.bungee.BungeeModernSerializerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.compat.layers.skills.AbstractMasterAnglerCompatibility;
|
||||
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.nms.NMSVersion;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import com.gmail.nossr50.util.text.StringUtils;
|
||||
import java.util.HashMap;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public class CompatibilityManager {
|
||||
private @NotNull HashMap<CompatibilityType, Boolean> supportedLayers;
|
||||
private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully
|
||||
private final @NotNull MinecraftGameVersion minecraftGameVersion;
|
||||
private final @NotNull NMSVersion nmsVersion;
|
||||
|
||||
/* Compatibility Layers */
|
||||
private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer;
|
||||
private AbstractMasterAnglerCompatibility masterAnglerCompatibility;
|
||||
|
||||
public CompatibilityManager(@NotNull MinecraftGameVersion minecraftGameVersion) {
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Loading compatibility layers...");
|
||||
this.minecraftGameVersion = minecraftGameVersion;
|
||||
this.nmsVersion = determineNMSVersion();
|
||||
init();
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Finished loading compatibility layers.");
|
||||
}
|
||||
|
||||
private void init() {
|
||||
initSupportedLayersMap();
|
||||
initCompatibilityLayers();
|
||||
}
|
||||
|
||||
private void initSupportedLayersMap() {
|
||||
supportedLayers = new HashMap<>(); //Init map
|
||||
|
||||
for (CompatibilityType compatibilityType : CompatibilityType.values()) {
|
||||
supportedLayers.put(compatibilityType,
|
||||
false); //All layers are set to false when initialized
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all necessary compatibility layers For any unsupported layers, load a dummy layer
|
||||
*/
|
||||
private void initCompatibilityLayers() {
|
||||
initBungeeSerializerLayer();
|
||||
initMasterAnglerLayer();
|
||||
|
||||
isFullyCompatibleServerSoftware = true;
|
||||
}
|
||||
|
||||
private void initMasterAnglerLayer() {
|
||||
if (minecraftGameVersion.isAtLeast(1, 16, 3)) {
|
||||
masterAnglerCompatibility = new MasterAnglerCompatibilityLayer();
|
||||
} else {
|
||||
masterAnglerCompatibility = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initBungeeSerializerLayer() {
|
||||
if (minecraftGameVersion.isAtLeast(1, 16, 0)) {
|
||||
bungeeSerializerCompatibilityLayer = new BungeeModernSerializerCompatibilityLayer();
|
||||
} else {
|
||||
bungeeSerializerCompatibilityLayer = new BungeeLegacySerializerCompatibilityLayer();
|
||||
}
|
||||
|
||||
supportedLayers.put(CompatibilityType.BUNGEE_SERIALIZER, true);
|
||||
}
|
||||
|
||||
//TODO: move to text manager
|
||||
public void reportCompatibilityStatus(@NotNull CommandSender commandSender) {
|
||||
if (isFullyCompatibleServerSoftware) {
|
||||
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
|
||||
"mcMMO is fully compatible with the currently running server software."));
|
||||
} else {
|
||||
//TODO: Better messages for each incompatible layer
|
||||
for (CompatibilityType compatibilityType : CompatibilityType.values()) {
|
||||
if (!supportedLayers.get(compatibilityType)) {
|
||||
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
|
||||
LocaleLoader.getString("Compatibility.Layer.Unsupported",
|
||||
StringUtils.getCapitalized(compatibilityType.toString()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commandSender.sendMessage(LocaleLoader.getString("mcMMO.Template.Prefix",
|
||||
"NMS Status - " + nmsVersion));
|
||||
}
|
||||
|
||||
public boolean isCompatibilityLayerOperational(@NotNull CompatibilityType compatibilityType) {
|
||||
return supportedLayers.get(compatibilityType);
|
||||
}
|
||||
|
||||
public boolean isFullyCompatibleServerSoftware() {
|
||||
return isFullyCompatibleServerSoftware;
|
||||
}
|
||||
|
||||
public @NotNull NMSVersion getNmsVersion() {
|
||||
return nmsVersion;
|
||||
}
|
||||
|
||||
private @NotNull NMSVersion determineNMSVersion() {
|
||||
//This bit here helps prevent mcMMO breaking if it isn't updated but the game continues to update
|
||||
if (minecraftGameVersion.isAtLeast(1, 17, 0)) {
|
||||
return NMSVersion.NMS_1_17;
|
||||
}
|
||||
|
||||
//Messy but it works
|
||||
if (minecraftGameVersion.getMajorVersion().asInt() == 1) {
|
||||
switch (minecraftGameVersion.getMinorVersion().asInt()) {
|
||||
case 12:
|
||||
return NMSVersion.NMS_1_12_2;
|
||||
case 13:
|
||||
return NMSVersion.NMS_1_13_2;
|
||||
case 14:
|
||||
return NMSVersion.NMS_1_14_4;
|
||||
case 15:
|
||||
return NMSVersion.NMS_1_15_2;
|
||||
case 16:
|
||||
if (minecraftGameVersion.getPatchVersion().asInt() == 1) {
|
||||
return NMSVersion.NMS_1_16_1;
|
||||
} else if (minecraftGameVersion.getPatchVersion().asInt() == 2) {
|
||||
return NMSVersion.NMS_1_16_2;
|
||||
} else if (minecraftGameVersion.getPatchVersion().asInt() == 3) {
|
||||
return NMSVersion.NMS_1_16_3;
|
||||
} else if (minecraftGameVersion.getPatchVersion().asInt() == 4) {
|
||||
return NMSVersion.NMS_1_16_4;
|
||||
} else if (minecraftGameVersion.getPatchVersion().asInt() >= 5) {
|
||||
return NMSVersion.NMS_1_16_5;
|
||||
}
|
||||
case 17:
|
||||
return NMSVersion.NMS_1_17;
|
||||
}
|
||||
}
|
||||
|
||||
return NMSVersion.UNSUPPORTED;
|
||||
}
|
||||
|
||||
public AbstractBungeeSerializerCompatibilityLayer getBungeeSerializerCompatibilityLayer() {
|
||||
return bungeeSerializerCompatibilityLayer;
|
||||
}
|
||||
|
||||
public @Nullable AbstractMasterAnglerCompatibility getMasterAnglerCompatibilityLayer() {
|
||||
return masterAnglerCompatibility;
|
||||
}
|
||||
|
||||
public @NotNull MinecraftGameVersion getMinecraftGameVersion() {
|
||||
return minecraftGameVersion;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat;
|
||||
|
||||
public enum CompatibilityType {
|
||||
PERSISTENT_DATA,
|
||||
BUNGEE_SERIALIZER,
|
||||
MASTER_ANGLER,
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers;
|
||||
|
||||
import com.gmail.nossr50.util.compat.CompatibilityLayer;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public abstract class AbstractCompatibilityLayer implements CompatibilityLayer {
|
||||
|
||||
protected boolean noErrorsOnInitialize = true;
|
||||
|
||||
/**
|
||||
* Initialize the CompatibilityLayer
|
||||
*
|
||||
* @return true if the CompatibilityLayer initialized and should be functional
|
||||
*/
|
||||
public abstract boolean initializeLayer();
|
||||
|
||||
@Override
|
||||
public boolean noErrorsOnInitialize() {
|
||||
return noErrorsOnInitialize;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers;
|
||||
|
||||
import com.gmail.nossr50.util.nms.NMSVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public abstract class AbstractNMSCompatibilityLayer extends AbstractCompatibilityLayer {
|
||||
|
||||
protected final @NotNull NMSVersion nmsVersion;
|
||||
|
||||
public AbstractNMSCompatibilityLayer(@NotNull NMSVersion nmsVersion) {
|
||||
this.nmsVersion = nmsVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the CompatibilityLayer
|
||||
*
|
||||
* @return true if the CompatibilityLayer initialized and should be functional
|
||||
*/
|
||||
public abstract boolean initializeLayer();
|
||||
|
||||
@Override
|
||||
public boolean noErrorsOnInitialize() {
|
||||
return noErrorsOnInitialize;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
|
||||
//
|
||||
//import com.gmail.nossr50.util.nms.NMSVersion;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//
|
||||
//import java.lang.reflect.InvocationTargetException;
|
||||
//
|
||||
//public class DummyPlayerAttackCooldownToolLayer extends PlayerAttackCooldownToolLayer {
|
||||
// public DummyPlayerAttackCooldownToolLayer() {
|
||||
// super(NMSVersion.UNSUPPORTED);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean initializeLayer() {
|
||||
// return noErrorsOnInitialize;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// return 1.0F; //Always full strength
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// return 0F;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// //Do nothing
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
|
||||
// }
|
||||
//}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.attackcooldown;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface PlayerAttackCooldownMethods {
|
||||
/**
|
||||
* Grabs the attack strength for a player Should be noted that as of today there is no way to
|
||||
* capture a players current attack strength in spigot when they attack an entity outside of
|
||||
* network packet listening
|
||||
*
|
||||
* @param player target player
|
||||
* @return the float value of the player's attack strength
|
||||
*/
|
||||
float getAttackStrength(@NotNull Player player)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
float getCooldownValue(@NotNull Player player)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
void resetAttackStrength(@NotNull Player player)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
int getCooldownFieldValue(@NotNull Player player)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
|
||||
void setCooldownFieldValue(@NotNull Player player, int fieldValue)
|
||||
throws InvocationTargetException, IllegalAccessException;
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
|
||||
//
|
||||
//import com.gmail.nossr50.mcMMO;
|
||||
//import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
|
||||
//import com.gmail.nossr50.util.nms.NMSConstants;
|
||||
//import com.gmail.nossr50.util.nms.NMSVersion;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.jetbrains.annotations.Nullable;
|
||||
//
|
||||
//import java.lang.reflect.Field;
|
||||
//import java.lang.reflect.InvocationTargetException;
|
||||
//import java.lang.reflect.Method;
|
||||
//
|
||||
/// **
|
||||
// *
|
||||
// * These classes are a band-aid solution for adding NMS support into 2.1.XXX
|
||||
// * In 2.2 we are switching to modules and that will clean things up significantly
|
||||
// *
|
||||
// */
|
||||
//public class PlayerAttackCooldownToolLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods {
|
||||
//
|
||||
// private final String cbNMSVersionPath;
|
||||
//
|
||||
// protected Class<?> craftPlayerClass;
|
||||
// protected Class<?> entityHumanClass;
|
||||
// protected Class<?> entityLivingClass;
|
||||
//
|
||||
// protected Method playerAttackCooldownMethod;
|
||||
// protected Method playerAttackStrengthMethod;
|
||||
// protected Method resetPlayerAttackCooldownMethod;
|
||||
// protected Method setPlayerAttackStrengthMethod;
|
||||
// protected Method getHandleMethod;
|
||||
// protected Field attackCooldownField;
|
||||
// protected String attackStrengthFieldName;
|
||||
//
|
||||
// public PlayerAttackCooldownToolLayer(@NotNull NMSVersion nmsVersion) {
|
||||
// super(nmsVersion);
|
||||
// mcMMO.p.getLogger().info("Loading Compatibility Layer... (Player Attack Cooldown Exploit Prevention)");
|
||||
// if (!isCompatibleWithMinecraftVersion(nmsVersion)) {
|
||||
// mcMMO.p.getLogger().severe("this version of mcMMO does not support NMS for this version of Minecraft, try updating mcMMO or updating Minecraft. Not all versions of Minecraft will have NMS support built into mcMMO.");
|
||||
// cbNMSVersionPath = "";
|
||||
// } else {
|
||||
// if (NMSConstants.getCraftBukkitVersionPath(nmsVersion) != null) {
|
||||
// cbNMSVersionPath = NMSConstants.getCraftBukkitVersionPath(nmsVersion);
|
||||
// noErrorsOnInitialize = initializeLayer();
|
||||
//
|
||||
// if (noErrorsOnInitialize) {
|
||||
// mcMMO.p.getLogger().info("Successfully Loaded Compatibility Layer! (Player Attack Cooldown Exploit Prevention)");
|
||||
// }
|
||||
// } else {
|
||||
// mcMMO.p.getLogger().info("Failed to load - CL (Player Attack Cooldown Exploit Prevention) Could not find CB NMS path for CL");
|
||||
// flagErrorsDuringStartup();
|
||||
// mcMMO.p.getLogger().warning("Could not wire NMS package path for CraftBukkit!");
|
||||
// cbNMSVersionPath = "";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static boolean isCompatibleWithMinecraftVersion(@NotNull NMSVersion nmsVersion) {
|
||||
// switch(nmsVersion) {
|
||||
// case NMS_1_13_2:
|
||||
// case NMS_1_14_4:
|
||||
// case NMS_1_15_2:
|
||||
// case NMS_1_16_4:
|
||||
// case NMS_1_16_5:
|
||||
// return true;
|
||||
// default:
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Cache all reflection methods/types/classes needed for the NMS of this CompatibilityLayer
|
||||
// * @param cooldownMethodName the cooldown method name
|
||||
// * @param attackStrengthMethodName the attack strength method name
|
||||
// * @param resetAttackCooldownMethodName the reset attack cooldown method name
|
||||
// * @param getHandleMethodName the get handle method name
|
||||
// * @return true if NMS was successfully wired
|
||||
// */
|
||||
// public boolean wireNMS(@NotNull String cooldownMethodName, @NotNull String attackStrengthMethodName, @NotNull String resetAttackCooldownMethodName, @NotNull String getHandleMethodName, @NotNull String attackStrengthFieldName) {
|
||||
// entityHumanClass = initEntityHumanClass();
|
||||
//
|
||||
// if (entityHumanClass != null) {
|
||||
// entityLivingClass = entityHumanClass.getSuperclass();
|
||||
// }
|
||||
//
|
||||
// craftPlayerClass = initCraftPlayerClass();
|
||||
// this.attackStrengthFieldName = attackStrengthFieldName;
|
||||
//
|
||||
// try {
|
||||
// this.attackCooldownField = entityLivingClass.getDeclaredField(attackStrengthFieldName);
|
||||
// this.attackCooldownField.setAccessible(true);
|
||||
// } catch (NoSuchFieldException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// this.playerAttackCooldownMethod = entityHumanClass.getMethod(cooldownMethodName);
|
||||
// this.playerAttackStrengthMethod = entityHumanClass.getMethod(attackStrengthMethodName, float.class);
|
||||
// this.resetPlayerAttackCooldownMethod = entityHumanClass.getMethod(resetAttackCooldownMethodName);
|
||||
//
|
||||
// if (craftPlayerClass != null) {
|
||||
// this.getHandleMethod = craftPlayerClass.getMethod(getHandleMethodName);
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// } catch (NoSuchMethodException e) {
|
||||
// flagErrorsDuringStartup();
|
||||
// e.printStackTrace();
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get the cached player attack cooldown method
|
||||
// * @return the cached player attack cooldown method
|
||||
// */
|
||||
// private @Nullable Method getPlayerAttackCooldownMethod() {
|
||||
// return playerAttackCooldownMethod;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get the cached player attack strength method
|
||||
// * @return the cached player attack strength method
|
||||
// */
|
||||
// private @Nullable Method getPlayerAttackStrengthMethod() {
|
||||
// return playerAttackStrengthMethod;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get the cached player attack cooldown reset method
|
||||
// * @return the cached player attack cooldown reset method
|
||||
// */
|
||||
// private @Nullable Method getResetPlayerAttackCooldownMethod() {
|
||||
// return resetPlayerAttackCooldownMethod;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Grab the CraftPlayer class type from NMS
|
||||
// * @return the CraftPlayer class type from NMS
|
||||
// */
|
||||
// private @Nullable Class<?> initCraftPlayerClass() {
|
||||
// try {
|
||||
// return Class.forName(NMSConstants.getCraftPlayerClassPath(cbNMSVersionPath));
|
||||
// } catch (ClassNotFoundException e) {
|
||||
// flagErrorsDuringStartup();
|
||||
// e.printStackTrace();
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Grab the EntityHuman class type from NMS
|
||||
// * @return the EntityHuman class type from NMS
|
||||
// */
|
||||
// private @Nullable Class<?> initEntityHumanClass() {
|
||||
// try {
|
||||
// return Class.forName(NMSConstants.getEntityHumanClassPath(cbNMSVersionPath));
|
||||
// } catch (ClassNotFoundException e) {
|
||||
// flagErrorsDuringStartup();
|
||||
// e.printStackTrace();
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void flagErrorsDuringStartup() {
|
||||
// noErrorsOnInitialize = false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Grabs the attack strength for a player
|
||||
// * Should be noted that as of today there is no way to capture a players current attack strength in spigot when they attack an entity outside of network packet listening
|
||||
// * @param player target player
|
||||
// * @return the float value of the player's attack strength
|
||||
// */
|
||||
// @Override
|
||||
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// Object craftPlayer = craftPlayerClass.cast(player);
|
||||
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
|
||||
//
|
||||
// return (float) playerAttackStrengthMethod.invoke(entityHuman, 0F); //Add no adjustment ticks
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// Object craftPlayer = craftPlayerClass.cast(player);
|
||||
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
|
||||
//
|
||||
// return (float) playerAttackCooldownMethod.invoke(entityHuman); //Add no adjustment ticks
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// Object craftPlayer = craftPlayerClass.cast(player);
|
||||
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
|
||||
// Object entityLiving = entityLivingClass.cast(entityHuman);
|
||||
//
|
||||
// resetPlayerAttackCooldownMethod.invoke(entityLiving);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
|
||||
// Object craftPlayer = craftPlayerClass.cast(player);
|
||||
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
|
||||
// Object entityLiving = entityLivingClass.cast(entityHuman);
|
||||
//
|
||||
// return attackCooldownField.getInt(entityLiving);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
|
||||
// Object craftPlayer = craftPlayerClass.cast(player);
|
||||
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
|
||||
//
|
||||
// attackCooldownField.setInt(entityHuman, fieldValue);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean initializeLayer() {
|
||||
// switch(nmsVersion) {
|
||||
// case NMS_1_12_2:
|
||||
// return wireNMS("dr", "n", "ds", "getHandle", "at");
|
||||
// case NMS_1_13_2:
|
||||
// return wireNMS("dG", "r", "dH", "getHandle", "at");
|
||||
// case NMS_1_14_4:
|
||||
// return wireNMS("dY", "s", "dZ", "getHandle", "at");
|
||||
// case NMS_1_15_2:
|
||||
// return wireNMS("ex", "s", "ey", "getHandle", "at");
|
||||
// case NMS_1_16_4:
|
||||
// return wireNMS("eR", "getAttackCooldown", "resetAttackCooldown", "getHandle", "at");
|
||||
// default:
|
||||
// throw new RuntimeException("Unexpected NMS version support in PlayerAttackCooldown compatibility layer initialization!");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.bungee;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public abstract class AbstractBungeeSerializerCompatibilityLayer {
|
||||
|
||||
public abstract @NonNull Component deserialize(final @NonNull BaseComponent @NonNull [] input);
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.bungee;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public class BungeeLegacySerializerCompatibilityLayer extends
|
||||
AbstractBungeeSerializerCompatibilityLayer {
|
||||
@Override
|
||||
public @NonNull Component deserialize(@NonNull BaseComponent @NonNull [] input) {
|
||||
return BungeeComponentSerializer.legacy().deserialize(input);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.bungee;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
public class BungeeModernSerializerCompatibilityLayer extends
|
||||
AbstractBungeeSerializerCompatibilityLayer {
|
||||
@Override
|
||||
public @NonNull Component deserialize(@NonNull BaseComponent @NonNull [] input) {
|
||||
return BungeeComponentSerializer.get().deserialize(input);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.skills;
|
||||
|
||||
import com.gmail.nossr50.util.compat.layers.AbstractCompatibilityLayer;
|
||||
|
||||
public abstract class AbstractMasterAnglerCompatibility extends AbstractCompatibilityLayer {
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.skills;
|
||||
|
||||
import org.bukkit.entity.FishHook;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MasterAnglerCompatibilityLayer extends AbstractMasterAnglerCompatibility {
|
||||
@Override
|
||||
public boolean initializeLayer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum number of ticks one has to wait for a fish biting.
|
||||
* <p>
|
||||
* The default is 100 ticks (5 seconds).<br> Note that this is before applying lure.
|
||||
*
|
||||
* @return Minimum number of ticks one has to wait for a fish biting
|
||||
*/
|
||||
public int getMinWaitTime(@NotNull FishHook fishHook) {
|
||||
return fishHook.getMinWaitTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum number of ticks one has to wait for a fish biting.
|
||||
* <p>
|
||||
* The default is 100 ticks (5 seconds).<br> Note that this is before applying lure.
|
||||
*
|
||||
* @param minWaitTime Minimum number of ticks one has to wait for a fish biting
|
||||
*/
|
||||
public void setMinWaitTime(@NotNull FishHook fishHook, int minWaitTime) {
|
||||
fishHook.setMinWaitTime(minWaitTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of ticks one has to wait for a fish biting.
|
||||
* <p>
|
||||
* The default is 600 ticks (30 seconds).<br> Note that this is before applying lure.
|
||||
*
|
||||
* @return Maximum number of ticks one has to wait for a fish biting
|
||||
*/
|
||||
public int getMaxWaitTime(@NotNull FishHook fishHook) {
|
||||
return fishHook.getMaxWaitTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of ticks one has to wait for a fish biting.
|
||||
* <p>
|
||||
* The default is 600 ticks (30 seconds).<br> Note that this is before applying lure.
|
||||
*
|
||||
* @param maxWaitTime Maximum number of ticks one has to wait for a fish biting
|
||||
*/
|
||||
public void setMaxWaitTime(@NotNull FishHook fishHook, int maxWaitTime) {
|
||||
fishHook.setMaxWaitTime(maxWaitTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the lure enchantment should be applied to reduce the wait time.
|
||||
* <p>
|
||||
* The default is true.<br> Lure reduces the wait time by 100 ticks (5 seconds) for each level
|
||||
* of the enchantment.
|
||||
*
|
||||
* @return Whether the lure enchantment should be applied to reduce the wait time
|
||||
*/
|
||||
public boolean getApplyLure(@NotNull FishHook fishHook) {
|
||||
return fishHook.getApplyLure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the lure enchantment should be applied to reduce the wait time.
|
||||
* <p>
|
||||
* The default is true.<br> Lure reduces the wait time by 100 ticks (5 seconds) for each level
|
||||
* of the enchantment.
|
||||
*
|
||||
* @param applyLure Whether the lure enchantment should be applied to reduce the wait time
|
||||
*/
|
||||
public void setApplyLure(@NotNull FishHook fishHook, boolean applyLure) {
|
||||
fishHook.setApplyLure(applyLure);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.gmail.nossr50.util.platform;
|
||||
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public abstract class AbstractPlatform implements Platform {
|
||||
|
||||
protected final CompatibilityManager compatibilityManager;
|
||||
protected final MinecraftGameVersion minecraftGameVersion;
|
||||
protected final ServerSoftwareType serverSoftwareType;
|
||||
|
||||
public AbstractPlatform(MinecraftGameVersion minecraftGameVersion,
|
||||
ServerSoftwareType serverSoftwareType, CompatibilityManager compatibilityManager) {
|
||||
this.minecraftGameVersion = minecraftGameVersion;
|
||||
this.serverSoftwareType = serverSoftwareType;
|
||||
this.compatibilityManager = compatibilityManager;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.gmail.nossr50.util.platform;
|
||||
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public class BukkitPlatform extends AbstractPlatform {
|
||||
public BukkitPlatform(MinecraftGameVersion minecraftGameVersion) {
|
||||
super(minecraftGameVersion, ServerSoftwareType.CRAFT_BUKKIT,
|
||||
new CompatibilityManager(minecraftGameVersion));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerSoftwareType getServerSoftwareType() {
|
||||
return super.serverSoftwareType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompatibilityManager getCompatibilityManager() {
|
||||
return compatibilityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull MinecraftGameVersion getGameVersion() {
|
||||
return super.minecraftGameVersion;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.gmail.nossr50.util.platform;
|
||||
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public interface Platform {
|
||||
|
||||
/**
|
||||
* Target {@link ServerSoftwareType} for this {@link Platform}
|
||||
*
|
||||
* @return the {@link ServerSoftwareType} for this {@link Platform}
|
||||
*/
|
||||
@NotNull ServerSoftwareType getServerSoftwareType();
|
||||
|
||||
/**
|
||||
* Get the {@link CompatibilityManager} for this {@link Platform}
|
||||
*
|
||||
* @return the {@link CompatibilityManager} for this platform
|
||||
*/
|
||||
@NotNull CompatibilityManager getCompatibilityManager();
|
||||
|
||||
/**
|
||||
* The target game version of this {@link Platform}
|
||||
*
|
||||
* @return the target {@link MinecraftGameVersion} of this {@link Platform}
|
||||
*/
|
||||
@NotNull MinecraftGameVersion getGameVersion();
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.gmail.nossr50.util.platform;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public class PlatformBuilder {
|
||||
private MinecraftGameVersion minecraftGameVersion;
|
||||
private ServerSoftwareType serverSoftwareType;
|
||||
|
||||
public PlatformBuilder() {
|
||||
|
||||
}
|
||||
|
||||
public PlatformBuilder setMinecraftGameVersion(
|
||||
@NotNull MinecraftGameVersion minecraftGameVersion) {
|
||||
this.minecraftGameVersion = minecraftGameVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PlatformBuilder setSoftwareType(@NotNull ServerSoftwareType softwareType) {
|
||||
this.serverSoftwareType = softwareType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @Nullable Platform build() {
|
||||
return switch (serverSoftwareType) {
|
||||
case PAPER, SPIGOT, CRAFT_BUKKIT -> createBukkitPlatform();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private BukkitPlatform createBukkitPlatform() {
|
||||
return new BukkitPlatform(minecraftGameVersion);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.gmail.nossr50.util.platform;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.LogUtils;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* These classes are a band-aid solution for adding NMS support into 2.1.XXX In 2.2 we are switching
|
||||
* to modules and that will clean things up significantly
|
||||
*/
|
||||
public class PlatformManager {
|
||||
protected Platform platform; //current platform
|
||||
|
||||
public PlatformManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
platform = loadPlatform();
|
||||
}
|
||||
|
||||
public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
private @Nullable Platform loadPlatform() {
|
||||
ServerSoftwareType serverSoftwareType = determinePlatformType();
|
||||
PlatformBuilder platformBuilder = new PlatformBuilder();
|
||||
MinecraftGameVersion gameVersion = determineGameVersion(Bukkit.getBukkitVersion());
|
||||
|
||||
return platformBuilder
|
||||
.setMinecraftGameVersion(gameVersion)
|
||||
.setSoftwareType(serverSoftwareType)
|
||||
.build();
|
||||
}
|
||||
|
||||
//TODO: make this work on things other than bukkit
|
||||
@Deprecated //Only good for determining bukkit game versions
|
||||
private @NotNull MinecraftGameVersion determineGameVersion(String platformVersionString) {
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Platform String: " + platformVersionString);
|
||||
|
||||
// Gets two numbers separated by . and optional third number after next dot. Must end with - or _
|
||||
Matcher versionMatch = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?[-_].*")
|
||||
.matcher(platformVersionString);
|
||||
|
||||
if (versionMatch.find()) {
|
||||
major = Integer.parseInt(versionMatch.group(1));
|
||||
minor = Integer.parseInt(versionMatch.group(2));
|
||||
|
||||
if (versionMatch.group(3) != null) {
|
||||
patch = Integer.parseInt(versionMatch.group(3));
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.debug(mcMMO.p.getLogger(), "Minecraft version determined to be - "
|
||||
+ major + "."
|
||||
+ minor + "."
|
||||
+ patch);
|
||||
|
||||
return new MinecraftGameVersion(major, minor, patch);
|
||||
}
|
||||
|
||||
//TODO: Rewrite this properly once we actually support a not-bukkit platform
|
||||
private @NotNull ServerSoftwareType determinePlatformType() {
|
||||
if (Bukkit.getVersion().toLowerCase(Locale.ENGLISH).contains("paper")) {
|
||||
return ServerSoftwareType.PAPER;
|
||||
} else if (Bukkit.getVersion().toLowerCase(Locale.ENGLISH).contains("spigot")) {
|
||||
return ServerSoftwareType.SPIGOT;
|
||||
} else {
|
||||
return ServerSoftwareType.CRAFT_BUKKIT;
|
||||
}
|
||||
}
|
||||
|
||||
public ServerSoftwareType getServerSoftware() {
|
||||
return platform.getServerSoftwareType();
|
||||
}
|
||||
|
||||
public String getServerSoftwareStr() {
|
||||
return switch (getServerSoftware()) {
|
||||
case PAPER -> "Paper";
|
||||
case SPIGOT -> "Spigot";
|
||||
default -> "CraftBukkit";
|
||||
};
|
||||
}
|
||||
|
||||
public @Nullable CompatibilityManager getCompatibilityManager() {
|
||||
return platform.getCompatibilityManager();
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.gmail.nossr50.util.skills;
|
||||
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.MobMetadataUtils.hasMobFlag;
|
||||
import static com.gmail.nossr50.util.Permissions.canUseSubSkill;
|
||||
import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile;
|
||||
|
||||
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.axes.AxesManager;
|
||||
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.taming.TamingManager;
|
||||
import com.gmail.nossr50.skills.tridents.TridentsManager;
|
||||
@@ -331,6 +333,46 @@ public final class CombatUtils {
|
||||
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,
|
||||
@NotNull EntityDamageByEntityEvent event) {
|
||||
if (event.getCause() == DamageCause.THORNS) {
|
||||
@@ -530,8 +572,12 @@ public final class CombatUtils {
|
||||
public static void processCombatAttack(@NotNull EntityDamageByEntityEvent event,
|
||||
@NotNull Entity painSourceRoot,
|
||||
@NotNull LivingEntity target) {
|
||||
Entity painSource = event.getDamager();
|
||||
EntityType entityType = painSource.getType();
|
||||
final Entity painSource = event.getDamager();
|
||||
final EntityType entityType = painSource.getType();
|
||||
final String damageType = event.getDamageSource().getDamageType().getKey().getKey();
|
||||
|
||||
boolean isDamageTypeSpear =
|
||||
damageType.equalsIgnoreCase("SPEAR");
|
||||
|
||||
if (target instanceof ArmorStand) {
|
||||
return;
|
||||
@@ -574,7 +620,7 @@ public final class CombatUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack heldItem = player.getInventory().getItemInMainHand();
|
||||
final ItemStack heldItem = player.getInventory().getItemInMainHand();
|
||||
|
||||
if (target instanceof Tameable) {
|
||||
if (heldItem.getType() == Material.BONE) {
|
||||
@@ -592,7 +638,16 @@ public final class CombatUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (ItemUtils.isSword(heldItem)) {
|
||||
if (isDamageTypeSpear) {
|
||||
if (!mcMMO.p.getSkillTools()
|
||||
.canCombatSkillsTrigger(PrimarySkillType.SPEARS, target)) {
|
||||
return;
|
||||
}
|
||||
if (mcMMO.p.getSkillTools()
|
||||
.doesPlayerHaveSkillPermission(player, PrimarySkillType.SPEARS)) {
|
||||
processSpearsCombat(target, player, event);
|
||||
}
|
||||
} if (ItemUtils.isSword(heldItem)) {
|
||||
if (!mcMMO.p.getSkillTools()
|
||||
.canCombatSkillsTrigger(PrimarySkillType.SWORDS, target)) {
|
||||
return;
|
||||
@@ -872,8 +927,6 @@ public final class CombatUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
//EventUtils.callFakeArmSwingEvent(attacker);
|
||||
|
||||
switch (type) {
|
||||
case SWORDS:
|
||||
if (entity instanceof Player) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.gmail.nossr50.util.skills;
|
||||
|
||||
import com.gmail.nossr50.api.exceptions.InvalidSkillException;
|
||||
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
@@ -18,6 +17,7 @@ import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -27,15 +27,16 @@ import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
public class SkillTools {
|
||||
private final mcMMO pluginRef;
|
||||
|
||||
// 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
|
||||
public final @NotNull ImmutableList<String> LOCALIZED_SKILL_NAMES;
|
||||
public final @NotNull ImmutableList<String> FORMATTED_SUBSKILL_NAMES;
|
||||
public final @NotNull ImmutableSet<String> EXACT_SUBSKILL_NAMES;
|
||||
public final @NotNull ImmutableList<PrimarySkillType> CHILD_SKILLS;
|
||||
public final static @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
|
||||
public final static @NotNull ImmutableList<PrimarySkillType> SALVAGE_PARENTS;
|
||||
public final static @NotNull ImmutableList<PrimarySkillType> SMELTING_PARENTS;
|
||||
public static final @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
|
||||
public static final @NotNull ImmutableList<PrimarySkillType> SALVAGE_PARENTS;
|
||||
public static final @NotNull ImmutableList<PrimarySkillType> SMELTING_PARENTS;
|
||||
public final @NotNull ImmutableList<PrimarySkillType> COMBAT_SKILLS;
|
||||
public final @NotNull ImmutableList<PrimarySkillType> GATHERING_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<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, ToolType> primarySkillToolMap;
|
||||
|
||||
static {
|
||||
// Build NON_CHILD_SKILLS once from the enum values
|
||||
ArrayList<PrimarySkillType> tempNonChildSkills = new ArrayList<>();
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
if (primarySkillType != PrimarySkillType.SALVAGE
|
||||
&& primarySkillType != PrimarySkillType.SMELTING) {
|
||||
if (!isChildSkill(primarySkillType)) {
|
||||
tempNonChildSkills.add(primarySkillType);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* Setup subskill -> parent relationship map
|
||||
*/
|
||||
EnumMap<SubSkillType, PrimarySkillType> tempSubParentMap = new EnumMap<>(
|
||||
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);
|
||||
this.subSkillParentRelationshipMap = buildSubSkillParentMap();
|
||||
|
||||
/*
|
||||
* Setup primary -> (collection) subskill map
|
||||
*/
|
||||
|
||||
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);
|
||||
this.primarySkillChildrenMap = buildPrimarySkillChildrenMap(subSkillParentRelationshipMap);
|
||||
|
||||
/*
|
||||
* 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.WOODCUTTING, ToolType.AXE);
|
||||
@@ -120,56 +189,74 @@ public class SkillTools {
|
||||
tempToolMap.put(PrimarySkillType.HERBALISM, ToolType.HOE);
|
||||
tempToolMap.put(PrimarySkillType.MINING, ToolType.PICKAXE);
|
||||
|
||||
primarySkillToolMap = ImmutableMap.copyOf(tempToolMap);
|
||||
return ImmutableMap.copyOf(tempToolMap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup ability -> primary map
|
||||
* Setup primary -> ability map
|
||||
*/
|
||||
/**
|
||||
* Holder for the two super ability maps, so we can build them in one pass.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
record SuperAbilityMaps(
|
||||
@NotNull ImmutableMap<SuperAbilityType, PrimarySkillType> superAbilityParentRelationshipMap,
|
||||
@NotNull ImmutableMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap) {
|
||||
}
|
||||
|
||||
EnumMap<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap = new EnumMap<>(
|
||||
SuperAbilityType.class);
|
||||
EnumMap<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap = new EnumMap<>(
|
||||
PrimarySkillType.class);
|
||||
@VisibleForTesting
|
||||
@NotNull
|
||||
SuperAbilityMaps buildSuperAbilityMaps() {
|
||||
final Map<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap =
|
||||
new EnumMap<>(SuperAbilityType.class);
|
||||
final Map<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap =
|
||||
new EnumMap<>(PrimarySkillType.class);
|
||||
|
||||
for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {
|
||||
try {
|
||||
PrimarySkillType parent = getSuperAbilityParent(superAbilityType);
|
||||
tempAbilityParentRelationshipMap.put(superAbilityType, parent);
|
||||
final PrimarySkillType parent = getSuperAbilityParent(superAbilityType);
|
||||
tempAbilityParentRelationshipMap.put(superAbilityType, parent);
|
||||
|
||||
if (superAbilityType != SuperAbilityType.BLAST_MINING) {
|
||||
//This map is used only for abilities that have a tool readying phase, so blast mining is ignored
|
||||
tempMainActivatedAbilityChildMap.put(parent, superAbilityType);
|
||||
}
|
||||
} catch (InvalidSkillException e) {
|
||||
e.printStackTrace();
|
||||
// This map is used only for abilities that have a tool readying phase,
|
||||
// so Blast Mining is ignored.
|
||||
if (superAbilityType != SuperAbilityType.BLAST_MINING) {
|
||||
tempMainActivatedAbilityChildMap.put(parent, superAbilityType);
|
||||
}
|
||||
}
|
||||
|
||||
superAbilityParentRelationshipMap = ImmutableMap.copyOf(tempAbilityParentRelationshipMap);
|
||||
mainActivatedAbilityChildMap = ImmutableMap.copyOf(tempMainActivatedAbilityChildMap);
|
||||
|
||||
/*
|
||||
* Build child skill and nonchild skill lists
|
||||
*/
|
||||
return new SuperAbilityMaps(
|
||||
ImmutableMap.copyOf(tempAbilityParentRelationshipMap),
|
||||
ImmutableMap.copyOf(tempMainActivatedAbilityChildMap)
|
||||
);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@NotNull
|
||||
ImmutableList<PrimarySkillType> buildChildSkills() {
|
||||
List<PrimarySkillType> childSkills = new ArrayList<>();
|
||||
|
||||
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
|
||||
if (isChildSkill(primarySkillType)) {
|
||||
childSkills.add(primarySkillType);
|
||||
}
|
||||
}
|
||||
return ImmutableList.copyOf(childSkills);
|
||||
}
|
||||
|
||||
CHILD_SKILLS = ImmutableList.copyOf(childSkills);
|
||||
|
||||
/*
|
||||
* Build categorized skill lists
|
||||
*/
|
||||
|
||||
// We are in a game version with Maces
|
||||
if (mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
|
||||
COMBAT_SKILLS = ImmutableList.of(
|
||||
@VisibleForTesting
|
||||
@NotNull
|
||||
ImmutableList<PrimarySkillType> buildCombatSkills() {
|
||||
if (mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 11)) {
|
||||
// We are in a game version with Spears and Maces
|
||||
return ImmutableList.of(
|
||||
PrimarySkillType.ARCHERY,
|
||||
PrimarySkillType.AXES,
|
||||
PrimarySkillType.CROSSBOWS,
|
||||
PrimarySkillType.MACES,
|
||||
PrimarySkillType.SWORDS,
|
||||
PrimarySkillType.SPEARS,
|
||||
PrimarySkillType.TAMING,
|
||||
PrimarySkillType.TRIDENTS,
|
||||
PrimarySkillType.UNARMED
|
||||
);
|
||||
} else if (mcMMO.getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
|
||||
// We are in a game version with Maces
|
||||
return ImmutableList.of(
|
||||
PrimarySkillType.ARCHERY,
|
||||
PrimarySkillType.AXES,
|
||||
PrimarySkillType.CROSSBOWS,
|
||||
@@ -177,42 +264,23 @@ public class SkillTools {
|
||||
PrimarySkillType.SWORDS,
|
||||
PrimarySkillType.TAMING,
|
||||
PrimarySkillType.TRIDENTS,
|
||||
PrimarySkillType.UNARMED);
|
||||
PrimarySkillType.UNARMED
|
||||
);
|
||||
} else {
|
||||
// No Maces in this version
|
||||
COMBAT_SKILLS = ImmutableList.of(
|
||||
return ImmutableList.of(
|
||||
PrimarySkillType.ARCHERY,
|
||||
PrimarySkillType.AXES,
|
||||
PrimarySkillType.CROSSBOWS,
|
||||
PrimarySkillType.SWORDS,
|
||||
PrimarySkillType.TAMING,
|
||||
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)
|
||||
throws InvalidSkillException {
|
||||
private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) {
|
||||
return switch (superAbilityType) {
|
||||
case BERSERK -> PrimarySkillType.UNARMED;
|
||||
case GREEN_TERRA -> PrimarySkillType.HERBALISM;
|
||||
@@ -225,11 +293,12 @@ public class SkillTools {
|
||||
case TRIDENTS_SUPER_ABILITY -> PrimarySkillType.TRIDENTS;
|
||||
case EXPLOSIVE_SHOT -> PrimarySkillType.ARCHERY;
|
||||
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
|
||||
*/
|
||||
@@ -272,9 +341,12 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a string of a skill to a skill This is NOT case sensitive 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
|
||||
* Matches a string of a skill to a skill.
|
||||
* This is NOT case-sensitive.
|
||||
* <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
|
||||
* @return the matching PrimarySkillType if one is found, otherwise null
|
||||
@@ -282,8 +354,9 @@ public class SkillTools {
|
||||
public PrimarySkillType matchSkill(String skillName) {
|
||||
if (!pluginRef.getGeneralConfig().getLocale().equalsIgnoreCase("en_US")) {
|
||||
for (PrimarySkillType type : PrimarySkillType.values()) {
|
||||
if (skillName.equalsIgnoreCase(LocaleLoader.getString(
|
||||
StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
|
||||
String localized = LocaleLoader.getString(
|
||||
StringUtils.getCapitalized(type.name()) + ".SkillName");
|
||||
if (skillName.equalsIgnoreCase(localized)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -297,15 +370,15 @@ public class SkillTools {
|
||||
|
||||
if (!skillName.equalsIgnoreCase("all")) {
|
||||
pluginRef.getLogger()
|
||||
.warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize
|
||||
.warning("Invalid mcMMO skill (" + skillName + ")"); // TODO: Localize
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PrimarySkillStype to which a SubSkillType belongs Return null if it does not belong
|
||||
* to one.. which should be impossible in most circumstances
|
||||
* Gets the PrimarySkillType to which a SubSkillType belongs.
|
||||
* Returns null if it does not belong to one (which should be impossible in most circumstances).
|
||||
*
|
||||
* @param subSkillType target subskill
|
||||
* @return the PrimarySkillType of this SubSkill, null if it doesn't exist
|
||||
@@ -315,8 +388,8 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PrimarySkillStype to which a SuperAbilityType belongs Return null if it does not
|
||||
* belong to one.. which should be impossible in most circumstances
|
||||
* Gets the PrimarySkillType to which a SuperAbilityType belongs.
|
||||
* Returns null if it does not belong to one (which should be impossible in most circumstances).
|
||||
*
|
||||
* @param superAbilityType target super ability
|
||||
* @return the PrimarySkillType of this SuperAbilityType, null if it doesn't exist
|
||||
@@ -326,16 +399,15 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
public SuperAbilityType getSuperAbility(PrimarySkillType primarySkillType) {
|
||||
if (mainActivatedAbilityChildMap.get(primarySkillType) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mainActivatedAbilityChildMap.get(primarySkillType);
|
||||
}
|
||||
|
||||
public boolean isSuperAbilityUnlocked(PrimarySkillType primarySkillType, Player player) {
|
||||
SuperAbilityType superAbilityType = mcMMO.p.getSkillTools()
|
||||
.getSuperAbility(primarySkillType);
|
||||
SuperAbilityType superAbilityType = getSuperAbility(primarySkillType);
|
||||
if (superAbilityType == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SubSkillType subSkillType = superAbilityType.getSubSkillTypeDefinition();
|
||||
return RankUtils.hasUnlockedSubskill(player, subSkillType);
|
||||
}
|
||||
@@ -368,7 +440,6 @@ public class SkillTools {
|
||||
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) {
|
||||
return switch (primarySkillType) {
|
||||
case SALVAGE, SMELTING -> true;
|
||||
@@ -392,8 +463,10 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
public boolean canCombatSkillsTrigger(PrimarySkillType primarySkillType, Entity target) {
|
||||
return (target instanceof Player || (target instanceof Tameable
|
||||
&& ((Tameable) target).isTamed())) ? getPVPEnabled(primarySkillType)
|
||||
boolean isPlayerOrTamed = (target instanceof Player)
|
||||
|| (target instanceof Tameable && ((Tameable) target).isTamed());
|
||||
return isPlayerOrTamed
|
||||
? getPVPEnabled(primarySkillType)
|
||||
: getPVEEnabled(primarySkillType);
|
||||
}
|
||||
|
||||
@@ -410,7 +483,7 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
public int getLevelCap(@NotNull PrimarySkillType primarySkillType) {
|
||||
return mcMMO.p.getGeneralConfig().getLevelCap(primarySkillType);
|
||||
return pluginRef.getGeneralConfig().getLevelCap(primarySkillType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,17 +518,12 @@ public class SkillTools {
|
||||
}
|
||||
|
||||
public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents(
|
||||
PrimarySkillType childSkill)
|
||||
throws IllegalArgumentException {
|
||||
switch (childSkill) {
|
||||
case SALVAGE -> {
|
||||
return SALVAGE_PARENTS;
|
||||
}
|
||||
case SMELTING -> {
|
||||
return SMELTING_PARENTS;
|
||||
}
|
||||
PrimarySkillType childSkill) throws IllegalArgumentException {
|
||||
return switch (childSkill) {
|
||||
case SALVAGE -> SALVAGE_PARENTS;
|
||||
case SMELTING -> SMELTING_PARENTS;
|
||||
default -> throw new IllegalArgumentException(
|
||||
"Skill " + childSkill + " is not a child skill");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.inventory.RecipeChoice;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
@@ -360,6 +361,8 @@ public final class SkillUtils {
|
||||
return 4;
|
||||
}
|
||||
|
||||
final ItemStack recipeItem = recipeMaterial != null ? new ItemStack(recipeMaterial) : null;
|
||||
|
||||
for (Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator();
|
||||
recipeIterator.hasNext(); ) {
|
||||
Recipe bukkitRecipe = recipeIterator.next();
|
||||
@@ -368,21 +371,17 @@ public final class SkillUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bukkitRecipe instanceof ShapelessRecipe) {
|
||||
for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
|
||||
if (ingredient != null
|
||||
&& (recipeMaterial == null || ingredient.getType() == recipeMaterial)
|
||||
&& (ingredient.getType() == recipeMaterial)) {
|
||||
quantity += ingredient.getAmount();
|
||||
if (bukkitRecipe instanceof ShapelessRecipe shapelessRecipe) {
|
||||
for (RecipeChoice ingredient : shapelessRecipe.getChoiceList()) {
|
||||
if (ingredient != null && recipeItem != null && ingredient.test(recipeItem)) {
|
||||
quantity += 1;
|
||||
}
|
||||
}
|
||||
} else if (bukkitRecipe instanceof ShapedRecipe) {
|
||||
for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap()
|
||||
} else if (bukkitRecipe instanceof ShapedRecipe shapedRecipe) {
|
||||
for (RecipeChoice ingredient : shapedRecipe.getChoiceMap()
|
||||
.values()) {
|
||||
if (ingredient != null
|
||||
&& (recipeMaterial == null || ingredient.getType() == recipeMaterial)
|
||||
&& (ingredient.getType() == recipeMaterial)) {
|
||||
quantity += ingredient.getAmount();
|
||||
if (ingredient != null && recipeItem != null && ingredient.test(recipeItem)) {
|
||||
quantity += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class TextComponentFactory {
|
||||
*
|
||||
* @param localeKey target locale string address
|
||||
* @param values vars to be passed to the locale loader
|
||||
* @return
|
||||
* @return a text component with the locale string and variables applied
|
||||
*/
|
||||
public static TextComponent getNotificationMultipleValues(String localeKey, String... values) {
|
||||
String preColoredString = LocaleLoader.getString(localeKey, (Object[]) values);
|
||||
@@ -544,18 +544,28 @@ public class TextComponentFactory {
|
||||
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,
|
||||
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) {
|
||||
for (SubSkillType subSkillType : SubSkillType.values()) {
|
||||
if (subSkillType.getParentSkill() == parentSkill) {
|
||||
//TODO: Hacky rewrite later
|
||||
//Only some versions of MC have this skill
|
||||
if (subSkillType == SubSkillType.FISHING_MASTER_ANGLER
|
||||
&& mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer()
|
||||
== null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Permissions.isSubSkillEnabled(player, subSkillType)) {
|
||||
if (!InteractionManager.hasSubSkill(subSkillType)) {
|
||||
textComponents.add(TextComponentFactory.getSubSkillTextComponent(player,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.gmail.nossr50.util.text;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentBuilder;
|
||||
@@ -10,7 +9,6 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -106,20 +104,6 @@ public class TextUtils {
|
||||
textComponent.hoverEvent(HoverEvent.showText(baseComponent));
|
||||
}
|
||||
|
||||
public static BaseComponent[] convertToBungeeComponent(@NotNull String displayName) {
|
||||
return net.md_5.bungee.api.chat.TextComponent.fromLegacyText(displayName);
|
||||
}
|
||||
|
||||
public static @NotNull TextComponent ofBungeeComponents(@NotNull BaseComponent[] bungeeName) {
|
||||
return Component.textOfChildren(
|
||||
mcMMO.getCompatibilityManager().getBungeeSerializerCompatibilityLayer()
|
||||
.deserialize(bungeeName));
|
||||
}
|
||||
|
||||
public static @NotNull TextComponent ofBungeeRawStrings(@NotNull String bungeeRawString) {
|
||||
return ofBungeeComponents(convertToBungeeComponent(bungeeRawString));
|
||||
}
|
||||
|
||||
public static @NotNull TextComponent ofLegacyTextRaw(@NotNull String rawString) {
|
||||
return LegacyComponentSerializer.legacySection().deserialize(rawString);
|
||||
}
|
||||
|
||||
@@ -647,4 +647,19 @@ Skills:
|
||||
Rank_1: 10
|
||||
Rank_2: 15
|
||||
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
|
||||
@@ -229,6 +229,7 @@ Hardcore:
|
||||
Tridents: false
|
||||
Crossbows: false
|
||||
Maces: false
|
||||
Spears: false
|
||||
Vampirism:
|
||||
Leech_Percentage: 5.0
|
||||
Level_Threshold: 0
|
||||
@@ -249,6 +250,7 @@ Hardcore:
|
||||
Tridents: false
|
||||
Crossbows: false
|
||||
Maces: false
|
||||
Spears: false
|
||||
|
||||
#
|
||||
# Settings for SMP Mods
|
||||
@@ -427,6 +429,10 @@ Skills:
|
||||
Enabled_For_PVP: true
|
||||
Enabled_For_PVE: true
|
||||
Level_Cap: 0
|
||||
Spears:
|
||||
Enabled_For_PVP: true
|
||||
Enabled_For_PVE: true
|
||||
Level_Cap: 0
|
||||
Taming:
|
||||
Enabled_For_PVP: true
|
||||
Enabled_For_PVE: true
|
||||
@@ -478,6 +484,7 @@ Green_Thumb_Replanting_Crops:
|
||||
Potatoes: true
|
||||
Beetroots: true
|
||||
Cocoa: true
|
||||
Sweet_Berry_Bush: true
|
||||
#
|
||||
# Settings for Double Drops
|
||||
###
|
||||
|
||||
@@ -95,6 +95,10 @@ Experience_Bars:
|
||||
Enable: true
|
||||
Color: BLUE
|
||||
BarStyle: SEGMENTED_6
|
||||
Spears:
|
||||
Enable: true
|
||||
Color: BLUE
|
||||
BarStyle: SEGMENTED_6
|
||||
Repair:
|
||||
Enable: true
|
||||
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.
|
||||
Skill_Multiplier:
|
||||
Spears: 1.0
|
||||
Maces: 1.0
|
||||
Crossbows: 1.0
|
||||
Tridents: 1.0
|
||||
@@ -218,6 +223,7 @@ Diminished_Returns:
|
||||
Crossbows: 20000
|
||||
Tridents: 20000
|
||||
Maces: 20000
|
||||
Spears: 20000
|
||||
|
||||
Time_Interval: 10
|
||||
|
||||
@@ -546,6 +552,7 @@ Experience_Values:
|
||||
Base: 1000.0
|
||||
Wood: 0.6
|
||||
Stone: 1.3
|
||||
Copper: 2.0
|
||||
Iron: 2.5
|
||||
Gold: 0.3
|
||||
Diamond: 5.0
|
||||
@@ -582,6 +589,7 @@ Experience_Values:
|
||||
Taming:
|
||||
Animal_Taming:
|
||||
Camel: 1300
|
||||
Camel_Husk: 1300
|
||||
Sniffer: 1500
|
||||
Snifflet: 900
|
||||
Llama: 1200
|
||||
@@ -600,12 +608,15 @@ Experience_Values:
|
||||
Goat: 250
|
||||
Axolotl: 600
|
||||
Frog: 900
|
||||
Nautilus: 1700
|
||||
Zombie_Nautilus: 1700
|
||||
Combat:
|
||||
Multiplier:
|
||||
Animals: 1.0
|
||||
Armadillo: 1.1
|
||||
Creeper: 4.0
|
||||
Skeleton: 3.0
|
||||
Parched: 2.5
|
||||
Spider: 2.0
|
||||
Giant: 4.0
|
||||
Zombie: 2.0
|
||||
@@ -683,6 +694,7 @@ Experience_Values:
|
||||
Sniffer: 1.1
|
||||
Snifflet: 1.1
|
||||
Camel: 1.2
|
||||
Camel_Husk: 1.25
|
||||
Bogged: 2.0
|
||||
Breeze: 4.0
|
||||
Armor_Stand: 0.0
|
||||
|
||||
@@ -27,6 +27,7 @@ JSON.Salvage=Salvage
|
||||
JSON.Swords=Swords
|
||||
JSON.Taming=Taming
|
||||
JSON.Tridents=Tridents
|
||||
JSON.Spears=Spears
|
||||
JSON.Maces=Maces
|
||||
JSON.Unarmed=Unarmed
|
||||
JSON.Woodcutting=Woodcutting
|
||||
@@ -98,6 +99,7 @@ Overhaul.Name.Smelting=Smelting
|
||||
Overhaul.Name.Swords=Swords
|
||||
Overhaul.Name.Taming=Taming
|
||||
Overhaul.Name.Tridents=Tridents
|
||||
Overhaul.Name.Spears=Spears
|
||||
Overhaul.Name.Maces=Maces
|
||||
Overhaul.Name.Unarmed=Unarmed
|
||||
Overhaul.Name.Woodcutting=Woodcutting
|
||||
@@ -125,6 +127,7 @@ XPBar.Smelting=Smelting Lv.&6{0}
|
||||
XPBar.Swords=Swords Lv.&6{0}
|
||||
XPBar.Taming=Taming Lv.&6{0}
|
||||
XPBar.Tridents=Tridents Lv.&6{0}
|
||||
XPBar.Spears=Spears Lv.&6{0}
|
||||
XPBar.Maces=Maces Lv.&6{0}
|
||||
XPBar.Unarmed=Unarmed 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.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.Ability.Lower=&7You lower 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.Taming=Animal Taming, or combat w/ your wolves
|
||||
Commands.XPGain.Tridents=Attacking Monsters
|
||||
Commands.XPGain.Spears=Attacking Monsters
|
||||
Commands.XPGain.Unarmed=Attacking Monsters
|
||||
Commands.XPGain.Woodcutting=Chopping down trees
|
||||
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ðis 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.
|
||||
# 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.
|
||||
# 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.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.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.
|
||||
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.Offline= &cYou do not have permission to inspect offline players!
|
||||
Inspect.OfflineStats=mcMMO Stats for Offline Player &e{0}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
name: mcMMO
|
||||
version: ${project.version}
|
||||
description: >
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
main: com.gmail.nossr50.mcMMO
|
||||
softdepend: [WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib]
|
||||
softdepend: [ WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib ]
|
||||
load: POSTWORLD
|
||||
folia-supported: true
|
||||
api-version: 1.13
|
||||
@@ -26,14 +26,14 @@ commands:
|
||||
mmocompat:
|
||||
description: Information about the server and whether its considered fully compatible or running in compatibility mode
|
||||
mmodebug:
|
||||
aliases: [mcmmodebugmode]
|
||||
aliases: [ mcmmodebugmode ]
|
||||
description: Toggles a debug mode which will print useful information to chat
|
||||
mmoinfo:
|
||||
aliases: [mcinfo]
|
||||
aliases: [ mcinfo ]
|
||||
description: Info pages for mcMMO
|
||||
permission: mcmmo.commands.mmoinfo
|
||||
xprate:
|
||||
aliases: [mcxprate]
|
||||
aliases: [ mcxprate ]
|
||||
description: Modify the xp rate or start an event
|
||||
permission: mcmmo.commands.xprate
|
||||
mcmmo:
|
||||
@@ -59,7 +59,7 @@ commands:
|
||||
permission: mcmmo.commands.mcrefresh
|
||||
mccooldown:
|
||||
description: Show the cooldowns on all your mcMMO abilities
|
||||
aliases: [mccooldowns]
|
||||
aliases: [ mccooldowns ]
|
||||
permission: mcmmo.commands.mccooldown
|
||||
mcchatspy:
|
||||
description: Toggle mcMMO Party Chat spying on/off
|
||||
@@ -68,7 +68,7 @@ commands:
|
||||
description: Toggle mcMMO god-mode on/off
|
||||
permission: mcmmo.commands.mcgod
|
||||
mcstats:
|
||||
aliases: [stats]
|
||||
aliases: [ stats ]
|
||||
description: Shows your mcMMO stats and xp
|
||||
permission: mcmmo.commands.mcstats
|
||||
mcremove:
|
||||
@@ -84,7 +84,7 @@ commands:
|
||||
description: Create/join a party
|
||||
permission: mcmmo.commands.party
|
||||
inspect:
|
||||
aliases: [mcinspect, mmoinspect]
|
||||
aliases: [ mcinspect, mmoinspect ]
|
||||
description: View detailed mcMMO info on another player
|
||||
permission: mcmmo.commands.inspect
|
||||
mmoshowdb:
|
||||
@@ -94,7 +94,7 @@ commands:
|
||||
description: Convert between different database and formula types
|
||||
permission: mcmmo.commands.mcconvert
|
||||
partychat:
|
||||
aliases: [pc, p]
|
||||
aliases: [ pc, p ]
|
||||
description: Toggle Party chat or send party chat messages
|
||||
permission: mcmmo.chat.partychat
|
||||
skillreset:
|
||||
@@ -145,6 +145,9 @@ commands:
|
||||
smelting:
|
||||
description: Detailed mcMMO skill info
|
||||
permission: mcmmo.commands.smelting
|
||||
spears:
|
||||
description: Detailed mcMMO skill info
|
||||
permission: mcmmo.commands.spears
|
||||
alchemy:
|
||||
description: Detailed mcMMO skill info
|
||||
permission: mcmmo.commands.alchemy
|
||||
@@ -157,24 +160,24 @@ commands:
|
||||
mmopower:
|
||||
description: Shows skill mastery and power level info
|
||||
permission: mcmmo.commands.mmopower
|
||||
aliases: [mmopowerlevel, powerlevel]
|
||||
aliases: [ mmopowerlevel, powerlevel ]
|
||||
adminchat:
|
||||
aliases: [ac, a]
|
||||
aliases: [ ac, a ]
|
||||
description: Toggle Admin chat or send admin chat messages
|
||||
permission: mcmmo.chat.adminchat
|
||||
mcpurge:
|
||||
description: Purge users with 0 powerlevel and/or who haven't connected in several months from the server DB.
|
||||
permission: mcmmo.commands.mcpurge
|
||||
mcnotify:
|
||||
aliases: [notify]
|
||||
aliases: [ notify ]
|
||||
description: Toggle mcMMO abilities chat display notifications on/off
|
||||
permission: mcmmo.commands.mcnotify
|
||||
mcscoreboard:
|
||||
aliases: [mcsb]
|
||||
aliases: [ mcsb ]
|
||||
description: Manage your mcMMO Scoreboard
|
||||
permission: mcmmo.commands.mcscoreboard
|
||||
mcmmoreloadlocale:
|
||||
aliases: [mcreloadlocale]
|
||||
aliases: [ mcreloadlocale ]
|
||||
description: Reloads locale
|
||||
permission: mcmmo.commands.reloadlocale
|
||||
permissions:
|
||||
@@ -237,6 +240,7 @@ permissions:
|
||||
mcmmo.ability.repair.all: true
|
||||
mcmmo.ability.salvage.all: true
|
||||
mcmmo.ability.smelting.all: true
|
||||
mcmmo.ability.spears.all: true
|
||||
mcmmo.ability.swords.all: true
|
||||
mcmmo.ability.taming.all: true
|
||||
mcmmo.ability.tridents.all: true
|
||||
@@ -320,19 +324,19 @@ permissions:
|
||||
mcmmo.ability.axes.skullsplitter:
|
||||
description: Allows access to the Skull Splitter ability
|
||||
mcmmo.ability.crossbows.*:
|
||||
description: Allows access to all Crossbows abilities
|
||||
children:
|
||||
description: Allows access to all Crossbows abilities
|
||||
children:
|
||||
mcmmo.ability.crossbows.all: true
|
||||
mcmmo.ability.crossbows.all:
|
||||
description: Allows access to all Crossbows abilities
|
||||
children:
|
||||
mcmmo.ability.crossbows.trickshot: true
|
||||
mcmmo.ability.crossbows.poweredshot: true
|
||||
mcmmo.ability.crossbows.crossbowslimitbreak: true
|
||||
description: Allows access to all Crossbows abilities
|
||||
children:
|
||||
mcmmo.ability.crossbows.trickshot: true
|
||||
mcmmo.ability.crossbows.poweredshot: true
|
||||
mcmmo.ability.crossbows.crossbowslimitbreak: true
|
||||
mcmmo.ability.crossbows.crossbowslimitbreak:
|
||||
description: Adds damage to crossbows
|
||||
description: Adds damage to crossbows
|
||||
mcmmo.ability.crossbows.trickshot:
|
||||
description: Allows access to the Trick Shot ability
|
||||
description: Allows access to the Trick Shot ability
|
||||
mcmmo.ability.crossbows.poweredshot:
|
||||
description: Allows access to the Powered Shot ability
|
||||
mcmmo.ability.excavation.*:
|
||||
@@ -646,6 +650,23 @@ permissions:
|
||||
description: Allows access to the Second Smelt ability
|
||||
mcmmo.ability.smelting.vanillaxpboost:
|
||||
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.*:
|
||||
default: false
|
||||
description: Allows access to all Swords abilities
|
||||
@@ -885,6 +906,7 @@ permissions:
|
||||
mcmmo.commands.repair: true
|
||||
mcmmo.commands.salvage: true
|
||||
mcmmo.commands.smelting: true
|
||||
mcmmo.commands.spears: true
|
||||
mcmmo.commands.swords: true
|
||||
mcmmo.commands.taming: true
|
||||
mcmmo.commands.unarmed: true
|
||||
@@ -898,7 +920,7 @@ permissions:
|
||||
mcmmo.commands.addxp: true
|
||||
mcmmo.commands.addxp.others: true
|
||||
mcmmo.commands.defaults: true
|
||||
# mcmmo.commands.hardcore.all: true
|
||||
# mcmmo.commands.hardcore.all: true
|
||||
mcmmo.commands.inspect.far: true
|
||||
mcmmo.commands.inspect.hidden: true
|
||||
mcmmo.commands.mcability.others: true
|
||||
@@ -918,7 +940,7 @@ permissions:
|
||||
mcmmo.commands.ptp.world.all: true
|
||||
mcmmo.commands.reloadlocale: true
|
||||
mcmmo.commands.skillreset.all: true
|
||||
# mcmmo.commands.vampirism.all: true
|
||||
# mcmmo.commands.vampirism.all: true
|
||||
mcmmo.commands.xprate.all: true
|
||||
mcmmo.commands.acrobatics:
|
||||
description: Allows access to the acrobatics command
|
||||
@@ -1058,6 +1080,7 @@ permissions:
|
||||
mcmmo.commands.mctop.repair: true
|
||||
mcmmo.commands.mctop.salvage: true
|
||||
mcmmo.commands.mctop.smelting: true
|
||||
mcmmo.commands.mctop.spears: true
|
||||
mcmmo.commands.mctop.swords: true
|
||||
mcmmo.commands.mctop.taming: true
|
||||
mcmmo.commands.mctop.tridents: true
|
||||
@@ -1091,6 +1114,8 @@ permissions:
|
||||
description: Allows access to the mctop command for salvage
|
||||
mcmmo.commands.mctop.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:
|
||||
description: Allows access to the mctop command for swords
|
||||
mcmmo.commands.mctop.taming:
|
||||
@@ -1239,6 +1264,7 @@ permissions:
|
||||
mcmmo.commands.skillreset.repair: true
|
||||
mcmmo.commands.skillreset.salvage: true
|
||||
mcmmo.commands.skillreset.smelting: true
|
||||
mcmmo.commands.skillreset.spears: true
|
||||
mcmmo.commands.skillreset.swords: true
|
||||
mcmmo.commands.skillreset.taming: true
|
||||
mcmmo.commands.skillreset.unarmed: true
|
||||
@@ -1268,6 +1294,8 @@ permissions:
|
||||
description: Allows access to the skillreset command for crossbows
|
||||
mcmmo.commands.skillreset.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:
|
||||
description: Allows access to the skillreset command for maces
|
||||
mcmmo.commands.skillreset.others.*:
|
||||
@@ -1290,6 +1318,7 @@ permissions:
|
||||
mcmmo.commands.skillreset.others.repair: true
|
||||
mcmmo.commands.skillreset.others.salvage: true
|
||||
mcmmo.commands.skillreset.others.smelting: true
|
||||
mcmmo.commands.skillreset.others.spears: true
|
||||
mcmmo.commands.skillreset.others.swords: true
|
||||
mcmmo.commands.skillreset.others.taming: true
|
||||
mcmmo.commands.skillreset.others.unarmed: true
|
||||
@@ -1321,6 +1350,8 @@ permissions:
|
||||
description: Allows access to the skillreset command for salvage for other players
|
||||
mcmmo.commands.skillreset.others.smelting:
|
||||
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:
|
||||
description: Allows access to the skillreset command for swords for other players
|
||||
mcmmo.commands.skillreset.others.taming:
|
||||
@@ -1406,7 +1437,7 @@ permissions:
|
||||
default: false
|
||||
description: implies access to all mcmmo perks
|
||||
children:
|
||||
mcmmo.perks.all: true
|
||||
mcmmo.perks.all: true
|
||||
mcmmo.perks.all:
|
||||
default: false
|
||||
description: implies access to all mcmmo perks
|
||||
@@ -1497,6 +1528,7 @@ permissions:
|
||||
mcmmo.perks.lucky.repair: true
|
||||
mcmmo.perks.lucky.salvage: true
|
||||
mcmmo.perks.lucky.smelting: true
|
||||
mcmmo.perks.lucky.spears: true
|
||||
mcmmo.perks.lucky.swords: true
|
||||
mcmmo.perks.lucky.taming: true
|
||||
mcmmo.perks.lucky.unarmed: true
|
||||
@@ -1539,6 +1571,9 @@ permissions:
|
||||
mcmmo.perks.lucky.salvage:
|
||||
default: false
|
||||
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:
|
||||
default: false
|
||||
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.repair: true
|
||||
mcmmo.perks.xp.150percentboost.smelting: true
|
||||
mcmmo.perks.xp.150percentboost.spears: true
|
||||
mcmmo.perks.xp.150percentboost.swords: true
|
||||
mcmmo.perks.xp.150percentboost.taming: true
|
||||
mcmmo.perks.xp.150percentboost.tridents: true
|
||||
@@ -1641,6 +1677,9 @@ permissions:
|
||||
mcmmo.perks.xp.150percentboost.smelting:
|
||||
default: false
|
||||
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:
|
||||
default: false
|
||||
description: Multiplies incoming Swords XP by 2.5
|
||||
@@ -1682,6 +1721,7 @@ permissions:
|
||||
mcmmo.perks.xp.50percentboost.mining: true
|
||||
mcmmo.perks.xp.50percentboost.repair: true
|
||||
mcmmo.perks.xp.50percentboost.smelting: true
|
||||
mcmmo.perks.xp.50percentboost.spears: true
|
||||
mcmmo.perks.xp.50percentboost.swords: true
|
||||
mcmmo.perks.xp.50percentboost.taming: true
|
||||
mcmmo.perks.xp.50percentboost.tridents: true
|
||||
@@ -1720,6 +1760,9 @@ permissions:
|
||||
mcmmo.perks.xp.50percentboost.repair:
|
||||
default: false
|
||||
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:
|
||||
default: false
|
||||
description: Multiplies incoming Smelting XP by 1.5
|
||||
@@ -1739,87 +1782,91 @@ permissions:
|
||||
default: false
|
||||
description: Multiplies incoming Woodcutting XP by 1.5
|
||||
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
|
||||
description: Multiplies incoming XP by 1.25
|
||||
children:
|
||||
mcmmo.perks.xp.25percentboost.all: true
|
||||
mcmmo.perks.xp.25percentboost.all:
|
||||
default: false
|
||||
description: Multiplies incoming XP by 1.25
|
||||
children:
|
||||
mcmmo.perks.xp.25percentboost.acrobatics: true
|
||||
mcmmo.perks.xp.25percentboost.alchemy: true
|
||||
mcmmo.perks.xp.25percentboost.archery: true
|
||||
mcmmo.perks.xp.25percentboost.axes: true
|
||||
mcmmo.perks.xp.25percentboost.crossbows: true
|
||||
mcmmo.perks.xp.25percentboost.excavation: true
|
||||
mcmmo.perks.xp.25percentboost.fishing: true
|
||||
mcmmo.perks.xp.25percentboost.herbalism: true
|
||||
mcmmo.perks.xp.25percentboost.maces: true
|
||||
mcmmo.perks.xp.25percentboost.mining: true
|
||||
mcmmo.perks.xp.25percentboost.repair: true
|
||||
mcmmo.perks.xp.25percentboost.smelting: true
|
||||
mcmmo.perks.xp.25percentboost.swords: true
|
||||
mcmmo.perks.xp.25percentboost.taming: true
|
||||
mcmmo.perks.xp.25percentboost.tridents: true
|
||||
mcmmo.perks.xp.25percentboost.unarmed: true
|
||||
mcmmo.perks.xp.25percentboost.woodcutting: true
|
||||
mcmmo.perks.xp.25percentboost.acrobatics:
|
||||
default: false
|
||||
description: Multiplies incoming Acrobatics XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.alchemy:
|
||||
default: false
|
||||
description: Multiplies incoming Acrobatics XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.archery:
|
||||
default: false
|
||||
description: Multiplies incoming Archery XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.axes:
|
||||
default: false
|
||||
description: Multiplies incoming Axes XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.crossbows:
|
||||
default: false
|
||||
description: Multiplies incoming Crossbows XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.excavation:
|
||||
default: false
|
||||
description: Multiplies incoming Excavation XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.fishing:
|
||||
default: false
|
||||
description: Multiplies incoming Fishing XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.herbalism:
|
||||
default: false
|
||||
description: Multiplies incoming Herbalism XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.maces:
|
||||
default: false
|
||||
description: Multiplies incoming Maces XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.mining:
|
||||
default: false
|
||||
description: Multiplies incoming Mining XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.repair:
|
||||
default: false
|
||||
description: Multiplies incoming Repair XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.smelting:
|
||||
default: false
|
||||
description: Multiplies incoming Smelting XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.swords:
|
||||
default: false
|
||||
description: Multiplies incoming Swords XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.taming:
|
||||
default: false
|
||||
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.25percentboost.all: true
|
||||
mcmmo.perks.xp.25percentboost:
|
||||
default: false
|
||||
description: Multiplies incoming XP by 1.25
|
||||
children:
|
||||
mcmmo.perks.xp.25percentboost.all: true
|
||||
mcmmo.perks.xp.25percentboost.all:
|
||||
default: false
|
||||
description: Multiplies incoming XP by 1.25
|
||||
children:
|
||||
mcmmo.perks.xp.25percentboost.acrobatics: true
|
||||
mcmmo.perks.xp.25percentboost.alchemy: true
|
||||
mcmmo.perks.xp.25percentboost.archery: true
|
||||
mcmmo.perks.xp.25percentboost.axes: true
|
||||
mcmmo.perks.xp.25percentboost.crossbows: true
|
||||
mcmmo.perks.xp.25percentboost.excavation: true
|
||||
mcmmo.perks.xp.25percentboost.fishing: true
|
||||
mcmmo.perks.xp.25percentboost.herbalism: true
|
||||
mcmmo.perks.xp.25percentboost.maces: true
|
||||
mcmmo.perks.xp.25percentboost.mining: true
|
||||
mcmmo.perks.xp.25percentboost.repair: true
|
||||
mcmmo.perks.xp.25percentboost.smelting: true
|
||||
mcmmo.perks.xp.25percentboost.spears: true
|
||||
mcmmo.perks.xp.25percentboost.swords: true
|
||||
mcmmo.perks.xp.25percentboost.taming: true
|
||||
mcmmo.perks.xp.25percentboost.tridents: true
|
||||
mcmmo.perks.xp.25percentboost.unarmed: true
|
||||
mcmmo.perks.xp.25percentboost.woodcutting: true
|
||||
mcmmo.perks.xp.25percentboost.acrobatics:
|
||||
default: false
|
||||
description: Multiplies incoming Acrobatics XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.alchemy:
|
||||
default: false
|
||||
description: Multiplies incoming Acrobatics XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.archery:
|
||||
default: false
|
||||
description: Multiplies incoming Archery XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.axes:
|
||||
default: false
|
||||
description: Multiplies incoming Axes XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.crossbows:
|
||||
default: false
|
||||
description: Multiplies incoming Crossbows XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.excavation:
|
||||
default: false
|
||||
description: Multiplies incoming Excavation XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.fishing:
|
||||
default: false
|
||||
description: Multiplies incoming Fishing XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.herbalism:
|
||||
default: false
|
||||
description: Multiplies incoming Herbalism XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.maces:
|
||||
default: false
|
||||
description: Multiplies incoming Maces XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.mining:
|
||||
default: false
|
||||
description: Multiplies incoming Mining XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.repair:
|
||||
default: false
|
||||
description: Multiplies incoming Repair XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.smelting:
|
||||
default: false
|
||||
description: Multiplies incoming Smelting XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.spears:
|
||||
default: false
|
||||
description: Multiplies incoming Spears XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.swords:
|
||||
default: false
|
||||
description: Multiplies incoming Swords XP by 1.25
|
||||
mcmmo.perks.xp.25percentboost.taming:
|
||||
default: false
|
||||
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.*:
|
||||
default: false
|
||||
description: Multiplies incoming XP by 1.1
|
||||
@@ -1846,6 +1893,7 @@ permissions:
|
||||
mcmmo.perks.xp.10percentboost.mining: true
|
||||
mcmmo.perks.xp.10percentboost.repair: true
|
||||
mcmmo.perks.xp.10percentboost.smelting: true
|
||||
mcmmo.perks.xp.10percentboost.spears: true
|
||||
mcmmo.perks.xp.10percentboost.swords: true
|
||||
mcmmo.perks.xp.10percentboost.taming: true
|
||||
mcmmo.perks.xp.10percentboost.tridents: true
|
||||
@@ -1884,6 +1932,9 @@ permissions:
|
||||
mcmmo.perks.xp.10percentboost.repair:
|
||||
default: false
|
||||
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:
|
||||
default: false
|
||||
description: Multiplies incoming Smelting XP by 1.1
|
||||
@@ -1928,6 +1979,7 @@ permissions:
|
||||
mcmmo.perks.xp.customboost.mining: true
|
||||
mcmmo.perks.xp.customboost.repair: true
|
||||
mcmmo.perks.xp.customboost.smelting: true
|
||||
mcmmo.perks.xp.customboost.spears: true
|
||||
mcmmo.perks.xp.customboost.swords: true
|
||||
mcmmo.perks.xp.customboost.taming: true
|
||||
mcmmo.perks.xp.customboost.tridents: true
|
||||
@@ -1966,6 +2018,9 @@ permissions:
|
||||
mcmmo.perks.xp.customboost.repair:
|
||||
default: false
|
||||
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:
|
||||
default: false
|
||||
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.repair: true
|
||||
mcmmo.perks.xp.double.smelting: true
|
||||
mcmmo.perks.xp.double.spears: true
|
||||
mcmmo.perks.xp.double.swords: true
|
||||
mcmmo.perks.xp.double.taming: true
|
||||
mcmmo.perks.xp.double.tridents: true
|
||||
@@ -2048,6 +2104,9 @@ permissions:
|
||||
mcmmo.perks.xp.double.repair:
|
||||
default: false
|
||||
description: Doubles incoming Repair XP
|
||||
mcmmo.perks.xp.double.spears:
|
||||
default: false
|
||||
description: Doubles incoming Smelting XP
|
||||
mcmmo.perks.xp.double.smelting:
|
||||
default: false
|
||||
description: Doubles incoming Smelting XP
|
||||
@@ -2092,6 +2151,7 @@ permissions:
|
||||
mcmmo.perks.xp.quadruple.mining: true
|
||||
mcmmo.perks.xp.quadruple.repair: true
|
||||
mcmmo.perks.xp.quadruple.smelting: true
|
||||
mcmmo.perks.xp.quadruple.spears: true
|
||||
mcmmo.perks.xp.quadruple.swords: true
|
||||
mcmmo.perks.xp.quadruple.taming: true
|
||||
mcmmo.perks.xp.quadruple.tridents: true
|
||||
@@ -2133,6 +2193,9 @@ permissions:
|
||||
mcmmo.perks.xp.quadruple.smelting:
|
||||
default: false
|
||||
description: Quadruples incoming Smelting XP
|
||||
mcmmo.perks.xp.quadruple.spears:
|
||||
default: false
|
||||
description: Quadruples incoming Spears XP
|
||||
mcmmo.perks.xp.quadruple.swords:
|
||||
default: false
|
||||
description: Quadruples incoming Swords XP
|
||||
@@ -2174,6 +2237,7 @@ permissions:
|
||||
mcmmo.perks.xp.triple.maces: true
|
||||
mcmmo.perks.xp.triple.repair: true
|
||||
mcmmo.perks.xp.triple.smelting: true
|
||||
mcmmo.perks.xp.triple.spears: true
|
||||
mcmmo.perks.xp.triple.swords: true
|
||||
mcmmo.perks.xp.triple.taming: true
|
||||
mcmmo.perks.xp.triple.tridents: true
|
||||
@@ -2215,6 +2279,9 @@ permissions:
|
||||
mcmmo.perks.xp.triple.smelting:
|
||||
default: false
|
||||
description: Triples incoming Smelting XP
|
||||
mcmmo.perks.xp.triple.spears:
|
||||
default: false
|
||||
description: Triples incoming Spears XP
|
||||
mcmmo.perks.xp.triple.swords:
|
||||
default: false
|
||||
description: Triples incoming Swords XP
|
||||
@@ -2257,6 +2324,7 @@ permissions:
|
||||
mcmmo.skills.salvage: true
|
||||
mcmmo.skills.swords: true
|
||||
mcmmo.skills.smelting: true
|
||||
mcmmo.skills.spears: true
|
||||
mcmmo.skills.taming: true
|
||||
mcmmo.skills.unarmed: true
|
||||
mcmmo.skills.woodcutting: true
|
||||
@@ -2322,6 +2390,11 @@ permissions:
|
||||
children:
|
||||
mcmmo.ability.smelting.all: 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:
|
||||
description: Allows access to the Swords skill
|
||||
children:
|
||||
|
||||
@@ -55,6 +55,9 @@ Repairables:
|
||||
WOODEN_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
WOODEN_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
WOODEN_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
@@ -74,6 +77,9 @@ Repairables:
|
||||
STONE_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
STONE_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
STONE_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
@@ -96,6 +102,12 @@ Repairables:
|
||||
ItemType: TOOL
|
||||
ItemMaterialCategory: COPPER
|
||||
RepairMaterial: COPPER_INGOT
|
||||
COPPER_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .3
|
||||
ItemType: TOOL
|
||||
ItemMaterialCategory: COPPER
|
||||
RepairMaterial: COPPER_INGOT
|
||||
COPPER_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .2
|
||||
@@ -152,6 +164,9 @@ Repairables:
|
||||
IRON_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .5
|
||||
IRON_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .5
|
||||
IRON_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .3
|
||||
@@ -190,6 +205,9 @@ Repairables:
|
||||
GOLDEN_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 4
|
||||
GOLDEN_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 4
|
||||
GOLDEN_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 2.6
|
||||
@@ -222,6 +240,9 @@ Repairables:
|
||||
DIAMOND_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .5
|
||||
DIAMOND_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .5
|
||||
DIAMOND_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .3
|
||||
@@ -255,6 +276,9 @@ Repairables:
|
||||
NETHERITE_SWORD:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .6
|
||||
NETHERITE_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .6
|
||||
NETHERITE_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .4
|
||||
|
||||
@@ -50,6 +50,10 @@ Salvageables:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
MaximumQuantity: 2
|
||||
WOODEN_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
MaximumQuantity: 1
|
||||
WOODEN_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
@@ -74,6 +78,10 @@ Salvageables:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
MaximumQuantity: 2
|
||||
STONE_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
MaximumQuantity: 1
|
||||
STONE_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .16
|
||||
@@ -98,6 +106,10 @@ Salvageables:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .4
|
||||
MaximumQuantity: 2
|
||||
COPPER_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
MaximumQuantity: 1
|
||||
COPPER_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .25
|
||||
@@ -139,6 +151,10 @@ Salvageables:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .5
|
||||
MaximumQuantity: 2
|
||||
IRON_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .3
|
||||
MaximumQuantity: 1
|
||||
IRON_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: .3
|
||||
@@ -186,6 +202,10 @@ Salvageables:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 4
|
||||
MaximumQuantity: 2
|
||||
GOLDEN_SPEAR:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 4
|
||||
MaximumQuantity: 1
|
||||
GOLDEN_SHOVEL:
|
||||
MinimumLevel: 0
|
||||
XpMultiplier: 2.6
|
||||
@@ -227,6 +247,10 @@ Salvageables:
|
||||
MinimumLevel: 50
|
||||
XpMultiplier: .5
|
||||
MaximumQuantity: 2
|
||||
DIAMOND_SPEAR:
|
||||
MinimumLevel: 50
|
||||
XpMultiplier: .5
|
||||
MaximumQuantity: 1
|
||||
DIAMOND_SHOVEL:
|
||||
MinimumLevel: 50
|
||||
XpMultiplier: .3
|
||||
@@ -268,6 +292,10 @@ Salvageables:
|
||||
MinimumLevel: 100
|
||||
XpMultiplier: .5
|
||||
MaximumQuantity: 4
|
||||
NETHERITE_SPEAR:
|
||||
MinimumLevel: 100
|
||||
XpMultiplier: .3
|
||||
MaximumQuantity: 4
|
||||
NETHERITE_SHOVEL:
|
||||
MinimumLevel: 100
|
||||
XpMultiplier: .3
|
||||
|
||||
@@ -404,6 +404,72 @@ Smelting:
|
||||
Rank_6: 750
|
||||
Rank_7: 850
|
||||
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:
|
||||
ScrapCollector:
|
||||
Standard:
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.TransientEntityTracker;
|
||||
import com.gmail.nossr50.util.blockmeta.ChunkManager;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import com.gmail.nossr50.util.player.NotificationManager;
|
||||
import com.gmail.nossr50.util.player.UserManager;
|
||||
@@ -85,19 +84,18 @@ public abstract class MMOTestEnvironment {
|
||||
protected ChunkManager chunkManager;
|
||||
protected MaterialMapStore materialMapStore;
|
||||
|
||||
protected CompatibilityManager compatibilityManager;
|
||||
protected MinecraftGameVersion minecraftGameVersion;
|
||||
|
||||
protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException {
|
||||
compatibilityManager = mock(CompatibilityManager.class);
|
||||
final MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
|
||||
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
// TODO: We should change minecraftGameVersion to be a passed in parameter instead of always returning true
|
||||
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
|
||||
mockedMcMMO = mockStatic(mcMMO.class);
|
||||
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
mcMMO.p = mock(mcMMO.class);
|
||||
when(mcMMO.p.getLogger()).thenReturn(logger);
|
||||
|
||||
// Game version
|
||||
minecraftGameVersion = mock(MinecraftGameVersion.class);
|
||||
when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true);
|
||||
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
|
||||
// place store
|
||||
chunkManager = mock(ChunkManager.class);
|
||||
when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,6 @@ import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -28,11 +27,9 @@ class PotionEffectUtilTest {
|
||||
mockedStaticMcMMO = mockStatic(mcMMO.class);
|
||||
mcMMO.p = mock(mcMMO.class);
|
||||
when(mcMMO.p.getLogger()).thenReturn(logger);
|
||||
CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
|
||||
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
|
||||
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false);
|
||||
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
@@ -8,7 +8,6 @@ import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import org.bukkit.potion.PotionType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -23,11 +22,9 @@ class PotionUtilTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mockedStaticMcMMO = mockStatic(mcMMO.class);
|
||||
CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
|
||||
MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
|
||||
when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(true);
|
||||
when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
||||
@@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.MinecraftGameVersionFactory;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -96,9 +97,8 @@ class MinecraftGameVersionTest {
|
||||
bukkit.when(Bukkit::getVersion).thenReturn(serverSoftwareVersion);
|
||||
bukkit.when(Bukkit::getBukkitVersion).thenReturn(gameVersion);
|
||||
|
||||
PlatformManager manager = new PlatformManager();
|
||||
Platform platform = manager.getPlatform();
|
||||
MinecraftGameVersion minecraftVersion = platform.getGameVersion();
|
||||
final MinecraftGameVersion minecraftVersion
|
||||
= MinecraftGameVersionFactory.calculateGameVersion(gameVersion);
|
||||
|
||||
assertEquals(major, minecraftVersion.getMajorVersion().asInt());
|
||||
assertEquals(minor, minecraftVersion.getMinorVersion().asInt());
|
||||
@@ -125,7 +125,8 @@ class MinecraftGameVersionTest {
|
||||
Arguments.of("1.14-pre5-SNAPSHOT", 1, 14, 0),
|
||||
Arguments.of("1.15-R0.1-SNAPSHOT", 1, 15, 0),
|
||||
Arguments.of("1.16.5-R0.1-SNAPSHOT", 1, 16, 5),
|
||||
Arguments.of("1.17-R0.1-SNAPSHOT", 1, 17, 0)
|
||||
Arguments.of("1.17-R0.1-SNAPSHOT", 1, 17, 0),
|
||||
Arguments.of("1.21.11-106-0d768aa", 1, 21, 11)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
350
src/test/java/com/gmail/nossr50/util/skills/SkillToolsTest.java
Normal file
350
src/test/java/com/gmail/nossr50/util/skills/SkillToolsTest.java
Normal file
@@ -0,0 +1,350 @@
|
||||
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.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;
|
||||
|
||||
@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");
|
||||
|
||||
// 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 {
|
||||
var mockGameVersion = mock(MinecraftGameVersion.class);
|
||||
when(mockGameVersion.isAtLeast(major, minor, patch))
|
||||
.thenReturn(true);
|
||||
when(mcMMO.getMinecraftGameVersion()).thenReturn(mockGameVersion);
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
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:
|
||||
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:
|
||||
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: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:
|
||||
Reference in New Issue
Block a user