1
0
mirror of https://github.com/mcMMO-Dev/mcMMO.git synced 2026-02-18 17:53:00 +01:00

Compare commits

...

75 Commits

Author SHA1 Message Date
nossr50
31d70a6072 spears update 2025-12-14 14:00:32 -08:00
nossr50
7bd4e9afe7 spears update 2025-12-14 13:58:20 -08:00
nossr50
ee94189574 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-14 13:39:03 -08:00
nossr50
a907bfd624 oops 2025-12-14 13:32:36 -08:00
nossr50
257292b6cc test number who knows 2025-12-14 13:31:21 -08:00
nossr50
2f452afdc7 try this instead part 3 2025-12-14 13:17:59 -08:00
nossr50
283c6d9771 Technically we don't need this 2025-12-14 13:08:41 -08:00
nossr50
fc62946e27 Try this instead... 2025-12-14 13:07:11 -08:00
nossr50
6b6263d0b3 Add deploy to Nexus stage 2025-12-14 13:03:51 -08:00
nossr50
f9acdeaf14 empty commit, testing webhooks 2025-12-13 16:27:09 -08:00
nossr50
5d6b499468 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-13 16:24:37 -08:00
nossr50
03bea40ad4 fix jenkins script 2025-12-13 16:21:34 -08:00
nossr50
6818d05079 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-13 16:11:09 -08:00
nossr50
401edf0bc9 no mvn wrapper 2025-12-13 16:10:58 -08:00
nossr50
cb164bb013 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-13 16:06:02 -08:00
nossr50
085197abc0 let's try a Jenkinsfile 2025-12-13 16:03:36 -08:00
nossr50
98eb706361 test 2025-12-13 15:57:29 -08:00
nossr50
09dfe4fd11 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO 2025-12-13 11:55:28 -08:00
nossr50
4f01439892 more work on the spears update 2025-12-13 11:55:13 -08:00
nossr50
1664ca005d Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-13 11:46:07 -08:00
るんく君
ced4ed2fd0 [Fix] isMagicHunterEnabled method doesn't considered the MagicHunter's permission (#5231) 2025-12-08 12:35:56 -08:00
nossr50
505352ac70 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-12-08 12:35:10 -08:00
Nadie
5c283fedb3 Change Protocollib's repo to use new namespace & group id (#5232) 2025-12-08 12:34:53 -08:00
Warrior
fae55c1edf Fix self damage awarding skill xp (#5233) 2025-12-08 12:34:09 -08:00
nossr50
4052e7e546 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO into spears 2025-11-30 13:39:59 -08:00
Tig3r98
d800aa9316 Update Italian Translation (#5230) 2025-11-30 13:37:49 -08:00
nossr50
7ac5cbf915 add spears to repair and salvage config defaults 2025-11-29 11:20:19 -08:00
nossr50
7e479049d0 spears momentum (wip pt 2) 2025-11-29 11:14:30 -08:00
nossr50
4bbdacd250 spears momentum (wip) 2025-11-28 14:33:13 -08:00
nossr50
706adb5942 add Spears to config.yml 2025-11-28 13:33:24 -08:00
nossr50
e26bb94b08 add Spears to experience.yml 2025-11-28 13:32:43 -08:00
nossr50
34f96dc687 add Spears interactions to CombatUtils 2025-11-28 13:32:35 -08:00
nossr50
461d2d4570 SkillTools refactor 2025-11-28 13:17:19 -08:00
nossr50
38396d48b4 FlatFileDatabaseManager refactor 2025-11-28 13:17:10 -08:00
nossr50
99bb38ea06 SQLDatabaseManager refactor pass 2 2025-11-27 12:42:22 -08:00
nossr50
43502b255c SQLDatabaseManager refactor pass 2025-11-27 11:57:58 -08:00
nossr50
ac9f060e79 more code coverage 2025-11-27 11:45:05 -08:00
nossr50
02ef9fad1d Spears (wip pt 2) 2025-11-27 11:31:35 -08:00
nossr50
1b28ad8f59 Spears (wip pt 1) 2025-11-25 14:31:38 -08:00
nossr50
1b49eb11b8 Spring-cleaning round 1: remove some more deprecated API invocations 2025-11-09 10:34:41 -08:00
nossr50
3533c50489 Spring-cleaning round 1: remove deprecated Player.updateInventory 2025-11-09 09:57:28 -08:00
nossr50
2a8be52be5 back to snapshots 2025-11-08 13:57:14 -08:00
nossr50
59093c5f22 2.2.045 2025-11-08 13:49:59 -08:00
nossr50
1f123a4eb2 Add missing permission nodes for copper repair and salvage Fixes #5225 2025-11-08 13:44:35 -08:00
nossr50
c96cb95443 Fixed bug where salvage and repair configs would re-add any deleted entry that existed in the default config Fixes #5223 2025-11-08 13:40:05 -08:00
nossr50
9f5994596a Fixed ageable cast class exception Fixes #5224
Fixed Herbalism not replanting certain crops
2025-11-08 13:27:53 -08:00
nossr50
ec6dce0cb2 back to snapshots 2025-11-02 12:30:55 -08:00
nossr50
80a61d2d89 2.2.044 Fix copper repair and salvage 2025-11-02 12:25:25 -08:00
nossr50
f71fe0de70 snapshots here we go 2025-10-05 13:55:04 -07:00
nossr50
eafa53e5b4 2.2.043 2025-10-05 13:46:32 -07:00
nossr50
5dfea51c5e slightly better logs 2025-10-05 13:46:13 -07:00
nossr50
00c0b2e5ec fix bug where armor stand could be renamed to heart symbols 2025-10-05 13:30:24 -07:00
nossr50
c79b3fe024 optimize imports 2025-10-05 13:19:17 -07:00
nossr50
24888d13c2 Fix potion names Fixes #5211 Fixes #5180 2025-10-05 13:18:35 -07:00
nossr50
2f624e329d misc optimization 2025-10-05 12:34:18 -07:00
nossr50
07d18e2eba 1.21.9 support for treasures.yml, experience.yml, fishing_treasures.yml, and settings for mannequins and a fix for armor stands 2025-10-05 12:27:20 -07:00
nossr50
c958a86aa3 add 1.21.9 support for repair, salvage, copper tool and armor (wip) 2025-10-04 14:20:32 -07:00
nossr50
22231dfa32 back to snapshots 2025-09-21 12:31:34 -07:00
nossr50
fdc652fd63 2.2.042 2025-09-21 12:24:42 -07:00
nossr50
c07b73d3d6 Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO 2025-09-21 12:20:06 -07:00
nossr50
d38d74f82a new event McMMOModifyBlockDropItemEvent and mcMMO now modifies the drop list in BlockDropItemEvent instead of spawning items
Fixes #5214
2025-09-21 12:19:55 -07:00
Justin
9a59200c0b Add null-safety and helper methods to AbilityAPI (#5217) 2025-09-21 10:53:32 -07:00
nossr50
8e049822a3 better phrasing 2025-08-30 12:08:14 -07:00
nossr50
06f979d7bf Reduce Blast Mining PVP damage Fixes #5213 2025-08-30 12:03:50 -07:00
nossr50
f78586675d different default for CustomSoundId in sounds.yml 2025-08-30 11:40:23 -07:00
nossr50
46bcd29998 update changelog with info about custom sound playing 2025-08-30 11:20:31 -07:00
Nathan V.
df69410e67 (Improvement) Implement playing sound by string ID (#5201)
* (improvement) implement playing sound by string ID

I've replaced enum-based sound playing events with string-based equivalents, which should open the door for server customization and other enhancements in the future

- Added SoundLookup class with different registry lookup methods depending on server version.
- Added the ability to configure what sounds are played depending on event, with a fallback built into SoundType.
- Removed getCrippleSound as SoundLookup can now fall back to the original default sound if the mace sound doesn't exist on the server's Minecraft version.
- Added a EnableCustomSounds config variable that will skip SoundLookup ID checking and just pass the sound string directly to the client, mainly due to the fact that it isn't possible to verify if resource pack values exist.
 - Cleaned up a few switch statements to match how the original getSound had it formatted.

I'd love to see/do a further expansion of sound configuration for each ability now that we can just fall back to generic, but that may be for another PR.

* Fix getIsEnabled using wrong key

* always use registry, simplify custom sound enabling logic, optimize reflection calls

* forgot we need this for legacy versions

---------

Co-authored-by: nossr50 <nossr50@gmail.com>
2025-08-30 11:15:26 -07:00
nossr50
99f7437d9d back to dev builds 2025-08-23 13:16:59 -07:00
nossr50
4bfbfa2de7 2.2.041 2025-08-23 13:12:58 -07:00
nossr50
724b66afaa expand Block Cracker to other blocks with cracked variants 2025-08-23 13:09:52 -07:00
nossr50
6ba4475a77 Fix Berserk block cracker not functioning Fixes #5207 2025-08-23 13:01:11 -07:00
nossr50
2c1c1fe53f update changelog 2025-08-23 12:38:30 -07:00
Warrior
ba673a02d0 Add early return for brewing stand hopper check (#5208) 2025-08-23 12:37:11 -07:00
handy
7cf4409c35 Add static to the method of the private class DatabaseAPI. (#5198) 2025-08-02 12:48:46 -07:00
Jake Ben-Tovim
f9513a8b40 fix(experience): parse diminished returns value from correct field (#5196) 2025-07-11 14:43:29 -07:00
101 changed files with 7846 additions and 3907 deletions

View File

@@ -1,4 +1,97 @@
Version 2.2.046
Added Spears combat skill
Added Spears to repair.vanilla.yml and salvage.vanilla.yml (see notes)
Added various permissions related to Spears
Added /spears skill command
Added Nautilus to taming XP in experience.yml
Added Camel_Husk to taming XP in experience.yml
Added Camel_Husk to combat XP in experience.yml
Added Parched to combat XP in experience.yml
Fixed bug where converting from SQL to FlatFile would not copy data for tridents, crossbows, maces, or spears
(Codebase) Added docker-based unit tests for SQL databases (see notes)
(Codebase) Large refactor to both SQLDatabaseManager and FlatFileDatabaseManager
(Codebase) Database related errors are now more descriptive and have had their logging improved
NOTES:
This update had a lot of changes behind the scenes, please report any bugs you find to our GitHub issues page!
You will need to manually update repair.vanilla.yml and salvage.vanilla.yml to get support for Spears, or...
If you want to update salvage/repair configs the easy way, you simply can delete these config files to have mcMMO regenerate them with the new entries.
If you don't want to delete them, you can find the default values for these config files in the defaults folder at plugins\mcMMO\defaults after running this mcMMO update at least once.
You can use this default file to copy paste if you please.
Docker is ONLY required for developers compiling mcMMO from source code and ONLY for running SQL-related unit tests.
mcMMO itself does NOT require Docker to run, and servers using prebuilt releases are completely unaffected.
New SQL database unit tests use Testcontainers to spin up temporary MySQL/MariaDB instances for testing purposes.
These containers are created at test time and are never used at runtime.
If you compile mcMMO locally and do not have Docker installed, SQL-related unit tests may fail.
In this case, you can safely compile with -DskipTests to skip unit tests entirely.
Skipping tests has no impact on mcMMO functionality when running on a server.
Known Issues:
I ran into an issue where having a spear in the offhand while the main hand is empty causes attacks to be incorrectly classified as unarmed. This allows unarmed abilities to apply to spear damage. As a temporary measure, Ive disabled unarmed skills from applying to combat when a spear is equipped in the offhand while I investigate a more robust solution.
Version 2.2.045
Green Thumb now replants some crops it was failing to replant before (see notes)
Green Thumb now replants harvested plants faster
Fixed an error that could happen when replanting crops with Green Thumb
Fixed a bug where salvage.vanilla.yml was readding deleted entries on server restart
Fixed a bug where repair.vanilla.yml was readding deleted entries on server restart
Added missing permission node 'mcmmo.ability.repair.copperrepair'
Added missing permission node 'mcmmo.ability.salvage.coppersalvage'
NOTES:
The delay from a plant being replanted from Green Thumb is intentional, and while looking into bugs it seemed maybe a tad slow, so I sped it up a bit.
Green Thumb still won't replant some stuff such as sugar canes, cacti, those are handled a bit differently, but I could add support for it in an upcoming patch if requested.
Version 2.2.044
Fixed copper armor and tools not working with Repair or Salvage
Version 2.2.043
Added support for the new copper tools and armor added in Minecraft 1.21.9
Added many missing buttons, trapdoors, doors, fence gates, etc to the ability/tool blacklists (see notes)
Added copper tools and armor to repair.vanilla.yml (see notes)
Added copper tools and armor to salvage.vanilla.yml (see notes)
Added copper tools and armor to fishing_treasures.yml (see notes)
Added Copper_Nugget to treasures.yml (see notes)
Added Copper_Nugget to experience.yml for Smelting XP
Added Copper_Golem to experience.yml for Combat XP
Fixed mcMMO custom potions not having their name set correctly (see notes)
Fixed ExploitFix.PreventArmorStandInteraction in experience.yml not being respected
Added ExploitFix.PreventMannequinInteraction to experience.yml to prevent mannequins from granting XP or other effects
Fixed bug where Armor Stands would get renamed to heart symbols upon breaking them (see notes)
Tweaked potions loaded msg during mcMMO startup to not include potions requiring newer game versions from being included in the total.
NOTES:
You don't need to update your experience.yml, that one updates automatically when you run mcMMO after an update.
You will need to manually update the following files manually repair.vanilla.yml, salvage.vanilla.yml, treasures.yml, and fishing_treasures.yml files to get support for copper tools and armor.
You can find the default 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
OR if you haven't customizes these config files, simply delete them to have mcMMO regenerate them with the new entries.
mcMMO has an internal blacklist of blocks that abilities and tools won't activate or "ready" on, pretty much anything that is interactable should go on this list, and I performed an audit and there were quite a few missing entries, so I've added them in this update, what this means is you won't click on a button and have it ready your tool anymore, as it should have been doing.
Mannequins are treated the same way armor stands are treated, the default behavior is mcMMO won't process on them unless you turn on the setting under ExploitFix in experience.yml, in addition to this their default XP is set to 0.0
mcMMO had a setting 'ExploitFix.PreventArmorStandInteraction' to allow mcMMO to process abilities and XP on armor stands, but it was never hooked up! I fixed that mistake in this update.
The fix for potion names will only apply to newly created potions.
Armor stands that had already been renamed from the heart symbol bug will keep their names, but the bug shouldn't happen anymore
Version 2.2.042
mcMMO now listens to BlockDropItemEvent at LOW priority instead of HIGHEST
Bonus drops from mcMMO now simply modify quantity in BlockDropItemEvent instead of spawning new ItemStacks.
Added McMMOModifyBlockDropItemEvent event, this event is called when mcMMO modifies the quantity of an ItemStack during a BlockDropItemEvent, it is modifiable and cancellable.
You can now define custom sounds to be played in sounds.yml (Thank you JeBobs, see notes)
Added a cap to how much Blast Mining PVP damage can do to other players
Notes:
The new sounds.yml config file allows you to override the sounds played by mcMMO.
Simply define the ID of the sound you want to play for each sound.
For example, add an entry for Sounds.TOOL_READY.CustomSoundId into sounds.yml to override the sound played when a tool is "readied".
If you are on older versions (1.18, 1.19, etc), instead of registering an ID, you specify the Sound enum.
Those who are on newer versions, can define the ID of any sound registered with Paper/Spigot, this allows you to even play custom sounds so long as they are properly loaded on the server.
Vanilla minecraft sounds tend to have IDs like "minecraft:ui.toast.challenge_complete", you can google what these keys are.
Version 2.2.041 Version 2.2.041
Fixed Berserk failing to crack blocks
Added 'Skills.Unarmed.Block_Cracker.Allow_Block_Cracker' to config.yml
Removed 'SmoothBrick_To_CrackedBrick', it has been replaced by `Allow_Block_Cracker`
Block Cracker can now crack deepslate bricks, deepslate tiles, polished blackstone bricks, and netherbricks
Optimizations for Hoppers & Alchemy (thanks Warriorrrr)
Fixed buckets being consumed by furnaces (thanks RunqRun) Fixed buckets being consumed by furnaces (thanks RunqRun)
Fixed Repair stripping unsafe enchantments from items (thanks Techirion) Fixed Repair stripping unsafe enchantments from items (thanks Techirion)
Fixed IronGolem causing cast exceptions in rare cases (thanks Techirion) Fixed IronGolem causing cast exceptions in rare cases (thanks Techirion)

43
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,43 @@
pipeline {
agent any
tools {
jdk 'jdk17'
// If you configured Maven as a Jenkins tool, add:
// maven 'Maven3'
}
options {
timestamps()
disableConcurrentBuilds()
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn -V -B clean package'
}
}
stage('Deploy to Nexus') {
steps {
configFileProvider([configFile(fileId: 'maven-settings-nexus', variable: 'MAVEN_SETTINGS')]) {
sh 'mvn -s "$MAVEN_SETTINGS" -V -B deploy'
}
}
}
}
post {
success {
archiveArtifacts artifacts: 'target/mcMMO.jar', fingerprint: true
}
}
}

View File

@@ -23,7 +23,7 @@ If you are using maven, you can add mcMMO API to your plugin by adding it to pom
<dependency> <dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId> <groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId> <artifactId>mcMMO</artifactId>
<version>2.2.004</version> <version>put-the-version-here</version>
</dependency> </dependency>
``` ```
### Builds ### Builds

120
pom.xml
View File

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

View File

@@ -7,41 +7,46 @@ import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@SuppressWarnings("unused")
public final class AbilityAPI { public final class AbilityAPI {
private AbilityAPI() { private AbilityAPI() {
} }
public static boolean berserkEnabled(Player player) { public static boolean berserkEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.BERSERK); return hasAbilityEnabled(player, SuperAbilityType.BERSERK);
} }
public static boolean gigaDrillBreakerEnabled(Player player) { public static boolean gigaDrillBreakerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER); return hasAbilityEnabled(player, SuperAbilityType.GIGA_DRILL_BREAKER);
} }
public static boolean greenTerraEnabled(Player player) { public static boolean greenTerraEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.GREEN_TERRA); return hasAbilityEnabled(player, SuperAbilityType.GREEN_TERRA);
} }
public static boolean serratedStrikesEnabled(Player player) { public static boolean serratedStrikesEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SERRATED_STRIKES); return hasAbilityEnabled(player, SuperAbilityType.SERRATED_STRIKES);
} }
public static boolean skullSplitterEnabled(Player player) { public static boolean skullSplitterEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SKULL_SPLITTER); return hasAbilityEnabled(player, SuperAbilityType.SKULL_SPLITTER);
} }
public static boolean superBreakerEnabled(Player player) { public static boolean superBreakerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.SUPER_BREAKER); return hasAbilityEnabled(player, SuperAbilityType.SUPER_BREAKER);
} }
public static boolean treeFellerEnabled(Player player) { public static boolean treeFellerEnabled(Player player) {
return UserManager.getPlayer(player).getAbilityMode(SuperAbilityType.TREE_FELLER); return hasAbilityEnabled(player, SuperAbilityType.TREE_FELLER);
} }
public static boolean isAnyAbilityEnabled(Player player) { public static boolean isAnyAbilityEnabled(Player player) {
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player); final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
if(mmoPlayer == null) {
return false;
}
for (SuperAbilityType ability : SuperAbilityType.values()) { for (SuperAbilityType ability : SuperAbilityType.values()) {
if (mmoPlayer.getAbilityMode(ability)) { if (mmoPlayer.getAbilityMode(ability)) {
return true; return true;
@@ -51,36 +56,57 @@ public final class AbilityAPI {
return false; return false;
} }
private static boolean hasAbilityEnabled(Player player, SuperAbilityType ability) {
McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
return mmoPlayer != null && mmoPlayer.getAbilityMode(ability);
}
public static void resetCooldowns(Player player) { public static void resetCooldowns(Player player) {
UserManager.getPlayer(player).resetCooldowns(); McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
if(mmoPlayer == null) {
return;
}
mmoPlayer.resetCooldowns();
} }
public static void setBerserkCooldown(Player player, long cooldown) { public static void setBerserkCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.BERSERK, cooldown); setAbilityCooldown(player, SuperAbilityType.BERSERK, cooldown);
} }
public static void setGigaDrillBreakerCooldown(Player player, long cooldown) { public static void setGigaDrillBreakerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.GIGA_DRILL_BREAKER, cooldown); setAbilityCooldown(player, SuperAbilityType.GIGA_DRILL_BREAKER, cooldown);
} }
public static void setGreenTerraCooldown(Player player, long cooldown) { public static void setGreenTerraCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.GREEN_TERRA, cooldown); setAbilityCooldown(player, SuperAbilityType.GREEN_TERRA, cooldown);
} }
public static void setSerratedStrikesCooldown(Player player, long cooldown) { public static void setSerratedStrikesCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SERRATED_STRIKES, cooldown); setAbilityCooldown(player, SuperAbilityType.SERRATED_STRIKES, cooldown);
} }
public static void setSkullSplitterCooldown(Player player, long cooldown) { public static void setSkullSplitterCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SKULL_SPLITTER, cooldown); setAbilityCooldown(player, SuperAbilityType.SKULL_SPLITTER, cooldown);
} }
public static void setSuperBreakerCooldown(Player player, long cooldown) { public static void setSuperBreakerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.SUPER_BREAKER, cooldown); setAbilityCooldown(player, SuperAbilityType.SUPER_BREAKER, cooldown);
} }
public static void setTreeFellerCooldown(Player player, long cooldown) { public static void setTreeFellerCooldown(Player player, long cooldown) {
UserManager.getPlayer(player).setAbilityDATS(SuperAbilityType.TREE_FELLER, cooldown); setAbilityCooldown(player, SuperAbilityType.TREE_FELLER, cooldown);
}
private static void setAbilityCooldown(Player player, SuperAbilityType ability, long cooldown) {
McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
if(mmoPlayer == null) {
return;
}
mmoPlayer.setAbilityDATS(ability, cooldown);
} }
public static boolean isBleeding(LivingEntity entity) { public static boolean isBleeding(LivingEntity entity) {

View File

@@ -16,7 +16,7 @@ public class DatabaseAPI {
* @param offlinePlayer target player * @param offlinePlayer target player
* @return true if the player exists in the DB, false if they do not * @return true if the player exists in the DB, false if they do not
*/ */
public boolean doesPlayerExistInDB(@NotNull OfflinePlayer offlinePlayer) { public static boolean doesPlayerExistInDB(@NotNull OfflinePlayer offlinePlayer) {
PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(offlinePlayer); PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(offlinePlayer);
return playerProfile.isLoaded(); return playerProfile.isLoaded();
@@ -28,7 +28,7 @@ public class DatabaseAPI {
* @param uuid target player * @param uuid target player
* @return true if the player exists in the DB, false if they do not * @return true if the player exists in the DB, false if they do not
*/ */
public boolean doesPlayerExistInDB(@NotNull UUID uuid) { public static boolean doesPlayerExistInDB(@NotNull UUID uuid) {
PlayerProfile playerProfile = null; PlayerProfile playerProfile = null;
try { try {
playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(uuid); playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(uuid);
@@ -45,7 +45,7 @@ public class DatabaseAPI {
* @param playerName target player * @param playerName target player
* @return true if the player exists in the DB, false if they do not * @return true if the player exists in the DB, false if they do not
*/ */
public boolean doesPlayerExistInDB(@NotNull String playerName) { public static boolean doesPlayerExistInDB(@NotNull String playerName) {
PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName); PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName);
return playerProfile.isLoaded(); return playerProfile.isLoaded();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -8,12 +8,13 @@ import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class BukkitConfig { public abstract class BukkitConfig {
boolean copyDefaults = true; boolean copyDefaults;
protected final String fileName; protected final String fileName;
protected final File configFile; protected final File configFile;
protected YamlConfiguration defaultYamlConfig; protected YamlConfiguration defaultYamlConfig;
@@ -58,7 +59,7 @@ public abstract class BukkitConfig {
savedDefaults = true; savedDefaults = true;
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); mcMMO.p.getLogger().log(Level.SEVERE, "Unable to save config file: " + fileName, e);
} }
} }

View File

@@ -424,10 +424,6 @@ public class GeneralConfig extends BukkitConfig {
return config.getBoolean("MySQL.Server.SSL", true); return config.getBoolean("MySQL.Server.SSL", true);
} }
public boolean getMySQLDebug() {
return config.getBoolean("MySQL.Debug", false);
}
public boolean getMySQLPublicKeyRetrieval() { public boolean getMySQLPublicKeyRetrieval() {
return config.getBoolean("MySQL.Server.allowPublicKeyRetrieval", true); return config.getBoolean("MySQL.Server.allowPublicKeyRetrieval", true);
} }
@@ -872,8 +868,8 @@ public class GeneralConfig extends BukkitConfig {
} }
/* Unarmed */ /* Unarmed */
public boolean getUnarmedBlockCrackerSmoothbrickToCracked() { public boolean isBlockCrackerAllowed() {
return config.getBoolean("Skills.Unarmed.Block_Cracker.SmoothBrick_To_CrackedBrick", true); return config.getBoolean("Skills.Unarmed.Block_Cracker.Allow_Block_Cracker", true);
} }
public boolean getUnarmedItemPickupDisabled() { public boolean getUnarmedItemPickupDisabled() {

View File

@@ -29,7 +29,7 @@ public class SoundConfig extends BukkitConfig {
@Override @Override
protected boolean validateKeys() { protected boolean validateKeys() {
for (SoundType soundType : SoundType.values()) { for (SoundType soundType : SoundType.values()) {
if (config.getDouble("Sounds." + soundType.toString() + ".Volume") < 0) { if (config.getDouble("Sounds." + soundType + ".Volume") < 0) {
LogUtils.debug(mcMMO.p.getLogger(), LogUtils.debug(mcMMO.p.getLogger(),
"[mcMMO] Sound volume cannot be below 0 for " + soundType); "[mcMMO] Sound volume cannot be below 0 for " + soundType);
return false; return false;
@@ -52,17 +52,22 @@ public class SoundConfig extends BukkitConfig {
} }
public float getVolume(SoundType soundType) { public float getVolume(SoundType soundType) {
String key = "Sounds." + soundType.toString() + ".Volume"; String key = "Sounds." + soundType + ".Volume";
return (float) config.getDouble(key, 1.0); return (float) config.getDouble(key, 1.0);
} }
public float getPitch(SoundType soundType) { public float getPitch(SoundType soundType) {
String key = "Sounds." + soundType.toString() + ".Pitch"; String key = "Sounds." + soundType + ".Pitch";
return (float) config.getDouble(key, 1.0); return (float) config.getDouble(key, 1.0);
} }
public String getSound(SoundType soundType) {
final String key = "Sounds." + soundType + ".CustomSoundId";
return config.getString(key);
}
public boolean getIsEnabled(SoundType soundType) { public boolean getIsEnabled(SoundType soundType) {
String key = "Sounds." + soundType.toString() + ".Enabled"; String key = "Sounds." + soundType + ".Enable";
return config.getBoolean(key, true); return config.getBoolean(key, true);
} }
} }

View File

@@ -201,6 +201,10 @@ public class ExperienceConfig extends BukkitConfig {
return config.getBoolean("ExploitFix.PreventArmorStandInteraction", true); return config.getBoolean("ExploitFix.PreventArmorStandInteraction", true);
} }
public boolean isMannequinInteractionPrevented() {
return config.getBoolean("ExploitFix.PreventMannequinInteraction", true);
}
public boolean isFishingExploitingPrevented() { public boolean isFishingExploitingPrevented() {
return config.getBoolean("ExploitFix.Fishing", true); return config.getBoolean("ExploitFix.Fishing", true);
} }
@@ -298,7 +302,7 @@ public class ExperienceConfig extends BukkitConfig {
/* Diminished Returns */ /* Diminished Returns */
public float getDiminishedReturnsCap() { public float getDiminishedReturnsCap() {
return (float) config.getDouble("Dimished_Returns.Guaranteed_Minimum_Percentage", 0.05D); return (float) config.getDouble("Diminished_Returns.Guaranteed_Minimum_Percentage", 0.05D);
} }
public boolean getDiminishedReturnsEnabled() { public boolean getDiminishedReturnsEnabled() {

View File

@@ -1,6 +1,6 @@
package com.gmail.nossr50.config.skills.alchemy; package com.gmail.nossr50.config.skills.alchemy;
import static com.gmail.nossr50.util.ItemUtils.setItemName; import static com.gmail.nossr50.util.ItemUtils.customName;
import static com.gmail.nossr50.util.PotionUtil.matchPotionType; import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
import static com.gmail.nossr50.util.PotionUtil.setBasePotionType; import static com.gmail.nossr50.util.PotionUtil.setBasePotionType;
import static com.gmail.nossr50.util.PotionUtil.setUpgradedAndExtendedProperties; import static com.gmail.nossr50.util.PotionUtil.setUpgradedAndExtendedProperties;
@@ -15,6 +15,9 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.Material; import org.bukkit.Material;
@@ -158,7 +161,7 @@ public class PotionConfig extends LegacyConfigLoader {
} }
} }
int totalPotions = potionsLoaded + incompatible + failures; int totalPotions = potionsLoaded + failures;
mcMMO.p.getLogger() mcMMO.p.getLogger()
.info("Loaded " + potionsLoaded + " of " + totalPotions + " Alchemy potions."); .info("Loaded " + potionsLoaded + " of " + totalPotions + " Alchemy potions.");
@@ -369,7 +372,9 @@ public class PotionConfig extends LegacyConfigLoader {
final String configuredName = section.getString("Name", null); final String configuredName = section.getString("Name", null);
if (configuredName != null) { if (configuredName != null) {
setItemName(potionMeta, configuredName); final TextComponent textComponent = Component.text(configuredName)
.decoration(TextDecoration.ITALIC, false);
customName(potionMeta, textComponent, configuredName);
} }
} }

View File

@@ -1,5 +1,20 @@
package com.gmail.nossr50.config.skills.repair; package com.gmail.nossr50.config.skills.repair;
import static com.gmail.nossr50.util.ItemUtils.isCopperArmor;
import static com.gmail.nossr50.util.ItemUtils.isCopperTool;
import static com.gmail.nossr50.util.ItemUtils.isDiamondArmor;
import static com.gmail.nossr50.util.ItemUtils.isDiamondTool;
import static com.gmail.nossr50.util.ItemUtils.isGoldArmor;
import static com.gmail.nossr50.util.ItemUtils.isGoldTool;
import static com.gmail.nossr50.util.ItemUtils.isIronArmor;
import static com.gmail.nossr50.util.ItemUtils.isIronTool;
import static com.gmail.nossr50.util.ItemUtils.isLeatherArmor;
import static com.gmail.nossr50.util.ItemUtils.isNetheriteArmor;
import static com.gmail.nossr50.util.ItemUtils.isNetheriteTool;
import static com.gmail.nossr50.util.ItemUtils.isStoneTool;
import static com.gmail.nossr50.util.ItemUtils.isStringTool;
import static com.gmail.nossr50.util.ItemUtils.isWoodTool;
import com.gmail.nossr50.config.BukkitConfig; import com.gmail.nossr50.config.BukkitConfig;
import com.gmail.nossr50.datatypes.skills.ItemType; import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.MaterialType; import com.gmail.nossr50.datatypes.skills.MaterialType;
@@ -13,6 +28,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Level;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -62,27 +78,27 @@ public class RepairConfig extends BukkitConfig {
String repairMaterialTypeString = config.getString( String repairMaterialTypeString = config.getString(
"Repairables." + key + ".MaterialType", "OTHER"); "Repairables." + key + ".MaterialType", "OTHER");
if (!config.contains("Repairables." + key + ".MaterialType") && itemMaterial != null) { if (!config.contains("Repairables." + key + ".MaterialType")) {
ItemStack repairItem = new ItemStack(itemMaterial); final ItemStack repairItem = new ItemStack(itemMaterial);
if (ItemUtils.isWoodTool(repairItem)) { if (isWoodTool(repairItem)) {
repairMaterialType = MaterialType.WOOD; repairMaterialType = MaterialType.WOOD;
} else if (ItemUtils.isStoneTool(repairItem)) { } else if (isStoneTool(repairItem)) {
repairMaterialType = MaterialType.STONE; repairMaterialType = MaterialType.STONE;
} else if (ItemUtils.isStringTool(repairItem)) { } else if (isStringTool(repairItem)) {
repairMaterialType = MaterialType.STRING; repairMaterialType = MaterialType.STRING;
} else if (ItemUtils.isLeatherArmor(repairItem)) { } else if (isLeatherArmor(repairItem)) {
repairMaterialType = MaterialType.LEATHER; repairMaterialType = MaterialType.LEATHER;
} else if (ItemUtils.isIronArmor(repairItem) || ItemUtils.isIronTool(repairItem)) { } else if (isIronArmor(repairItem) || isIronTool(repairItem)) {
repairMaterialType = MaterialType.IRON; repairMaterialType = MaterialType.IRON;
} else if (ItemUtils.isGoldArmor(repairItem) || ItemUtils.isGoldTool(repairItem)) { } else if (isGoldArmor(repairItem) || isGoldTool(repairItem)) {
repairMaterialType = MaterialType.GOLD; repairMaterialType = MaterialType.GOLD;
} else if (ItemUtils.isDiamondArmor(repairItem) || ItemUtils.isDiamondTool( } else if (isDiamondArmor(repairItem) || isDiamondTool(repairItem)) {
repairItem)) {
repairMaterialType = MaterialType.DIAMOND; repairMaterialType = MaterialType.DIAMOND;
} else if (ItemUtils.isNetheriteArmor(repairItem) || ItemUtils.isNetheriteTool( } else if (isNetheriteArmor(repairItem) || isNetheriteTool(repairItem)) {
repairItem)) {
repairMaterialType = MaterialType.NETHERITE; repairMaterialType = MaterialType.NETHERITE;
} else if (isCopperTool(repairItem) || isCopperArmor(repairItem)) {
repairMaterialType = MaterialType.COPPER;
} }
} else { } else {
try { try {
@@ -104,9 +120,7 @@ public class RepairConfig extends BukkitConfig {
} }
// Maximum Durability // Maximum Durability
short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() short maximumDurability = itemMaterial.getMaxDurability();
: (short) config.getInt(
"Repairables." + key + ".MaximumDurability"));
if (maximumDurability <= 0) { if (maximumDurability <= 0) {
maximumDurability = (short) config.getInt( maximumDurability = (short) config.getInt(
@@ -153,17 +167,22 @@ public class RepairConfig extends BukkitConfig {
} }
if (noErrorsInRepairable(reason)) { if (noErrorsInRepairable(reason)) {
Repairable repairable = RepairableFactory.getRepairable( try {
final Repairable repairable = RepairableFactory.getRepairable(
itemMaterial, repairMaterial, null, minimumLevel, maximumDurability, itemMaterial, repairMaterial, null, minimumLevel, maximumDurability,
repairItemType, repairItemType,
repairMaterialType, xpMultiplier, minimumQuantity); repairMaterialType, xpMultiplier, minimumQuantity);
repairables.add(repairable); repairables.add(repairable);
} catch (Exception e) {
mcMMO.p.getLogger().log(Level.SEVERE,
"Error loading repairable from config entry: " + key, e);
}
} }
} }
//Report unsupported //Report unsupported
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
if (notSupported.size() > 0) { if (!notSupported.isEmpty()) {
stringBuilder.append( stringBuilder.append(
"mcMMO found the following materials in the Repair config that are not supported by the version of Minecraft running on this server: "); "mcMMO found the following materials in the Repair config that are not supported by the version of Minecraft running on this server: ");

View File

@@ -15,7 +15,7 @@ public class RepairConfigManager {
Pattern pattern = Pattern.compile("repair\\.(?:.+)\\.yml"); Pattern pattern = Pattern.compile("repair\\.(?:.+)\\.yml");
File dataFolder = plugin.getDataFolder(); File dataFolder = plugin.getDataFolder();
RepairConfig mainRepairConfig = new RepairConfig(REPAIR_VANILLA_YML, true); RepairConfig mainRepairConfig = new RepairConfig(REPAIR_VANILLA_YML, false);
repairables.addAll(mainRepairConfig.getLoadedRepairables()); repairables.addAll(mainRepairConfig.getLoadedRepairables());
for (String fileName : dataFolder.list()) { for (String fileName : dataFolder.list()) {

View File

@@ -1,5 +1,21 @@
package com.gmail.nossr50.config.skills.salvage; package com.gmail.nossr50.config.skills.salvage;
import static com.gmail.nossr50.util.ItemUtils.isCopperArmor;
import static com.gmail.nossr50.util.ItemUtils.isCopperTool;
import static com.gmail.nossr50.util.ItemUtils.isDiamondArmor;
import static com.gmail.nossr50.util.ItemUtils.isDiamondTool;
import static com.gmail.nossr50.util.ItemUtils.isGoldArmor;
import static com.gmail.nossr50.util.ItemUtils.isGoldTool;
import static com.gmail.nossr50.util.ItemUtils.isIronArmor;
import static com.gmail.nossr50.util.ItemUtils.isIronTool;
import static com.gmail.nossr50.util.ItemUtils.isLeatherArmor;
import static com.gmail.nossr50.util.ItemUtils.isNetheriteArmor;
import static com.gmail.nossr50.util.ItemUtils.isNetheriteTool;
import static com.gmail.nossr50.util.ItemUtils.isPrismarineTool;
import static com.gmail.nossr50.util.ItemUtils.isStoneTool;
import static com.gmail.nossr50.util.ItemUtils.isStringTool;
import static com.gmail.nossr50.util.ItemUtils.isWoodTool;
import com.gmail.nossr50.config.BukkitConfig; import com.gmail.nossr50.config.BukkitConfig;
import com.gmail.nossr50.datatypes.database.UpgradeType; import com.gmail.nossr50.datatypes.database.UpgradeType;
import com.gmail.nossr50.datatypes.skills.ItemType; import com.gmail.nossr50.datatypes.skills.ItemType;
@@ -27,8 +43,8 @@ public class SalvageConfig extends BukkitConfig {
private final HashSet<String> notSupported; private final HashSet<String> notSupported;
private Set<Salvageable> salvageables; private Set<Salvageable> salvageables;
public SalvageConfig(String fileName, boolean copyDefaults) { public SalvageConfig(String fileName) {
super(fileName, copyDefaults); super(fileName, false);
notSupported = new HashSet<>(); notSupported = new HashSet<>();
loadKeys(); loadKeys();
} }
@@ -50,9 +66,9 @@ public class SalvageConfig extends BukkitConfig {
mcMMO.p.getLogger().log( mcMMO.p.getLogger().log(
Level.INFO, Level.INFO,
"Fixing incorrect Salvage quantities on Netherite gear, this will only run once..."); "Fixing incorrect Salvage quantities on Netherite gear, this will only run once...");
for (String namespacedkey : mcMMO.getMaterialMapStore().getNetheriteArmor()) { for (String namespacedKey : mcMMO.getMaterialMapStore().getNetheriteArmor()) {
config.set( config.set(
"Salvageables." + namespacedkey.toUpperCase(Locale.ENGLISH) "Salvageables." + namespacedKey.toUpperCase(Locale.ENGLISH)
+ ".MaximumQuantity", + ".MaximumQuantity",
4); //TODO: Doesn't make sense to default to 4 for everything 4); //TODO: Doesn't make sense to default to 4 for everything
} }
@@ -64,10 +80,9 @@ public class SalvageConfig extends BukkitConfig {
LogUtils.debug(mcMMO.p.getLogger(), LogUtils.debug(mcMMO.p.getLogger(),
"Fixed incorrect Salvage quantities for Netherite gear!"); "Fixed incorrect Salvage quantities for Netherite gear!");
} catch (IOException e) { } catch (IOException e) {
LogUtils.debug( mcMMO.p.getLogger().log(Level.SEVERE,
mcMMO.p.getLogger(), "Unable to fix Salvage config, please delete the salvage yml file"
"Unable to fix Salvage config, please delete the salvage yml file to generate a new one."); + " to generate a new one.", e);
e.printStackTrace();
} }
} }
@@ -85,34 +100,32 @@ public class SalvageConfig extends BukkitConfig {
// Salvage Material Type // Salvage Material Type
MaterialType salvageMaterialType = MaterialType.OTHER; MaterialType salvageMaterialType = MaterialType.OTHER;
String salvageMaterialTypeString = config.getString( final String salvageMaterialTypeString = config.getString(
"Salvageables." + key + ".MaterialType", "OTHER"); "Salvageables." + key + ".MaterialType", "OTHER");
if (!config.contains("Salvageables." + key + ".MaterialType") && itemMaterial != null) { if (!config.contains("Salvageables." + key + ".MaterialType")) {
ItemStack salvageItem = new ItemStack(itemMaterial); final ItemStack salvageItem = new ItemStack(itemMaterial);
if (ItemUtils.isWoodTool(salvageItem)) { if (isWoodTool(salvageItem)) {
salvageMaterialType = MaterialType.WOOD; salvageMaterialType = MaterialType.WOOD;
} else if (ItemUtils.isStoneTool(salvageItem)) { } else if (isStoneTool(salvageItem)) {
salvageMaterialType = MaterialType.STONE; salvageMaterialType = MaterialType.STONE;
} else if (ItemUtils.isStringTool(salvageItem)) { } else if (isStringTool(salvageItem)) {
salvageMaterialType = MaterialType.STRING; salvageMaterialType = MaterialType.STRING;
} else if (ItemUtils.isPrismarineTool(salvageItem)) { } else if (isPrismarineTool(salvageItem)) {
salvageMaterialType = MaterialType.PRISMARINE; salvageMaterialType = MaterialType.PRISMARINE;
} else if (ItemUtils.isLeatherArmor(salvageItem)) { } else if (isLeatherArmor(salvageItem)) {
salvageMaterialType = MaterialType.LEATHER; salvageMaterialType = MaterialType.LEATHER;
} else if (ItemUtils.isIronArmor(salvageItem) || ItemUtils.isIronTool( } else if (isIronArmor(salvageItem) || isIronTool(salvageItem)) {
salvageItem)) {
salvageMaterialType = MaterialType.IRON; salvageMaterialType = MaterialType.IRON;
} else if (ItemUtils.isGoldArmor(salvageItem) || ItemUtils.isGoldTool( } else if (isGoldArmor(salvageItem) || isGoldTool(salvageItem)) {
salvageItem)) {
salvageMaterialType = MaterialType.GOLD; salvageMaterialType = MaterialType.GOLD;
} else if (ItemUtils.isDiamondArmor(salvageItem) || ItemUtils.isDiamondTool( } else if (isDiamondArmor(salvageItem) || isDiamondTool(salvageItem)) {
salvageItem)) {
salvageMaterialType = MaterialType.DIAMOND; salvageMaterialType = MaterialType.DIAMOND;
} else if (ItemUtils.isNetheriteTool(salvageItem) || ItemUtils.isNetheriteArmor( } else if (isNetheriteTool(salvageItem) || isNetheriteArmor(salvageItem)) {
salvageItem)) {
salvageMaterialType = MaterialType.NETHERITE; salvageMaterialType = MaterialType.NETHERITE;
} else if (isCopperTool(salvageItem) || isCopperArmor(salvageItem)) {
salvageMaterialType = MaterialType.COPPER;
} }
} else { } else {
try { try {
@@ -120,14 +133,12 @@ public class SalvageConfig extends BukkitConfig {
salvageMaterialTypeString.replace(" ", "_") salvageMaterialTypeString.replace(" ", "_")
.toUpperCase(Locale.ENGLISH)); .toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
reason.add( reason.add(key + " has an invalid MaterialType of " + salvageMaterialTypeString);
key + " has an invalid MaterialType of " + salvageMaterialTypeString);
} }
} }
// Salvage Material // Salvage Material
String salvageMaterialName = config.getString( String salvageMaterialName = config.getString("Salvageables." + key + ".SalvageMaterial");
"Salvageables." + key + ".SalvageMaterial");
Material salvageMaterial = (salvageMaterialName == null Material salvageMaterial = (salvageMaterialName == null
? salvageMaterialType.getDefaultMaterial() ? salvageMaterialType.getDefaultMaterial()
: Material.matchMaterial(salvageMaterialName)); : Material.matchMaterial(salvageMaterialName));
@@ -138,16 +149,14 @@ public class SalvageConfig extends BukkitConfig {
} }
// Maximum Durability // Maximum Durability
short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() short maximumDurability = itemMaterial.getMaxDurability();
: (short) config.getInt(
"Salvageables." + key + ".MaximumDurability"));
// Item Type // Item Type
ItemType salvageItemType = ItemType.OTHER; ItemType salvageItemType = ItemType.OTHER;
String salvageItemTypeString = config.getString("Salvageables." + key + ".ItemType", String salvageItemTypeString = config.getString("Salvageables." + key + ".ItemType",
"OTHER"); "OTHER");
if (!config.contains("Salvageables." + key + ".ItemType") && itemMaterial != null) { if (!config.contains("Salvageables." + key + ".ItemType")) {
ItemStack salvageItem = new ItemStack(itemMaterial); ItemStack salvageItem = new ItemStack(itemMaterial);
if (ItemUtils.isMinecraftTool(salvageItem)) { if (ItemUtils.isMinecraftTool(salvageItem)) {
@@ -172,11 +181,11 @@ public class SalvageConfig extends BukkitConfig {
} }
// Maximum Quantity // Maximum Quantity
int maximumQuantity = itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities( int maximumQuantity = SkillUtils.getRepairAndSalvageQuantities(
itemMaterial, itemMaterial,
salvageMaterial) : config.getInt("Salvageables." + key + ".MaximumQuantity", 1); salvageMaterial);
if (maximumQuantity <= 0 && itemMaterial != null) { if (maximumQuantity <= 0) {
maximumQuantity = config.getInt("Salvageables." + key + ".MaximumQuantity", 1); maximumQuantity = config.getInt("Salvageables." + key + ".MaximumQuantity", 1);
} }
@@ -192,17 +201,23 @@ public class SalvageConfig extends BukkitConfig {
} }
if (noErrorsInSalvageable(reason)) { if (noErrorsInSalvageable(reason)) {
Salvageable salvageable = SalvageableFactory.getSalvageable( try {
final Salvageable salvageable = SalvageableFactory.getSalvageable(
itemMaterial, salvageMaterial, minimumLevel, itemMaterial, salvageMaterial, minimumLevel,
maximumQuantity, maximumDurability, salvageItemType, salvageMaterialType, maximumQuantity, maximumDurability, salvageItemType,
salvageMaterialType,
xpMultiplier); xpMultiplier);
salvageables.add(salvageable); salvageables.add(salvageable);
} catch (Exception e) {
mcMMO.p.getLogger().log(Level.SEVERE,
"Error loading salvageable from config entry: " + key, e);
}
} }
} }
//Report unsupported //Report unsupported
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
if (notSupported.size() > 0) { if (!notSupported.isEmpty()) {
stringBuilder.append( stringBuilder.append(
"mcMMO found the following materials in the Salvage config that are not supported by the version of Minecraft running on this server: "); "mcMMO found the following materials in the Salvage config that are not supported by the version of Minecraft running on this server: ");

View File

@@ -16,7 +16,7 @@ public class SalvageConfigManager {
Pattern pattern = Pattern.compile("salvage\\.(?:.+)\\.yml"); Pattern pattern = Pattern.compile("salvage\\.(?:.+)\\.yml");
File dataFolder = plugin.getDataFolder(); File dataFolder = plugin.getDataFolder();
SalvageConfig mainSalvageConfig = new SalvageConfig(SALVAGE_VANILLA_YML, true); SalvageConfig mainSalvageConfig = new SalvageConfig(SALVAGE_VANILLA_YML);
salvageables.addAll(mainSalvageConfig.getLoadedSalvageables()); salvageables.addAll(mainSalvageConfig.getLoadedSalvageables());
for (String fileName : dataFolder.list()) { for (String fileName : dataFolder.list()) {
@@ -34,7 +34,7 @@ public class SalvageConfigManager {
continue; continue;
} }
SalvageConfig salvageConfig = new SalvageConfig(fileName, false); SalvageConfig salvageConfig = new SalvageConfig(fileName);
salvageables.addAll(salvageConfig.getLoadedSalvageables()); salvageables.addAll(salvageConfig.getLoadedSalvageables());
} }
} }

View File

@@ -99,7 +99,10 @@ public class TreasureConfig extends BukkitConfig {
type + "." + treasureName + ".Data"); type + "." + treasureName + ".Data");
if (material == null) { if (material == null) {
reason.add("Invalid material: " + materialName); LogUtils.debug(mcMMO.p.getLogger(),
String.format("Material '%s' for treasure '%s' is not recognized."
+ " Skipping...", materialName, treasureName));
continue;
} }
if (amount <= 0) { if (amount <= 0) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,16 @@
package com.gmail.nossr50.datatypes.experience; package com.gmail.nossr50.datatypes.experience;
public enum XPGainSource { public enum XPGainSource {
/** From direct sources, either your own actions or actions done to you. */
SELF, SELF,
/** From Vampirism Kills */
VAMPIRISM, //From Vampirism kills VAMPIRISM, //From Vampirism kills
/** From Smelting, Brewing, etc... */
PASSIVE, //Smelting, Brewing, etc... PASSIVE, //Smelting, Brewing, etc...
/** From shared XP from party members */
PARTY_MEMBERS, //From other members of a party PARTY_MEMBERS, //From other members of a party
/** From commands or API */
COMMAND, COMMAND,
/** Uncategorized, Other Plugins, etc... */
CUSTOM, //Outside Sources CUSTOM, //Outside Sources
} }

View File

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

View File

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

View File

@@ -8,6 +8,7 @@ public enum MaterialType {
WOOD, WOOD,
STONE, STONE,
IRON, IRON,
COPPER,
GOLD, GOLD,
DIAMOND, DIAMOND,
NETHERITE, NETHERITE,
@@ -45,6 +46,8 @@ public enum MaterialType {
} }
case PRISMARINE: case PRISMARINE:
return Material.PRISMARINE_CRYSTALS; return Material.PRISMARINE_CRYSTALS;
case COPPER:
return Material.COPPER_INGOT;
case OTHER: case OTHER:
default: default:

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,226 @@
package com.gmail.nossr50.events.items;
import static java.util.Objects.requireNonNull;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockDropItemEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when mcMMO is modifying the amount of bonus drops to add to an Item involved in a {@link BlockDropItemEvent}.
* <p>
* This event is called before mcMMO has modified the ItemStack quantity on the {@link Item} entity.
* <p>
* This event is called once per Item entity that is involved in the {@link BlockDropItemEvent}.
* <p>
* This event is called during mcMMO logic on the {@link BlockDropItemEvent}, and can be used to
* modify the quantity that mcMMO will add to the ItemStack.
* <p>
* This event is considered cancelled if it is either cancelled directly or if bonus drops are 0 or
* less.
*/
public class McMMOModifyBlockDropItemEvent extends Event implements Cancellable {
private final @NotNull BlockDropItemEvent blockDropItemEvent;
private final int originalBonusAmountToAdd;
private int modifiedItemStackQuantity;
private final @NotNull Item itemThatHasBonusDrops;
private boolean isCancelled = false;
private final int originalItemStackQuantity;
public McMMOModifyBlockDropItemEvent(@NotNull BlockDropItemEvent blockDropItemEvent,
@NotNull Item itemThatHasBonusDrops, int bonusDropsToAdd) {
super(false);
requireNonNull(blockDropItemEvent, "blockDropItemEvent cannot be null");
requireNonNull(itemThatHasBonusDrops, "itemThatHasBonusDrops cannot be null");
if (bonusDropsToAdd <= 0) {
throw new IllegalArgumentException("cannot instantiate a new"
+ " McMMOModifyBlockDropItemEvent with a bonusDropsToAdd that is <= 0");
}
this.blockDropItemEvent = blockDropItemEvent;
this.itemThatHasBonusDrops = itemThatHasBonusDrops;
this.originalItemStackQuantity = itemThatHasBonusDrops.getItemStack().getAmount();
this.originalBonusAmountToAdd = bonusDropsToAdd;
this.modifiedItemStackQuantity = itemThatHasBonusDrops.getItemStack().getAmount()
+ bonusDropsToAdd;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.isCancelled = cancel;
}
/**
* The original BlockDropItemEvent which caused this event to be fired.
* @return the original BlockDropItemEvent
*/
public @NotNull BlockDropItemEvent getBlockDropItemEvent() {
return blockDropItemEvent;
}
/**
* The original bonus mcMMO would have added before any modifications to this event from
* other plugins.
* @return the original bonus amount to add
*/
public int getOriginalBonusAmountToAdd() {
return originalBonusAmountToAdd;
}
/**
* The Item entity that is being modified by this event.
* This item returned by this call should not be modified, it is provided as a convenience.
* @return the Item entity that is having bonus drops added to it.
*/
public @NotNull Item getItem() {
return itemThatHasBonusDrops;
}
/**
* The modified ItemStack quantity that will be set on the Item entity if this event is not
* cancelled.
*
* @return the modified ItemStack quantity that will be set on the Item entity
*/
public int getModifiedItemStackQuantity() {
return modifiedItemStackQuantity;
}
/**
* The original ItemStack quantity of the Item entity before any modifications from this event.
* This is a reflection of the state of the Item when mcMMO fired this event.
* It is possible it has modified since then, so do not rely on this value to be the current.
* @return the original ItemStack quantity of the Item entity before any modifications from this event
*/
public int getOriginalItemStackQuantity() {
return originalItemStackQuantity;
}
/**
* The amount of bonus that will be added to the ItemStack quantity if this event is not
* cancelled.
* @return the amount of bonus that will be added to the ItemStack quantity
*/
public int getBonusAmountToAdd() {
return Math.max(0, modifiedItemStackQuantity - originalItemStackQuantity);
}
/**
* Set the amount of bonus that will be added to the ItemStack quantity if this event is not
* cancelled.
* @param bonus the amount of bonus that will be added to the ItemStack quantity
* @throws IllegalArgumentException if bonus is less than 0
*/
public void setBonusAmountToAdd(int bonus) {
if (bonus < 0) throw new IllegalArgumentException("bonus must be >= 0");
this.modifiedItemStackQuantity = originalItemStackQuantity + bonus;
}
/**
* Set the modified ItemStack quantity that will be set on the Item entity if this event is not
* cancelled. This CANNOT be lower than the original quantity of the ItemStack.
* @param modifiedItemStackQuantity the modified ItemStack quantity that will be set on the Item entity
* @throws IllegalArgumentException if modifiedItemStackQuantity is less than originalItemStackQuantity
*/
public void setModifiedItemStackQuantity(int modifiedItemStackQuantity) {
if (modifiedItemStackQuantity < originalItemStackQuantity) {
throw new IllegalArgumentException(
"modifiedItemStackQuantity cannot be less than the originalItemStackQuantity");
}
this.modifiedItemStackQuantity = modifiedItemStackQuantity;
}
public boolean isEffectivelyNoBonus() {
return modifiedItemStackQuantity == originalItemStackQuantity;
}
/**
* Delegate method for {@link BlockDropItemEvent}, gets the Player that is breaking the block
* involved in this event.
*
* @return The Player that is breaking the block involved in this event
*/
public @NotNull Player getPlayer() {
return blockDropItemEvent.getPlayer();
}
/**
* Delegate method for {@link BlockDropItemEvent#getBlock()}.
* Gets the Block involved in this event.
*
* @return the Block involved in this event
*/
public @NotNull Block getBlock() {
return blockDropItemEvent.getBlock();
}
/**
* Delegate method for {@link BlockDropItemEvent#getBlockState()}.
* Gets the BlockState of the block involved in this event.
*
* @return the BlockState of the block involved in this event
*/
public @NotNull BlockState getBlockState() {
return blockDropItemEvent.getBlockState();
}
private static final @NotNull HandlerList handlers = new HandlerList();
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static @NotNull HandlerList getHandlerList() {
return handlers;
}
@Override
public @NotNull String toString() {
return "McMMOModifyBlockDropItemEvent{" +
"blockDropItemEvent=" + blockDropItemEvent +
", originalBonusAmountToAdd=" + originalBonusAmountToAdd +
", modifiedItemStackQuantity=" + modifiedItemStackQuantity +
", itemThatHasBonusDrops=" + itemThatHasBonusDrops +
", isCancelled=" + isCancelled +
", originalItemStackQuantity=" + originalItemStackQuantity +
'}';
}
@Override
public final boolean equals(Object o) {
if (!(o instanceof McMMOModifyBlockDropItemEvent that)) {
return false;
}
return originalBonusAmountToAdd == that.originalBonusAmountToAdd
&& modifiedItemStackQuantity == that.modifiedItemStackQuantity
&& isCancelled == that.isCancelled
&& originalItemStackQuantity == that.originalItemStackQuantity
&& blockDropItemEvent.equals(that.blockDropItemEvent)
&& itemThatHasBonusDrops.equals(
that.itemThatHasBonusDrops);
}
@Override
public int hashCode() {
int result = blockDropItemEvent.hashCode();
result = 31 * result + originalBonusAmountToAdd;
result = 31 * result + modifiedItemStackQuantity;
result = 31 * result + itemThatHasBonusDrops.hashCode();
result = 31 * result + Boolean.hashCode(isCancelled);
result = 31 * result + originalItemStackQuantity;
return result;
}
}

View File

@@ -1,12 +1,10 @@
package com.gmail.nossr50.listeners; package com.gmail.nossr50.listeners;
import static com.gmail.nossr50.util.Misc.getBlockCenter; import static com.gmail.nossr50.util.MetadataConstants.METADATA_KEY_BONUS_DROPS;
import com.gmail.nossr50.api.ItemSpawnReason;
import com.gmail.nossr50.config.HiddenConfig; import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.config.WorldBlacklist; import com.gmail.nossr50.config.WorldBlacklist;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.meta.BonusDropMeta;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType; import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
@@ -14,6 +12,7 @@ import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.events.fake.FakeBlockBreakEvent; import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
import com.gmail.nossr50.events.fake.FakeBlockDamageEvent; import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
import com.gmail.nossr50.events.fake.FakeEvent; import com.gmail.nossr50.events.fake.FakeEvent;
import com.gmail.nossr50.events.items.McMMOModifyBlockDropItemEvent;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.alchemy.Alchemy; import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.excavation.ExcavationManager; import com.gmail.nossr50.skills.excavation.ExcavationManager;
@@ -26,7 +25,6 @@ import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.ContainerMetadataUtils; import com.gmail.nossr50.util.ContainerMetadataUtils;
import com.gmail.nossr50.util.EventUtils; import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.MetadataConstants;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
@@ -35,6 +33,8 @@ import com.gmail.nossr50.util.sounds.SoundType;
import com.gmail.nossr50.worldguard.WorldGuardManager; import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils; import com.gmail.nossr50.worldguard.WorldGuardUtils;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
@@ -62,6 +62,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.EntityBlockFormEvent; import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
public class BlockListener implements Listener { public class BlockListener implements Listener {
private final mcMMO plugin; private final mcMMO plugin;
@@ -70,29 +71,33 @@ public class BlockListener implements Listener {
this.plugin = plugin; this.plugin = plugin;
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = false) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onBlockDropItemEvent(BlockDropItemEvent event) { public void onBlockDropItemEvent(BlockDropItemEvent event) {
//Make sure we clean up metadata on these blocks //Make sure we clean up metadata on these blocks
final Block block = event.getBlock();
if (event.isCancelled()) { if (event.isCancelled()) {
if (event.getBlock().hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) { if (block.hasMetadata(METADATA_KEY_BONUS_DROPS)) {
event.getBlock().removeMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, plugin); block.removeMetadata(METADATA_KEY_BONUS_DROPS, plugin);
} }
return; return;
} }
try {
int tileEntityTolerance = 1; int tileEntityTolerance = 1;
// beetroot hotfix, potentially other plants may need this fix // beetroot hotfix, potentially other plants may need this fix
if (event.getBlock().getType() == Material.BEETROOTS) { final Material blockType = block.getType();
if (blockType == Material.BEETROOTS) {
tileEntityTolerance = 2; tileEntityTolerance = 2;
} }
//Track how many "things" are being dropped //Track how many "things" are being dropped
HashSet<Material> uniqueMaterials = new HashSet<>(); final Set<Material> uniqueMaterials = new HashSet<>();
boolean dontRewardTE = false; //If we suspect TEs are mixed in with other things don't reward bonus drops for anything that isn't a block boolean dontRewardTE = false; //If we suspect TEs are mixed in with other things don't reward bonus drops for anything that isn't a block
int blockCount = 0; int blockCount = 0;
for (Item item : event.getItems()) { final List<Item> eventItems = event.getItems();
for (Item item : eventItems) {
//Track unique materials //Track unique materials
uniqueMaterials.add(item.getItemStack().getType()); uniqueMaterials.add(item.getItemStack().getType());
@@ -103,55 +108,59 @@ public class BlockListener implements Listener {
} }
if (uniqueMaterials.size() > tileEntityTolerance) { if (uniqueMaterials.size() > tileEntityTolerance) {
//Too many things are dropping, assume tile entities might be duped // Too many things are dropping, assume tile entities might be duped
//Technically this would also prevent something like coal from being bonus dropped if you placed a TE above a coal ore when mining it but that's pretty edge case and this is a good solution for now // Technically this would also prevent something like coal from being bonus dropped
// if you placed a TE above a coal ore when mining it but that's pretty edge case
// and this is a good solution for now
dontRewardTE = true; dontRewardTE = true;
} }
//If there are more than one block in the item list we can't really trust it and will back out of rewarding bonus drops //If there are more than one block in the item list we can't really trust it
// and will back out of rewarding bonus drops
if (!block.getMetadata(METADATA_KEY_BONUS_DROPS).isEmpty()) {
final MetadataValue bonusDropMeta = block
.getMetadata(METADATA_KEY_BONUS_DROPS).get(0);
if (blockCount <= 1) { if (blockCount <= 1) {
for (Item item : event.getItems()) { for (final Item item : eventItems) {
ItemStack is = new ItemStack(item.getItemStack()); final ItemStack eventItemStack = item.getItemStack();
int originalAmount = eventItemStack.getAmount();
if (is.getAmount() <= 0) { if (eventItemStack.getAmount() <= 0) {
continue; continue;
} }
//TODO: Ignore this abomination its rewritten in 2.2 final Material itemType = eventItemStack.getType();
if (!mcMMO.p.getGeneralConfig() if (!mcMMO.p.getGeneralConfig()
.getDoubleDropsEnabled(PrimarySkillType.MINING, is.getType()) .getDoubleDropsEnabled(PrimarySkillType.MINING, itemType)
&& !mcMMO.p.getGeneralConfig() && !mcMMO.p.getGeneralConfig()
.getDoubleDropsEnabled(PrimarySkillType.HERBALISM, is.getType()) .getDoubleDropsEnabled(PrimarySkillType.HERBALISM, itemType)
&& !mcMMO.p.getGeneralConfig() && !mcMMO.p.getGeneralConfig()
.getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, is.getType())) { .getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, itemType)) {
continue; continue;
} }
//If we suspect TEs might be duped only reward block //If we suspect TEs might be duped only reward block
if (dontRewardTE) { if (dontRewardTE) {
if (!is.getType().isBlock()) { if (!itemType.isBlock()) {
continue; continue;
} }
} }
if (event.getBlock().getMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS).size() int amountToAddFromBonus = bonusDropMeta.asInt();
> 0) { final McMMOModifyBlockDropItemEvent modifyBlockDropItemEvent
final BonusDropMeta bonusDropMeta = = new McMMOModifyBlockDropItemEvent(event, item, amountToAddFromBonus);
(BonusDropMeta) event.getBlock().getMetadata( plugin.getServer().getPluginManager().callEvent(modifyBlockDropItemEvent);
MetadataConstants.METADATA_KEY_BONUS_DROPS).get(0); if (!modifyBlockDropItemEvent.isCancelled()
int bonusCount = bonusDropMeta.asInt(); && modifyBlockDropItemEvent.getModifiedItemStackQuantity() > originalAmount) {
final Location centeredLocation = getBlockCenter(event.getBlock()); eventItemStack.setAmount(modifyBlockDropItemEvent.getModifiedItemStackQuantity());
for (int i = 0; i < bonusCount; i++) {
ItemUtils.spawnItemNaturally(event.getPlayer(),
centeredLocation, is, ItemSpawnReason.BONUS_DROPS);
} }
} }
} }
} }
} finally {
if (event.getBlock().hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) { if (block.hasMetadata(METADATA_KEY_BONUS_DROPS)) {
event.getBlock().removeMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, plugin); block.removeMetadata(METADATA_KEY_BONUS_DROPS, plugin);
}
} }
} }
@@ -696,7 +705,7 @@ public class BlockListener implements Listener {
if (mmoPlayer.getUnarmedManager().canUseBlockCracker() if (mmoPlayer.getUnarmedManager().canUseBlockCracker()
&& BlockUtils.affectedByBlockCracker(block)) { && BlockUtils.affectedByBlockCracker(block)) {
if (EventUtils.simulateBlockBreak(block, player)) { if (EventUtils.simulateBlockBreak(block, player)) {
mmoPlayer.getUnarmedManager().blockCrackerCheck(block.getState()); mmoPlayer.getUnarmedManager().blockCrackerCheck(block);
} }
} else if (!event.getInstaBreak() && SuperAbilityType.BERSERK.blockCheck(block) } else if (!event.getInstaBreak() && SuperAbilityType.BERSERK.blockCheck(block)
&& EventUtils.simulateBlockBreak(block, player)) { && EventUtils.simulateBlockBreak(block, player)) {

View File

@@ -43,7 +43,6 @@ import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.AnimalTamer; import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.Animals; import org.bukkit.entity.Animals;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Arrow; import org.bukkit.entity.Arrow;
import org.bukkit.entity.Enderman; import org.bukkit.entity.Enderman;
import org.bukkit.entity.Endermite; import org.bukkit.entity.Endermite;
@@ -89,13 +88,18 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource; import org.bukkit.projectiles.ProjectileSource;
public class EntityListener implements Listener { public class EntityListener implements Listener {
private static final String MULTISHOT = "multishot";
private static final String PIERCING = "piercing";
private static final String DEEPSLATE_REDSTONE_ORE = "deepslate_redstone_ore";
private static final Set<String> ARMOR_STAND = Set.of("ARMOR_STAND", "armor_stand");
private static final Set<String> MANNEQUIN = Set.of("mannequin", "MANNEQUIN");
private final mcMMO pluginRef; private final mcMMO pluginRef;
/** /**
* We can use this {@link NamespacedKey} for {@link Enchantment} comparisons to check if a * We can use this {@link NamespacedKey} for {@link Enchantment} comparisons to check if a
* {@link Player} has a {@link Trident} enchanted with "Piercing". * {@link Player} has a {@link Trident} enchanted with "Piercing".
*/ */
private final NamespacedKey piercingEnchantment = NamespacedKey.minecraft("piercing"); private final NamespacedKey piercingEnchantment = NamespacedKey.minecraft(PIERCING);
private final static Set<EntityType> TRANSFORMABLE_ENTITIES private final static Set<EntityType> TRANSFORMABLE_ENTITIES
= Set.of(EntityType.SLIME, EntityType.MAGMA_CUBE); = Set.of(EntityType.SLIME, EntityType.MAGMA_CUBE);
@@ -205,7 +209,7 @@ public class EntityListener implements Listener {
CombatUtils.delayArrowMetaCleanup(arrow); CombatUtils.delayArrowMetaCleanup(arrow);
// If fired from an item with multi-shot, we need to track // If fired from an item with multi-shot, we need to track
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, "multishot")) { if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, MULTISHOT)) {
arrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW, arrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW,
MetadataConstants.MCMMO_METADATA_VALUE); MetadataConstants.MCMMO_METADATA_VALUE);
} }
@@ -221,7 +225,7 @@ public class EntityListener implements Listener {
} }
//Check both hands //Check both hands
if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) { if (ItemUtils.doesPlayerHaveEnchantmentInHands(player, PIERCING)) {
return; return;
} }
@@ -282,7 +286,7 @@ public class EntityListener implements Listener {
entity.removeMetadata(MetadataConstants.METADATA_KEY_TRAVELING_BLOCK, pluginRef); entity.removeMetadata(MetadataConstants.METADATA_KEY_TRAVELING_BLOCK, pluginRef);
} }
} else if ((block.getType() == Material.REDSTONE_ORE || block.getType().getKey().getKey() } else if ((block.getType() == Material.REDSTONE_ORE || block.getType().getKey().getKey()
.equalsIgnoreCase("deepslate_redstone_ore"))) { .equalsIgnoreCase(DEEPSLATE_REDSTONE_ORE))) {
//Redstone ore fire this event and should be ignored //Redstone ore fire this event and should be ignored
} else { } else {
if (mcMMO.getUserBlockTracker().isIneligible(block)) { if (mcMMO.getUserBlockTracker().isIneligible(block)) {
@@ -352,11 +356,13 @@ public class EntityListener implements Listener {
return; return;
} }
// Don't process this event for marked entities, for players this is handled above, if (ExperienceConfig.getInstance().isArmorStandInteractionPrevented()
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes && isArmorStandEntity(attacker)) {
// properly return;
}
if (event.getEntity() instanceof ArmorStand) { if (ExperienceConfig.getInstance().isMannequinInteractionPrevented()
&& isMannequinEntity(attacker)) {
return; return;
} }
@@ -385,8 +391,8 @@ public class EntityListener implements Listener {
if (animalTamer != null && ((OfflinePlayer) animalTamer).isOnline()) { if (animalTamer != null && ((OfflinePlayer) animalTamer).isOnline()) {
attacker = (Entity) animalTamer; attacker = (Entity) animalTamer;
} }
} else if (attacker instanceof TNTPrimed && defender instanceof Player) { } else if (attacker instanceof TNTPrimed tntAttacker && defender instanceof Player) {
if (BlastMining.processBlastMiningExplosion(event, (TNTPrimed) attacker, if (BlastMining.processBlastMiningExplosion(event, tntAttacker,
(Player) defender)) { (Player) defender)) {
return; return;
} }
@@ -1196,4 +1202,12 @@ public class EntityListener implements Listener {
} }
} }
} }
public static boolean isMannequinEntity(Entity attacker) {
return MANNEQUIN.contains(attacker.getType().toString());
}
public static boolean isArmorStandEntity(Entity attacker) {
return ARMOR_STAND.contains(attacker.getType().toString());
}
} }

View File

@@ -6,7 +6,6 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.events.fake.FakeBrewEvent; import com.gmail.nossr50.events.fake.FakeBrewEvent;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.player.PlayerUpdateInventoryTask;
import com.gmail.nossr50.skills.alchemy.Alchemy; import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer; import com.gmail.nossr50.skills.alchemy.AlchemyPotionBrewer;
import com.gmail.nossr50.util.ContainerMetadataUtils; import com.gmail.nossr50.util.ContainerMetadataUtils;
@@ -270,7 +269,6 @@ public class InventoryListener implements Listener {
} }
event.setCancelled(true); event.setCancelled(true);
AlchemyPotionBrewer.scheduleUpdate(inventory);
AlchemyPotionBrewer.scheduleCheck(stand); AlchemyPotionBrewer.scheduleCheck(stand);
return; return;
default: default:
@@ -294,7 +292,6 @@ public class InventoryListener implements Listener {
event.setCurrentItem(cursor.clone()); event.setCurrentItem(cursor.clone());
event.setCursor(null); event.setCursor(null);
AlchemyPotionBrewer.scheduleUpdate(inventory);
AlchemyPotionBrewer.scheduleCheck(stand); AlchemyPotionBrewer.scheduleCheck(stand);
} else if (click == ClickType.RIGHT) { } else if (click == ClickType.RIGHT) {
event.setCancelled(true); event.setCancelled(true);
@@ -308,7 +305,6 @@ public class InventoryListener implements Listener {
event.setCurrentItem(one); event.setCurrentItem(one);
event.setCursor(rest); event.setCursor(rest);
AlchemyPotionBrewer.scheduleUpdate(inventory);
AlchemyPotionBrewer.scheduleCheck(stand); AlchemyPotionBrewer.scheduleCheck(stand);
} }
} }
@@ -371,7 +367,6 @@ public class InventoryListener implements Listener {
} }
event.setCancelled(true); event.setCancelled(true);
AlchemyPotionBrewer.scheduleUpdate(inventory);
} }
} }
@@ -406,23 +401,17 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) { public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) {
/* WORLD BLACKLIST CHECK */
if (event.getSource().getLocation() != null) {
if (WorldBlacklist.isWorldBlacklisted(event.getSource().getLocation().getWorld())) {
return;
}
}
final Inventory inventory = event.getDestination(); final Inventory inventory = event.getDestination();
if (!(inventory instanceof BrewerInventory)) { if (!(inventory instanceof BrewerInventory)) {
return; return;
} }
final InventoryHolder holder = inventory.getHolder(); /* WORLD BLACKLIST CHECK */
final Location sourceLocation = event.getSource().getLocation();
if (holder instanceof BrewingStand brewingStand) { if (sourceLocation != null && WorldBlacklist.isWorldBlacklisted(sourceLocation.getWorld())) {
return;
}
ItemStack item = event.getItem(); ItemStack item = event.getItem();
@@ -439,6 +428,14 @@ public class InventoryListener implements Listener {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (!mcMMO.p.getGeneralConfig().getEnabledForHoppers()) {
return;
}
final InventoryHolder holder = inventory.getHolder();
if (holder instanceof BrewingStand brewingStand) {
int ingredientLevel = 1; int ingredientLevel = 1;
OfflinePlayer offlinePlayer = ContainerMetadataUtils.getContainerOwner(brewingStand); OfflinePlayer offlinePlayer = ContainerMetadataUtils.getContainerOwner(brewingStand);
@@ -449,8 +446,7 @@ public class InventoryListener implements Listener {
} }
} }
if (mcMMO.p.getGeneralConfig().getEnabledForHoppers() if (AlchemyPotionBrewer.isValidIngredientByLevel(ingredientLevel, item)) {
&& AlchemyPotionBrewer.isValidIngredientByLevel(ingredientLevel, item)) {
AlchemyPotionBrewer.scheduleCheck(brewingStand); AlchemyPotionBrewer.scheduleCheck(brewingStand);
} }
} }
@@ -510,9 +506,6 @@ public class InventoryListener implements Listener {
return; return;
} }
} }
mcMMO.p.getFoliaLib().getScheduler()
.runAtEntity(whoClicked, new PlayerUpdateInventoryTask((Player) whoClicked));
} }
} }

View File

@@ -168,6 +168,7 @@ public class PlayerListener implements Listener {
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) {
return; return;
} }
// world guard main flag check // world guard main flag check
if (WorldGuardUtils.isWorldGuardLoaded() && !WorldGuardManager.getInstance() if (WorldGuardUtils.isWorldGuardLoaded() && !WorldGuardManager.getInstance()
.hasMainFlag((Player) event.getEntity())) { .hasMainFlag((Player) event.getEntity())) {
@@ -342,8 +343,8 @@ public class PlayerListener implements Listener {
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager(); FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
switch (event.getState()) { switch (event.getState()) {
// CAUGHT_FISH happens for any item caught (including junk and treasure)
case CAUGHT_FISH: case CAUGHT_FISH:
//TODO Update to new API once available! Waiting for case CAUGHT_TREASURE
if (event.getCaught() != null) { if (event.getCaught() != null) {
Item fishingCatch = (Item) event.getCaught(); Item fishingCatch = (Item) event.getCaught();
@@ -675,6 +676,10 @@ public class PlayerListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteractLowest(PlayerInteractEvent event) { public void onPlayerInteractLowest(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL) {
return;
}
/* WORLD BLACKLIST CHECK */ /* WORLD BLACKLIST CHECK */
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
return; return;
@@ -737,7 +742,6 @@ public class PlayerListener implements Listener {
// Make sure the player knows what he's doing when trying to repair an enchanted item // Make sure the player knows what he's doing when trying to repair an enchanted item
if (repairManager.checkConfirmation(true)) { if (repairManager.checkConfirmation(true)) {
repairManager.handleRepair(heldItem); repairManager.handleRepair(heldItem);
player.updateInventory();
} }
} }
/* SALVAGE CHECKS */ /* SALVAGE CHECKS */
@@ -756,7 +760,6 @@ public class PlayerListener implements Listener {
if (salvageManager.checkConfirmation(true)) { if (salvageManager.checkConfirmation(true)) {
SkillUtils.removeAbilityBoostsFromInventory(player); SkillUtils.removeAbilityBoostsFromInventory(player);
salvageManager.handleSalvage(clickedBlock.getLocation(), heldItem); salvageManager.handleSalvage(clickedBlock.getLocation(), heldItem);
player.updateInventory();
} }
} }
@@ -819,6 +822,10 @@ public class PlayerListener implements Listener {
*/ */
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerInteractMonitor(PlayerInteractEvent event) { public void onPlayerInteractMonitor(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL) {
return;
}
/* WORLD BLACKLIST CHECK */ /* WORLD BLACKLIST CHECK */
if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) { if (WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
return; return;
@@ -926,7 +933,6 @@ public class PlayerListener implements Listener {
// Bukkit.getPluginManager().callEvent(fakeSwing); // Bukkit.getPluginManager().callEvent(fakeSwing);
player.getInventory().getItemInMainHand() player.getInventory().getItemInMainHand()
.setAmount(heldItem.getAmount() - 1); .setAmount(heldItem.getAmount() - 1);
player.updateInventory();
if (herbalismManager.processGreenThumbBlocks(blockState) if (herbalismManager.processGreenThumbBlocks(blockState)
&& EventUtils.simulateBlockBreak(block, player)) { && EventUtils.simulateBlockBreak(block, player)) {
blockState.update(true); blockState.update(true);

View File

@@ -78,6 +78,7 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.shatteredlands.shatt.backup.ZipLibrary; import net.shatteredlands.shatt.backup.ZipLibrary;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
@@ -86,10 +87,8 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -244,7 +243,7 @@ public class mcMMO extends JavaPlugin {
checkForOutdatedAPI(); checkForOutdatedAPI();
if (serverAPIOutdated) { if (serverAPIOutdated) {
foliaLib.getImpl().runTimer( foliaLib.getScheduler().runTimer(
() -> getLogger().severe( () -> getLogger().severe(
"You are running an outdated version of " "You are running an outdated version of "
+ platformManager.getServerSoftware() + platformManager.getServerSoftware()
@@ -252,7 +251,7 @@ public class mcMMO extends JavaPlugin {
20, 20 * 60 * 30); 20, 20 * 60 * 30);
if (platformManager.getServerSoftware() == ServerSoftwareType.CRAFT_BUKKIT) { if (platformManager.getServerSoftware() == ServerSoftwareType.CRAFT_BUKKIT) {
foliaLib.getImpl().runTimer( foliaLib.getScheduler().runTimer(
() -> getLogger().severe( () -> 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."), "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."),
20, 20 * 60 * 30); 20, 20 * 60 * 30);
@@ -306,13 +305,11 @@ public class mcMMO extends JavaPlugin {
} }
} }
} catch (Throwable t) { } catch (Throwable t) {
getLogger().severe("There was an error while enabling mcMMO!"); getLogger().log(Level.SEVERE, "There was an error while enabling mcMMO!", t);
if (!(t instanceof ExceptionInInitializerError)) { if (t instanceof ExceptionInInitializerError) {
t.printStackTrace(); getLogger().info("Please do not replace the mcMMO jar while the server"
} else { + " is running.");
getLogger().info(
"Please do not replace the mcMMO jar while the server is running.");
} }
getServer().getPluginManager().disablePlugin(this); getServer().getPluginManager().disablePlugin(this);
@@ -399,7 +396,7 @@ public class mcMMO extends JavaPlugin {
formulaManager.saveFormula(); formulaManager.saveFormula();
chunkManager.closeAll(); chunkManager.closeAll();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); getLogger().log(Level.SEVERE, "An error occurred while disabling mcMMO!", e);
} }
if (generalConfig.getBackupsEnabled()) { if (generalConfig.getBackupsEnabled()) {
@@ -587,7 +584,6 @@ public class mcMMO extends JavaPlugin {
TreasureConfig.getInstance(); TreasureConfig.getInstance();
FishingTreasureConfig.getInstance(); FishingTreasureConfig.getInstance();
HiddenConfig.getInstance(); HiddenConfig.getInstance();
mcMMO.p.getAdvancedConfig();
// init potion config // init potion config
potionConfig = new PotionConfig(); potionConfig = new PotionConfig();
@@ -597,16 +593,15 @@ public class mcMMO extends JavaPlugin {
SoundConfig.getInstance(); SoundConfig.getInstance();
RankConfig.getInstance(); RankConfig.getInstance();
List<Repairable> repairables = new ArrayList<>();
// Load repair configs, make manager, and register them at this time // Load repair configs, make manager, and register them at this time
repairables.addAll(new RepairConfigManager(this).getLoadedRepairables()); final List<Repairable> repairables = new ArrayList<>(
new RepairConfigManager(this).getLoadedRepairables());
repairableManager = new SimpleRepairableManager(repairables.size()); repairableManager = new SimpleRepairableManager(repairables.size());
repairableManager.registerRepairables(repairables); repairableManager.registerRepairables(repairables);
// Load salvage configs, make manager and register them at this time // Load salvage configs, make manager and register them at this time
SalvageConfigManager sManager = new SalvageConfigManager(this); SalvageConfigManager sManager = new SalvageConfigManager(this);
List<Salvageable> salvageables = sManager.getLoadedSalvageables(); final List<Salvageable> salvageables = sManager.getLoadedSalvageables();
salvageableManager = new SimpleSalvageableManager(salvageables.size()); salvageableManager = new SimpleSalvageableManager(salvageables.size());
salvageableManager.registerSalvageables(salvageables); salvageableManager.registerSalvageables(salvageables);
} }

View File

@@ -172,10 +172,8 @@ public final class ShareHandler {
} }
private static void awardDrop(Player winningPlayer, ItemStack drop) { private static void awardDrop(Player winningPlayer, ItemStack drop) {
if (winningPlayer.getInventory().addItem(drop).size() != 0) { if (!winningPlayer.getInventory().addItem(drop).isEmpty()) {
winningPlayer.getWorld().dropItem(winningPlayer.getLocation(), drop); winningPlayer.getWorld().dropItem(winningPlayer.getLocation(), drop);
} }
winningPlayer.updateInventory();
} }
} }

View File

@@ -1,18 +0,0 @@
package com.gmail.nossr50.runnables.player;
import com.gmail.nossr50.util.CancellableRunnable;
import org.bukkit.entity.Player;
@SuppressWarnings("deprecation")
public class PlayerUpdateInventoryTask extends CancellableRunnable {
private final Player player;
public PlayerUpdateInventoryTask(Player player) {
this.player = player;
}
@Override
public void run() {
player.updateInventory();
}
}

View File

@@ -12,6 +12,7 @@ import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class AbilityDisableTask extends CancellableRunnable { public class AbilityDisableTask extends CancellableRunnable {
@@ -72,7 +73,7 @@ public class AbilityDisableTask extends CancellableRunnable {
} }
} }
private void resendChunkRadiusAt(Player player) { private void resendChunkRadiusAt(Entity player) {
Chunk chunk = player.getLocation().getChunk(); Chunk chunk = player.getLocation().getChunk();
World world = player.getWorld(); World world = player.getWorld();

View File

@@ -159,13 +159,13 @@ public class AlchemyBrewTask extends CancellableRunnable {
private void finish() { private void finish() {
if (mmoPlayer == null) { if (mmoPlayer == null) {
// Still need to finish brewing if the player is null // Still need to finish brewing if the player is null
AlchemyPotionBrewer.finishBrewing(brewingStand, null, false); AlchemyPotionBrewer.finishBrewing(brewingStand, null);
} else { } else {
final McMMOPlayerBrewEvent event = new McMMOPlayerBrewEvent(mmoPlayer, brewingStand); final McMMOPlayerBrewEvent event = new McMMOPlayerBrewEvent(mmoPlayer, brewingStand);
mcMMO.p.getServer().getPluginManager().callEvent(event); mcMMO.p.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) { if (!event.isCancelled()) {
AlchemyPotionBrewer.finishBrewing(brewingStand, mmoPlayer, false); AlchemyPotionBrewer.finishBrewing(brewingStand, mmoPlayer);
} }
} }
@@ -175,7 +175,7 @@ public class AlchemyBrewTask extends CancellableRunnable {
public void finishImmediately() { public void finishImmediately() {
this.cancel(); this.cancel();
AlchemyPotionBrewer.finishBrewing(brewingStand, mmoPlayer, true); AlchemyPotionBrewer.finishBrewing(brewingStand, mmoPlayer);
Alchemy.brewingStandMap.remove(brewingStand.getLocation()); Alchemy.brewingStandMap.remove(brewingStand.getLocation());
} }

View File

@@ -51,8 +51,7 @@ public class DelayedCropReplant extends CancellableRunnable {
@Override @Override
public void run() { public void run() {
Block cropBlock = cropLocation.getBlock(); final BlockState blockState = cropLocation.getBlock().getState();
BlockState currentState = cropBlock.getState();
PlantAnchorType plantAnchorType = PlantAnchorType.NORMAL; PlantAnchorType plantAnchorType = PlantAnchorType.NORMAL;
//Remove the metadata marking the block as recently replanted //Remove the metadata marking the block as recently replanted
@@ -64,50 +63,43 @@ public class DelayedCropReplant extends CancellableRunnable {
wasImmaturePlant = true; wasImmaturePlant = true;
} }
//Two kinds of air in Minecraft if (blockIsAirOrExpectedCrop(blockState)) {
if (currentState.getType().equals(cropMaterial) || currentState.getType() // Modify the new state of the block, not any old snapshot of it
.equals(Material.AIR) || currentState.getType().equals(Material.CAVE_AIR)) { blockState.setType(cropMaterial);
// if (currentState.getBlock().getRelative(BlockFace.DOWN)) final BlockData newData = blockState.getBlockData();
//The space is not currently occupied by a block so we can fill it
cropBlock.setType(cropMaterial);
//Get new state (necessary?) // Immature plants should be age 0, others get the desired age
BlockState newState = cropBlock.getState(); int age = wasImmaturePlant ? 0 : desiredCropAge;
BlockData newData = newState.getBlockData();
int age = 0;
//Crop age should always be 0 if the plant was immature
if (!wasImmaturePlant) {
age = desiredCropAge;
//Otherwise make the plant the desired age
}
if (newData instanceof Directional) { if (newData instanceof Directional) {
//Cocoa Version // Cocoa Version
Directional directional = (Directional) newState.getBlockData(); Directional directional = (Directional) blockState.getBlockData();
directional.setFacing(cropFace); directional.setFacing(cropFace);
newState.setBlockData(directional); blockState.setBlockData(directional);
if (newData instanceof Cocoa) { if (newData instanceof Cocoa) {
plantAnchorType = PlantAnchorType.COCOA; plantAnchorType = PlantAnchorType.COCOA;
} }
} }
//Age the crop if (blockState.getBlockData() instanceof Ageable ageable) {
Ageable ageable = (Ageable) newState.getBlockData();
ageable.setAge(age); ageable.setAge(age);
newState.setBlockData(ageable); blockState.setBlockData(ageable);
blockState.update(true, true);
newState.update(true, true);
//Play an effect //Play an effect
ParticleEffectUtils.playGreenThumbEffect(cropLocation); ParticleEffectUtils.playGreenThumbEffect(cropLocation);
mcMMO.p.getFoliaLib().getScheduler().runAtLocationLater(newState.getLocation(), mcMMO.p.getFoliaLib().getScheduler().runAtLocationLater(blockState.getLocation(),
new PhysicsBlockUpdate(newState.getBlock(), cropFace, plantAnchorType), 1); new PhysicsBlockUpdate(blockState.getBlock(), cropFace, plantAnchorType), 1);
} }
} }
}
private boolean blockIsAirOrExpectedCrop(BlockState blockState) {
return blockState.getType().equals(cropMaterial) || blockState.getType()
.equals(Material.AIR) || blockState.getType().equals(Material.CAVE_AIR);
}
private enum PlantAnchorType { private enum PlantAnchorType {
NORMAL, NORMAL,

View File

@@ -32,7 +32,7 @@ public abstract class SkillManager {
* @param xpGainReason the reason for the XP gain * @param xpGainReason the reason for the XP gain
* @deprecated use applyXpGain(float, XPGainReason, XPGainSource) * @deprecated use applyXpGain(float, XPGainReason, XPGainSource)
*/ */
@Deprecated @Deprecated(forRemoval = true)
public void applyXpGain(float xp, XPGainReason xpGainReason) { public void applyXpGain(float xp, XPGainReason xpGainReason) {
mmoPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF); mmoPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
} }

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.acrobatics;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.BlockLocationHistory; import com.gmail.nossr50.datatypes.BlockLocationHistory;
import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.experience.XPGainSource;
import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -19,6 +20,8 @@ import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import com.tcoded.folialib.wrapper.task.WrappedTask;
import java.util.function.Consumer;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LightningStrike; import org.bukkit.entity.LightningStrike;
@@ -118,10 +121,10 @@ public class AcrobaticsManager extends SkillManager {
if (count <= 5) { if (count <= 5) {
applyXpGain((float) (damage * Acrobatics.dodgeXpModifier), applyXpGain((float) (damage * Acrobatics.dodgeXpModifier),
XPGainReason.PVE); XPGainReason.PVE, XPGainSource.SELF);
mob.setMetadata(MetadataConstants.METADATA_KEY_DODGE_TRACKER, mob.setMetadata(MetadataConstants.METADATA_KEY_DODGE_TRACKER,
new FixedMetadataValue(mcMMO.p, count + 1)); new FixedMetadataValue(mcMMO.p, count + 1));
MobDodgeMetaCleanup metaCleanupTask = new MobDodgeMetaCleanup(mob, final Consumer<WrappedTask> metaCleanupTask = new MobDodgeMetaCleanup(mob,
mcMMO.p); mcMMO.p);
mcMMO.p.getFoliaLib().getScheduler() mcMMO.p.getFoliaLib().getScheduler()
.runAtEntityTimer(mob, metaCleanupTask, 20, .runAtEntityTimer(mob, metaCleanupTask, 20,
@@ -129,7 +132,7 @@ public class AcrobaticsManager extends SkillManager {
} }
} else { } else {
applyXpGain((float) (damage * Acrobatics.dodgeXpModifier), applyXpGain((float) (damage * Acrobatics.dodgeXpModifier),
XPGainReason.PVE); XPGainReason.PVE, XPGainSource.SELF);
} }
} }
} }

View File

@@ -6,7 +6,6 @@ import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion;
import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage; import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage;
import com.gmail.nossr50.events.fake.FakeBrewEvent; import com.gmail.nossr50.events.fake.FakeBrewEvent;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.player.PlayerUpdateInventoryTask;
import com.gmail.nossr50.runnables.skills.AlchemyBrewCheckTask; import com.gmail.nossr50.runnables.skills.AlchemyBrewCheckTask;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.player.UserManager;
@@ -18,11 +17,9 @@ import java.util.List;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand; import org.bukkit.block.BrewingStand;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.BrewerInventory; import org.bukkit.inventory.BrewerInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -164,8 +161,7 @@ public final class AlchemyPotionBrewer {
? 1 : mmoPlayer.getAlchemyManager().getTier()); ? 1 : mmoPlayer.getAlchemyManager().getTier());
} }
public static void finishBrewing(BlockState brewingStand, @Nullable McMMOPlayer mmoPlayer, public static void finishBrewing(BlockState brewingStand, @Nullable McMMOPlayer mmoPlayer) {
boolean forced) {
// Check if the brewing stand block state is an actual brewing stand // Check if the brewing stand block state is an actual brewing stand
if (!(brewingStand instanceof BrewingStand)) { if (!(brewingStand instanceof BrewingStand)) {
return; return;
@@ -257,11 +253,6 @@ public final class AlchemyPotionBrewer {
} }
} }
} }
// If the brewing was not forced by external conditions, schedule a new update
if (!forced) {
scheduleUpdate(inventory);
}
} }
public static boolean transferItems(InventoryView view, int fromSlot, ClickType click) { public static boolean transferItems(InventoryView view, int fromSlot, ClickType click) {
@@ -356,13 +347,4 @@ public final class AlchemyPotionBrewer {
mcMMO.p.getFoliaLib().getScheduler().runAtLocation( mcMMO.p.getFoliaLib().getScheduler().runAtLocation(
brewingStand.getLocation(), new AlchemyBrewCheckTask(brewingStand)); brewingStand.getLocation(), new AlchemyBrewCheckTask(brewingStand));
} }
public static void scheduleUpdate(Inventory inventory) {
for (HumanEntity humanEntity : inventory.getViewers()) {
if (humanEntity instanceof Player) {
mcMMO.p.getFoliaLib().getScheduler().runAtEntity(humanEntity,
new PlayerUpdateInventoryTask((Player) humanEntity));
}
}
}
} }

View File

@@ -4,6 +4,7 @@ import com.gmail.nossr50.api.ItemSpawnReason;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.config.treasure.FishingTreasureConfig; import com.gmail.nossr50.config.treasure.FishingTreasureConfig;
import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.experience.XPGainSource;
import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -435,6 +436,7 @@ public class FishingManager extends SkillManager {
public boolean isMagicHunterEnabled() { public boolean isMagicHunterEnabled() {
return RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_MAGIC_HUNTER) return RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_MAGIC_HUNTER)
&& RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER) && RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MAGIC_HUNTER)
&& Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER); && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_TREASURE_HUNTER);
} }
@@ -526,7 +528,7 @@ public class FishingManager extends SkillManager {
fishingCatch.setItemStack(treasureDrop); fishingCatch.setItemStack(treasureDrop);
} }
applyXpGain(fishXp + treasureXp, XPGainReason.PVE); applyXpGain(fishXp + treasureXp, XPGainReason.PVE, XPGainSource.SELF);
} }
/** /**
@@ -596,8 +598,6 @@ public class FishingManager extends SkillManager {
drop.getAmount() - 1) : null); drop.getAmount() - 1) : null);
drop.setAmount(1); drop.setAmount(1);
} }
targetPlayer.updateInventory();
} }
break; break;
@@ -633,7 +633,8 @@ public class FishingManager extends SkillManager {
// Make it so you can shake a mob no more than 4 times. // Make it so you can shake a mob no more than 4 times.
double dmg = Math.min(Math.max(target.getMaxHealth() / 4, 1), 10); double dmg = Math.min(Math.max(target.getMaxHealth() / 4, 1), 10);
CombatUtils.safeDealDamage(target, dmg, getPlayer()); CombatUtils.safeDealDamage(target, dmg, getPlayer());
applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE); applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE,
XPGainSource.SELF);
} }
} }

View File

@@ -2,7 +2,10 @@ package com.gmail.nossr50.skills.herbalism;
import static com.gmail.nossr50.util.ItemUtils.hasItemIncludingOffHand; import static com.gmail.nossr50.util.ItemUtils.hasItemIncludingOffHand;
import static com.gmail.nossr50.util.ItemUtils.removeItemIncludingOffHand; import static com.gmail.nossr50.util.ItemUtils.removeItemIncludingOffHand;
import static com.gmail.nossr50.util.Misc.TICK_CONVERSION_FACTOR;
import static com.gmail.nossr50.util.Misc.getBlockCenter; import static com.gmail.nossr50.util.Misc.getBlockCenter;
import static com.gmail.nossr50.util.Permissions.isSubSkillEnabled;
import static com.gmail.nossr50.util.skills.RankUtils.hasUnlockedSubskill;
import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString; import static com.gmail.nossr50.util.text.ConfigStringUtils.getMaterialConfigString;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
@@ -29,7 +32,6 @@ import com.gmail.nossr50.util.CancellableRunnable;
import com.gmail.nossr50.util.EventUtils; import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.MetadataConstants; import com.gmail.nossr50.util.MetadataConstants;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.random.ProbabilityUtil; import com.gmail.nossr50.util.random.ProbabilityUtil;
@@ -61,17 +63,23 @@ import org.jetbrains.annotations.NotNull;
public class HerbalismManager extends SkillManager { public class HerbalismManager extends SkillManager {
private final static HashMap<String, Integer> plantBreakLimits; private final static HashMap<String, Integer> plantBreakLimits;
private static final String CACTUS_STR = "cactus"; private static final String CACTUS_ID = "cactus";
private static final String CACTUS_FLOWER_STR = "cactus_flower"; private static final String CACTUS_FLOWER_STR = "cactus_flower";
private static final String BAMBOO_ID = "bamboo";
private static final String SUGAR_CANE_ID = "sugar_cane";
private static final String KELP_ID = "kelp";
private static final String KELP_PLANT_ID = "kelp_plant";
private static final String CHORUS_PLANT_ID = "chorus_plant";
private static final String SWEET_BERRY_BUSH_ID = "sweet_berry_bush";
static { static {
plantBreakLimits = new HashMap<>(); plantBreakLimits = new HashMap<>();
plantBreakLimits.put(CACTUS_STR, 3); plantBreakLimits.put(CACTUS_ID, 3);
plantBreakLimits.put("bamboo", 20); plantBreakLimits.put(BAMBOO_ID, 20);
plantBreakLimits.put("sugar_cane", 3); plantBreakLimits.put(SUGAR_CANE_ID, 3);
plantBreakLimits.put("kelp", 26); plantBreakLimits.put(KELP_ID, 26);
plantBreakLimits.put("kelp_plant", 26); plantBreakLimits.put(KELP_PLANT_ID, 26);
plantBreakLimits.put("chorus_plant", 22); plantBreakLimits.put(CHORUS_PLANT_ID, 22);
} }
public HerbalismManager(McMMOPlayer mmoPlayer) { public HerbalismManager(McMMOPlayer mmoPlayer) {
@@ -79,7 +87,7 @@ public class HerbalismManager extends SkillManager {
} }
public boolean canGreenThumbBlock(BlockState blockState) { public boolean canGreenThumbBlock(BlockState blockState) {
if (!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_GREEN_THUMB)) { if (!hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_GREEN_THUMB)) {
return false; return false;
} }
@@ -97,7 +105,7 @@ public class HerbalismManager extends SkillManager {
return false; return false;
} }
if (!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_SHROOM_THUMB)) { if (!hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_SHROOM_THUMB)) {
return false; return false;
} }
@@ -109,12 +117,12 @@ public class HerbalismManager extends SkillManager {
|| itemType == Material.RED_MUSHROOM) || itemType == Material.RED_MUSHROOM)
&& inventory.contains(Material.BROWN_MUSHROOM, 1) && inventory.contains(Material.BROWN_MUSHROOM, 1)
&& inventory.contains(Material.RED_MUSHROOM, 1) && inventory.contains(Material.RED_MUSHROOM, 1)
&& Permissions.isSubSkillEnabled(player, SubSkillType.HERBALISM_SHROOM_THUMB); && isSubSkillEnabled(player, SubSkillType.HERBALISM_SHROOM_THUMB);
} }
public void processBerryBushHarvesting(@NotNull BlockState blockState) { public void processBerryBushHarvesting(@NotNull BlockState blockState) {
/* Check if the player is harvesting a berry bush */ /* Check if the player is harvesting a berry bush */
if (blockState.getType().toString().equalsIgnoreCase("sweet_berry_bush")) { if (blockState.getType().toString().equalsIgnoreCase(SWEET_BERRY_BUSH_ID)) {
if (mmoPlayer.isDebugMode()) { if (mmoPlayer.isDebugMode()) {
mmoPlayer.getPlayer().sendMessage("Processing sweet berry bush rewards"); mmoPlayer.getPlayer().sendMessage("Processing sweet berry bush rewards");
} }
@@ -166,7 +174,7 @@ public class HerbalismManager extends SkillManager {
public void run() { public void run() {
BlockState blockState = block.getState(); BlockState blockState = block.getState();
if (blockState.getType().toString().equalsIgnoreCase("sweet_berry_bush")) { if (blockState.getType().toString().equalsIgnoreCase(SWEET_BERRY_BUSH_ID)) {
if (blockState.getBlockData() instanceof Ageable ageable) { if (blockState.getBlockData() instanceof Ageable ageable) {
if (ageable.getAge() <= 1) { if (ageable.getAge() <= 1) {
@@ -179,16 +187,16 @@ public class HerbalismManager extends SkillManager {
public boolean canUseHylianLuck() { public boolean canUseHylianLuck() {
if (!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK)) { if (!hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK)) {
return false; return false;
} }
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK); return isSubSkillEnabled(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK);
} }
public boolean canActivateAbility() { public boolean canActivateAbility() {
return mmoPlayer.getToolPreparationMode(ToolType.HOE) && Permissions.greenTerra( return mmoPlayer.getToolPreparationMode(ToolType.HOE)
getPlayer()); && Permissions.greenTerra(getPlayer());
} }
public boolean isGreenTerraActive() { public boolean isGreenTerraActive() {
@@ -378,8 +386,8 @@ public class HerbalismManager extends SkillManager {
public void checkDoubleDropsOnBrokenPlants(Player player, Collection<Block> brokenPlants) { public void checkDoubleDropsOnBrokenPlants(Player player, Collection<Block> brokenPlants) {
//Only proceed if skill unlocked and permission enabled //Only proceed if skill unlocked and permission enabled
if (!RankUtils.hasUnlockedSubskill(player, SubSkillType.HERBALISM_DOUBLE_DROPS) if (!hasUnlockedSubskill(player, SubSkillType.HERBALISM_DOUBLE_DROPS)
|| !Permissions.isSubSkillEnabled(player, SubSkillType.HERBALISM_DOUBLE_DROPS)) { || !isSubSkillEnabled(player, SubSkillType.HERBALISM_DOUBLE_DROPS)) {
return; return;
} }
@@ -469,7 +477,7 @@ public class HerbalismManager extends SkillManager {
/* /*
* Unnatural Blocks * Unnatural Blocks
*/ */
//If its a Crop we need to reward XP when its fully grown //If it's a Crop we need to reward XP when its fully grown
if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) { if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) {
xpToReward += ExperienceConfig.getInstance() xpToReward += ExperienceConfig.getInstance()
.getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType()); .getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType());
@@ -659,7 +667,7 @@ public class HerbalismManager extends SkillManager {
} }
private boolean isCactus(Material material) { private boolean isCactus(Material material) {
return material.getKey().getKey().equalsIgnoreCase(CACTUS_STR) return material.getKey().getKey().equalsIgnoreCase(CACTUS_ID)
|| material.getKey().getKey().equalsIgnoreCase(CACTUS_FLOWER_STR); || material.getKey().getKey().equalsIgnoreCase(CACTUS_FLOWER_STR);
} }
@@ -798,7 +806,6 @@ public class HerbalismManager extends SkillManager {
playerInventory.removeItem(new ItemStack(Material.BROWN_MUSHROOM)); playerInventory.removeItem(new ItemStack(Material.BROWN_MUSHROOM));
playerInventory.removeItem(new ItemStack(Material.RED_MUSHROOM)); playerInventory.removeItem(new ItemStack(Material.RED_MUSHROOM));
getPlayer().updateInventory();
if (!ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.HERBALISM_SHROOM_THUMB, mmoPlayer)) { if (!ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.HERBALISM_SHROOM_THUMB, mmoPlayer)) {
NotificationManager.sendPlayerInformation(getPlayer(), NotificationManager.sendPlayerInformation(getPlayer(),
@@ -822,7 +829,7 @@ public class HerbalismManager extends SkillManager {
mcMMO.p.getFoliaLib().getScheduler() mcMMO.p.getFoliaLib().getScheduler()
.runAtLocationLater(blockBreakEvent.getBlock().getLocation(), .runAtLocationLater(blockBreakEvent.getBlock().getLocation(),
new DelayedCropReplant(blockBreakEvent, cropState, desiredCropAge, new DelayedCropReplant(blockBreakEvent, cropState, desiredCropAge,
isImmature), 2 * Misc.TICK_CONVERSION_FACTOR); isImmature), TICK_CONVERSION_FACTOR);
blockBreakEvent.getBlock().setMetadata(MetadataConstants.METADATA_KEY_REPLANT, blockBreakEvent.getBlock().setMetadata(MetadataConstants.METADATA_KEY_REPLANT,
new RecentlyReplantedCropMeta(mcMMO.p, true)); new RecentlyReplantedCropMeta(mcMMO.p, true));
} }
@@ -914,9 +921,7 @@ public class HerbalismManager extends SkillManager {
//Immature plants will start over at 0 //Immature plants will start over at 0
if (!isAgeableMature(ageable)) { if (!isAgeableMature(ageable)) {
// blockBreakEvent.setCancelled(true);
startReplantTask(0, blockBreakEvent, blockState, true); startReplantTask(0, blockBreakEvent, blockState, true);
// blockState.setType(Material.AIR);
blockBreakEvent.setDropItems(false); blockBreakEvent.setDropItems(false);
return true; return true;
} }

View File

@@ -10,7 +10,8 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
public class BlastMining { public class BlastMining {
public final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100; public static final int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100;
private static final double BLAST_MINING_PVP_DAMAGE_CAP = 24D;
public static double getBlastRadiusModifier(int rank) { public static double getBlastRadiusModifier(int rank) {
return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank); return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank);
@@ -41,17 +42,22 @@ public class BlastMining {
} }
public static boolean processBlastMiningExplosion(EntityDamageByEntityEvent event, public static boolean processBlastMiningExplosion(EntityDamageByEntityEvent event,
TNTPrimed tnt, Player defender) { TNTPrimed tntAttacker, Player defender) {
if (!tnt.hasMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT) if (!tntAttacker.hasMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT)
|| !UserManager.hasPlayerDataKey(defender)) { || !UserManager.hasPlayerDataKey(defender)) {
return false; return false;
} }
// We can make this assumption because we (should) be the only ones using this exact metadata // We can make this assumption because we (should) be the only ones using this exact metadata
Player player = mcMMO.p.getServer().getPlayerExact( Player player = mcMMO.p.getServer().getPlayerExact(
tnt.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString()); tntAttacker.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString());
if (!(player != null && player.equals(defender))) { if (!(player != null && player.equals(defender))) {
double cappedDamage = Math.min(event.getDamage(), BLAST_MINING_PVP_DAMAGE_CAP);
event.setDamage(Math.max(cappedDamage, 0D));
if (event.getFinalDamage() <= 0) {
event.setCancelled(true);
}
return false; return false;
} }
@@ -67,7 +73,7 @@ public class BlastMining {
event.setDamage(miningManager.processDemolitionsExpertise(event.getDamage())); event.setDamage(miningManager.processDemolitionsExpertise(event.getDamage()));
if (event.getFinalDamage() == 0) { if (event.getFinalDamage() <= 0) {
event.setCancelled(true); event.setCancelled(true);
return false; return false;
} }

View File

@@ -121,7 +121,7 @@ public class MiningManager extends SkillManager {
Player player = getPlayer(); Player player = getPlayer();
applyXpGain(ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, block), applyXpGain(ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, block),
XPGainReason.PVE); XPGainReason.PVE, XPGainSource.SELF);
if (!Permissions.isSubSkillEnabled(player, SubSkillType.MINING_DOUBLE_DROPS)) { if (!Permissions.isSubSkillEnabled(player, SubSkillType.MINING_DOUBLE_DROPS)) {
return; return;

View File

@@ -2,6 +2,7 @@ package com.gmail.nossr50.skills.repair;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.experience.XPGainSource;
import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -212,7 +213,7 @@ public class RepairManager extends SkillManager {
* repairable.getXpMultiplier()) * repairable.getXpMultiplier())
* ExperienceConfig.getInstance().getRepairXPBase() * ExperienceConfig.getInstance().getRepairXPBase()
* ExperienceConfig.getInstance().getRepairXP(repairable.getRepairMaterialType())), * ExperienceConfig.getInstance().getRepairXP(repairable.getRepairMaterialType())),
XPGainReason.PVE); XPGainReason.PVE, XPGainSource.SELF);
// BWONG BWONG BWONG // BWONG BWONG BWONG
if (mcMMO.p.getGeneralConfig().getRepairAnvilUseSoundsEnabled()) { if (mcMMO.p.getGeneralConfig().getRepairAnvilUseSoundsEnabled()) {

View File

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

View File

@@ -425,7 +425,6 @@ public class TamingManager extends SkillManager {
int itemAmountAfterPayingCost = int itemAmountAfterPayingCost =
itemInMainHand.getAmount() - tamingSummon.getItemAmountRequired(); itemInMainHand.getAmount() - tamingSummon.getItemAmountRequired();
itemInMainHand.setAmount(itemAmountAfterPayingCost); itemInMainHand.setAmount(itemAmountAfterPayingCost);
player.updateInventory();
} }
} else { } else {

View File

@@ -1,78 +0,0 @@
package com.gmail.nossr50.skills.unarmed;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.inventory.ItemStack;
public class Unarmed {
public static boolean blockCrackerSmoothBrick = mcMMO.p.getGeneralConfig()
.getUnarmedBlockCrackerSmoothbrickToCracked();
public static double berserkDamageModifier = 1.5;
public static void handleItemPickup(Player player, EntityPickupItemEvent event) {
ItemStack[] storageContents = player.getInventory().getStorageContents();
ItemStack itemDrop = event.getItem().getItemStack();
int heldItemSlotID = player.getInventory().getHeldItemSlot();
int amount = itemDrop.getAmount();
boolean grabbedItem = false;
for (int i = 0; i <= storageContents.length - 1; i++) {
if (amount <= 0) {
break;
}
if (i == heldItemSlotID) {
continue;
}
//EMPTY SLOT!
if (storageContents[i] == null) {
player.getInventory().setItem(i, itemDrop);
amount = 0;
grabbedItem = true;
break;
} else if (itemDrop.isSimilar(storageContents[i])
&& storageContents[i].getAmount() < storageContents[i].getMaxStackSize()) {
//If we can fit this whole itemstack into this item
if (amount + storageContents[i].getAmount()
<= storageContents[i].getMaxStackSize()) {
ItemStack modifiedAmount = storageContents[i];
modifiedAmount.setAmount(amount + storageContents[i].getAmount());
player.getInventory().setItem(i, modifiedAmount);
grabbedItem = true;
amount = 0;
} else {
//Add what we can from this stack
ItemStack modifiedAmount = storageContents[i];
int amountThatCanFit =
storageContents[i].getMaxStackSize() - storageContents[i].getAmount();
modifiedAmount.setAmount(amountThatCanFit);
player.getInventory().setItem(i, modifiedAmount);
//Remove the amount we've added
grabbedItem = true;
amount -= amountThatCanFit;
}
}
}
if (amount <= 0) {
event.getItem().remove(); //Cleanup Item
} else {
event.getItem().getItemStack().setAmount(amount);
}
event.setCancelled(true);
if (grabbedItem) {
SoundManager.sendSound(player, player.getLocation(), SoundType.POP);
player.updateInventory();
}
}
}

View File

@@ -21,7 +21,7 @@ import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.random.ProbabilityUtil; import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.RankUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockState; import org.bukkit.block.Block;
import org.bukkit.entity.Item; import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -29,6 +29,7 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class UnarmedManager extends SkillManager { public class UnarmedManager extends SkillManager {
public static final double BERSERK_DMG_MODIFIER = 1.5;
public UnarmedManager(McMMOPlayer mmoPlayer) { public UnarmedManager(McMMOPlayer mmoPlayer) {
super(mmoPlayer, PrimarySkillType.UNARMED); super(mmoPlayer, PrimarySkillType.UNARMED);
@@ -79,28 +80,33 @@ public class UnarmedManager extends SkillManager {
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.UNARMED_BLOCK_CRACKER); return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.UNARMED_BLOCK_CRACKER);
} }
public void blockCrackerCheck(@NotNull BlockState blockState) { public void blockCrackerCheck(@NotNull Block block) {
if (!mcMMO.p.getGeneralConfig().isBlockCrackerAllowed()) {
return;
}
if (!ProbabilityUtil.isNonRNGSkillActivationSuccessful(SubSkillType.UNARMED_BLOCK_CRACKER, if (!ProbabilityUtil.isNonRNGSkillActivationSuccessful(SubSkillType.UNARMED_BLOCK_CRACKER,
mmoPlayer)) { mmoPlayer)) {
return; return;
} }
switch (blockState.getType()) { switch (block.getType()) {
case STONE_BRICKS: case STONE_BRICKS:
if (!Unarmed.blockCrackerSmoothBrick) { block.setType(Material.CRACKED_STONE_BRICKS);
return;
}
blockState.getBlock().setType(Material.CRACKED_STONE_BRICKS);
blockState.update(true);
return; return;
case INFESTED_STONE_BRICKS: case INFESTED_STONE_BRICKS:
if (!Unarmed.blockCrackerSmoothBrick) { block.setType(Material.INFESTED_CRACKED_STONE_BRICKS);
return; return;
} case DEEPSLATE_BRICKS:
block.setType(Material.CRACKED_DEEPSLATE_BRICKS);
blockState.getBlock().setType(Material.INFESTED_CRACKED_STONE_BRICKS); return;
blockState.update(true); case DEEPSLATE_TILES:
block.setType(Material.CRACKED_DEEPSLATE_TILES);
return;
case POLISHED_BLACKSTONE_BRICKS:
block.setType(Material.CRACKED_POLISHED_BLACKSTONE_BRICKS);
return;
case NETHER_BRICKS:
block.setType(Material.CRACKED_NETHER_BRICKS);
return; return;
default: default:
} }
@@ -158,7 +164,7 @@ public class UnarmedManager extends SkillManager {
*/ */
public double berserkDamage(double damage) { public double berserkDamage(double damage) {
damage = damage =
((damage * Unarmed.berserkDamageModifier) * mmoPlayer.getAttackStrength()) - damage; ((damage * BERSERK_DMG_MODIFIER) * mmoPlayer.getAttackStrength()) - damage;
return damage; return damage;
} }

View File

@@ -18,6 +18,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.kyori.adventure.text.Component;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@@ -35,20 +36,20 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public final class ItemUtils { public final class ItemUtils {
// Reflection for setItemName only available in newer APIs // Use custom name if available
private static final Method setItemName; private static final Method customName;
static { static {
setItemName = getSetItemName(); customName = getCustomNameMethod();
} }
private ItemUtils() { private ItemUtils() {
// private constructor // private constructor
} }
private static Method getSetItemName() { private static Method getCustomNameMethod() {
try { try {
return ItemMeta.class.getMethod("setItemName", String.class); return ItemMeta.class.getMethod("customName", Component.class);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
return null; return null;
} }
@@ -60,17 +61,17 @@ public final class ItemUtils {
* @param itemMeta The item meta to set the name on * @param itemMeta The item meta to set the name on
* @param name The name to set * @param name The name to set
*/ */
public static void setItemName(ItemMeta itemMeta, String name) { public static void customName(ItemMeta itemMeta, Component name, String fallbackName) {
if (setItemName != null) { if (customName != null) {
setItemNameModern(itemMeta, name); setItemNameModern(itemMeta, name);
} else { } else {
itemMeta.setDisplayName(ChatColor.RESET + name); itemMeta.setDisplayName(ChatColor.RESET + fallbackName);
} }
} }
private static void setItemNameModern(ItemMeta itemMeta, String name) { private static void setItemNameModern(ItemMeta itemMeta, Component name) {
try { try {
setItemName.invoke(itemMeta, name); customName.invoke(itemMeta, name);
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
mcMMO.p.getLogger().severe("Failed to set item name: " + e.getMessage()); mcMMO.p.getLogger().severe("Failed to set item name: " + e.getMessage());
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -165,20 +166,6 @@ public final class ItemUtils {
} }
} }
// TODO: Unit tests
public static boolean isCrossbow(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());
}
// TODO: Unit tests
public static boolean isTrident(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey());
}
public static boolean isMace(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isMace(item.getType().getKey().getKey());
}
public static boolean hasItemInEitherHand(@NotNull Player player, Material material) { public static boolean hasItemInEitherHand(@NotNull Player player, Material material) {
return player.getInventory().getItemInMainHand().getType() == material return player.getInventory().getItemInMainHand().getType() == material
|| player.getInventory().getItemInOffHand().getType() == material; || player.getInventory().getItemInOffHand().getType() == material;
@@ -275,6 +262,46 @@ public final class ItemUtils {
return null; return null;
} }
/**
* Checks if the item is a crossbow.
*
* @param item Item to check
* @return true if the item is a crossbow, false otherwise
*/
public static boolean isCrossbow(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());
}
/**
* Checks if the item is a trident.
*
* @param item Item to check
* @return true if the item is a trident, false otherwise
*/
public static boolean isTrident(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey());
}
/**
* Checks if the item is a mace.
*
* @param item Item to check
* @return true if the item is a mace, false otherwise
*/
public static boolean isMace(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isMace(item.getType().getKey().getKey());
}
/**
* Checks if the item is a spear.
* @param item Item to check
*
* @return true if the item is a spear, false otherwise
*/
public static boolean isSpear(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isSpear(item.getType().getKey().getKey());
}
/** /**
* Checks if the item is a sword. * Checks if the item is a sword.
* *
@@ -379,6 +406,10 @@ public final class ItemUtils {
return mcMMO.getMaterialMapStore().isIronArmor(item.getType().getKey().getKey()); return mcMMO.getMaterialMapStore().isIronArmor(item.getType().getKey().getKey());
} }
public static boolean isCopperArmor(ItemStack item) {
return mcMMO.getMaterialMapStore().isCopperArmor(item.getType().getKey().getKey());
}
/** /**
* Checks to see if an item is a diamond armor piece. * Checks to see if an item is a diamond armor piece.
* *
@@ -451,6 +482,10 @@ public final class ItemUtils {
return mcMMO.getMaterialMapStore().isPrismarineTool(item.getType().getKey().getKey()); return mcMMO.getMaterialMapStore().isPrismarineTool(item.getType().getKey().getKey());
} }
public static boolean isCopperTool(ItemStack item) {
return mcMMO.getMaterialMapStore().isCopperTool(item.getType().getKey().getKey());
}
/** /**
* Checks to see if an item is a gold tool. * Checks to see if an item is a gold tool.
* *

View File

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

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.util;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set;
import org.bukkit.Material; import org.bukkit.Material;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -29,6 +30,8 @@ public class MaterialMapStore {
private final @NotNull HashSet<String> woodTools; private final @NotNull HashSet<String> woodTools;
private final @NotNull HashSet<String> stoneTools; private final @NotNull HashSet<String> stoneTools;
private final @NotNull HashSet<String> leatherArmor; private final @NotNull HashSet<String> leatherArmor;
private final @NotNull HashSet<String> copperTools;
private final @NotNull HashSet<String> copperArmor;
private final @NotNull HashSet<String> ironArmor; private final @NotNull HashSet<String> ironArmor;
private final @NotNull HashSet<String> ironTools; private final @NotNull HashSet<String> ironTools;
private final @NotNull HashSet<String> stringTools; private final @NotNull HashSet<String> stringTools;
@@ -48,9 +51,10 @@ public class MaterialMapStore {
private final @NotNull HashSet<String> tridents; private final @NotNull HashSet<String> tridents;
private final @NotNull HashSet<String> bows; private final @NotNull HashSet<String> bows;
private final @NotNull HashSet<String> crossbows; private final @NotNull HashSet<String> crossbows;
private final @NotNull HashSet<String> tools;
private final @NotNull HashSet<String> enchantables;
private final @NotNull HashSet<String> maces; private final @NotNull HashSet<String> maces;
private final @NotNull HashSet<String> spears;
private final @NotNull HashSet<String> enchantables;
private final @NotNull HashSet<String> tools;
private final @NotNull HashSet<String> ores; private final @NotNull HashSet<String> ores;
private final @NotNull HashSet<String> intendedToolPickAxe; private final @NotNull HashSet<String> intendedToolPickAxe;
@@ -74,6 +78,7 @@ public class MaterialMapStore {
leatherArmor = new HashSet<>(); leatherArmor = new HashSet<>();
ironArmor = new HashSet<>(); ironArmor = new HashSet<>();
copperArmor = new HashSet<>();
chainmailArmor = new HashSet<>(); chainmailArmor = new HashSet<>();
goldArmor = new HashSet<>(); goldArmor = new HashSet<>();
diamondArmor = new HashSet<>(); diamondArmor = new HashSet<>();
@@ -82,6 +87,7 @@ public class MaterialMapStore {
woodTools = new HashSet<>(); woodTools = new HashSet<>();
stoneTools = new HashSet<>(); stoneTools = new HashSet<>();
copperTools = new HashSet<>();
ironTools = new HashSet<>(); ironTools = new HashSet<>();
goldTools = new HashSet<>(); goldTools = new HashSet<>();
diamondTools = new HashSet<>(); diamondTools = new HashSet<>();
@@ -90,15 +96,15 @@ public class MaterialMapStore {
crossbows = new HashSet<>(); crossbows = new HashSet<>();
stringTools = new HashSet<>(); stringTools = new HashSet<>();
prismarineTools = new HashSet<>(); prismarineTools = new HashSet<>();
tools = new HashSet<>();
swords = new HashSet<>(); swords = new HashSet<>();
axes = new HashSet<>(); axes = new HashSet<>();
pickAxes = new HashSet<>(); pickAxes = new HashSet<>();
shovels = new HashSet<>(); shovels = new HashSet<>();
hoes = new HashSet<>(); hoes = new HashSet<>();
tridents = new HashSet<>(); tridents = new HashSet<>();
spears = new HashSet<>();
maces = new HashSet<>(); maces = new HashSet<>();
tools = new HashSet<>();
enchantables = new HashSet<>(); enchantables = new HashSet<>();
@@ -174,6 +180,10 @@ public class MaterialMapStore {
tierValue.put(id, 1); tierValue.put(id, 1);
} }
for (String id : copperArmor) {
tierValue.put(id, 1);
}
for (String id : ironArmor) { for (String id : ironArmor) {
tierValue.put(id, 2); tierValue.put(id, 2);
} }
@@ -421,6 +431,7 @@ public class MaterialMapStore {
private void fillArmors() { private void fillArmors() {
fillLeatherArmorWhiteList(); fillLeatherArmorWhiteList();
fillCopperArmorWhiteList();
fillIronArmorWhiteList(); fillIronArmorWhiteList();
fillChainmailWhiteList(); fillChainmailWhiteList();
fillGoldArmorWhiteList(); fillGoldArmorWhiteList();
@@ -429,6 +440,7 @@ public class MaterialMapStore {
//Add all armors to armors hashset //Add all armors to armors hashset
armors.addAll(leatherArmor); armors.addAll(leatherArmor);
armors.addAll(copperArmor);
armors.addAll(ironArmor); armors.addAll(ironArmor);
armors.addAll(chainmailArmor); armors.addAll(chainmailArmor);
armors.addAll(goldArmor); armors.addAll(goldArmor);
@@ -448,6 +460,7 @@ public class MaterialMapStore {
enchantables.addAll(bows); enchantables.addAll(bows);
enchantables.addAll(crossbows); enchantables.addAll(crossbows);
enchantables.addAll(maces); enchantables.addAll(maces);
enchantables.addAll(spears);
enchantables.add("shears"); enchantables.add("shears");
enchantables.add("fishing_rod"); enchantables.add("fishing_rod");
@@ -460,6 +473,7 @@ public class MaterialMapStore {
private void fillTools() { private void fillTools() {
fillWoodToolsWhiteList(); fillWoodToolsWhiteList();
fillStoneToolsWhiteList(); fillStoneToolsWhiteList();
fillCopperToolsWhiteList();
fillIronToolsWhiteList(); fillIronToolsWhiteList();
fillGoldToolsWhiteList(); fillGoldToolsWhiteList();
fillDiamondToolsWhiteList(); fillDiamondToolsWhiteList();
@@ -472,6 +486,7 @@ public class MaterialMapStore {
fillShovels(); fillShovels();
fillTridents(); fillTridents();
fillMaces(); fillMaces();
fillSpears();
fillStringTools(); fillStringTools();
fillPrismarineTools(); fillPrismarineTools();
fillBows(); fillBows();
@@ -480,6 +495,7 @@ public class MaterialMapStore {
//Tools collection //Tools collection
tools.addAll(woodTools); tools.addAll(woodTools);
tools.addAll(stoneTools); tools.addAll(stoneTools);
tools.addAll(copperTools);
tools.addAll(ironTools); tools.addAll(ironTools);
tools.addAll(goldTools); tools.addAll(goldTools);
tools.addAll(diamondTools); tools.addAll(diamondTools);
@@ -489,6 +505,7 @@ public class MaterialMapStore {
tools.addAll(bows); tools.addAll(bows);
tools.addAll(crossbows); tools.addAll(crossbows);
tools.addAll(maces); tools.addAll(maces);
tools.addAll(spears);
} }
private void fillBows() { private void fillBows() {
@@ -514,6 +531,16 @@ public class MaterialMapStore {
maces.add("mace"); maces.add("mace");
} }
private void fillSpears() {
spears.add("wooden_spear");
spears.add("stone_spear");
spears.add("copper_spear");
spears.add("iron_spear");
spears.add("golden_spear");
spears.add("diamond_spear");
spears.add("netherite_spear");
}
private void fillTridents() { private void fillTridents() {
tridents.add("trident"); tridents.add("trident");
} }
@@ -522,6 +549,7 @@ public class MaterialMapStore {
swords.add("wood_sword"); swords.add("wood_sword");
swords.add("wooden_sword"); swords.add("wooden_sword");
swords.add("stone_sword"); swords.add("stone_sword");
swords.add("copper_sword");
swords.add("iron_sword"); swords.add("iron_sword");
swords.add("gold_sword"); swords.add("gold_sword");
swords.add("golden_sword"); swords.add("golden_sword");
@@ -533,6 +561,7 @@ public class MaterialMapStore {
axes.add("wood_axe"); axes.add("wood_axe");
axes.add("wooden_axe"); axes.add("wooden_axe");
axes.add("stone_axe"); axes.add("stone_axe");
axes.add("copper_axe");
axes.add("iron_axe"); axes.add("iron_axe");
axes.add("gold_axe"); axes.add("gold_axe");
axes.add("golden_axe"); axes.add("golden_axe");
@@ -544,6 +573,7 @@ public class MaterialMapStore {
pickAxes.add("wood_pickaxe"); pickAxes.add("wood_pickaxe");
pickAxes.add("wooden_pickaxe"); pickAxes.add("wooden_pickaxe");
pickAxes.add("stone_pickaxe"); pickAxes.add("stone_pickaxe");
pickAxes.add("copper_pickaxe");
pickAxes.add("iron_pickaxe"); pickAxes.add("iron_pickaxe");
pickAxes.add("gold_pickaxe"); pickAxes.add("gold_pickaxe");
pickAxes.add("golden_pickaxe"); pickAxes.add("golden_pickaxe");
@@ -555,6 +585,7 @@ public class MaterialMapStore {
hoes.add("wood_hoe"); hoes.add("wood_hoe");
hoes.add("wooden_hoe"); hoes.add("wooden_hoe");
hoes.add("stone_hoe"); hoes.add("stone_hoe");
hoes.add("copper_hoe");
hoes.add("iron_hoe"); hoes.add("iron_hoe");
hoes.add("gold_hoe"); hoes.add("gold_hoe");
hoes.add("golden_hoe"); hoes.add("golden_hoe");
@@ -566,6 +597,7 @@ public class MaterialMapStore {
shovels.add("wood_shovel"); shovels.add("wood_shovel");
shovels.add("wooden_shovel"); shovels.add("wooden_shovel");
shovels.add("stone_shovel"); shovels.add("stone_shovel");
shovels.add("copper_shovel");
shovels.add("iron_shovel"); shovels.add("iron_shovel");
shovels.add("gold_shovel"); shovels.add("gold_shovel");
shovels.add("golden_shovel"); shovels.add("golden_shovel");
@@ -580,6 +612,13 @@ public class MaterialMapStore {
leatherArmor.add("leather_boots"); leatherArmor.add("leather_boots");
} }
private void fillCopperArmorWhiteList() {
copperArmor.add("copper_helmet");
copperArmor.add("copper_chestplate");
copperArmor.add("copper_leggings");
copperArmor.add("copper_boots");
}
private void fillIronArmorWhiteList() { private void fillIronArmorWhiteList() {
ironArmor.add("iron_helmet"); ironArmor.add("iron_helmet");
ironArmor.add("iron_chestplate"); ironArmor.add("iron_chestplate");
@@ -644,6 +683,14 @@ public class MaterialMapStore {
stoneTools.add("stone_shovel"); stoneTools.add("stone_shovel");
} }
private void fillCopperToolsWhiteList() {
copperTools.add("copper_sword");
copperTools.add("copper_axe");
copperTools.add("copper_hoe");
copperTools.add("copper_pickaxe");
copperTools.add("copper_shovel");
}
private void fillIronToolsWhiteList() { private void fillIronToolsWhiteList() {
ironTools.add("iron_sword"); ironTools.add("iron_sword");
ironTools.add("iron_axe"); ironTools.add("iron_axe");
@@ -841,6 +888,14 @@ public class MaterialMapStore {
return maces.contains(id); return maces.contains(id);
} }
public boolean isSpear(@NotNull Material material) {
return isSpear(material.getKey().getKey());
}
public boolean isSpear(@NotNull String id) {
return spears.contains(id);
}
public boolean isLeatherArmor(@NotNull Material material) { public boolean isLeatherArmor(@NotNull Material material) {
return isLeatherArmor(material.getKey().getKey()); return isLeatherArmor(material.getKey().getKey());
} }
@@ -849,6 +904,14 @@ public class MaterialMapStore {
return leatherArmor.contains(id); return leatherArmor.contains(id);
} }
public boolean isCopperArmor(@NotNull Material material) {
return isCopperArmor(material.getKey().getKey());
}
public boolean isCopperArmor(@NotNull String id) {
return copperArmor.contains(id);
}
public boolean isIronArmor(@NotNull Material material) { public boolean isIronArmor(@NotNull Material material) {
return isIronArmor(material.getKey().getKey()); return isIronArmor(material.getKey().getKey());
} }
@@ -905,6 +968,14 @@ public class MaterialMapStore {
return stoneTools.contains(id); return stoneTools.contains(id);
} }
public boolean isCopperTool(@NotNull Material material) {
return isCopperTool(material.getKey().getKey());
}
public boolean isCopperTool(@NotNull String id) {
return copperTools.contains(id);
}
public boolean isIronTool(@NotNull Material material) { public boolean isIronTool(@NotNull Material material) {
return isIronTool(material.getKey().getKey()); return isIronTool(material.getKey().getKey());
} }
@@ -1070,255 +1141,305 @@ public class MaterialMapStore {
mossyWhiteList.add("cobblestone_wall"); mossyWhiteList.add("cobblestone_wall");
} }
private void addCommonToBlackList(Set<String> blackList) {
// All things that should be on both the tools and ability blacklist get added here
addButtonsToBlackList(blackList);
addTrapdoorsToBlackList(blackList);
addFenceGatesToBlackList(blackList);
addBedsToBlacklist(blackList);
addPressurePlatesToBlackList(blackList);
addChestsToBlackList(blackList);
addGolemStatuesToBlackList(blackList);
addShelvesToBlackList(blackList);
addDoorsToBlackList(blackList);
addFencesToBlackList(blackList);
addSignsToBlackList(blackList);
addHangingSignsToBlackList(blackList);
addShulkerBoxesToBlackList(blackList);
addMiscInteractableToBlackList(blackList);
}
private void addButtonsToBlackList(Set<String> blackList) {
blackList.add("oak_button");
blackList.add("spruce_button");
blackList.add("birch_button");
blackList.add("jungle_button");
blackList.add("acacia_button");
blackList.add("dark_oak_button");
blackList.add("mangrove_button");
blackList.add("cherry_button");
blackList.add("pale_oak_button");
blackList.add("bamboo_button");
blackList.add("crimson_button");
blackList.add("warped_button");
// Non-wood buttons
blackList.add("stone_button");
blackList.add("polished_blackstone_button");
}
private void addTrapdoorsToBlackList(Set<String> blackList) {
// Wood Trapdoors
blackList.add("oak_trapdoor");
blackList.add("spruce_trapdoor");
blackList.add("birch_trapdoor");
blackList.add("jungle_trapdoor");
blackList.add("acacia_trapdoor");
blackList.add("dark_oak_trapdoor");
blackList.add("mangrove_trapdoor");
blackList.add("cherry_trapdoor");
blackList.add("pale_oak_trapdoor");
blackList.add("bamboo_trapdoor");
blackList.add("crimson_trapdoor");
blackList.add("warped_trapdoor");
// Copper Trapdoors
blackList.add("waxed_copper_trapdoor");
blackList.add("waxed_exposed_copper_trapdoor");
blackList.add("waxed_weathered_copper_trapdoor");
blackList.add("waxed_oxidized_copper_trapdoor");
blackList.add("copper_trapdoor");
blackList.add("exposed_copper_trapdoor");
blackList.add("weathered_copper_trapdoor");
blackList.add("oxidized_copper_trapdoor");
// Other Trapdoors
blackList.add("iron_trapdoor");
}
private void addFenceGatesToBlackList(Set<String> blackList) {
// Fence Gates
blackList.add("oak_fence_gate");
blackList.add("spruce_fence_gate");
blackList.add("birch_fence_gate");
blackList.add("jungle_fence_gate");
blackList.add("acacia_fence_gate");
blackList.add("dark_oak_fence_gate");
blackList.add("mangrove_fence_gate");
blackList.add("cherry_fence_gate");
blackList.add("pale_oak_fence_gate");
blackList.add("bamboo_fence_gate");
blackList.add("crimson_fence_gate");
blackList.add("warped_fence_gate");
}
private void addBedsToBlacklist(Set<String> blackList) {
blackList.add("black_bed");
blackList.add("blue_bed");
blackList.add("brown_bed");
blackList.add("cyan_bed");
blackList.add("gray_bed");
blackList.add("green_bed");
blackList.add("light_blue_bed");
blackList.add("light_gray_bed");
blackList.add("lime_bed");
blackList.add("magenta_bed");
blackList.add("orange_bed");
blackList.add("pink_bed");
blackList.add("purple_bed");
blackList.add("red_bed");
blackList.add("white_bed");
blackList.add("yellow_bed");
}
private void addPressurePlatesToBlackList(Set<String> blackList) {
blackList.add("oak_pressure_plate");
blackList.add("spruce_pressure_plate");
blackList.add("birch_pressure_plate");
blackList.add("jungle_pressure_plate");
blackList.add("acacia_pressure_plate");
blackList.add("dark_oak_pressure_plate");
blackList.add("mangrove_pressure_plate");
blackList.add("cherry_pressure_plate");
blackList.add("pale_oak_pressure_plate");
blackList.add("bamboo_pressure_plate");
blackList.add("crimson_pressure_plate");
blackList.add("warped_pressure_plate");
blackList.add("stone_pressure_plate");
blackList.add("light_weighted_pressure_plate");
blackList.add("heavy_weighted_pressure_plate");
blackList.add("polished_blackstone_pressure_plate");
}
private void addChestsToBlackList(Set<String> blackList) {
blackList.add("chest");
blackList.add("copper_chest");
blackList.add("waxed_copper_chest");
blackList.add("exposed_copper_chest");
blackList.add("weathered_copper_chest");
blackList.add("oxidized_copper_chest");
blackList.add("trapped_chest");
blackList.add("ender_chest");
}
private void addShelvesToBlackList(Set<String> blackList) {
blackList.add("oak_shelf");
blackList.add("spruce_shelf");
blackList.add("birch_shelf");
blackList.add("jungle_shelf");
blackList.add("acacia_shelf");
blackList.add("dark_oak_shelf");
blackList.add("mangrove_shelf");
blackList.add("cherry_shelf");
blackList.add("pale_oak_shelf");
blackList.add("bamboo_shelf");
blackList.add("crimson_shelf");
blackList.add("warped_shelf");
}
private void addGolemStatuesToBlackList(Set<String> blackList) {
blackList.add("copper_golem_statue");
blackList.add("waxed_copper_golem_statue");
blackList.add("exposed_copper_golem_statue");
blackList.add("weathered_copper_golem_statue");
blackList.add("oxidized_copper_golem_statue");
}
private void addDoorsToBlackList(Set<String> blackList) {
// Doors
blackList.add("oak_door");
blackList.add("spruce_door");
blackList.add("birch_door");
blackList.add("jungle_door");
blackList.add("acacia_door");
blackList.add("dark_oak_door");
blackList.add("mangrove_door");
blackList.add("cherry_door");
blackList.add("pale_oak_door");
blackList.add("bamboo_door");
blackList.add("crimson_door");
blackList.add("warped_door");
// Metal
blackList.add("iron_door");
blackList.add("copper_door");
blackList.add("exposed_copper_door");
blackList.add("weathered_copper_door");
blackList.add("oxidized_copper_door");
blackList.add("waxed_copper_door");
blackList.add("waxed_exposed_copper_door");
blackList.add("waxed_weathered_copper_door");
blackList.add("waxed_oxidized_copper_door");
}
private void addFencesToBlackList(Set<String> blackList) {
// Fences
blackList.add("oak_fence");
blackList.add("spruce_fence");
blackList.add("birch_fence");
blackList.add("jungle_fence");
blackList.add("acacia_fence");
blackList.add("dark_oak_fence");
blackList.add("mangrove_fence");
blackList.add("cherry_fence");
blackList.add("pale_oak_fence");
blackList.add("bamboo_fence");
blackList.add("crimson_fence");
blackList.add("warped_fence");
blackList.add("dispenser");
blackList.add("enchanting_table");
// Metal Fences
blackList.add("nether_brick_fence");
blackList.add("iron_bars");
}
private void addSignsToBlackList(Set<String> blackList) {
// Sign
blackList.add("oak_sign");
blackList.add("spruce_sign");
blackList.add("birch_sign");
blackList.add("jungle_sign");
blackList.add("acacia_sign");
blackList.add("dark_oak_sign");
blackList.add("mangrove_sign");
blackList.add("cherry_sign");
blackList.add("pale_oak_sign");
blackList.add("bamboo_sign");
blackList.add("crimson_sign");
blackList.add("warped_sign");
}
private void addHangingSignsToBlackList(Set<String> blackList) {
// Hanging Sign
blackList.add("oak_hanging_sign");
blackList.add("spruce_hanging_sign");
blackList.add("birch_hanging_sign");
blackList.add("jungle_hanging_sign");
blackList.add("acacia_hanging_sign");
blackList.add("dark_oak_hanging_sign");
blackList.add("mangrove_hanging_sign");
blackList.add("cherry_hanging_sign");
blackList.add("pale_oak_hanging_sign");
blackList.add("bamboo_hanging_sign");
blackList.add("crimson_hanging_sign");
blackList.add("warped_hanging_sign");
}
private void addShulkerBoxesToBlackList(Set<String> blackList) {
// Shulker Boxes
blackList.add("black_shulker_box");
blackList.add("blue_shulker_box");
blackList.add("brown_shulker_box");
blackList.add("cyan_shulker_box");
blackList.add("gray_shulker_box");
blackList.add("green_shulker_box");
blackList.add("light_blue_shulker_box");
blackList.add("lime_shulker_box");
blackList.add("magenta_shulker_box");
blackList.add("orange_shulker_box");
blackList.add("pink_shulker_box");
blackList.add("purple_shulker_box");
blackList.add("red_shulker_box");
blackList.add("light_gray_shulker_box");
blackList.add("white_shulker_box");
blackList.add("yellow_shulker_box");
blackList.add("shulker_box");
}
private void addMiscInteractableToBlackList(Set<String> blackList) {
blackList.add("bell");
blackList.add("barrel");
blackList.add("blast_furnace");
blackList.add("campfire");
blackList.add("soul_campfire");
blackList.add("cartography_table");
blackList.add("composter");
blackList.add("grindstone");
blackList.add("lectern");
blackList.add("loom");
blackList.add("scaffolding");
blackList.add("smoker");
blackList.add("stonecutter");
blackList.add("sweet_berry_bush");
blackList.add("smithing_table");
blackList.add("lodestone");
blackList.add("respawn_anchor");
blackList.add("chiseled_bookshelf");
blackList.add("brewing_stand");
blackList.add("bookshelf");
blackList.add("cake");
blackList.add("dispenser");
blackList.add("enchanting_table");
blackList.add("furnace");
blackList.add("jukebox");
blackList.add("lever");
blackList.add("note_block");
blackList.add("crafting_table");
blackList.add("beacon");
blackList.add("anvil");
blackList.add("dropper");
blackList.add("hopper");
blackList.add("armor_stand");
blackList.add("mannequin");
}
private void fillAbilityBlackList() { private void fillAbilityBlackList() {
abilityBlackList.add("warped_fence_gate"); addCommonToBlackList(abilityBlackList);
abilityBlackList.add("crimson_fence_gate");
abilityBlackList.add("warped_pressure_plate");
abilityBlackList.add("crimson_pressure_plate");
abilityBlackList.add("warped_button");
abilityBlackList.add("crimson_button");
abilityBlackList.add("warped_door");
abilityBlackList.add("crimson_door");
abilityBlackList.add("warped_trapdoor");
abilityBlackList.add("crimson_trapdoor");
abilityBlackList.add("black_bed");
abilityBlackList.add("blue_bed");
abilityBlackList.add("brown_bed");
abilityBlackList.add("cyan_bed");
abilityBlackList.add("gray_bed");
abilityBlackList.add("green_bed");
abilityBlackList.add("light_blue_bed");
abilityBlackList.add("light_gray_bed");
abilityBlackList.add("lime_bed");
abilityBlackList.add("magenta_bed");
abilityBlackList.add("orange_bed");
abilityBlackList.add("pink_bed");
abilityBlackList.add("purple_bed");
abilityBlackList.add("red_bed");
abilityBlackList.add("white_bed");
abilityBlackList.add("yellow_bed");
abilityBlackList.add("brewing_stand");
abilityBlackList.add("bookshelf");
abilityBlackList.add("cake");
abilityBlackList.add("chest");
abilityBlackList.add("dispenser");
abilityBlackList.add("enchanting_table");
abilityBlackList.add("ender_chest");
abilityBlackList.add("oak_fence_gate");
abilityBlackList.add("acacia_fence_gate");
abilityBlackList.add("dark_oak_fence_gate");
abilityBlackList.add("pale_oak_fence_gate");
abilityBlackList.add("spruce_fence_gate");
abilityBlackList.add("birch_fence_gate");
abilityBlackList.add("jungle_fence_gate");
abilityBlackList.add("furnace");
abilityBlackList.add("jukebox");
abilityBlackList.add("lever");
abilityBlackList.add("note_block");
abilityBlackList.add("stone_button");
abilityBlackList.add("oak_button");
abilityBlackList.add("birch_button");
abilityBlackList.add("acacia_button");
abilityBlackList.add("dark_oak_button");
abilityBlackList.add("pale_oak_button");
abilityBlackList.add("jungle_button");
abilityBlackList.add("spruce_button");
abilityBlackList.add("acacia_trapdoor");
abilityBlackList.add("birch_trapdoor");
abilityBlackList.add("dark_oak_trapdoor");
abilityBlackList.add("pale_oak_trapdoor");
abilityBlackList.add("jungle_trapdoor");
abilityBlackList.add("oak_trapdoor");
abilityBlackList.add("spruce_trapdoor");
abilityBlackList.add("acacia_sign");
abilityBlackList.add("acacia_wall_sign");
abilityBlackList.add("birch_sign");
abilityBlackList.add("birch_wall_sign");
abilityBlackList.add("dark_oak_sign");
abilityBlackList.add("pale_oak_sign");
abilityBlackList.add("dark_oak_wall_sign");
abilityBlackList.add("pale_oak_wall_sign");
abilityBlackList.add("jungle_sign");
abilityBlackList.add("jungle_wall_sign");
abilityBlackList.add("spruce_sign");
abilityBlackList.add("spruce_wall_sign");
abilityBlackList.add("oak_sign");
abilityBlackList.add("oak_wall_sign");
abilityBlackList.add("crafting_table");
abilityBlackList.add("beacon");
abilityBlackList.add("anvil");
abilityBlackList.add("dropper");
abilityBlackList.add("hopper");
abilityBlackList.add("trapped_chest");
abilityBlackList.add("iron_door");
abilityBlackList.add("iron_trapdoor");
abilityBlackList.add("oak_door");
abilityBlackList.add("acacia_door");
abilityBlackList.add("spruce_door");
abilityBlackList.add("birch_door");
abilityBlackList.add("jungle_door");
abilityBlackList.add("dark_oak_door");
abilityBlackList.add("pale_oak_door");
abilityBlackList.add("oak_fence");
abilityBlackList.add("acacia_fence");
abilityBlackList.add("dark_oak_fence");
abilityBlackList.add("pale_oak_fence");
abilityBlackList.add("birch_fence");
abilityBlackList.add("jungle_fence");
abilityBlackList.add("spruce_fence");
abilityBlackList.add("armor_stand");
abilityBlackList.add("black_shulker_box");
abilityBlackList.add("blue_shulker_box");
abilityBlackList.add("brown_shulker_box");
abilityBlackList.add("cyan_shulker_box");
abilityBlackList.add("gray_shulker_box");
abilityBlackList.add("green_shulker_box");
abilityBlackList.add("light_blue_shulker_box");
abilityBlackList.add("lime_shulker_box");
abilityBlackList.add("magenta_shulker_box");
abilityBlackList.add("orange_shulker_box");
abilityBlackList.add("pink_shulker_box");
abilityBlackList.add("purple_shulker_box");
abilityBlackList.add("red_shulker_box");
abilityBlackList.add("light_gray_shulker_box");
abilityBlackList.add("white_shulker_box");
abilityBlackList.add("yellow_shulker_box");
abilityBlackList.add("shulker_box");
abilityBlackList.add("wall_sign"); //1.13 and lower?
abilityBlackList.add("sign"); //1.13 and lower?
abilityBlackList.add("cartography_table");
abilityBlackList.add("grindstone");
abilityBlackList.add("lectern");
abilityBlackList.add("loom");
abilityBlackList.add("scaffolding");
abilityBlackList.add("smoker");
abilityBlackList.add("stonecutter");
abilityBlackList.add("sweet_berry_bush");
abilityBlackList.add("bell");
abilityBlackList.add("barrel");
abilityBlackList.add("blast_furnace");
abilityBlackList.add("campfire");
abilityBlackList.add("soul_campfire");
abilityBlackList.add("composter");
abilityBlackList.add("lodestone");
abilityBlackList.add("respawn_anchor");
} }
private void fillToolBlackList() { private void fillToolBlackList() {
toolBlackList.add("chiseled_bookshelf"); addCommonToBlackList(toolBlackList);
toolBlackList.add("black_bed"); // TODO: Organize later...
toolBlackList.add("blue_bed");
toolBlackList.add("brown_bed");
toolBlackList.add("cyan_bed");
toolBlackList.add("gray_bed");
toolBlackList.add("green_bed");
toolBlackList.add("light_blue_bed");
toolBlackList.add("light_gray_bed");
toolBlackList.add("lime_bed");
toolBlackList.add("magenta_bed");
toolBlackList.add("orange_bed");
toolBlackList.add("pink_bed");
toolBlackList.add("purple_bed");
toolBlackList.add("red_bed");
toolBlackList.add("white_bed");
toolBlackList.add("yellow_bed");
toolBlackList.add("brewing_stand");
toolBlackList.add("bookshelf");
toolBlackList.add("cake");
toolBlackList.add("chest");
toolBlackList.add("dispenser");
toolBlackList.add("enchanting_table");
toolBlackList.add("ender_chest");
toolBlackList.add("oak_fence_gate");
toolBlackList.add("acacia_fence_gate");
toolBlackList.add("dark_oak_fence_gate");
toolBlackList.add("pale_oak_fence_gate");
toolBlackList.add("spruce_fence_gate");
toolBlackList.add("birch_fence_gate");
toolBlackList.add("jungle_fence_gate");
toolBlackList.add("furnace");
toolBlackList.add("jukebox");
toolBlackList.add("lever");
toolBlackList.add("note_block");
toolBlackList.add("stone_button");
toolBlackList.add("oak_button");
toolBlackList.add("birch_button");
toolBlackList.add("acacia_button");
toolBlackList.add("dark_oak_button");
toolBlackList.add("pale_oak_button");
toolBlackList.add("jungle_button");
toolBlackList.add("spruce_button");
toolBlackList.add("acacia_trapdoor");
toolBlackList.add("birch_trapdoor");
toolBlackList.add("dark_oak_trapdoor");
toolBlackList.add("pale_oak_trapdoor");
toolBlackList.add("jungle_trapdoor");
toolBlackList.add("oak_trapdoor");
toolBlackList.add("spruce_trapdoor");
toolBlackList.add("crafting_table");
toolBlackList.add("beacon");
toolBlackList.add("anvil");
toolBlackList.add("dropper");
toolBlackList.add("hopper");
toolBlackList.add("trapped_chest");
toolBlackList.add("iron_door");
toolBlackList.add("iron_trapdoor");
toolBlackList.add("oak_door");
toolBlackList.add("acacia_door");
toolBlackList.add("spruce_door");
toolBlackList.add("birch_door");
toolBlackList.add("jungle_door");
toolBlackList.add("dark_oak_door");
toolBlackList.add("pale_oak_door");
toolBlackList.add("oak_fence");
toolBlackList.add("acacia_fence");
toolBlackList.add("dark_oak_fence");
toolBlackList.add("pale_oak_fence");
toolBlackList.add("birch_fence");
toolBlackList.add("jungle_fence");
toolBlackList.add("spruce_fence");
toolBlackList.add("armor_stand");
toolBlackList.add("black_shulker_box");
toolBlackList.add("blue_shulker_box");
toolBlackList.add("brown_shulker_box");
toolBlackList.add("cyan_shulker_box");
toolBlackList.add("gray_shulker_box");
toolBlackList.add("green_shulker_box");
toolBlackList.add("light_blue_shulker_box");
toolBlackList.add("lime_shulker_box");
toolBlackList.add("magenta_shulker_box");
toolBlackList.add("orange_shulker_box");
toolBlackList.add("pink_shulker_box");
toolBlackList.add("purple_shulker_box");
toolBlackList.add("red_shulker_box");
toolBlackList.add("light_gray_shulker_box");
toolBlackList.add("white_shulker_box");
toolBlackList.add("yellow_shulker_box");
toolBlackList.add("shulker_box");
toolBlackList.add("acacia_sign");
toolBlackList.add("acacia_hanging_sign");
toolBlackList.add("acacia_wall_sign");
toolBlackList.add("birch_sign");
toolBlackList.add("birch_hanging_sign");
toolBlackList.add("birch_wall_sign");
toolBlackList.add("dark_oak_sign");
toolBlackList.add("pale_oak_sign");
toolBlackList.add("dark_oak_hanging_sign");
toolBlackList.add("pale_oak_hanging_sign");
toolBlackList.add("dark_oak_wall_sign");
toolBlackList.add("pale_oak_wall_sign");
toolBlackList.add("jungle_sign");
toolBlackList.add("jungle_hanging_sign");
toolBlackList.add("jungle_wall_sign");
toolBlackList.add("spruce_sign");
toolBlackList.add("spruce_hanging_sign");
toolBlackList.add("spruce_wall_sign");
toolBlackList.add("oak_sign");
toolBlackList.add("oak_hanging_sign");
toolBlackList.add("oak_wall_sign");
toolBlackList.add("cherry_sign");
toolBlackList.add("cherry_hanging_sign");
toolBlackList.add("cherry_wall_sign");
toolBlackList.add("stripped_cherry_log"); toolBlackList.add("stripped_cherry_log");
toolBlackList.add("stripped_cherry_wood"); toolBlackList.add("stripped_cherry_wood");
toolBlackList.add("stripped_acacia_log"); toolBlackList.add("stripped_acacia_log");
@@ -1351,22 +1472,6 @@ public class MaterialMapStore {
toolBlackList.add("oak_log"); toolBlackList.add("oak_log");
toolBlackList.add("oak_wood"); toolBlackList.add("oak_wood");
toolBlackList.add("spruce_log"); toolBlackList.add("spruce_log");
toolBlackList.add("bell");
toolBlackList.add("barrel");
toolBlackList.add("blast_furnace");
toolBlackList.add("campfire");
toolBlackList.add("soul_campfire");
toolBlackList.add("cartography_table");
toolBlackList.add("composter");
toolBlackList.add("grindstone");
toolBlackList.add("lectern");
toolBlackList.add("loom");
toolBlackList.add("smoker");
toolBlackList.add("stonecutter");
toolBlackList.add("lodestone");
toolBlackList.add("respawn_anchor");
toolBlackList.add("sweet_berry_bush");
toolBlackList.add("smithing_table");
} }
public boolean isIntendedToolPickaxe(@NotNull Material material) { public boolean isIntendedToolPickaxe(@NotNull Material material) {

View File

@@ -1,5 +1,8 @@
package com.gmail.nossr50.util; package com.gmail.nossr50.util;
import static com.gmail.nossr50.listeners.EntityListener.isArmorStandEntity;
import static com.gmail.nossr50.listeners.EntityListener.isMannequinEntity;
import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.MobHealthbarType;
import com.gmail.nossr50.datatypes.meta.OldName; import com.gmail.nossr50.datatypes.meta.OldName;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
@@ -40,8 +43,12 @@ public final class MobHealthbarUtils {
* @param damage damage done by the attack triggering this * @param damage damage done by the attack triggering this
*/ */
public static void handleMobHealthbars(LivingEntity target, double damage, mcMMO plugin) { public static void handleMobHealthbars(LivingEntity target, double damage, mcMMO plugin) {
if (mcMMO.isHealthBarPluginEnabled() || !mcMMO.p.getGeneralConfig() if (isArmorStandEntity(target) || isMannequinEntity(target)) {
.getMobHealthbarEnabled()) { return;
}
if (mcMMO.isHealthBarPluginEnabled()
|| !mcMMO.p.getGeneralConfig().getMobHealthbarEnabled()) {
return; return;
} }
@@ -54,13 +61,13 @@ public final class MobHealthbarUtils {
return; return;
} }
String originalName = target.getName(); final String originalName = target.getName();
String oldName = target.getCustomName(); String oldName = target.getCustomName();
/* /*
* Store the name in metadata * Store the name in metadata
*/ */
if (target.getMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY).size() <= 0) { if (target.getMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY).isEmpty()) {
target.setMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY, target.setMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY,
new OldName(originalName, plugin)); new OldName(originalName, plugin));
} }

View File

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

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.util.skills;
import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP; import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP;
import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED; import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED;
import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag; import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag;
import static com.gmail.nossr50.util.Permissions.canUseSubSkill;
import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile; import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile;
import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.experience.ExperienceConfig;
@@ -19,6 +20,7 @@ import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.archery.ArcheryManager; import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager; import com.gmail.nossr50.skills.axes.AxesManager;
import com.gmail.nossr50.skills.maces.MacesManager; import com.gmail.nossr50.skills.maces.MacesManager;
import com.gmail.nossr50.skills.spears.SpearsManager;
import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.swords.SwordsManager;
import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.tridents.TridentsManager; import com.gmail.nossr50.skills.tridents.TridentsManager;
@@ -58,7 +60,7 @@ import org.jetbrains.annotations.Nullable;
public final class CombatUtils { public final class CombatUtils {
private static final ThreadLocal<Boolean> IN_MCMO_DAMAGE private static final ThreadLocal<Boolean> IN_MCMMO_DAMAGE
= ThreadLocal.withInitial(() -> false); = ThreadLocal.withInitial(() -> false);
@@ -75,14 +77,14 @@ public final class CombatUtils {
*/ */
public static void safeDealDamage(@NotNull LivingEntity target, double amount, public static void safeDealDamage(@NotNull LivingEntity target, double amount,
@Nullable Entity attacker) { @Nullable Entity attacker) {
boolean prev = IN_MCMO_DAMAGE.get(); boolean prev = IN_MCMMO_DAMAGE.get();
if (prev || target.isDead()) { if (prev || target.isDead()) {
return; return;
} }
try { try {
IN_MCMO_DAMAGE.set(true); IN_MCMMO_DAMAGE.set(true);
if (!hasIgnoreDamageMetadata(target)) { if (!hasIgnoreDamageMetadata(target)) {
applyIgnoreDamageMetadata(target); applyIgnoreDamageMetadata(target);
} }
@@ -93,7 +95,7 @@ public final class CombatUtils {
target.damage(amount); target.damage(amount);
} }
} finally { } finally {
IN_MCMO_DAMAGE.set(false); IN_MCMMO_DAMAGE.set(false);
if (hasIgnoreDamageMetadata(target)) { if (hasIgnoreDamageMetadata(target)) {
removeIgnoreDamageMetadata(target); removeIgnoreDamageMetadata(target);
} }
@@ -331,6 +333,46 @@ public final class CombatUtils {
printFinalDamageDebug(player, event, mmoPlayer); printFinalDamageDebug(player, event, mmoPlayer);
} }
private static void processSpearsCombat(@NotNull LivingEntity target,
@NotNull Player player,
@NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
}
double boostedDamage = event.getDamage();
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if (mmoPlayer == null) {
return;
}
final SpearsManager spearsManager = mmoPlayer.getSpearsManager();
if (canUseSubSkill(player, SubSkillType.SPEARS_SPEAR_MASTERY)) {
boostedDamage += spearsManager.getSpearMasteryBonusDamage()
* mmoPlayer.getAttackStrength();
}
// Apply Limit Break DMG
if (canUseLimitBreak(player, target, SubSkillType.SPEARS_SPEARS_LIMIT_BREAK)) {
boostedDamage += (getLimitBreakDamage(
player, target, SubSkillType.SPEARS_SPEARS_LIMIT_BREAK)
* mmoPlayer.getAttackStrength());
}
event.setDamage(boostedDamage);
// Apply any non-damage effects here
spearsManager.potentiallyApplyMomentum();
processCombatXP(mmoPlayer, target, PrimarySkillType.SPEARS);
printFinalDamageDebug(player, event, mmoPlayer);
}
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player,
@NotNull EntityDamageByEntityEvent event) { @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) { if (event.getCause() == DamageCause.THORNS) {
@@ -391,6 +433,11 @@ public final class CombatUtils {
double boostedDamage = event.getDamage(); double boostedDamage = event.getDamage();
// TODO: Temporary hack to avoid unintended spear / unarmed interactions
if (ItemUtils.isSpear(player.getInventory().getItemInOffHand())) {
return;
}
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player); final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded //Make sure the profiles been loaded
@@ -642,6 +689,15 @@ public final class CombatUtils {
.doesPlayerHaveSkillPermission(player, PrimarySkillType.MACES)) { .doesPlayerHaveSkillPermission(player, PrimarySkillType.MACES)) {
processMacesCombat(target, player, event); processMacesCombat(target, player, event);
} }
} else if (ItemUtils.isSpear(heldItem)) {
if (!mcMMO.p.getSkillTools()
.canCombatSkillsTrigger(PrimarySkillType.SPEARS, target)) {
return;
}
if (mcMMO.p.getSkillTools()
.doesPlayerHaveSkillPermission(player, PrimarySkillType.SPEARS)) {
processSpearsCombat(target, player, event);
}
} }
} else if (entityType == EntityType.WOLF) { } else if (entityType == EntityType.WOLF) {
Wolf wolf = (Wolf) painSource; Wolf wolf = (Wolf) painSource;
@@ -935,7 +991,8 @@ public final class CombatUtils {
XPGainReason xpGainReason; XPGainReason xpGainReason;
if (target instanceof Player defender) { if (target instanceof Player defender) {
if (!ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled() if (defender.equals(mmoPlayer.getPlayer())
|| !ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled()
|| ||
(mcMMO.p.getPartyConfig().isPartyEnabled() (mcMMO.p.getPartyConfig().isPartyEnabled()
&& mcMMO.p.getPartyManager() && mcMMO.p.getPartyManager()

View File

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

View File

@@ -4,6 +4,8 @@ import com.gmail.nossr50.config.SoundConfig;
import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Misc;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.SoundCategory; import org.bukkit.SoundCategory;
@@ -11,12 +13,12 @@ import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class SoundManager { public class SoundManager {
private static final Map<SoundType, Sound> soundCache = new ConcurrentHashMap<>();
private static final String NULL_FALLBACK_ID = null;
private static Sound CRIPPLE_SOUND; private static Sound CRIPPLE_SOUND;
private static final String ITEM_MACE_SMASH_GROUND = "ITEM_MACE_SMASH_GROUND"; private static final String ITEM_MACE_SMASH_GROUND = "ITEM_MACE_SMASH_GROUND";
private static final String VALUE_OF = "valueOf"; private static final String VALUE_OF = "valueOf";
private static final String ORG_BUKKIT_SOUND = "org.bukkit.Sound"; private static final String ORG_BUKKIT_SOUND = "org.bukkit.Sound";
/** /**
@@ -98,16 +100,78 @@ public class SoundManager {
} }
private static float getPitch(SoundType soundType) { private static float getPitch(SoundType soundType) {
if (soundType == SoundType.FIZZ) { return switch (soundType)
return getFizzPitch(); {
} else if (soundType == SoundType.POP) { case FIZZ -> getFizzPitch();
return getPopPitch(); case POP -> getPopPitch();
} else { default -> SoundConfig.getInstance().getPitch(soundType);
return SoundConfig.getInstance().getPitch(soundType); };
}
} }
private static Sound getSound(SoundType soundType) { private static Sound getSound(SoundType soundType) {
final String soundId = SoundConfig.getInstance().getSound(soundType);
// Legacy versions use a different lookup method
if (SoundRegistryUtils.useLegacyLookup()) {
return getSoundLegacyCustom(soundId, soundType);
}
if (soundCache.containsKey(soundType)) {
return soundCache.get(soundType);
}
Sound sound;
if (soundId != null && !soundId.isEmpty()) {
sound = SoundRegistryUtils.getSound(soundId, soundType.id());
} else {
sound = SoundRegistryUtils.getSound(soundType.id(), NULL_FALLBACK_ID);
}
if (sound != null) {
soundCache.putIfAbsent(soundType, sound);
return sound;
}
throw new RuntimeException("Could not find Sound for SoundType: " + soundType);
}
private static Sound getSoundLegacyCustom(String id, SoundType soundType) {
if (soundCache.containsKey(soundType)) {
return soundCache.get(soundType);
}
// Try to look up a custom legacy sound
if (id != null && !id.isEmpty()) {
Sound sound;
if (Sound.class.isEnum()) {
// Sound is only an ENUM in legacy versions
// Use reflection to loop through the values, finding the first enum matching our ID
try {
Method method = Sound.class.getMethod("getKey");
for (Object legacyEnumEntry : Sound.class.getEnumConstants()) {
// This enum extends Keyed which adds the getKey() method
// we need to invoke this method to get the NamespacedKey and compare to our ID
if (method.invoke(legacyEnumEntry).toString().equals(id)) {
sound = (Sound) legacyEnumEntry;
soundCache.putIfAbsent(soundType, sound);
return sound;
}
}
} catch (NoSuchMethodException | InvocationTargetException |
IllegalAccessException e) {
// Ignore
}
}
throw new RuntimeException("Unable to find legacy sound by ID %s for SoundType %s"
.formatted(id, soundType));
}
// Failsafe -- we haven't found a matching sound
final Sound sound = getSoundLegacyFallBack(soundType);
soundCache.putIfAbsent(soundType, sound);
return sound;
}
private static Sound getSoundLegacyFallBack(SoundType soundType) {
return switch (soundType) { return switch (soundType) {
case ANVIL -> Sound.BLOCK_ANVIL_PLACE; case ANVIL -> Sound.BLOCK_ANVIL_PLACE;
case ITEM_BREAK -> Sound.ENTITY_ITEM_BREAK; case ITEM_BREAK -> Sound.ENTITY_ITEM_BREAK;
@@ -153,8 +217,4 @@ public class SoundManager {
public static float getPopPitch() { public static float getPopPitch() {
return ((Misc.getRandom().nextFloat() - Misc.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F; return ((Misc.getRandom().nextFloat() - Misc.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F;
} }
public static float getKrakenPitch() {
return (Misc.getRandom().nextFloat() - Misc.getRandom().nextFloat()) * 0.2F + 1.0F;
}
} }

View File

@@ -0,0 +1,91 @@
package com.gmail.nossr50.util.sounds;
import static java.lang.String.format;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.AttributeMapper;
import com.gmail.nossr50.util.LogUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.jetbrains.annotations.Nullable;
public final class SoundRegistryUtils {
private static Method registryLookup;
private static Object soundReg;
public static final String PAPER_SOUND_REGISTRY_FIELD = "SOUND_EVENT";
public static final String SPIGOT_SOUND_REGISTRY_FIELD = "SOUNDS";
public static final String METHOD_GET_OR_THROW_NAME = "getOrThrow";
public static final String METHOD_GET_NAME = "get";
static {
boolean foundRegistry = false;
Class<?> registry;
try {
registry = Class.forName(AttributeMapper.ORG_BUKKIT_REGISTRY);
try {
// First check for Paper's sound registry, held by field SOUND_EVENT
soundReg = registry.getField(PAPER_SOUND_REGISTRY_FIELD).get(null);
foundRegistry = true;
} catch (NoSuchFieldException | IllegalAccessException e) {
try {
soundReg = registry.getField(SPIGOT_SOUND_REGISTRY_FIELD);
foundRegistry = true;
} catch (NoSuchFieldException ex) {
// ignored
}
}
} catch (ClassNotFoundException e) {
// ignored
}
if (foundRegistry) {
try {
// getOrThrow isn't in all API versions, but we use it if it exists
registryLookup = soundReg.getClass().getMethod(METHOD_GET_OR_THROW_NAME,
NamespacedKey.class);
} catch (NoSuchMethodException e) {
try {
registryLookup = soundReg.getClass().getMethod(METHOD_GET_NAME,
NamespacedKey.class);
} catch (NoSuchMethodException ex) {
// ignored exception
registryLookup = null;
}
}
}
}
public static boolean useLegacyLookup() {
return registryLookup == null;
}
public static @Nullable Sound getSound(String id, String fallBackId) {
if (registryLookup != null) {
try {
return (Sound) registryLookup.invoke(soundReg, NamespacedKey.fromString(id));
} catch(InvocationTargetException | IllegalAccessException
| IllegalArgumentException e) {
if (fallBackId != null) {
LogUtils.debug(mcMMO.p.getLogger(),
format("Could not find sound with ID '%s', trying fallback ID '%s'", id,
fallBackId));
try {
return (Sound) registryLookup.invoke(soundReg,
NamespacedKey.fromString(fallBackId));
} catch (IllegalAccessException | InvocationTargetException ex) {
mcMMO.p.getLogger().severe(format("Could not find sound with ID %s,"
+ " fallback ID of %s also failed.", id, fallBackId));
}
} else {
mcMMO.p.getLogger().severe(format("Could not find sound with ID %s.", id));
}
throw new RuntimeException(e);
}
}
return null;
}
}

View File

@@ -1,31 +1,39 @@
package com.gmail.nossr50.util.sounds; package com.gmail.nossr50.util.sounds;
public enum SoundType { public enum SoundType {
ANVIL, ANVIL("minecraft:block.anvil.place"),
LEVEL_UP, ITEM_BREAK("minecraft:entity.item.break"),
FIZZ, POP("minecraft:entity.item.pickup"),
ITEM_BREAK, CHIMAERA_WING("minecraft:entity.bat.takeoff"),
POP, LEVEL_UP("minecraft:entity.player.levelup"),
CHIMAERA_WING, FIZZ("minecraft:block.fire.extinguish"),
ROLL_ACTIVATED, TOOL_READY("minecraft:item.armor.equip_gold"),
SKILL_UNLOCKED, ROLL_ACTIVATED("minecraft:entity.llama.swag"),
DEFLECT_ARROWS, SKILL_UNLOCKED("minecraft:ui.toast.challenge_complete"),
TOOL_READY, ABILITY_ACTIVATED_BERSERK("minecraft:block.conduit.ambient"),
ABILITY_ACTIVATED_GENERIC, TIRED("minecraft:block.conduit.ambient"),
ABILITY_ACTIVATED_BERSERK, ABILITY_ACTIVATED_GENERIC("minecraft:item.trident.riptide_3"),
BLEED, DEFLECT_ARROWS("minecraft:entity.ender_eye.death"),
GLASS, BLEED("minecraft:entity.ender_eye.death"),
ITEM_CONSUMED, GLASS("minecraft:block.glass.break"),
CRIPPLE, ITEM_CONSUMED("minecraft:item.bottle.empty"),
TIRED; CRIPPLE("minecraft:block.anvil.place");
public boolean usesCustomPitch() { private final String soundRegistryId;
switch (this) {
case POP: SoundType(String soundRegistryId) {
case FIZZ: this.soundRegistryId = soundRegistryId;
return true;
default:
return false;
} }
public String id() {
return soundRegistryId;
}
public boolean usesCustomPitch()
{
return switch (this) {
case POP, FIZZ -> true;
default -> false;
};
} }
} }

View File

@@ -544,8 +544,26 @@ public class TextComponentFactory {
componentBuilder.append(Component.newline()); componentBuilder.append(Component.newline());
} }
/**
* @deprecated use appendSubSkillTextComponents(Player, List<Component>, PrimarySkillType)
* @param player target player
* @param textComponents list to append to
* @param parentSkill the parent skill
*/
@Deprecated(since = "2.2.046", forRemoval = true)
public static void getSubSkillTextComponents(Player player, List<Component> textComponents, public static void getSubSkillTextComponents(Player player, List<Component> textComponents,
PrimarySkillType parentSkill) { 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()) { for (SubSkillType subSkillType : SubSkillType.values()) {
if (subSkillType.getParentSkill() == parentSkill) { if (subSkillType.getParentSkill() == parentSkill) {
//TODO: Hacky rewrite later //TODO: Hacky rewrite later

View File

@@ -111,7 +111,7 @@ public class TextUtils {
} }
public static @NotNull TextComponent ofBungeeComponents(@NotNull BaseComponent[] bungeeName) { public static @NotNull TextComponent ofBungeeComponents(@NotNull BaseComponent[] bungeeName) {
return TextComponent.ofChildren( return Component.textOfChildren(
mcMMO.getCompatibilityManager().getBungeeSerializerCompatibilityLayer() mcMMO.getCompatibilityManager().getBungeeSerializerCompatibilityLayer()
.deserialize(bungeeName)); .deserialize(bungeeName));
} }

View File

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

View File

@@ -229,6 +229,7 @@ Hardcore:
Tridents: false Tridents: false
Crossbows: false Crossbows: false
Maces: false Maces: false
Spears: false
Vampirism: Vampirism:
Leech_Percentage: 5.0 Leech_Percentage: 5.0
Level_Threshold: 0 Level_Threshold: 0
@@ -249,6 +250,7 @@ Hardcore:
Tridents: false Tridents: false
Crossbows: false Crossbows: false
Maces: false Maces: false
Spears: false
# #
# Settings for SMP Mods # Settings for SMP Mods
@@ -427,6 +429,10 @@ Skills:
Enabled_For_PVP: true Enabled_For_PVP: true
Enabled_For_PVE: true Enabled_For_PVE: true
Level_Cap: 0 Level_Cap: 0
Spears:
Enabled_For_PVP: true
Enabled_For_PVE: true
Level_Cap: 0
Taming: Taming:
Enabled_For_PVP: true Enabled_For_PVP: true
Enabled_For_PVE: true Enabled_For_PVE: true
@@ -460,7 +466,7 @@ Skills:
Enabled_For_PVE: true Enabled_For_PVE: true
Level_Cap: 0 Level_Cap: 0
Block_Cracker: Block_Cracker:
SmoothBrick_To_CrackedBrick: true Allow_Block_Cracker: true
# When using Unarmed, picked up items will automatically get moved to a free slot instead of going in the slot # When using Unarmed, picked up items will automatically get moved to a free slot instead of going in the slot
# of your hand. Should item pickup be disabled when your entire inventory - except for your hand - is full? # of your hand. Should item pickup be disabled when your entire inventory - except for your hand - is full?
Item_Pickup_Disabled_Full_Inventory: true Item_Pickup_Disabled_Full_Inventory: true

View File

@@ -30,6 +30,7 @@ ExploitFix:
PistonCheating: true PistonCheating: true
SnowGolemExcavation: true SnowGolemExcavation: true
PreventArmorStandInteraction: true PreventArmorStandInteraction: true
PreventMannequinInteraction: true
# This include NPCs from stuff like Citizens, this is not a setting for Vanilla Minecraft Villagers (Which can be considered NPCs) # This include NPCs from stuff like Citizens, this is not a setting for Vanilla Minecraft Villagers (Which can be considered NPCs)
# mcMMO normally doesn't process attacks against an Entity if it is an NPC from another plugin # mcMMO normally doesn't process attacks against an Entity if it is an NPC from another plugin
# Of course, mcMMO doesn't know for sure whether something is an NPC, it checks a few known things, see our source code to see how # Of course, mcMMO doesn't know for sure whether something is an NPC, it checks a few known things, see our source code to see how
@@ -94,6 +95,10 @@ Experience_Bars:
Enable: true Enable: true
Color: BLUE Color: BLUE
BarStyle: SEGMENTED_6 BarStyle: SEGMENTED_6
Spears:
Enable: true
Color: BLUE
BarStyle: SEGMENTED_6
Repair: Repair:
Enable: true Enable: true
Color: PURPLE Color: PURPLE
@@ -166,6 +171,7 @@ Experience_Formula:
# Experience gained will get multiplied by these values. 1.0 by default, 0.5 means half XP gained. This happens right before multiplying the XP by the global multiplier. # Experience gained will get multiplied by these values. 1.0 by default, 0.5 means half XP gained. This happens right before multiplying the XP by the global multiplier.
Skill_Multiplier: Skill_Multiplier:
Spears: 1.0
Maces: 1.0 Maces: 1.0
Crossbows: 1.0 Crossbows: 1.0
Tridents: 1.0 Tridents: 1.0
@@ -217,6 +223,7 @@ Diminished_Returns:
Crossbows: 20000 Crossbows: 20000
Tridents: 20000 Tridents: 20000
Maces: 20000 Maces: 20000
Spears: 20000
Time_Interval: 10 Time_Interval: 10
@@ -553,6 +560,7 @@ Experience_Values:
String: 1.8 String: 1.8
Other: 1.5 Other: 1.5
Smelting: Smelting:
Copper_Nugget: 85
Raw_Copper: 75 Raw_Copper: 75
Deepslate_Redstone_Ore: 30 Deepslate_Redstone_Ore: 30
Deepslate_Copper_Ore: 100 Deepslate_Copper_Ore: 100
@@ -580,6 +588,7 @@ Experience_Values:
Taming: Taming:
Animal_Taming: Animal_Taming:
Camel: 1300 Camel: 1300
Camel_Husk: 1300
Sniffer: 1500 Sniffer: 1500
Snifflet: 900 Snifflet: 900
Llama: 1200 Llama: 1200
@@ -598,12 +607,15 @@ Experience_Values:
Goat: 250 Goat: 250
Axolotl: 600 Axolotl: 600
Frog: 900 Frog: 900
Nautilus: 1700
Zombie_Nautilus: 1700
Combat: Combat:
Multiplier: Multiplier:
Animals: 1.0 Animals: 1.0
Armadillo: 1.1 Armadillo: 1.1
Creeper: 4.0 Creeper: 4.0
Skeleton: 3.0 Skeleton: 3.0
Parched: 2.5
Spider: 2.0 Spider: 2.0
Giant: 4.0 Giant: 4.0
Zombie: 2.0 Zombie: 2.0
@@ -621,6 +633,7 @@ Experience_Values:
Wither: 1.0 Wither: 1.0
Witch: 0.1 Witch: 0.1
Iron_Golem: 2.0 Iron_Golem: 2.0
Copper_Golem: 1.0
Wither_Skeleton: 4.0 Wither_Skeleton: 4.0
Endermite: 2.0 Endermite: 2.0
Guardian: 1.0 Guardian: 1.0
@@ -680,5 +693,8 @@ Experience_Values:
Sniffer: 1.1 Sniffer: 1.1
Snifflet: 1.1 Snifflet: 1.1
Camel: 1.2 Camel: 1.2
Camel_Husk: 1.25
Bogged: 2.0 Bogged: 2.0
Breeze: 4.0 Breeze: 4.0
Armor_Stand: 0.0
Mannequin: 0.0

View File

@@ -63,6 +63,26 @@ Fishing:
Amount: 1 Amount: 1
XP: 200 XP: 200
Rarity: UNCOMMON Rarity: UNCOMMON
COPPER_SWORD:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_SHOVEL:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_PICKAXE:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_AXE:
Amount: 1
XP: 200
Rarity: UNCOMMON
COPPER_HOE:
Amount: 1
XP: 200
Rarity: UNCOMMON
GOLDEN_SWORD: GOLDEN_SWORD:
Amount: 1 Amount: 1
XP: 200 XP: 200
@@ -143,6 +163,22 @@ Fishing:
Amount: 1 Amount: 1
XP: 200 XP: 200
Rarity: RARE Rarity: RARE
COPPER_BOOTS:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_HELMET:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_LEGGINGS:
Amount: 1
XP: 200
Rarity: COMMON
COPPER_CHESTPLATE:
Amount: 1
XP: 200
Rarity: COMMON
IRON_BOOTS: IRON_BOOTS:
Amount: 1 Amount: 1
XP: 200 XP: 200

View File

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

View File

@@ -1,7 +1,4 @@
#I'm going to try to normalize our locale file, forgive the mess for now. #Placeholder= This value is for any WIP locale entries that will not be displayed to users #TODO REMOVE
#DO NOT USE COLOR CODES IN THE JSON KEYS
#COLORS ARE DEFINED IN advanced.yml IF YOU WISH TO CHANGE THEM
JSON.Rank=Grado JSON.Rank=Grado
JSON.DescriptionHeader=Descrizione JSON.DescriptionHeader=Descrizione
JSON.JWrapper.Header=Dettagli JSON.JWrapper.Header=Dettagli
@@ -20,6 +17,7 @@ JSON.Acrobatics=Acrobatica
JSON.Alchemy=Alchimia JSON.Alchemy=Alchimia
JSON.Archery=Tiro con l'Arco JSON.Archery=Tiro con l'Arco
JSON.Axes=Asce JSON.Axes=Asce
JSON.Crossbows=Balestre
JSON.Excavation=Scavo JSON.Excavation=Scavo
JSON.Fishing=Pesca JSON.Fishing=Pesca
JSON.Herbalism=Erboristeria JSON.Herbalism=Erboristeria
@@ -28,6 +26,8 @@ JSON.Repair=Riparazione
JSON.Salvage=Rottamazione JSON.Salvage=Rottamazione
JSON.Swords=Spade JSON.Swords=Spade
JSON.Taming=Domesticazione JSON.Taming=Domesticazione
JSON.Tridents=Tridenti
JSON.Maces=Mazze
JSON.Unarmed=Lotta JSON.Unarmed=Lotta
JSON.Woodcutting=Taglialegna JSON.Woodcutting=Taglialegna
JSON.URL.Website=Il sito web ufficiale di mcMMO! JSON.URL.Website=Il sito web ufficiale di mcMMO!
@@ -39,7 +39,6 @@ JSON.URL.Wiki=La wiki ufficiale di mcMMO!
JSON.SkillUnlockMessage=&6[ mcMMO&e @&3{0} &6Grado &3{1}&6 Sbloccato! ] JSON.SkillUnlockMessage=&6[ mcMMO&e @&3{0} &6Grado &3{1}&6 Sbloccato! ]
JSON.Hover.Rank=&e&lGrado:&r &f{0} JSON.Hover.Rank=&e&lGrado:&r &f{0}
JSON.Hover.NextRank=&7&oProssimo upgrade al livello {0} JSON.Hover.NextRank=&7&oProssimo upgrade al livello {0}
# for JSON.Hover.Mystery you can add {0} to insert the level required into the name, I don't like how that looks so I'm not doing that atm # for JSON.Hover.Mystery you can add {0} to insert the level required into the name, I don't like how that looks so I'm not doing that atm
JSON.Hover.Mystery=&7??? JSON.Hover.Mystery=&7???
JSON.Hover.Mystery2=&e[&8{0}&e]&8???&r JSON.Hover.Mystery2=&e[&8{0}&e]&8???&r
@@ -82,13 +81,13 @@ Overhaul.mcMMO.Header=&c[]=====[]&a mcMMO - Era della Revisione &c[]=====[]
Overhaul.mcMMO.Url.Wrap.Prefix=&c[| Overhaul.mcMMO.Url.Wrap.Prefix=&c[|
Overhaul.mcMMO.Url.Wrap.Suffix=&c|] Overhaul.mcMMO.Url.Wrap.Suffix=&c|]
Overhaul.mcMMO.MmoInfo.Wiki=&e[&fVisualizza questa abilità sulla wiki!&e] Overhaul.mcMMO.MmoInfo.Wiki=&e[&fVisualizza questa abilità sulla wiki!&e]
# Overhaul.Levelup can take {0} - Skill Name defined in Overhaul.Name {1} - Amount of levels gained {2} - Level in skill # Overhaul.Levelup can take {0} - Skill Name defined in Overhaul.Name {1} - Amount of levels gained {2} - Level in skill
Overhaul.Levelup=&l{0} è aumentata a &r&a&l{2}&r&f. Overhaul.Levelup=&l{0} è aumentata a &r&a&l{2}&r&f.
Overhaul.Name.Acrobatics=Acrobatica Overhaul.Name.Acrobatics=Acrobatica
Overhaul.Name.Alchemy=Alchimia Overhaul.Name.Alchemy=Alchimia
Overhaul.Name.Archery=Tiro con l'Arco Overhaul.Name.Archery=Tiro con l'Arco
Overhaul.Name.Axes=Asce Overhaul.Name.Axes=Asce
Overhaul.Name.Crossbows=Balestre
Overhaul.Name.Excavation=Scavo Overhaul.Name.Excavation=Scavo
Overhaul.Name.Fishing=Pesca Overhaul.Name.Fishing=Pesca
Overhaul.Name.Herbalism=Erboristeria Overhaul.Name.Herbalism=Erboristeria
@@ -98,15 +97,15 @@ Overhaul.Name.Salvage=Rottamazione
Overhaul.Name.Smelting=Fusione Overhaul.Name.Smelting=Fusione
Overhaul.Name.Swords=Spade Overhaul.Name.Swords=Spade
Overhaul.Name.Taming=Domesticazione Overhaul.Name.Taming=Domesticazione
Overhaul.Name.Tridents=Tridenti
Overhaul.Name.Maces=Mazze
Overhaul.Name.Unarmed=Lotta Overhaul.Name.Unarmed=Lotta
Overhaul.Name.Woodcutting=Taglialegna Overhaul.Name.Woodcutting=Taglialegna
# /mcMMO Command Style Stuff # /mcMMO Command Style Stuff
Commands.mcc.Header=&c---[]&aComandi mcMMO&c[]--- Commands.mcc.Header=&c---[]&aComandi mcMMO&c[]---
Commands.Other=&c---[]&aCOMANDI SPECIALI&c[]--- Commands.Other=&c---[]&aCOMANDI SPECIALI&c[]---
Commands.Party.Header=&c-----[]&aPARTY&c[]----- Commands.Party.Header=&c-----[]&aPARTY&c[]-----
Commands.Party.Features.Header=&c-----[]&aFUNZIONALITà&c[]----- Commands.Party.Features.Header=&c-----[]&aFUNZIONALITà&c[]-----
# XP BAR Allows for the following variables -- {0} = Skill Level, {1} Current XP, {2} XP Needed for next level, {3} Power Level, {4} Percentage of Level # XP BAR Allows for the following variables -- {0} = Skill Level, {1} Current XP, {2} XP Needed for next level, {3} Power Level, {4} Percentage of Level
# Make sure you turn on Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained if you want the XP bar title to update every time a player gains XP! # Make sure you turn on Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained if you want the XP bar title to update every time a player gains XP!
XPBar.Template={0} XPBar.Template={0}
@@ -114,9 +113,10 @@ XPBar.Template.EarlyGameBoost=&6Imparando una nuova abilità...
XPBar.Acrobatics=Acrobatica Lv.&6{0} XPBar.Acrobatics=Acrobatica Lv.&6{0}
XPBar.Alchemy=Alchimia Lv.&6{0} XPBar.Alchemy=Alchimia Lv.&6{0}
XPBar.Archery=Tiro con l'Arco Lv.&6{0} XPBar.Archery=Tiro con l'Arco Lv.&6{0}
XPBar.Axes=Axes Lv.&6{0} XPBar.Axes=Asce Lv.&6{0}
XPBar.Crossbows=Balestre Lv.&6{0}
XPBar.Excavation=Scavo Lv.&6{0} XPBar.Excavation=Scavo Lv.&6{0}
XPBar.Fishing=Fishing Lv.&6{0} XPBar.Fishing=Pesca Lv.&6{0}
XPBar.Herbalism=Erboristeria Lv.&6{0} XPBar.Herbalism=Erboristeria Lv.&6{0}
XPBar.Mining=Estrazione Lv.&6{0} XPBar.Mining=Estrazione Lv.&6{0}
XPBar.Repair=Riparazione Lv.&6{0} XPBar.Repair=Riparazione Lv.&6{0}
@@ -124,6 +124,8 @@ XPBar.Salvage=Rottamazione Lv.&6{0}
XPBar.Smelting=Fusione Lv.&6{0} XPBar.Smelting=Fusione Lv.&6{0}
XPBar.Swords=Spade Lv.&6{0} XPBar.Swords=Spade Lv.&6{0}
XPBar.Taming=Domesticazione Lv.&6{0} XPBar.Taming=Domesticazione Lv.&6{0}
XPBar.Tridents=Tridenti Lv.&6{0}
XPBar.Maces=Mazze Lv.&6{0}
XPBar.Unarmed=Lotta Lv.&6{0} XPBar.Unarmed=Lotta Lv.&6{0}
XPBar.Woodcutting=Taglialegna Lv.&6{0} XPBar.Woodcutting=Taglialegna Lv.&6{0}
#This is just a preset template that gets used if the 'ExtraDetails' setting is turned on in experience.yml (off by default), you can ignore this template and just edit the strings above #This is just a preset template that gets used if the 'ExtraDetails' setting is turned on in experience.yml (off by default), you can ignore this template and just edit the strings above
@@ -151,7 +153,6 @@ Acrobatics.SubSkill.Dodge.Stat=Possibilità di Schivata
Acrobatics.Listener=Acrobatica: Acrobatics.Listener=Acrobatica:
Acrobatics.Roll.Text=&o**Capriola Eseguita** Acrobatics.Roll.Text=&o**Capriola Eseguita**
Acrobatics.SkillName=ACROBATICA Acrobatics.SkillName=ACROBATICA
#ALCHEMY #ALCHEMY
Alchemy.SubSkill.Catalysis.Name=Catalisi Alchemy.SubSkill.Catalysis.Name=Catalisi
Alchemy.SubSkill.Catalysis.Description=Aumenta la velocità di preparazione delle pozioni Alchemy.SubSkill.Catalysis.Description=Aumenta la velocità di preparazione delle pozioni
@@ -163,7 +164,6 @@ Alchemy.SubSkill.Concoctions.Stat.Extra=Ingredienti [&a{0}&3]: &a{1}
Alchemy.Listener=Alchimia: Alchemy.Listener=Alchimia:
Alchemy.Ability.Locked.0=BLOCCATO FINO AD ABILITà {0}+ (CATALISI) Alchemy.Ability.Locked.0=BLOCCATO FINO AD ABILITà {0}+ (CATALISI)
Alchemy.SkillName=ALCHIMIA Alchemy.SkillName=ALCHIMIA
#ARCHERY #ARCHERY
Archery.SubSkill.SkillShot.Name=Tiro da Maestro Archery.SubSkill.SkillShot.Name=Tiro da Maestro
Archery.SubSkill.SkillShot.Description=Aumenta il danno inflitto con gli archi Archery.SubSkill.SkillShot.Description=Aumenta il danno inflitto con gli archi
@@ -179,7 +179,13 @@ Archery.SubSkill.ArcheryLimitBreak.Description=Supera i tuoi limiti. Danni aumen
Archery.SubSkill.ArcheryLimitBreak.Stat=Danno Massimo di Danni Aumentati Archery.SubSkill.ArcheryLimitBreak.Stat=Danno Massimo di Danni Aumentati
Archery.Listener=Tiro con l'Arco: Archery.Listener=Tiro con l'Arco:
Archery.SkillName=ARCO Archery.SkillName=ARCO
Archery.SubSkill.ExplosiveShot.Name=Tiro Esplosivo
Archery.SubSkill.ExplosiveShot.Description=Scocca una freccia esplosiva
Archery.Skills.ExplosiveShot.Off=
Archery.Skills.ExplosiveShot.On=&a**TIRO ESPLOSIVO ATTIVATO**
Archery.Skills.ExplosiveShot.Other.Off=Tiro esplosivo&a si è esaurito per &e{0}
Archery.Skills.ExplosiveShot.Other.On=&a{0}&2 ha usato &cTiro Esplosivo!
Archery.Skills.ExplosiveShot.Refresh=&aLa tua capacità &eTiro esplosivo &asi è rigenerata!
#AXES #AXES
Axes.Ability.Bonus.0=Maestria con l'Ascia Axes.Ability.Bonus.0=Maestria con l'Ascia
Axes.Ability.Bonus.1={0} Danni Bonus Axes.Ability.Bonus.1={0} Danni Bonus
@@ -189,6 +195,7 @@ Axes.Ability.Bonus.4=Impatto Migliorato
Axes.Ability.Bonus.5=Infligge {0} danni bonus ai nemici senza armatura Axes.Ability.Bonus.5=Infligge {0} danni bonus ai nemici senza armatura
Axes.Ability.Lower=&7Abbassi l'Ascia. Axes.Ability.Lower=&7Abbassi l'Ascia.
Axes.Ability.Ready=&6Prepari&3 l'Ascia. Axes.Ability.Ready=&6Prepari&3 l'Ascia.
Axes.Ability.Ready.Extra=&6Prepari&3 l'Ascia. &7({0} è in recupero per {1}s)
Axes.Combat.CritStruck=&4Hai subito un colpo CRITICO! Axes.Combat.CritStruck=&4Hai subito un colpo CRITICO!
Axes.Combat.CriticalHit=COLPO CRITICO! Axes.Combat.CriticalHit=COLPO CRITICO!
Axes.Combat.GI.Proc=&a**COLPITO CON GRANDE FORZA** Axes.Combat.GI.Proc=&a**COLPITO CON GRANDE FORZA**
@@ -216,7 +223,6 @@ Axes.Skills.SS.On=&a**Spacca Crani ATTIVATO**
Axes.Skills.SS.Refresh=&aLa tua capacità &eSpacca Crani &asi è rigenerata! Axes.Skills.SS.Refresh=&aLa tua capacità &eSpacca Crani &asi è rigenerata!
Axes.Skills.SS.Other.Off=Spacca Crani&a si è esaurito per &e{0} Axes.Skills.SS.Other.Off=Spacca Crani&a si è esaurito per &e{0}
Axes.Skills.SS.Other.On=&a{0}&2 ha usato &cSpacca Crani! Axes.Skills.SS.Other.On=&a{0}&2 ha usato &cSpacca Crani!
#EXCAVATION #EXCAVATION
Excavation.Ability.Lower=&7Abbassi la Pala. Excavation.Ability.Lower=&7Abbassi la Pala.
Excavation.Ability.Ready=&6Prepari&3 la Pala. Excavation.Ability.Ready=&6Prepari&3 la Pala.
@@ -234,7 +240,6 @@ Excavation.Skills.GigaDrillBreaker.On=&a**GIGA-TRIVELLA DEMOLITRICE ATTIVATA**
Excavation.Skills.GigaDrillBreaker.Refresh=&aLa tua capacità &eGiga-Trivella Demolitrice &asi è rigenerata! Excavation.Skills.GigaDrillBreaker.Refresh=&aLa tua capacità &eGiga-Trivella Demolitrice &asi è rigenerata!
Excavation.Skills.GigaDrillBreaker.Other.Off=Giga-Trivella Demolitrice&a si è esaurita per &e{0} Excavation.Skills.GigaDrillBreaker.Other.Off=Giga-Trivella Demolitrice&a si è esaurita per &e{0}
Excavation.Skills.GigaDrillBreaker.Other.On=&a{0}&2 ha usato &cGiga-Trivella Demolitrice! Excavation.Skills.GigaDrillBreaker.Other.On=&a{0}&2 ha usato &cGiga-Trivella Demolitrice!
#FISHING #FISHING
Fishing.ScarcityTip=&e&oQuesta zona soffre di pesca eccessiva, getta la tua canna in un punto diverso per più pesci. Almeno a {0} blocchi di distanza. Fishing.ScarcityTip=&e&oQuesta zona soffre di pesca eccessiva, getta la tua canna in un punto diverso per più pesci. Almeno a {0} blocchi di distanza.
Fishing.Scared=&7&oI movimenti caotici spaventeranno i pesci! Fishing.Scared=&7&oI movimenti caotici spaventeranno i pesci!
@@ -258,6 +263,9 @@ Fishing.SubSkill.FishermansDiet.Name=Dieta del Pescatore
Fishing.SubSkill.FishermansDiet.Description=Aumenta la fame recuperata tramite cibi pescati Fishing.SubSkill.FishermansDiet.Description=Aumenta la fame recuperata tramite cibi pescati
Fishing.SubSkill.FishermansDiet.Stat=Dieta del Pescatore:&a Grado {0} Fishing.SubSkill.FishermansDiet.Stat=Dieta del Pescatore:&a Grado {0}
Fishing.SubSkill.MasterAngler.Name=Pescatore Provetto Fishing.SubSkill.MasterAngler.Name=Pescatore Provetto
Fishing.SubSkill.MasterAngler.Description=I pesci vengono presi più frequentemente, funziona meglio pescando da una barca.
Fishing.SubSkill.MasterAngler.Stat=Riduzione del tempo di attesa minimo per la pesca: &a-{0} secondi
Fishing.SubSkill.MasterAngler.Stat.Extra=Riduzione del tempo di attesa massimo per la pesca: &a-{0} secondi
Fishing.SubSkill.IceFishing.Name=Pesca sul Ghiaccio Fishing.SubSkill.IceFishing.Name=Pesca sul Ghiaccio
Fishing.SubSkill.IceFishing.Description=Ti permette di pescare in biomi ghiacciati Fishing.SubSkill.IceFishing.Description=Ti permette di pescare in biomi ghiacciati
Fishing.SubSkill.IceFishing.Stat=Pesca sul Ghiaccio Fishing.SubSkill.IceFishing.Stat=Pesca sul Ghiaccio
@@ -267,7 +275,6 @@ Fishing.Ability.TH.MagicFound=&7Senti un tocco di magia in questa cattura...
Fishing.Ability.TH.Boom=&7BOOM TIME!!! Fishing.Ability.TH.Boom=&7BOOM TIME!!!
Fishing.Ability.TH.Poison=&7C'è qualcosa che puzza... Fishing.Ability.TH.Poison=&7C'è qualcosa che puzza...
Fishing.SkillName=PESCA Fishing.SkillName=PESCA
#HERBALISM #HERBALISM
Herbalism.Ability.GTe.NeedMore=Ti servono più semi per diffondere Terra Verde. Herbalism.Ability.GTe.NeedMore=Ti servono più semi per diffondere Terra Verde.
Herbalism.Ability.GTh.Fail=**POLLICE VERDE FALLITO** Herbalism.Ability.GTh.Fail=**POLLICE VERDE FALLITO**
@@ -288,8 +295,11 @@ Herbalism.SubSkill.FarmersDiet.Name=Dieta del Contadino
Herbalism.SubSkill.FarmersDiet.Description=Aumenta la fame recuperata tramite cibi coltivati Herbalism.SubSkill.FarmersDiet.Description=Aumenta la fame recuperata tramite cibi coltivati
Herbalism.SubSkill.FarmersDiet.Stat=Dieta del Contadino: &aGrado {0} Herbalism.SubSkill.FarmersDiet.Stat=Dieta del Contadino: &aGrado {0}
Herbalism.SubSkill.DoubleDrops.Name=Doppi Drop Herbalism.SubSkill.DoubleDrops.Name=Doppi Drop
Herbalism.SubSkill.DoubleDrops.Description=Raddoppia il normale drop Herbalism.SubSkill.DoubleDrops.Description=Raccogli abilmente il doppio del normale drop
Herbalism.SubSkill.DoubleDrops.Stat=Possibilità di Doppio Drop Herbalism.SubSkill.DoubleDrops.Stat=Possibilità di Doppio Drop
Herbalism.SubSkill.VerdantBounty.Name=Ricompensa Rigogliosa
Herbalism.SubSkill.VerdantBounty.Description=Raccogli magistralmente il triplo del normale drop
Herbalism.SubSkill.VerdantBounty.Stat=Possibilità di Triplo Drop
Herbalism.SubSkill.HylianLuck.Name=Fortuna Hylian Herbalism.SubSkill.HylianLuck.Name=Fortuna Hylian
Herbalism.SubSkill.HylianLuck.Description=Dà una piccola possibilità di trovare oggetti rari Herbalism.SubSkill.HylianLuck.Description=Dà una piccola possibilità di trovare oggetti rari
Herbalism.SubSkill.HylianLuck.Stat=Possibilità Fortuna Hylian Herbalism.SubSkill.HylianLuck.Stat=Possibilità Fortuna Hylian
@@ -304,7 +314,6 @@ Herbalism.Skills.GTe.On=&a**TERRA VERDE ATTIVATA**
Herbalism.Skills.GTe.Refresh=&aLa tua capacità &eTerra Verde &asi è rigenerata! Herbalism.Skills.GTe.Refresh=&aLa tua capacità &eTerra Verde &asi è rigenerata!
Herbalism.Skills.GTe.Other.Off=Terra Verde&a si è esaurita per &e{0} Herbalism.Skills.GTe.Other.Off=Terra Verde&a si è esaurita per &e{0}
Herbalism.Skills.GTe.Other.On=&a{0}&2 ha usato &cTerra Verde! Herbalism.Skills.GTe.Other.On=&a{0}&2 ha usato &cTerra Verde!
#MINING #MINING
Mining.Ability.Locked.0=BLOCCATO FINO AD ABILITà (ESTRAZIONE ESPLOSIVA) Mining.Ability.Locked.0=BLOCCATO FINO AD ABILITà (ESTRAZIONE ESPLOSIVA)
Mining.Ability.Locked.1=BLOCCATO FINO AD ABILITà (BOMBE PIù GRANDI) Mining.Ability.Locked.1=BLOCCATO FINO AD ABILITà (BOMBE PIù GRANDI)
@@ -315,8 +324,11 @@ Mining.SubSkill.SuperBreaker.Name=Super Demolitore
Mining.SubSkill.SuperBreaker.Description=Velocità+, Possibilità Triplo Drop Mining.SubSkill.SuperBreaker.Description=Velocità+, Possibilità Triplo Drop
Mining.SubSkill.SuperBreaker.Stat=Durata di Super Demolitore Mining.SubSkill.SuperBreaker.Stat=Durata di Super Demolitore
Mining.SubSkill.DoubleDrops.Name=Doppi Drop Mining.SubSkill.DoubleDrops.Name=Doppi Drop
Mining.SubSkill.DoubleDrops.Description=Raddoppia il normale drop Mining.SubSkill.DoubleDrops.Description=Raccogli abilmente il doppio del normale drop
Mining.SubSkill.DoubleDrops.Stat=Possibilità di Doppio Drop Mining.SubSkill.DoubleDrops.Stat=Possibilità di Doppio Drop
Mining.SubSkill.MotherLode.Name=Vena Principale
Mining.SubSkill.MotherLode.Description=Raccogli magistralmente il triplo del normale drop
Mining.SubSkill.MotherLode.Stat=Possibilità di Triplo Drop
Mining.SubSkill.BlastMining.Name=Estrazione Esplosiva Mining.SubSkill.BlastMining.Name=Estrazione Esplosiva
Mining.SubSkill.BlastMining.Description=Bonus nell'estrarre minerali col TNT Mining.SubSkill.BlastMining.Description=Bonus nell'estrarre minerali col TNT
Mining.SubSkill.BlastMining.Stat=Estrazione Esplosiva:&a Grado {0}/{1} &7({2}) Mining.SubSkill.BlastMining.Stat=Estrazione Esplosiva:&a Grado {0}/{1} &7({2})
@@ -326,6 +338,7 @@ Mining.SubSkill.BiggerBombs.Description=Aumenta il raggio di esplosione del TNT
Mining.SubSkill.DemolitionsExpertise.Name=Perizia nelle Demolizioni Mining.SubSkill.DemolitionsExpertise.Name=Perizia nelle Demolizioni
Mining.SubSkill.DemolitionsExpertise.Description=Riduce il danno da esplosioni di TNT Mining.SubSkill.DemolitionsExpertise.Description=Riduce il danno da esplosioni di TNT
Mining.SubSkill.DemolitionsExpertise.Stat=Riduzione del Danno da Perizia nelle Demolizioni Mining.SubSkill.DemolitionsExpertise.Stat=Riduzione del Danno da Perizia nelle Demolizioni
Mining.Listener=Estrazione: Mining.Listener=Estrazione:
Mining.SkillName=ESTRAZIONE Mining.SkillName=ESTRAZIONE
Mining.Skills.SuperBreaker.Off=**Super Demolitore si è esaurito** Mining.Skills.SuperBreaker.Off=**Super Demolitore si è esaurito**
@@ -339,7 +352,6 @@ Mining.Blast.Cooldown=
Mining.Blast.Effect=+{0} minerale raccolto, drop {1}x Mining.Blast.Effect=+{0} minerale raccolto, drop {1}x
Mining.Blast.Other.On=&a{0}&2 ha usato &cEstrazione Esplosiva! Mining.Blast.Other.On=&a{0}&2 ha usato &cEstrazione Esplosiva!
Mining.Blast.Refresh=&aLa tua capacità &eEstrazione Esplosiva &asi è rigenerata! Mining.Blast.Refresh=&aLa tua capacità &eEstrazione Esplosiva &asi è rigenerata!
#REPAIR #REPAIR
Repair.SubSkill.Repair.Name=Riparazione Repair.SubSkill.Repair.Name=Riparazione
Repair.SubSkill.Repair.Description=Ripara Attrezzi e Armature Repair.SubSkill.Repair.Description=Ripara Attrezzi e Armature
@@ -408,6 +420,59 @@ Salvage.Skills.Lottery.Perfect=&a&lPerfetto!&r&6 Hai rottamato senza sforzo &3{1
Salvage.Skills.Lottery.Untrained=&7Non sei adeguatamente addestrato nel recupero. Sei riuscito a recuperare solo &c{0}&7 materiali da &a{1}&7. Salvage.Skills.Lottery.Untrained=&7Non sei adeguatamente addestrato nel recupero. Sei riuscito a recuperare solo &c{0}&7 materiali da &a{1}&7.
#Anvil (Shared between SALVAGE and REPAIR) #Anvil (Shared between SALVAGE and REPAIR)
Anvil.Unbreakable=Questo oggetto è indistruttibile! Anvil.Unbreakable=Questo oggetto è indistruttibile!
Anvil.Repair.Reject.CustomModelData=Una forza misteriosa ti impedisce di riparare questo oggetto...
Anvil.Salvage.Reject.CustomModelData=Una forza misteriosa ti impedisce di rottamare questo oggetto...
#CROSSBOWS
Crossbows.SkillName=BALESTRE
Crossbows.Ability.Lower=&7Abbassi la tua balestra.
Crossbows.Ability.Ready=&6Prepari&3 la tua balestra.
Crossbows.Skills.SSG.Refresh=&aLa tua capacità &eSuper Fucile &asi è rigenerata!
Crossbows.Skills.SSG.Other.On=&a{0}&2 ha usato &cSuper Fucile!
Crossbows.SubSkill.PoweredShot.Name=Colpo potenziato
Crossbows.SubSkill.PoweredShot.Description=Aumenta i danni fatti con la balestra
Crossbows.SubSkill.PoweredShot.Stat=Danno Bonus Colpo Potenziato
Crossbows.SubSkill.CrossbowsLimitBreak.Name=Danni Aumentati Balestre
Crossbows.SubSkill.CrossbowsLimitBreak.Description=Supera i tuoi limiti. Danni aumentati contro avversari difficili. Destinato al PVP, sta alle impostazioni del server se aumenterà o meno i danni nel PVE.
Crossbows.SubSkill.CrossbowsLimitBreak.Stat=Danno Massimo di Danni Aumentati
Crossbows.SubSkill.TrickShot.Name=Tiro ad Effetto
Crossbows.SubSkill.TrickShot.Description=Rimbalza le frecce con angoli stretti
Crossbows.SubSkill.TrickShot.Stat=Massimi Rimbalzi Tiro ad Effetto
Crossbows.SubSkill.TrickShot.Stat.Extra=Massimi Rimbalzi Tiro ad Effetto: &a{0}
Crossbows.SubSkill.TrickShot.Stat.Extra2=Danni Ridotti per Rimbalzo di Tiro ad Effetto: &a{0}
Crossbows.SubSkill.SuperShotgun.Name=Super Fucile
Crossbows.Listener=Crossbows:
#TRIDENTS
Tridents.SkillName=TRIDENTI
Tridents.Ability.Lower=&7Abbassi il tuo tridente.
Tridents.Ability.Ready=&6Prepari&3 il tuo tridente.
Tridents.SubSkill.Impale.Name=Trafittura
Tridents.SubSkill.Impale.Description=Aumenta i danni fatti con i tridenti
Tridents.SubSkill.Impale.Stat=Danno Bonus Trafittura
Tridents.SubSkill.TridentsLimitBreak.Name=Danni Aumentati Tridenti
Tridents.SubSkill.TridentsLimitBreak.Description=Supera i tuoi limiti. Danni aumentati contro avversari difficili. Destinato al PVP, sta alle impostazioni del server se aumenterà o meno i danni nel PVE.
Tridents.SubSkill.TridentsLimitBreak.Stat=Danno Massimo di Danni Aumentati
Tridents.SubSkill.TridentAbility.Name=WIP
Tridents.Listener=Tridents:
#MACES
Commands.McTop.MacesNotSupported=[[GREEN]]Le mazze non sono supportate in questa versione di Minecraft.
Maces.SkillName=Mazze
Maces.Ability.Lower=&7Abbassi la tua mazza.
Maces.Ability.Ready=&6Prepari&3 la tua mazza.
Maces.SubSkill.MacesLimitBreak.Name=Danni Aumentati Mazze
Maces.SubSkill.MacesLimitBreak.Description=Supera i tuoi limiti. Danni aumentati contro avversari difficili. Destinato al PVP, sta alle impostazioni del server se aumenterà o meno i danni nel PVE.
Maces.SubSkill.MacesLimitBreak.Stat=Danno Massimo di Danni Aumentati
Maces.SubSkill.Crush.Name=Frantumazione
Maces.SubSkill.Crush.Description=Aggiunge danno bonus ai tuoi attacchi.
Maces.SubSkill.Crush.Stat=Danno Frantumazione
Maces.SubSkill.Cripple.Proc=**AZZOPPATO**
Maces.SubSkill.Cripple.Activated=OBIETTIVO AZZOPPATO!
Maces.SubSkill.Cripple.Name=Azzoppatura
Maces.SubSkill.Cripple.Description=Aggiunge una possibilità di azzopppare il tuo obiettivo.
Maces.SubSkill.Cripple.Stat=Probabilità di Azzoppatura
Maces.SubSkill.Cripple.Stat.Extra=&3Durata Azzoppatura: &e{0}s&a vs Giocatori, &e{1}s&a vs Mob.
Maces.Listener=Maces:
#SWORDS #SWORDS
Swords.Ability.Lower=&7Abbassi la Spada. Swords.Ability.Lower=&7Abbassi la Spada.
@@ -434,7 +499,9 @@ Swords.SubSkill.SwordsLimitBreak.Name=Danni Aumentati Spade
Swords.SubSkill.SwordsLimitBreak.Description=Supera i tuoi limiti. Danni aumentati contro avversari difficili. Destinato al PVP, sta alle impostazioni del server se aumenterà o meno i danni nel PVE. Swords.SubSkill.SwordsLimitBreak.Description=Supera i tuoi limiti. Danni aumentati contro avversari difficili. Destinato al PVP, sta alle impostazioni del server se aumenterà o meno i danni nel PVE.
Swords.SubSkill.SwordsLimitBreak.Stat=Danno Massimo di Danni Aumentati Swords.SubSkill.SwordsLimitBreak.Stat=Danno Massimo di Danni Aumentati
Swords.SubSkill.Rupture.Stat=Possibilità di Emorragia Swords.SubSkill.Rupture.Stat=Possibilità di Emorragia
Swords.SubSkill.Rupture.Stat.Extra=Emorragia: &a{0} tick [{1} Danno vs Giocatori] [{2} Danno vs Mob] Swords.SubSkill.Rupture.Stat.Extra=&3Durata Emorragia: &e{0}s&a vs Giocatori, &e{1}s&a vs Mob.
Swords.SubSkill.Rupture.Stat.TickDamage=&3Danno per tick Emorragia: &e{0}&a vs Giocatori, &e{1}&a vs Mob.
Swords.SubSkill.Rupture.Stat.ExplosionDamage=&3Danno esplosione Emorragia: &e{0}&a vs Giocatori, &e{1}&a vs Mob.
Swords.Effect.4=Colpi Seghettati Emorragia+ Swords.Effect.4=Colpi Seghettati Emorragia+
Swords.Effect.5={0} Tick di Emorragia Swords.Effect.5={0} Tick di Emorragia
Swords.Listener=Spade: Swords.Listener=Spade:
@@ -444,7 +511,6 @@ Swords.Skills.SS.On=&a**COLPI SEGHETTATI ATTIVATO**
Swords.Skills.SS.Refresh=&aLa tua capacità &eColpi Seghettati &asi è rigenerata! Swords.Skills.SS.Refresh=&aLa tua capacità &eColpi Seghettati &asi è rigenerata!
Swords.Skills.SS.Other.Off=Colpi Seghettati&a si è esaurito per &e{0} Swords.Skills.SS.Other.Off=Colpi Seghettati&a si è esaurito per &e{0}
Swords.Skills.SS.Other.On=&a{0}&2 ha usato &cColpi Seghettati! Swords.Skills.SS.Other.On=&a{0}&2 ha usato &cColpi Seghettati!
#TAMING #TAMING
Taming.Ability.Bonus.0=Sicurezza Ambientale Taming.Ability.Bonus.0=Sicurezza Ambientale
Taming.Ability.Bonus.1=I lupi evitano il pericolo Taming.Ability.Bonus.1=I lupi evitano il pericolo
@@ -494,10 +560,10 @@ Taming.Summon.COTW.Success.WithoutLifespan=&a(Richiamo della Natura) &7Hai evoca
Taming.Summon.COTW.Success.WithLifespan=&a(Richiamo della Natura) &7Hai evocato un &6{0}&7 e ha una durata di &6{1}&7 secondi. Taming.Summon.COTW.Success.WithLifespan=&a(Richiamo della Natura) &7Hai evocato un &6{0}&7 e ha una durata di &6{1}&7 secondi.
Taming.Summon.COTW.Limit=&a(Richiamo della Natura) &7Puoi avere solo &c{0} &7animali domestici &7{1} allo stesso tempo. Taming.Summon.COTW.Limit=&a(Richiamo della Natura) &7Puoi avere solo &c{0} &7animali domestici &7{1} allo stesso tempo.
Taming.Summon.COTW.TimeExpired=&a(Richiamo della Natura) &7Il tempo è scaduto, il tuo &6{0}&7 se ne va. Taming.Summon.COTW.TimeExpired=&a(Richiamo della Natura) &7Il tempo è scaduto, il tuo &6{0}&7 se ne va.
Taming.Summon.COTW.Removed=&a(Richiamo della Natura) &7Il tuo &6{0}&7 è svanito da questo mondo.
Taming.Summon.COTW.BreedingDisallowed=&a(Richiamo della Natura) &cNon puoi allevare un animale evocato. Taming.Summon.COTW.BreedingDisallowed=&a(Richiamo della Natura) &cNon puoi allevare un animale evocato.
Taming.Summon.COTW.NeedMoreItems=&a(Richiamo della Natura) &7Ti servono altri &e{0} &3{1} Taming.Summon.COTW.NeedMoreItems=&a(Richiamo della Natura) &7Ti servono altri &e{0} &3{1}
Taming.Summon.Name.Format=&6(RDN) &f{1} di {0} Taming.Summon.Name.Format=&6(RDN) &f{1} di {0}
#UNARMED #UNARMED
Unarmed.Ability.Bonus.0=Stile Braccio di Ferro Unarmed.Ability.Bonus.0=Stile Braccio di Ferro
Unarmed.Ability.Bonus.1=Potenziamento Danno +{0} Unarmed.Ability.Bonus.1=Potenziamento Danno +{0}
@@ -531,7 +597,6 @@ Unarmed.Skills.Berserk.On=&a**FURORE ATTIVATO**
Unarmed.Skills.Berserk.Other.Off=Furore&a si è esaurito per &e{0} Unarmed.Skills.Berserk.Other.Off=Furore&a si è esaurito per &e{0}
Unarmed.Skills.Berserk.Other.On=&a{0}&2 ha usato &cFurore! Unarmed.Skills.Berserk.Other.On=&a{0}&2 ha usato &cFurore!
Unarmed.Skills.Berserk.Refresh=&aLa tua capacità &eFurore &asi è rigenerata! Unarmed.Skills.Berserk.Refresh=&aLa tua capacità &eFurore &asi è rigenerata!
#WOODCUTTING #WOODCUTTING
Woodcutting.Ability.0=Soffia Foglie Woodcutting.Ability.0=Soffia Foglie
Woodcutting.Ability.1=Soffia via le foglie Woodcutting.Ability.1=Soffia via le foglie
@@ -541,9 +606,17 @@ Woodcutting.SubSkill.TreeFeller.Description=Fa esplodere gli alberi
Woodcutting.SubSkill.TreeFeller.Stat=Durata di Abbattitore d'Alberi Woodcutting.SubSkill.TreeFeller.Stat=Durata di Abbattitore d'Alberi
Woodcutting.SubSkill.LeafBlower.Name=Soffia Foglie Woodcutting.SubSkill.LeafBlower.Name=Soffia Foglie
Woodcutting.SubSkill.LeafBlower.Description=Soffia via le foglie Woodcutting.SubSkill.LeafBlower.Description=Soffia via le foglie
Woodcutting.SubSkill.KnockOnWood.Name=Superstizione Legnosa
Woodcutting.SubSkill.KnockOnWood.Description=Trova maggiori ricompense quando usi Abbattitore d'Alberi
Woodcutting.SubSkill.KnockOnWood.Stat=Superstizione Legnosa
Woodcutting.SubSkill.KnockOnWood.Loot.Normal=Drop standard dagli alberi
Woodcutting.SubSkill.KnockOnWood.Loot.Rank2=Drop standard dagli alberi e sfere d'esperienza
Woodcutting.SubSkill.HarvestLumber.Name=Raccoglitore di Legname Woodcutting.SubSkill.HarvestLumber.Name=Raccoglitore di Legname
Woodcutting.SubSkill.HarvestLumber.Description=Estrae abilmente più Legname Woodcutting.SubSkill.HarvestLumber.Description=Estrae abilmente più Legname
Woodcutting.SubSkill.HarvestLumber.Stat=Possibilità di Doppio Drop Woodcutting.SubSkill.HarvestLumber.Stat=Possibilità di Doppio Drop
Woodcutting.SubSkill.CleanCuts.Name=Clean Cuts
Woodcutting.SubSkill.CleanCuts.Description=Masterfully extract up to triple the Lumber
Woodcutting.SubSkill.CleanCuts.Stat=Triple Drop Chance
Woodcutting.SubSkill.Splinter.Name=Scheggia Woodcutting.SubSkill.Splinter.Name=Scheggia
Woodcutting.SubSkill.Splinter.Description=Taglia gli alberi in modo più efficiente. Woodcutting.SubSkill.Splinter.Description=Taglia gli alberi in modo più efficiente.
Woodcutting.SubSkill.BarkSurgeon.Name=Chirurgo della Corteccia Woodcutting.SubSkill.BarkSurgeon.Name=Chirurgo della Corteccia
@@ -567,11 +640,11 @@ Combat.BeastLore=&a**CONOSCENZA DELLE BESTIE**
Combat.BeastLoreHealth=&3Salute (&a{0}&3/{1}) Combat.BeastLoreHealth=&3Salute (&a{0}&3/{1})
Combat.BeastLoreOwner=&3Proprietario (&c{0}&3) Combat.BeastLoreOwner=&3Proprietario (&c{0}&3)
Combat.BeastLoreHorseSpeed=&3Velocità di Movimento del Cavallo (&a{0} blocchi/s&3) Combat.BeastLoreHorseSpeed=&3Velocità di Movimento del Cavallo (&a{0} blocchi/s&3)
Combat.BeastLoreHorseJumpStrength=&3Potenza del Salto del Cavallo (&aMassimo {0} blocchi&3)
Combat.Gore=&a**SBRANATO** Combat.Gore=&a**SBRANATO**
Combat.StruckByGore=**SEI STATO SBRANATO** Combat.StruckByGore=**SEI STATO SBRANATO**
Combat.TargetDazed=Il bersaglio è stato &4Stordito Combat.TargetDazed=Il bersaglio è stato &4Stordito
Combat.TouchedFuzzy=&4Urto Stordino. Vado nel Pallone. Combat.TouchedFuzzy=&4Urto Stordino. Vado nel Pallone.
#COMMANDS #COMMANDS
##generic ##generic
mcMMO.Description=&3Introduzione al Progetto &emcMMO&3:,&6mcMMO è una mod RPG &copen source&6 creata nel febbraio 2011,&6da &9nossr50&6. L'obbiettivo è di fornire una esperienza di RPG di qualità.,&3Consigli:,&6 - &aUsa &c/mcmmo help&a per vedere i comandi,&6 - &aDigita &c/NOMEABILITà&a per visualizzare informazioni dettagliate sull'abilità,&3Sviluppatori:,&6 - &anossr50 &9(Creatore & Responsabile del Progetto),&6 - &aelectronicboy &9(Sviluppatore),&6 - &akashike &9(Sviluppatore),&6 - &at00thpick1 &9(Manutentore versione Classica) mcMMO.Description=&3Introduzione al Progetto &emcMMO&3:,&6mcMMO è una mod RPG &copen source&6 creata nel febbraio 2011,&6da &9nossr50&6. L'obbiettivo è di fornire una esperienza di RPG di qualità.,&3Consigli:,&6 - &aUsa &c/mcmmo help&a per vedere i comandi,&6 - &aDigita &c/NOMEABILITà&a per visualizzare informazioni dettagliate sull'abilità,&3Sviluppatori:,&6 - &anossr50 &9(Creatore & Responsabile del Progetto),&6 - &aelectronicboy &9(Sviluppatore),&6 - &akashike &9(Sviluppatore),&6 - &at00thpick1 &9(Manutentore versione Classica)
@@ -593,6 +666,7 @@ Commands.Cooldowns.Header=&6--= &aRicariche Capacità mcMMO&6 =--
Commands.Cooldowns.Row.N=\ &c{0}&f - &6{1} secondi rimanenti Commands.Cooldowns.Row.N=\ &c{0}&f - &6{1} secondi rimanenti
Commands.Cooldowns.Row.Y=\ &b{0}&f - &2Pronta! Commands.Cooldowns.Row.Y=\ &b{0}&f - &2Pronta!
Commands.Database.CooldownMS=Devi aspettare {0} millisecondi prima di utilizzare nuovamente questo comando. Commands.Database.CooldownMS=Devi aspettare {0} millisecondi prima di utilizzare nuovamente questo comando.
Commands.Database.Cooldown=Devi aspettare {0} secondi prima di utilizzare nuovamente questo comando.
Commands.Database.Processing=Il tuo comando precedente è ancora in fase di elaborazione. Attendere prego. Commands.Database.Processing=Il tuo comando precedente è ancora in fase di elaborazione. Attendere prego.
Commands.Disabled=Questo comando è disabilitato. Commands.Disabled=Questo comando è disabilitato.
Commands.DoesNotExist= &cQuel giocatore non esiste nel database! Commands.DoesNotExist= &cQuel giocatore non esiste nel database!
@@ -710,6 +784,8 @@ Commands.Scoreboard.Help.2=&3/mcscoreboard&b keep &f - mantiene la scoreboard mc
Commands.Scoreboard.Help.3=&3/mcscoreboard&b time [n] &f - rimuove la scoreboard mcMMO dopo &dn&f secondi Commands.Scoreboard.Help.3=&3/mcscoreboard&b time [n] &f - rimuove la scoreboard mcMMO dopo &dn&f secondi
Commands.Scoreboard.Tip.Keep=&6Consiglio: Usa &c/mcscoreboard keep&6 quando la scoreboard è attiva per evitare che vada via. Commands.Scoreboard.Tip.Keep=&6Consiglio: Usa &c/mcscoreboard keep&6 quando la scoreboard è attiva per evitare che vada via.
Commands.Scoreboard.Tip.Clear=&6Consiglio: Usa &c/mcscoreboard clear&6 per sbarazzarti della scoreboard. Commands.Scoreboard.Tip.Clear=&6Consiglio: Usa &c/mcscoreboard clear&6 per sbarazzarti della scoreboard.
Commands.XPBar.Reset=&6Le impostazioni per la barra XP di mcMMO sono state resettate.
Commands.XPBar.SettingChanged=&6L'impostazione per la barra XP per &a{0}&6 è ora impostata a &a{1}
Commands.Skill.Invalid=Quello non è un nome di abilità valido! Commands.Skill.Invalid=Quello non è un nome di abilità valido!
Commands.Skill.ChildSkill=Le abilità figlie non sono valide per questo comando! Commands.Skill.ChildSkill=Le abilità figlie non sono valide per questo comando!
Commands.Skill.Leaderboard=--mcMMO &9{0}&e Classifica-- Commands.Skill.Leaderboard=--mcMMO &9{0}&e Classifica--
@@ -720,6 +796,7 @@ Commands.Usage.0=&cL'uso appropriato è /{0}
Commands.Usage.1=&cL'uso appropriato è /{0} {1} Commands.Usage.1=&cL'uso appropriato è /{0} {1}
Commands.Usage.2=&cL'uso appropriato è /{0} {1} {2} Commands.Usage.2=&cL'uso appropriato è /{0} {1} {2}
Commands.Usage.3=&cL'uso appropriato è /{0} {1} {2} {3} Commands.Usage.3=&cL'uso appropriato è /{0} {1} {2} {3}
Commands.Usage.3.XP=&cL'uso appropriato è /{0} {1} {2} {3}&7 (Puoi includere -s alla fine per eseguire il comando senza informare il giocatore, di fatto silenziandolo)
Commands.Usage.FullClassName=nome classe Commands.Usage.FullClassName=nome classe
Commands.Usage.Level=livello Commands.Usage.Level=livello
Commands.Usage.Message=messaggio Commands.Usage.Message=messaggio
@@ -744,7 +821,6 @@ Commands.Mmodebug.Toggle=La modalità debug di mcMMO è ora &6{0}&7, usa di nuov
mcMMO.NoInvites=&cNon hai inviti in questo momento mcMMO.NoInvites=&cNon hai inviti in questo momento
mcMMO.NoPermission=&4Permessi insufficienti. mcMMO.NoPermission=&4Permessi insufficienti.
mcMMO.NoSkillNote=&8Se non hai accesso a un'abilità, non verrà mostrata qui. mcMMO.NoSkillNote=&8Se non hai accesso a un'abilità, non verrà mostrata qui.
##party ##party
Party.Forbidden=[mcMMO] I party non sono consentiti in questo mondo (Vedi i Permessi) Party.Forbidden=[mcMMO] I party non sono consentiti in questo mondo (Vedi i Permessi)
Party.Help.0=&cL'uso appropriato è &3{0} <giocatore> [password]. Party.Help.0=&cL'uso appropriato è &3{0} <giocatore> [password].
@@ -821,20 +897,22 @@ Party.ItemShare.Category.Mining=Estrazione
Party.ItemShare.Category.Herbalism=Erboristeria Party.ItemShare.Category.Herbalism=Erboristeria
Party.ItemShare.Category.Woodcutting=Taglialegna Party.ItemShare.Category.Woodcutting=Taglialegna
Party.ItemShare.Category.Misc=Varie Party.ItemShare.Category.Misc=Varie
##xp ##xp
Commands.XPGain.Acrobatics=Cadendo Commands.XPGain.Acrobatics=Cadendo
Commands.XPGain.Alchemy=Preparando Pozioni Commands.XPGain.Alchemy=Preparando Pozioni
Commands.XPGain.Archery=Attaccando Mostri Commands.XPGain.Archery=Attaccando Mostri
Commands.XPGain.Axes=Attaccando Mostri Commands.XPGain.Axes=Attaccando Mostri
Commands.XPGain.Child=Ottenendo livelli con le Abilità Madri Commands.XPGain.Child=Ottenendo livelli con le Abilità Madri
Commands.XPGain.Crossbows=Attaccando Mostri
Commands.XPGain.Excavation=Scavando e trovando tesori Commands.XPGain.Excavation=Scavando e trovando tesori
Commands.XPGain.Fishing=Pescando (ma va'!) Commands.XPGain.Fishing=Pescando (ma va'!)
Commands.XPGain.Herbalism=Raccogliendo Piante Commands.XPGain.Herbalism=Raccogliendo Piante
Commands.XPGain.Maces=Attaccando Mostri
Commands.XPGain.Mining=Estraendo Pietra e Minerali Grezzi Commands.XPGain.Mining=Estraendo Pietra e Minerali Grezzi
Commands.XPGain.Repair=Riparando Commands.XPGain.Repair=Riparando
Commands.XPGain.Swords=Attaccando Mostri Commands.XPGain.Swords=Attaccando Mostri
Commands.XPGain.Taming=Addomesticando Animali, o combattendo con i tuoi lupi Commands.XPGain.Taming=Addomesticando Animali, o combattendo con i tuoi lupi
Commands.XPGain.Tridents=Attaccando Mostri
Commands.XPGain.Unarmed=Attaccando Mostri Commands.XPGain.Unarmed=Attaccando Mostri
Commands.XPGain.Woodcutting=Abbattendo alberi Commands.XPGain.Woodcutting=Abbattendo alberi
Commands.XPGain=&8GUADAGNO XP: &f{0} Commands.XPGain=&8GUADAGNO XP: &f{0}
@@ -883,6 +961,7 @@ Guides.Alchemy.Section.3=&3Ingredienti Intrugli di grado 1:\n&ePolvere di blaze,
Guides.Alchemy.Section.4=&3Ingredienti Intrugli di grado 2:\n&eCarota (Pozione di velocità)\n&ePalla di slime (Pozione di Affaticamento)\n\n&3Ingredienti Intrugli di grado 3:\n&eQuartzo (Pozione di Assorbimento)\n&eFungo rosso (Pozione di salto) Guides.Alchemy.Section.4=&3Ingredienti Intrugli di grado 2:\n&eCarota (Pozione di velocità)\n&ePalla di slime (Pozione di Affaticamento)\n\n&3Ingredienti Intrugli di grado 3:\n&eQuartzo (Pozione di Assorbimento)\n&eFungo rosso (Pozione di salto)
Guides.Alchemy.Section.5=&3Ingredienti Intrugli di grado 4:\n&eMela (Pozione di salute ampliata)\n&eCarne marcia (Pozione di fame)\n\n&3Ingredienti Intrugli di grado 5:\n&eFungo marrone (Pozione di nausea)\n&eSacca d'inchiostro (Pozione di Cecità) Guides.Alchemy.Section.5=&3Ingredienti Intrugli di grado 4:\n&eMela (Pozione di salute ampliata)\n&eCarne marcia (Pozione di fame)\n\n&3Ingredienti Intrugli di grado 5:\n&eFungo marrone (Pozione di nausea)\n&eSacca d'inchiostro (Pozione di Cecità)
Guides.Alchemy.Section.6=&3Ingredienti Intrugli di grado 6:\n&eFelce (Pozione di Sazietà)\n\n&3Ingredienti Intrugli di grado 7:\n&ePatata velenosa (Pozione di Avvizzimento)\n\n&3Ingredienti Intrugli di grado 8:\n&eMela d'oro (Pozione di Resistenza) Guides.Alchemy.Section.6=&3Ingredienti Intrugli di grado 6:\n&eFelce (Pozione di Sazietà)\n\n&3Ingredienti Intrugli di grado 7:\n&ePatata velenosa (Pozione di Avvizzimento)\n\n&3Ingredienti Intrugli di grado 8:\n&eMela d'oro (Pozione di Resistenza)
##Archery ##Archery
Guides.Archery.Section.0=&3Introduzione al Tiro con l'Arco:\n&eTiro con l'Arco riguarda il tirare con arco e freccia.\n&eFornisce vari bonus di combattimento, come un aumento di danni\n&eche scala con il livello e la capacità di stordire i tuoi\n&eavversari in PvP. Inoltre puoi recuperare\n&edai cadaveri dei tuoi nemici alcune delle frecce usate.\n\n\n&3GUADAGNO XP:\n&ePer ottenere XP in questa abilità devi colpire mob o\n&ealtri giocatori. Guides.Archery.Section.0=&3Introduzione al Tiro con l'Arco:\n&eTiro con l'Arco riguarda il tirare con arco e freccia.\n&eFornisce vari bonus di combattimento, come un aumento di danni\n&eche scala con il livello e la capacità di stordire i tuoi\n&eavversari in PvP. Inoltre puoi recuperare\n&edai cadaveri dei tuoi nemici alcune delle frecce usate.\n\n\n&3GUADAGNO XP:\n&ePer ottenere XP in questa abilità devi colpire mob o\n&ealtri giocatori.
Guides.Archery.Section.1=&3Come funziona Tiro da Maestro?\n&eTiro da Maestro un danno aggiuntivo ai tuoi colpi.\n&eIl danno bonus da Tiro da Maestro aumenta\n&eall'aumentare del livello di Tiro con l'Arco.\n&eCon le impostazioni predefinite, il danno dei tiri con l'arco aumenta del 10%\n&eogni 50 livelli, fino a un massimo del 200%. Guides.Archery.Section.1=&3Come funziona Tiro da Maestro?\n&eTiro da Maestro un danno aggiuntivo ai tuoi colpi.\n&eIl danno bonus da Tiro da Maestro aumenta\n&eall'aumentare del livello di Tiro con l'Arco.\n&eCon le impostazioni predefinite, il danno dei tiri con l'arco aumenta del 10%\n&eogni 50 livelli, fino a un massimo del 200%.
@@ -963,17 +1042,22 @@ Guides.Unarmed.Section.3=&3Come funziona Deviazione Frecce?\n&eDeviazione Frecce
Guides.Unarmed.Section.4=&3Come funziona Presa di Ferro?\n&ePresa di Ferro è una capacità passiva che contrasta il disarmo. All'aumentare\n&edel tuo livello in Lotta, la possibilità di prevenire un disarmo aumenta. Guides.Unarmed.Section.4=&3Come funziona Presa di Ferro?\n&ePresa di Ferro è una capacità passiva che contrasta il disarmo. All'aumentare\n&edel tuo livello in Lotta, la possibilità di prevenire un disarmo aumenta.
Guides.Unarmed.Section.5=&3Come funziona Disarmo?\n&eQuesta capacità passiva consente ai giocatori di disarmare altri giocatori,\n&efacendo cadere a terra l'oggetto equipaggiato dal bersaglio. Guides.Unarmed.Section.5=&3Come funziona Disarmo?\n&eQuesta capacità passiva consente ai giocatori di disarmare altri giocatori,\n&efacendo cadere a terra l'oggetto equipaggiato dal bersaglio.
##Woodcutting ##Woodcutting
Guides.Woodcutting.Section.0=&3Introduzione a Taglialegna:\n&eTaglialegna consiste tutto nell'abbattere alberi.\n\n&3GUADAGNO XP:\n&eGli XP si ottengono ogni volta che rompi i tronchi d'albero. Guides.Woodcutting.Section.0=&3Introduzione a Taglialegna:\n&eTaglialegna consiste nell'abbattere alberi.\n\n&3GUADAGNO XP:\n&eGli XP si ottengono ogni volta che rompi i tronchi d'albero.
Guides.Woodcutting.Section.1=&3Come funziona Abbattitore d'Alberi?\n&eAbbattitore d'Alberi è una capacità attiva, puoi fare clic-destro\n&econ un'ascia in mano per attivare Abbattitore d'Alberi. Questo\n&efarà rompere l'intero albero istantaneamente, droppando tutti\n&ei suoi tronchi insieme. Guides.Woodcutting.Section.1=&3Come funziona Abbattitore d'Alberi?\n&eAbbattitore d'Alberi è una capacità attiva, puoi fare clic-destro\n&econ un'ascia in mano per attivare Abbattitore d'Alberi. Questo\n&efarà rompere l'intero albero istantaneamente, droppando tutti\n&ei suoi tronchi insieme.
Guides.Woodcutting.Section.2=&3Come funziona Soffia Foglie?\n&eSoffia Foglie è una capacità passiva che fa\n&ecadere le foglie istantaneamente quando colpite da un'ascia. Di default,\n&equesta capacità si sblocca al livello 100. Guides.Woodcutting.Section.2=&3Come funziona Soffia Foglie?\n&eSoffia Foglie è una capacità passiva che fa\n&ecadere le foglie istantaneamente quando colpite da un'ascia. Di default,\n&equesta capacità si sblocca al livello 100.
Guides.Woodcutting.Section.3=&3Come funziona Doppi Drop?\n&eQuesta capacità passiva ti dà una possibilità di ottenere un blocco\n&eextra per ogni tronco che tagli. Guides.Woodcutting.Section.3=&3Come funziona Doppi Drop?\n&eQuesta capacità passiva ti dà una possibilità di ottenere un blocco\n&eextra per ogni tronco che tagli.
# Crossbows
Guides.Crossbows.Section.0=&3Introduzione a Balestre:\n&eBalestre consiste nello scoccare frecce con la tua balestra.\n\n&3GUADAGNO XP:\n&eGli XP si ottengono ogni volta che tiri a un mob con una balestra.\nQuesta abilità è ancora in sviluppo e più informazioni verranno presto aggiunte.
Guides.Crossbows.Section.1=&3Come funziona Tiro ad Effetto?\n&eTiro ad Effetto è un'abilità passiva, tiri i tuoi dardi ad un basso angolo con una balestra per tentare un Tiro ad Effetto. Questo farà sì che la freccia rimbalzi sui blocchi, potenzialmente colpendo un obiettivo. Il numero di potenziali rimbalzi dipende dal livello del Tiro ad Effetto.
# Tridents
Guides.Tridents.Section.0=&3Introduzione a Tridenti:\n&eTridenti riguarda trafiggere i tuoi nemici col tuo tridente.\n\n&3GUADAGNO XP:\n&eGli XP si ottengono ogni volta che colpisci un mob con un tridente.\nQuesta abilità è ancora in sviluppo e più informazioni verranno presto aggiunte.
Guides.Maces.Section.0=&3About Maces:\n&eMazze consiste nel massacrare i tuoi nemici con una mazza.\n\n&3GUADAGNO XP:\n&eGli XP si ottengono ogni volta che colpisci un mob con un tridente.\nQuesta abilità è ancora in sviluppo e più informazioni verranno presto aggiunte.
#INSPECT #INSPECT
Inspect.Offline= &cNon hai il permesso per ispezionare i giocatori offline! Inspect.Offline= &cNon hai il permesso per ispezionare i giocatori offline!
Inspect.OfflineStats=Statistiche mcMMO per il Giocatore Offline &e{0} Inspect.OfflineStats=Statistiche mcMMO per il Giocatore Offline &e{0}
Inspect.Stats=&aStatistiche mcMMO per &e{0} Inspect.Stats=&aStatistiche mcMMO per &e{0}
Inspect.TooFar=Sei troppo lontano per ispezionare quel giocatore! Inspect.TooFar=Sei troppo lontano per ispezionare quel giocatore!
#ITEMS #ITEMS
Item.ChimaeraWing.Fail=&c**ALA DI CHIMERA FALLITA!** Item.ChimaeraWing.Fail=&c**ALA DI CHIMERA FALLITA!**
Item.ChimaeraWing.Pass=**ALA DI CHIMERA** Item.ChimaeraWing.Pass=**ALA DI CHIMERA**
@@ -986,11 +1070,9 @@ Item.Injured.Wait=Sei stato ferito di recente e devi aspettare per usarlo. &e({0
Item.FluxPickaxe.Name=Piccone a Fusione Item.FluxPickaxe.Name=Piccone a Fusione
Item.FluxPickaxe.Lore.1=&7C'è la possibilità che fonda istantaneamente i minerali estratti. Item.FluxPickaxe.Lore.1=&7C'è la possibilità che fonda istantaneamente i minerali estratti.
Item.FluxPickaxe.Lore.2=&7Richiede il livello di Fusione {0}+ Item.FluxPickaxe.Lore.2=&7Richiede il livello di Fusione {0}+
#TELEPORTATION #TELEPORTATION
Teleport.Commencing=&7Il teletrasporto inizierà tra &6({0}) &7secondi, non muoverti... Teleport.Commencing=&7Il teletrasporto inizierà tra &6({0}) &7secondi, non muoverti...
Teleport.Cancelled=&4Teletrasporto annullato! Teleport.Cancelled=&4Teletrasporto annullato!
#SKILLS #SKILLS
Skills.Child=&6(ABILITà FIGLIA) Skills.Child=&6(ABILITà FIGLIA)
Skills.Disarmed=&4Sei stato disarmato! Skills.Disarmed=&4Sei stato disarmato!
@@ -1000,17 +1082,18 @@ Skills.NeedMore.Extra=&4Hai bisogno di altri &7{0}{1}
Skills.Parents= GENITORI Skills.Parents= GENITORI
Skills.Stats={0}&a{1}&3 XP(&7{2}&3/&7{3}&3) Skills.Stats={0}&a{1}&3 XP(&7{2}&3/&7{3}&3)
Skills.ChildStats={0}&a{1} Skills.ChildStats={0}&a{1}
Skills.MaxXP=Massimo
Skills.TooTired=Sei troppo stanco per usare di nuovo quella capacità. &e({0}s) Skills.TooTired=Sei troppo stanco per usare di nuovo quella capacità. &e({0}s)
Skills.TooTired.Named=&7(&6{0}&e {1}s&7)
Skills.TooTired.Extra=&6{0} &eTempi di recupero Super Abilità - {1}
Skills.Cancelled=&6{0} &cannullato! Skills.Cancelled=&6{0} &cannullato!
Skills.ConfirmOrCancel=&aFai nuovamente click-destro per confermare &6{0}&a. Click-sinistro per annullare. Skills.ConfirmOrCancel=&aFai nuovamente click-destro per confermare &6{0}&a. Click-sinistro per annullare.
Skills.AbilityGateRequirementFail=&7Ti servono altri &e{0}&7 livelli di &3{1}&7 per usare questa super capacità. Skills.AbilityGateRequirementFail=&7Ti servono altri &e{0}&7 livelli di &3{1}&7 per usare questa super capacità.
#STATISTICS #STATISTICS
Stats.Header.Combat=&6-=ABILITà DI COMBATTIMENTO=- Stats.Header.Combat=&6-=ABILITà DI COMBATTIMENTO=-
Stats.Header.Gathering=&6-=ABILITà DI RACCOLTA=- Stats.Header.Gathering=&6-=ABILITà DI RACCOLTA=-
Stats.Header.Misc=&6-=ABILITà VARIE=- Stats.Header.Misc=&6-=ABILITà VARIE=-
Stats.Own.Stats=&a[mcMMO] Statistiche Stats.Own.Stats=&a[mcMMO] Statistiche
#PERKS #PERKS
Perks.XP.Name=Esperienza Perks.XP.Name=Esperienza
Perks.XP.Desc=Ricevi XP potenziati in determinate abilità. Perks.XP.Desc=Ricevi XP potenziati in determinate abilità.
@@ -1023,7 +1106,6 @@ Perks.Cooldowns.Desc=Riduce il tempo di recupero di {0}.
Perks.ActivationTime.Name=Resistenza Perks.ActivationTime.Name=Resistenza
Perks.ActivationTime.Desc=Aumenta il tempo di attivazione delle capacità di {0} secondi. Perks.ActivationTime.Desc=Aumenta il tempo di attivazione delle capacità di {0} secondi.
Perks.ActivationTime.Bonus=&6 ({0}s con il Vantaggio Resistenza) Perks.ActivationTime.Bonus=&6 ({0}s con il Vantaggio Resistenza)
#HARDCORE #HARDCORE
Hardcore.Mode.Disabled=&6[mcMMO] Modalità hardcore {0} disabilitata per {1}. Hardcore.Mode.Disabled=&6[mcMMO] Modalità hardcore {0} disabilitata per {1}.
Hardcore.Mode.Enabled=&6[mcMMO] Modalità hardcore {0} abilitata per {1}. Hardcore.Mode.Enabled=&6[mcMMO] Modalità hardcore {0} abilitata per {1}.
@@ -1036,7 +1118,6 @@ Hardcore.Vampirism.Killer.Success=&6[mcMMO] &3Hai rubato &9{0}&3 livelli da &e{1
Hardcore.Vampirism.Victim.Failure=&6[mcMMO] &e{0}&7 non è riuscito a rubarti la conoscenza! Hardcore.Vampirism.Victim.Failure=&6[mcMMO] &e{0}&7 non è riuscito a rubarti la conoscenza!
Hardcore.Vampirism.Victim.Success=&6[mcMMO] &e{0}&4 ha rubato &9{1}&4 livelli da te! Hardcore.Vampirism.Victim.Success=&6[mcMMO] &e{0}&4 ha rubato &9{1}&4 livelli da te!
Hardcore.Vampirism.PercentageChanged=&6[mcMMO] La percentuale di Vampirismo è stata modificata a {0}. Hardcore.Vampirism.PercentageChanged=&6[mcMMO] La percentuale di Vampirismo è stata modificata a {0}.
#MOTD #MOTD
MOTD.Donate=&3Info Donazioni: MOTD.Donate=&3Info Donazioni:
MOTD.Hardcore.Enabled=&6[mcMMO] &3Modalità hardcore abilitata: &4{0} MOTD.Hardcore.Enabled=&6[mcMMO] &3Modalità hardcore abilitata: &4{0}
@@ -1045,7 +1126,6 @@ MOTD.Hardcore.Vampirism.Stats=&6[mcMMO] &3Percentuale di Vampirismo: &4{0}%
MOTD.PerksPrefix=&6[Vantaggi mcMMO] MOTD.PerksPrefix=&6[Vantaggi mcMMO]
MOTD.Version=&6[mcMMO] Versione &3{0} MOTD.Version=&6[mcMMO] Versione &3{0}
MOTD.Website=&6[mcMMO] &a{0}&e - Sito Web di mcMMO MOTD.Website=&6[mcMMO] &a{0}&e - Sito Web di mcMMO
#SMELTING #SMELTING
Smelting.SubSkill.UnderstandingTheArt.Name=Capire l'Arte Smelting.SubSkill.UnderstandingTheArt.Name=Capire l'Arte
Smelting.SubSkill.UnderstandingTheArt.Description=Forse stai trascorrendo un po' troppo tempo a fondere nelle caverne.\nPotenzia varie proprietà della Fusione. Smelting.SubSkill.UnderstandingTheArt.Description=Forse stai trascorrendo un po' troppo tempo a fondere nelle caverne.\nPotenzia varie proprietà della Fusione.
@@ -1065,7 +1145,6 @@ Smelting.SubSkill.FluxMining.Description=Possibilità di fusione istantanea dei
Smelting.SubSkill.FluxMining.Stat=Possibilità Fusione Istantanea Smelting.SubSkill.FluxMining.Stat=Possibilità Fusione Istantanea
Smelting.Listener=Fusione: Smelting.Listener=Fusione:
Smelting.SkillName=FUSIONE Smelting.SkillName=FUSIONE
#COMMAND DESCRIPTIONS #COMMAND DESCRIPTIONS
Commands.Description.addlevels=Aggiungi livelli di mcMMO a un utente Commands.Description.addlevels=Aggiungi livelli di mcMMO a un utente
Commands.Description.adminchat=Attiva / disattiva la chat admin di mcMMO o invia messaggi in chat admin Commands.Description.adminchat=Attiva / disattiva la chat admin di mcMMO o invia messaggi in chat admin
@@ -1099,11 +1178,9 @@ Commands.Description.skillreset=Azzera i livelli mcMMO di un utente
Commands.Description.vampirism=Modifica la percentuale di vampirismo mcMMO o attiva/disattiva la modalità vampirismo Commands.Description.vampirism=Modifica la percentuale di vampirismo mcMMO o attiva/disattiva la modalità vampirismo
Commands.Description.xplock=Blocca la barra XP mcMMO su un'abilità mcMMO specifica Commands.Description.xplock=Blocca la barra XP mcMMO su un'abilità mcMMO specifica
Commands.Description.xprate=Modifica il tasso XP di mcMMO o avvia un evento XP mcMMO Commands.Description.xprate=Modifica il tasso XP di mcMMO o avvia un evento XP mcMMO
#UPDATE CHECKER #UPDATE CHECKER
UpdateChecker.Outdated=Stai utilizzando una versione non aggiornata di mcMMO! UpdateChecker.Outdated=Stai utilizzando una versione non aggiornata di mcMMO!
UpdateChecker.NewAvailable=C'è una nuova versione disponibile su Spigot. UpdateChecker.NewAvailable=C'è una nuova versione disponibile su Spigot.
#SCOREBOARD HEADERS #SCOREBOARD HEADERS
Scoreboard.Header.PlayerStats=&eStatistiche mcMMO Scoreboard.Header.PlayerStats=&eStatistiche mcMMO
Scoreboard.Header.PlayerCooldowns=&eRicariche mcMMO Scoreboard.Header.PlayerCooldowns=&eRicariche mcMMO
@@ -1117,26 +1194,37 @@ Scoreboard.Misc.RemainingXP=&eXP Rimanenti
Scoreboard.Misc.Cooldown=&dRicarica Scoreboard.Misc.Cooldown=&dRicarica
Scoreboard.Misc.Overall=&6Complessivo Scoreboard.Misc.Overall=&6Complessivo
Scoreboard.Misc.Ability=Capacità Scoreboard.Misc.Ability=Capacità
#DATABASE RECOVERY #DATABASE RECOVERY
Profile.PendingLoad=&cI tuoi dati di mcMMO non sono stati ancora caricati. Profile.PendingLoad=&cI tuoi dati di mcMMO non sono stati ancora caricati.
Profile.Loading.Success=&aIl tuo profilo mcMMO è stato caricato. Profile.Loading.Success=&aIl tuo profilo mcMMO è stato caricato.
Profile.Loading.FailurePlayer=&cmcMMO ha dei problemi nel caricare i tuoi dati, abbiamo tentato di caricarli &a{0}&c volte.&c Potresti voler contattare gli amministratori del server per questo problema. mcMMO tenterà di caricare i tuoi dati fino a che non ti disconnetterai, non guadagnerai XP né potrai usare abilità finché i dati non verranno caricati. Profile.Loading.FailurePlayer=&cmcMMO ha dei problemi nel caricare i tuoi dati, abbiamo tentato di caricarli &a{0}&c volte.&c Potresti voler contattare gli amministratori del server per questo problema. mcMMO tenterà di caricare i tuoi dati fino a che non ti disconnetterai, non guadagnerai XP né potrai usare abilità finché i dati non verranno caricati.
Profile.Loading.FailureNotice=&4[A]&c mcMMO non è stato in grado di caricare i dati per &e{0}&c. &dControlla la configurazione del database. Tentativi fatti finora {1}. Profile.Loading.FailureNotice=&4[A]&c mcMMO non è stato in grado di caricare i dati per &e{0}&c. &dControlla la configurazione del database. Tentativi fatti finora {1}.
#Holiday #Holiday
Holiday.AprilFools.Levelup=&6{0} è ora al livello &a{1}&6! Holiday.AprilFools.Levelup=&6{0} è ora al livello &a{1}&6!
Holiday.Anniversary=&9Buon Capodanno {0}!\n&9In onore di tutto il lavoro di nossr50 e di tutti gli sviluppatori, ecco uno spettacolo pirotecnico! Holiday.Anniversary=&9Buon Capodanno {0}!\n&9In onore di tutto il lavoro di nossr50 e di tutti gli sviluppatori, ecco uno spettacolo pirotecnico!
#Reminder Messages #Reminder Messages
Reminder.Squelched=&7Promemoria: Al momento non ricevi notifiche da mcMMO, per abilitare le notifiche esegui nuovamente il comando /mcnotify. Questo è un promemoria automatico per ogni ora. Reminder.Squelched=&7Promemoria: Al momento non ricevi notifiche da mcMMO, per abilitare le notifiche esegui nuovamente il comando /mcnotify. Questo è un promemoria automatico per ogni ora.
#Locale #Locale
Locale.Reloaded=&aTraduzioni ricaricate! Locale.Reloaded=&aTraduzioni ricaricate!
#Player Leveling Stuff #Player Leveling Stuff
LevelCap.PowerLevel=&6(&amcMMO&6) &eHai raggiunto il livello massimo di potenza di &c{0}&e. Da questo punto in poi cesserai di aumentare di livello nelle tue abilità. LevelCap.PowerLevel=&6(&amcMMO&6) &eHai raggiunto il livello massimo di potenza di &c{0}&e. Da questo punto in poi cesserai di aumentare di livello nelle tue abilità.
LevelCap.Skill=&6(&amcMMO&6) &eHai raggiunto il livello massimo di &c{0}&e per &6{1}&e. Da questo punto in poi cesserai di salire di livello in questa abilità. LevelCap.Skill=&6(&amcMMO&6) &eHai raggiunto il livello massimo di &c{0}&e per &6{1}&e. Da questo punto in poi cesserai di salire di livello in questa abilità.
Commands.XPBar.Usage=Proper usage is /mmoxpbar <skillname | reset> <show | hide> Commands.XPBar.Usage=L'uso appropriato è /mmoxpbar <skillname | reset> <show | hide>
Commands.Description.mmoxpbar=Player settings for mcMMO XP bars Commands.Description.mmoxpbar=Impostazioni giocatore per la barra XP di mcMMO
Commands.Description.mmocompat=Information about mcMMO and whether its in compatibility mode or fully functional. Commands.Description.mmocompat=Informazioni riguardo mcMMO e se è in modalità compatibilità o pienamente funzionante.
Compatibility.Layer.Unsupported=&6La compatibilità per &a{0}&6 non è supportata da questa versione di Minecraft.
Compatibility.Layer.PartialSupport=&6La compatibilità per &a{0}&6 non è pienamente supportata da questa versione di Minecraft, ma mcMMO sta usando un sistema secondario per emulare alcune delle funzioni mancanti.
Commands.XPBar.DisableAll=&6 Tutte le barre XP di mcMMO sono ora disabilitate, usa /mmoxpbar reset per reimpostare le impostazioni di default.
#Modern Chat Settings
Chat.Style.Admin=&b(A) &r{0} &b\u2192 &r{1}
Chat.Style.Party=&a(P) &r{0} &a\u2192 &r{1}
Chat.Style.Party.Leader=&a(P) &r{0} &6\u2192 &r{1}
Chat.Identity.Console=&6* Console *
Chat.Channel.On=&6(&amcMMO-Chat&6) &eI tuoi messaggi di chat verranno ora automaticamente consegnati nel canale chat &a{0}.
Chat.Channel.Off=&6(&amcMMO-Chat&6) &7I tuoi messaggi di chat non verranno più automaticamente consegnati in canali chat specifici.
Chat.Spy.Party=&6[&eSPY&6-&a{2}&6] &r{0} &b\u2192 &r{1}
Broadcasts.LevelUpMilestone=&6(&amcMMO&6) {0}&7 ha raggiunto il livello &a{1}&7 in &3{2}&7!
Broadcasts.PowerLevelUpMilestone=&6(&amcMMO&6) {0}&7 ha raggiunto un livello di Potere di &a{1}&7!
Scoreboard.Recovery=Cercando di ripristinare la scoreboard mcMMO...
Scoreboard.Disabled=Le scoreboards mcMMO per questo server sono disabilitate, quest'impostazione si trova in mcMMO/config.yml
Scoreboard.NotSetupYet=La tua scoreboard mcMMO non è ancora stata impostata, riprova più tardi.

View File

@@ -11,10 +11,10 @@ description: >
in order to evaluate and balance the mechanics of mcMMO in every update. in order to evaluate and balance the mechanics of mcMMO in every update.
author: nossr50 author: nossr50
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, electronicboy, kashike] authors: [ GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, electronicboy, kashike ]
website: https://www.mcmmo.org website: https://www.mcmmo.org
main: com.gmail.nossr50.mcMMO main: com.gmail.nossr50.mcMMO
softdepend: [WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib] softdepend: [ WorldGuard, CombatTag, HealthBar, PlaceholderAPI, ProtocolLib ]
load: POSTWORLD load: POSTWORLD
folia-supported: true folia-supported: true
api-version: 1.13 api-version: 1.13
@@ -26,14 +26,14 @@ commands:
mmocompat: mmocompat:
description: Information about the server and whether its considered fully compatible or running in compatibility mode description: Information about the server and whether its considered fully compatible or running in compatibility mode
mmodebug: mmodebug:
aliases: [mcmmodebugmode] aliases: [ mcmmodebugmode ]
description: Toggles a debug mode which will print useful information to chat description: Toggles a debug mode which will print useful information to chat
mmoinfo: mmoinfo:
aliases: [mcinfo] aliases: [ mcinfo ]
description: Info pages for mcMMO description: Info pages for mcMMO
permission: mcmmo.commands.mmoinfo permission: mcmmo.commands.mmoinfo
xprate: xprate:
aliases: [mcxprate] aliases: [ mcxprate ]
description: Modify the xp rate or start an event description: Modify the xp rate or start an event
permission: mcmmo.commands.xprate permission: mcmmo.commands.xprate
mcmmo: mcmmo:
@@ -59,7 +59,7 @@ commands:
permission: mcmmo.commands.mcrefresh permission: mcmmo.commands.mcrefresh
mccooldown: mccooldown:
description: Show the cooldowns on all your mcMMO abilities description: Show the cooldowns on all your mcMMO abilities
aliases: [mccooldowns] aliases: [ mccooldowns ]
permission: mcmmo.commands.mccooldown permission: mcmmo.commands.mccooldown
mcchatspy: mcchatspy:
description: Toggle mcMMO Party Chat spying on/off description: Toggle mcMMO Party Chat spying on/off
@@ -68,7 +68,7 @@ commands:
description: Toggle mcMMO god-mode on/off description: Toggle mcMMO god-mode on/off
permission: mcmmo.commands.mcgod permission: mcmmo.commands.mcgod
mcstats: mcstats:
aliases: [stats] aliases: [ stats ]
description: Shows your mcMMO stats and xp description: Shows your mcMMO stats and xp
permission: mcmmo.commands.mcstats permission: mcmmo.commands.mcstats
mcremove: mcremove:
@@ -84,7 +84,7 @@ commands:
description: Create/join a party description: Create/join a party
permission: mcmmo.commands.party permission: mcmmo.commands.party
inspect: inspect:
aliases: [mcinspect, mmoinspect] aliases: [ mcinspect, mmoinspect ]
description: View detailed mcMMO info on another player description: View detailed mcMMO info on another player
permission: mcmmo.commands.inspect permission: mcmmo.commands.inspect
mmoshowdb: mmoshowdb:
@@ -94,7 +94,7 @@ commands:
description: Convert between different database and formula types description: Convert between different database and formula types
permission: mcmmo.commands.mcconvert permission: mcmmo.commands.mcconvert
partychat: partychat:
aliases: [pc, p] aliases: [ pc, p ]
description: Toggle Party chat or send party chat messages description: Toggle Party chat or send party chat messages
permission: mcmmo.chat.partychat permission: mcmmo.chat.partychat
skillreset: skillreset:
@@ -145,6 +145,9 @@ commands:
smelting: smelting:
description: Detailed mcMMO skill info description: Detailed mcMMO skill info
permission: mcmmo.commands.smelting permission: mcmmo.commands.smelting
spears:
description: Detailed mcMMO skill info
permission: mcmmo.commands.spears
alchemy: alchemy:
description: Detailed mcMMO skill info description: Detailed mcMMO skill info
permission: mcmmo.commands.alchemy permission: mcmmo.commands.alchemy
@@ -157,24 +160,24 @@ commands:
mmopower: mmopower:
description: Shows skill mastery and power level info description: Shows skill mastery and power level info
permission: mcmmo.commands.mmopower permission: mcmmo.commands.mmopower
aliases: [mmopowerlevel, powerlevel] aliases: [ mmopowerlevel, powerlevel ]
adminchat: adminchat:
aliases: [ac, a] aliases: [ ac, a ]
description: Toggle Admin chat or send admin chat messages description: Toggle Admin chat or send admin chat messages
permission: mcmmo.chat.adminchat permission: mcmmo.chat.adminchat
mcpurge: mcpurge:
description: Purge users with 0 powerlevel and/or who haven't connected in several months from the server DB. description: Purge users with 0 powerlevel and/or who haven't connected in several months from the server DB.
permission: mcmmo.commands.mcpurge permission: mcmmo.commands.mcpurge
mcnotify: mcnotify:
aliases: [notify] aliases: [ notify ]
description: Toggle mcMMO abilities chat display notifications on/off description: Toggle mcMMO abilities chat display notifications on/off
permission: mcmmo.commands.mcnotify permission: mcmmo.commands.mcnotify
mcscoreboard: mcscoreboard:
aliases: [mcsb] aliases: [ mcsb ]
description: Manage your mcMMO Scoreboard description: Manage your mcMMO Scoreboard
permission: mcmmo.commands.mcscoreboard permission: mcmmo.commands.mcscoreboard
mcmmoreloadlocale: mcmmoreloadlocale:
aliases: [mcreloadlocale] aliases: [ mcreloadlocale ]
description: Reloads locale description: Reloads locale
permission: mcmmo.commands.reloadlocale permission: mcmmo.commands.reloadlocale
permissions: permissions:
@@ -237,6 +240,7 @@ permissions:
mcmmo.ability.repair.all: true mcmmo.ability.repair.all: true
mcmmo.ability.salvage.all: true mcmmo.ability.salvage.all: true
mcmmo.ability.smelting.all: true mcmmo.ability.smelting.all: true
mcmmo.ability.spears.all: true
mcmmo.ability.swords.all: true mcmmo.ability.swords.all: true
mcmmo.ability.taming.all: true mcmmo.ability.taming.all: true
mcmmo.ability.tridents.all: true mcmmo.ability.tridents.all: true
@@ -529,6 +533,7 @@ permissions:
mcmmo.ability.repair.armorrepair: true mcmmo.ability.repair.armorrepair: true
mcmmo.ability.repair.netheriterepair: true mcmmo.ability.repair.netheriterepair: true
mcmmo.ability.repair.diamondrepair: true mcmmo.ability.repair.diamondrepair: true
mcmmo.ability.repair.copperrepair: true
mcmmo.ability.repair.goldrepair: true mcmmo.ability.repair.goldrepair: true
mcmmo.ability.repair.ironrepair: true mcmmo.ability.repair.ironrepair: true
mcmmo.ability.repair.leatherrepair: true mcmmo.ability.repair.leatherrepair: true
@@ -548,6 +553,8 @@ permissions:
description: Allows ability to repair Netherite tools & armor description: Allows ability to repair Netherite tools & armor
mcmmo.ability.repair.diamondrepair: mcmmo.ability.repair.diamondrepair:
description: Allows ability to repair Diamond tools & armor description: Allows ability to repair Diamond tools & armor
mcmmo.ability.repair.copperrepair:
description: Allows ability to repair Copper tools & armor
mcmmo.ability.repair.goldrepair: mcmmo.ability.repair.goldrepair:
description: Allows ability to repair Gold tools & armor description: Allows ability to repair Gold tools & armor
mcmmo.ability.repair.ironrepair: mcmmo.ability.repair.ironrepair:
@@ -584,6 +591,7 @@ permissions:
mcmmo.ability.salvage.diamondsalvage: true mcmmo.ability.salvage.diamondsalvage: true
mcmmo.ability.salvage.netheritesalvage: true mcmmo.ability.salvage.netheritesalvage: true
mcmmo.ability.salvage.goldsalvage: true mcmmo.ability.salvage.goldsalvage: true
mcmmo.ability.salvage.coppersalvage: true
mcmmo.ability.salvage.ironsalvage: true mcmmo.ability.salvage.ironsalvage: true
mcmmo.ability.salvage.leathersalvage: true mcmmo.ability.salvage.leathersalvage: true
mcmmo.ability.salvage.othermaterialsalvage: true mcmmo.ability.salvage.othermaterialsalvage: true
@@ -604,6 +612,8 @@ permissions:
description: Allows ability to salvage Diamond tools & armor description: Allows ability to salvage Diamond tools & armor
mcmmo.ability.salvage.goldsalvage: mcmmo.ability.salvage.goldsalvage:
description: Allows ability to salvage Gold tools & armor description: Allows ability to salvage Gold tools & armor
mcmmo.ability.salvage.coppersalvage:
description: Allows ability to salvage Copper tools & armor
mcmmo.ability.salvage.ironsalvage: mcmmo.ability.salvage.ironsalvage:
description: Allows ability to salvage Iron tools & armor description: Allows ability to salvage Iron tools & armor
mcmmo.ability.salvage.leathersalvage: mcmmo.ability.salvage.leathersalvage:
@@ -640,6 +650,23 @@ permissions:
description: Allows access to the Second Smelt ability description: Allows access to the Second Smelt ability
mcmmo.ability.smelting.vanillaxpboost: mcmmo.ability.smelting.vanillaxpboost:
description: Allows vanilla XP boost from Smelting description: Allows vanilla XP boost from Smelting
mcmmo.ability.spears.*:
default: false
description: Allows access to all Spear abilities
children:
mcmmo.ability.spears.all: true
mcmmo.ability.spears.all:
description: Allows access to all Spear abilities
children:
mcmmo.ability.spears.spearslimitbreak: true
mcmmo.ability.spears.momentum: true
mcmmo.ability.spears.spearmastery: true
mcmmo.ability.spears.spearslimitbreak:
description: Adds damage to spears
mcmmo.ability.spears.momentum:
description: Allows access to the Spear Momentum ability
mcmmo.ability.spears.spearmastery:
description: Allows access to the Spear Mastery ability
mcmmo.ability.swords.*: mcmmo.ability.swords.*:
default: false default: false
description: Allows access to all Swords abilities description: Allows access to all Swords abilities
@@ -879,6 +906,7 @@ permissions:
mcmmo.commands.repair: true mcmmo.commands.repair: true
mcmmo.commands.salvage: true mcmmo.commands.salvage: true
mcmmo.commands.smelting: true mcmmo.commands.smelting: true
mcmmo.commands.spears: true
mcmmo.commands.swords: true mcmmo.commands.swords: true
mcmmo.commands.taming: true mcmmo.commands.taming: true
mcmmo.commands.unarmed: true mcmmo.commands.unarmed: true
@@ -892,7 +920,7 @@ permissions:
mcmmo.commands.addxp: true mcmmo.commands.addxp: true
mcmmo.commands.addxp.others: true mcmmo.commands.addxp.others: true
mcmmo.commands.defaults: true mcmmo.commands.defaults: true
# mcmmo.commands.hardcore.all: true # mcmmo.commands.hardcore.all: true
mcmmo.commands.inspect.far: true mcmmo.commands.inspect.far: true
mcmmo.commands.inspect.hidden: true mcmmo.commands.inspect.hidden: true
mcmmo.commands.mcability.others: true mcmmo.commands.mcability.others: true
@@ -912,7 +940,7 @@ permissions:
mcmmo.commands.ptp.world.all: true mcmmo.commands.ptp.world.all: true
mcmmo.commands.reloadlocale: true mcmmo.commands.reloadlocale: true
mcmmo.commands.skillreset.all: true mcmmo.commands.skillreset.all: true
# mcmmo.commands.vampirism.all: true # mcmmo.commands.vampirism.all: true
mcmmo.commands.xprate.all: true mcmmo.commands.xprate.all: true
mcmmo.commands.acrobatics: mcmmo.commands.acrobatics:
description: Allows access to the acrobatics command description: Allows access to the acrobatics command
@@ -1052,6 +1080,7 @@ permissions:
mcmmo.commands.mctop.repair: true mcmmo.commands.mctop.repair: true
mcmmo.commands.mctop.salvage: true mcmmo.commands.mctop.salvage: true
mcmmo.commands.mctop.smelting: true mcmmo.commands.mctop.smelting: true
mcmmo.commands.mctop.spears: true
mcmmo.commands.mctop.swords: true mcmmo.commands.mctop.swords: true
mcmmo.commands.mctop.taming: true mcmmo.commands.mctop.taming: true
mcmmo.commands.mctop.tridents: true mcmmo.commands.mctop.tridents: true
@@ -1085,6 +1114,8 @@ permissions:
description: Allows access to the mctop command for salvage description: Allows access to the mctop command for salvage
mcmmo.commands.mctop.smelting: mcmmo.commands.mctop.smelting:
description: Allows access to the mctop command for smelting description: Allows access to the mctop command for smelting
mcmmo.commands.mctop.spears:
description: Allows access to the mctop command for spears
mcmmo.commands.mctop.swords: mcmmo.commands.mctop.swords:
description: Allows access to the mctop command for swords description: Allows access to the mctop command for swords
mcmmo.commands.mctop.taming: mcmmo.commands.mctop.taming:
@@ -1233,6 +1264,7 @@ permissions:
mcmmo.commands.skillreset.repair: true mcmmo.commands.skillreset.repair: true
mcmmo.commands.skillreset.salvage: true mcmmo.commands.skillreset.salvage: true
mcmmo.commands.skillreset.smelting: true mcmmo.commands.skillreset.smelting: true
mcmmo.commands.skillreset.spears: true
mcmmo.commands.skillreset.swords: true mcmmo.commands.skillreset.swords: true
mcmmo.commands.skillreset.taming: true mcmmo.commands.skillreset.taming: true
mcmmo.commands.skillreset.unarmed: true mcmmo.commands.skillreset.unarmed: true
@@ -1262,6 +1294,8 @@ permissions:
description: Allows access to the skillreset command for crossbows description: Allows access to the skillreset command for crossbows
mcmmo.commands.skillreset.tridents: mcmmo.commands.skillreset.tridents:
description: Allows access to the skillreset command for tridents description: Allows access to the skillreset command for tridents
mcmmo.commands.skillreset.spears:
description: Allows access to the skillreset command for spears
mcmmo.commands.skillreset.maces: mcmmo.commands.skillreset.maces:
description: Allows access to the skillreset command for maces description: Allows access to the skillreset command for maces
mcmmo.commands.skillreset.others.*: mcmmo.commands.skillreset.others.*:
@@ -1284,6 +1318,7 @@ permissions:
mcmmo.commands.skillreset.others.repair: true mcmmo.commands.skillreset.others.repair: true
mcmmo.commands.skillreset.others.salvage: true mcmmo.commands.skillreset.others.salvage: true
mcmmo.commands.skillreset.others.smelting: true mcmmo.commands.skillreset.others.smelting: true
mcmmo.commands.skillreset.others.spears: true
mcmmo.commands.skillreset.others.swords: true mcmmo.commands.skillreset.others.swords: true
mcmmo.commands.skillreset.others.taming: true mcmmo.commands.skillreset.others.taming: true
mcmmo.commands.skillreset.others.unarmed: true mcmmo.commands.skillreset.others.unarmed: true
@@ -1315,6 +1350,8 @@ permissions:
description: Allows access to the skillreset command for salvage for other players description: Allows access to the skillreset command for salvage for other players
mcmmo.commands.skillreset.others.smelting: mcmmo.commands.skillreset.others.smelting:
description: Allows access to the skillreset command for smelting for other players description: Allows access to the skillreset command for smelting for other players
mcmmo.commands.skillreset.others.spears:
description: Allows access to the skillreset command for spears for other players
mcmmo.commands.skillreset.others.swords: mcmmo.commands.skillreset.others.swords:
description: Allows access to the skillreset command for swords for other players description: Allows access to the skillreset command for swords for other players
mcmmo.commands.skillreset.others.taming: mcmmo.commands.skillreset.others.taming:
@@ -1491,6 +1528,7 @@ permissions:
mcmmo.perks.lucky.repair: true mcmmo.perks.lucky.repair: true
mcmmo.perks.lucky.salvage: true mcmmo.perks.lucky.salvage: true
mcmmo.perks.lucky.smelting: true mcmmo.perks.lucky.smelting: true
mcmmo.perks.lucky.spears: true
mcmmo.perks.lucky.swords: true mcmmo.perks.lucky.swords: true
mcmmo.perks.lucky.taming: true mcmmo.perks.lucky.taming: true
mcmmo.perks.lucky.unarmed: true mcmmo.perks.lucky.unarmed: true
@@ -1533,6 +1571,9 @@ permissions:
mcmmo.perks.lucky.salvage: mcmmo.perks.lucky.salvage:
default: false default: false
description: Gives Salvage abilities & skills a 33.3% better chance to activate. description: Gives Salvage abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.spears:
default: false
description: Gives Spears abilities & skills a 33.3% better chance to activate.
mcmmo.perks.lucky.smelting: mcmmo.perks.lucky.smelting:
default: false default: false
description: Gives Smelting abilities & skills a 33.3% better chance to activate. description: Gives Smelting abilities & skills a 33.3% better chance to activate.
@@ -1594,6 +1635,7 @@ permissions:
mcmmo.perks.xp.150percentboost.mining: true mcmmo.perks.xp.150percentboost.mining: true
mcmmo.perks.xp.150percentboost.repair: true mcmmo.perks.xp.150percentboost.repair: true
mcmmo.perks.xp.150percentboost.smelting: true mcmmo.perks.xp.150percentboost.smelting: true
mcmmo.perks.xp.150percentboost.spears: true
mcmmo.perks.xp.150percentboost.swords: true mcmmo.perks.xp.150percentboost.swords: true
mcmmo.perks.xp.150percentboost.taming: true mcmmo.perks.xp.150percentboost.taming: true
mcmmo.perks.xp.150percentboost.tridents: true mcmmo.perks.xp.150percentboost.tridents: true
@@ -1635,6 +1677,9 @@ permissions:
mcmmo.perks.xp.150percentboost.smelting: mcmmo.perks.xp.150percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 2.5 description: Multiplies incoming Smelting XP by 2.5
mcmmo.perks.xp.150percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 2.5
mcmmo.perks.xp.150percentboost.swords: mcmmo.perks.xp.150percentboost.swords:
default: false default: false
description: Multiplies incoming Swords XP by 2.5 description: Multiplies incoming Swords XP by 2.5
@@ -1676,6 +1721,7 @@ permissions:
mcmmo.perks.xp.50percentboost.mining: true mcmmo.perks.xp.50percentboost.mining: true
mcmmo.perks.xp.50percentboost.repair: true mcmmo.perks.xp.50percentboost.repair: true
mcmmo.perks.xp.50percentboost.smelting: true mcmmo.perks.xp.50percentboost.smelting: true
mcmmo.perks.xp.50percentboost.spears: true
mcmmo.perks.xp.50percentboost.swords: true mcmmo.perks.xp.50percentboost.swords: true
mcmmo.perks.xp.50percentboost.taming: true mcmmo.perks.xp.50percentboost.taming: true
mcmmo.perks.xp.50percentboost.tridents: true mcmmo.perks.xp.50percentboost.tridents: true
@@ -1714,6 +1760,9 @@ permissions:
mcmmo.perks.xp.50percentboost.repair: mcmmo.perks.xp.50percentboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by 1.5 description: Multiplies incoming Repair XP by 1.5
mcmmo.perks.xp.50percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 1.5
mcmmo.perks.xp.50percentboost.smelting: mcmmo.perks.xp.50percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 1.5 description: Multiplies incoming Smelting XP by 1.5
@@ -1758,6 +1807,7 @@ permissions:
mcmmo.perks.xp.25percentboost.mining: true mcmmo.perks.xp.25percentboost.mining: true
mcmmo.perks.xp.25percentboost.repair: true mcmmo.perks.xp.25percentboost.repair: true
mcmmo.perks.xp.25percentboost.smelting: true mcmmo.perks.xp.25percentboost.smelting: true
mcmmo.perks.xp.25percentboost.spears: true
mcmmo.perks.xp.25percentboost.swords: true mcmmo.perks.xp.25percentboost.swords: true
mcmmo.perks.xp.25percentboost.taming: true mcmmo.perks.xp.25percentboost.taming: true
mcmmo.perks.xp.25percentboost.tridents: true mcmmo.perks.xp.25percentboost.tridents: true
@@ -1799,6 +1849,9 @@ permissions:
mcmmo.perks.xp.25percentboost.smelting: mcmmo.perks.xp.25percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 1.25 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: mcmmo.perks.xp.25percentboost.swords:
default: false default: false
description: Multiplies incoming Swords XP by 1.25 description: Multiplies incoming Swords XP by 1.25
@@ -1840,6 +1893,7 @@ permissions:
mcmmo.perks.xp.10percentboost.mining: true mcmmo.perks.xp.10percentboost.mining: true
mcmmo.perks.xp.10percentboost.repair: true mcmmo.perks.xp.10percentboost.repair: true
mcmmo.perks.xp.10percentboost.smelting: true mcmmo.perks.xp.10percentboost.smelting: true
mcmmo.perks.xp.10percentboost.spears: true
mcmmo.perks.xp.10percentboost.swords: true mcmmo.perks.xp.10percentboost.swords: true
mcmmo.perks.xp.10percentboost.taming: true mcmmo.perks.xp.10percentboost.taming: true
mcmmo.perks.xp.10percentboost.tridents: true mcmmo.perks.xp.10percentboost.tridents: true
@@ -1878,6 +1932,9 @@ permissions:
mcmmo.perks.xp.10percentboost.repair: mcmmo.perks.xp.10percentboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by 1.1 description: Multiplies incoming Repair XP by 1.1
mcmmo.perks.xp.10percentboost.spears:
default: false
description: Multiplies incoming Spears XP by 1.1
mcmmo.perks.xp.10percentboost.smelting: mcmmo.perks.xp.10percentboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by 1.1 description: Multiplies incoming Smelting XP by 1.1
@@ -1922,6 +1979,7 @@ permissions:
mcmmo.perks.xp.customboost.mining: true mcmmo.perks.xp.customboost.mining: true
mcmmo.perks.xp.customboost.repair: true mcmmo.perks.xp.customboost.repair: true
mcmmo.perks.xp.customboost.smelting: true mcmmo.perks.xp.customboost.smelting: true
mcmmo.perks.xp.customboost.spears: true
mcmmo.perks.xp.customboost.swords: true mcmmo.perks.xp.customboost.swords: true
mcmmo.perks.xp.customboost.taming: true mcmmo.perks.xp.customboost.taming: true
mcmmo.perks.xp.customboost.tridents: true mcmmo.perks.xp.customboost.tridents: true
@@ -1960,6 +2018,9 @@ permissions:
mcmmo.perks.xp.customboost.repair: mcmmo.perks.xp.customboost.repair:
default: false default: false
description: Multiplies incoming Repair XP by the boost amount defined in the experience config description: Multiplies incoming Repair XP by the boost amount defined in the experience config
mcmmo.perks.xp.customboost.spears:
default: false
description: Multiplies incoming Smelting XP by the boost amount defined in the experience config
mcmmo.perks.xp.customboost.smelting: mcmmo.perks.xp.customboost.smelting:
default: false default: false
description: Multiplies incoming Smelting XP by the boost amount defined in the experience config description: Multiplies incoming Smelting XP by the boost amount defined in the experience config
@@ -2004,6 +2065,7 @@ permissions:
mcmmo.perks.xp.double.mining: true mcmmo.perks.xp.double.mining: true
mcmmo.perks.xp.double.repair: true mcmmo.perks.xp.double.repair: true
mcmmo.perks.xp.double.smelting: true mcmmo.perks.xp.double.smelting: true
mcmmo.perks.xp.double.spears: true
mcmmo.perks.xp.double.swords: true mcmmo.perks.xp.double.swords: true
mcmmo.perks.xp.double.taming: true mcmmo.perks.xp.double.taming: true
mcmmo.perks.xp.double.tridents: true mcmmo.perks.xp.double.tridents: true
@@ -2042,6 +2104,9 @@ permissions:
mcmmo.perks.xp.double.repair: mcmmo.perks.xp.double.repair:
default: false default: false
description: Doubles incoming Repair XP description: Doubles incoming Repair XP
mcmmo.perks.xp.double.spears:
default: false
description: Doubles incoming Smelting XP
mcmmo.perks.xp.double.smelting: mcmmo.perks.xp.double.smelting:
default: false default: false
description: Doubles incoming Smelting XP description: Doubles incoming Smelting XP
@@ -2086,6 +2151,7 @@ permissions:
mcmmo.perks.xp.quadruple.mining: true mcmmo.perks.xp.quadruple.mining: true
mcmmo.perks.xp.quadruple.repair: true mcmmo.perks.xp.quadruple.repair: true
mcmmo.perks.xp.quadruple.smelting: true mcmmo.perks.xp.quadruple.smelting: true
mcmmo.perks.xp.quadruple.spears: true
mcmmo.perks.xp.quadruple.swords: true mcmmo.perks.xp.quadruple.swords: true
mcmmo.perks.xp.quadruple.taming: true mcmmo.perks.xp.quadruple.taming: true
mcmmo.perks.xp.quadruple.tridents: true mcmmo.perks.xp.quadruple.tridents: true
@@ -2127,6 +2193,9 @@ permissions:
mcmmo.perks.xp.quadruple.smelting: mcmmo.perks.xp.quadruple.smelting:
default: false default: false
description: Quadruples incoming Smelting XP description: Quadruples incoming Smelting XP
mcmmo.perks.xp.quadruple.spears:
default: false
description: Quadruples incoming Spears XP
mcmmo.perks.xp.quadruple.swords: mcmmo.perks.xp.quadruple.swords:
default: false default: false
description: Quadruples incoming Swords XP description: Quadruples incoming Swords XP
@@ -2168,6 +2237,7 @@ permissions:
mcmmo.perks.xp.triple.maces: true mcmmo.perks.xp.triple.maces: true
mcmmo.perks.xp.triple.repair: true mcmmo.perks.xp.triple.repair: true
mcmmo.perks.xp.triple.smelting: true mcmmo.perks.xp.triple.smelting: true
mcmmo.perks.xp.triple.spears: true
mcmmo.perks.xp.triple.swords: true mcmmo.perks.xp.triple.swords: true
mcmmo.perks.xp.triple.taming: true mcmmo.perks.xp.triple.taming: true
mcmmo.perks.xp.triple.tridents: true mcmmo.perks.xp.triple.tridents: true
@@ -2209,6 +2279,9 @@ permissions:
mcmmo.perks.xp.triple.smelting: mcmmo.perks.xp.triple.smelting:
default: false default: false
description: Triples incoming Smelting XP description: Triples incoming Smelting XP
mcmmo.perks.xp.triple.spears:
default: false
description: Triples incoming Spears XP
mcmmo.perks.xp.triple.swords: mcmmo.perks.xp.triple.swords:
default: false default: false
description: Triples incoming Swords XP description: Triples incoming Swords XP
@@ -2251,6 +2324,7 @@ permissions:
mcmmo.skills.salvage: true mcmmo.skills.salvage: true
mcmmo.skills.swords: true mcmmo.skills.swords: true
mcmmo.skills.smelting: true mcmmo.skills.smelting: true
mcmmo.skills.spears: true
mcmmo.skills.taming: true mcmmo.skills.taming: true
mcmmo.skills.unarmed: true mcmmo.skills.unarmed: true
mcmmo.skills.woodcutting: true mcmmo.skills.woodcutting: true
@@ -2316,6 +2390,11 @@ permissions:
children: children:
mcmmo.ability.smelting.all: true mcmmo.ability.smelting.all: true
mcmmo.commands.smelting: true mcmmo.commands.smelting: true
mcmmo.skills.spears:
description: Allows access to the Spears skill
children:
mcmmo.ability.spears.all: true
mcmmo.commands.spears: true
mcmmo.skills.swords: mcmmo.skills.swords:
description: Allows access to the Swords skill description: Allows access to the Swords skill
children: children:

View File

@@ -55,6 +55,9 @@ Repairables:
WOODEN_SWORD: WOODEN_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
WOODEN_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
WOODEN_SHOVEL: WOODEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -74,6 +77,9 @@ Repairables:
STONE_SWORD: STONE_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
STONE_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
STONE_SHOVEL: STONE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -87,12 +93,80 @@ Repairables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
# #
# Copper repairables
###
# Tools
COPPER_SWORD:
MinimumLevel: 0
XpMultiplier: .3
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
ItemType: TOOL
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_PICKAXE:
MinimumLevel: 0
XpMultiplier: .6
ItemType: TOOL
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_AXE:
MinimumLevel: 0
XpMultiplier: .6
ItemType: TOOL
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_HOE:
MinimumLevel: 0
XpMultiplier: .3
ItemType: TOOL
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
# Armor
COPPER_HELMET:
MinimumLevel: 0
XpMultiplier: 1.8
ItemType: ARMOR
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_CHESTPLATE:
MinimumLevel: 0
XpMultiplier: 1.8
ItemType: ARMOR
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_LEGGINGS:
MinimumLevel: 0
XpMultiplier: 1.8
ItemType: ARMOR
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
COPPER_BOOTS:
MinimumLevel: 0
XpMultiplier: 1.8
ItemType: ARMOR
ItemMaterialCategory: COPPER
RepairMaterial: COPPER_INGOT
#
# Iron repairables # Iron repairables
### ###
# Tools # Tools
IRON_SWORD: IRON_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
IRON_SPEAR:
MinimumLevel: 0
XpMultiplier: .5
IRON_SHOVEL: IRON_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -131,6 +205,9 @@ Repairables:
GOLDEN_SWORD: GOLDEN_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 4 XpMultiplier: 4
GOLDEN_SPEAR:
MinimumLevel: 0
XpMultiplier: 4
GOLDEN_SHOVEL: GOLDEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 2.6 XpMultiplier: 2.6
@@ -163,6 +240,9 @@ Repairables:
DIAMOND_SWORD: DIAMOND_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
DIAMOND_SPEAR:
MinimumLevel: 0
XpMultiplier: .5
DIAMOND_SHOVEL: DIAMOND_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -196,6 +276,9 @@ Repairables:
NETHERITE_SWORD: NETHERITE_SWORD:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .6 XpMultiplier: .6
NETHERITE_SPEAR:
MinimumLevel: 0
XpMultiplier: .6
NETHERITE_SHOVEL: NETHERITE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .4 XpMultiplier: .4

View File

@@ -50,6 +50,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
MaximumQuantity: 2 MaximumQuantity: 2
WOODEN_SPEAR:
MinimumLevel: 0
XpMultiplier: .16
MaximumQuantity: 1
WOODEN_SHOVEL: WOODEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -74,6 +78,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .25 XpMultiplier: .25
MaximumQuantity: 2 MaximumQuantity: 2
STONE_SPEAR:
MinimumLevel: 0
XpMultiplier: .16
MaximumQuantity: 1
STONE_SHOVEL: STONE_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .16 XpMultiplier: .16
@@ -91,6 +99,51 @@ Salvageables:
XpMultiplier: .25 XpMultiplier: .25
MaximumQuantity: 2 MaximumQuantity: 2
# #
# Copper salvageables
###
# Tools
COPPER_SWORD:
MinimumLevel: 0
XpMultiplier: .4
MaximumQuantity: 2
COPPER_SPEAR:
MinimumLevel: 0
XpMultiplier: .25
MaximumQuantity: 1
COPPER_SHOVEL:
MinimumLevel: 0
XpMultiplier: .25
MaximumQuantity: 1
COPPER_PICKAXE:
MinimumLevel: 0
XpMultiplier: .9
MaximumQuantity: 3
COPPER_AXE:
MinimumLevel: 0
XpMultiplier: .9
MaximumQuantity: 3
COPPER_HOE:
MinimumLevel: 0
XpMultiplier: .4
MaximumQuantity: 2
# Armor
COPPER_HELMET:
MinimumLevel: 0
XpMultiplier: 1.9
MaximumQuantity: 5
COPPER_CHESTPLATE:
MinimumLevel: 0
XpMultiplier: 1.9
MaximumQuantity: 8
COPPER_LEGGINGS:
MinimumLevel: 0
XpMultiplier: 1.9
MaximumQuantity: 7
COPPER_BOOTS:
MinimumLevel: 0
XpMultiplier: 1.9
MaximumQuantity: 4
#
# Iron salvageables # Iron salvageables
### ###
# Tools # Tools
@@ -98,6 +151,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 2 MaximumQuantity: 2
IRON_SPEAR:
MinimumLevel: 0
XpMultiplier: .3
MaximumQuantity: 1
IRON_SHOVEL: IRON_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: .3 XpMultiplier: .3
@@ -145,6 +202,10 @@ Salvageables:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 4 XpMultiplier: 4
MaximumQuantity: 2 MaximumQuantity: 2
GOLDEN_SPEAR:
MinimumLevel: 0
XpMultiplier: 4
MaximumQuantity: 1
GOLDEN_SHOVEL: GOLDEN_SHOVEL:
MinimumLevel: 0 MinimumLevel: 0
XpMultiplier: 2.6 XpMultiplier: 2.6
@@ -186,6 +247,10 @@ Salvageables:
MinimumLevel: 50 MinimumLevel: 50
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 2 MaximumQuantity: 2
DIAMOND_SPEAR:
MinimumLevel: 50
XpMultiplier: .5
MaximumQuantity: 1
DIAMOND_SHOVEL: DIAMOND_SHOVEL:
MinimumLevel: 50 MinimumLevel: 50
XpMultiplier: .3 XpMultiplier: .3
@@ -219,11 +284,18 @@ Salvageables:
MinimumLevel: 50 MinimumLevel: 50
XpMultiplier: 6 XpMultiplier: 6
MaximumQuantity: 4 MaximumQuantity: 4
#
# Netherite salvageables
###
# Tools
NETHERITE_SWORD: NETHERITE_SWORD:
MinimumLevel: 100 MinimumLevel: 100
XpMultiplier: .5 XpMultiplier: .5
MaximumQuantity: 4 MaximumQuantity: 4
NETHERITE_SPEAR:
MinimumLevel: 100
XpMultiplier: .3
MaximumQuantity: 4
NETHERITE_SHOVEL: NETHERITE_SHOVEL:
MinimumLevel: 100 MinimumLevel: 100
XpMultiplier: .3 XpMultiplier: .3

View File

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

View File

@@ -4,71 +4,90 @@ Sounds:
# 1.0 = Max volume # 1.0 = Max volume
# 0.0 = No Volume # 0.0 = No Volume
MasterVolume: 1.0 MasterVolume: 1.0
# If you want to use custom sounds, provide an ID for CustomSoundId
# Sound IDs are strings, such as minecraft:entity.player.levelup
ITEM_CONSUMED: ITEM_CONSUMED:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 1.0 Pitch: 1.0
CustomSoundId: ''
GLASS: GLASS:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 1.0 Pitch: 1.0
CustomSoundId: ''
ANVIL: ANVIL:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.3 Pitch: 0.3
CustomSoundId: ''
#Fizz, and Pop make use of a adding and multiplying random numbers together to make a unique pitch everytime they are heard #Fizz, and Pop make use of a adding and multiplying random numbers together to make a unique pitch everytime they are heard
FIZZ: FIZZ:
Enable: true Enable: true
Volume: 0.5 Volume: 0.5
CustomSoundId: ''
LEVEL_UP: LEVEL_UP:
Enable: true Enable: true
Volume: 0.3 Volume: 0.3
Pitch: 0.5 Pitch: 0.5
CustomSoundId: ''
ITEM_BREAK: ITEM_BREAK:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 1.0 Pitch: 1.0
CustomSoundId: ''
#Fizz, and Pop make use of a adding and multiplying random numbers together to make a unique pitch everytime they are heard #Fizz, and Pop make use of a adding and multiplying random numbers together to make a unique pitch everytime they are heard
POP: POP:
Enable: true Enable: true
Volume: 0.2 Volume: 0.2
CustomSoundId: ''
CHIMAERA_WING: CHIMAERA_WING:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.6 Pitch: 0.6
CustomSoundId: ''
ROLL_ACTIVATED: ROLL_ACTIVATED:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.7 Pitch: 0.7
CustomSoundId: ''
SKILL_UNLOCKED: SKILL_UNLOCKED:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 1.4 Pitch: 1.4
CustomSoundId: ''
DEFLECT_ARROWS: DEFLECT_ARROWS:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 2.0 Pitch: 2.0
CustomSoundId: ''
TOOL_READY: TOOL_READY:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.4 Pitch: 0.4
CustomSoundId: ''
ABILITY_ACTIVATED_GENERIC: ABILITY_ACTIVATED_GENERIC:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.1 Pitch: 0.1
CustomSoundId: ''
ABILITY_ACTIVATED_BERSERK: ABILITY_ACTIVATED_BERSERK:
Enable: true Enable: true
Volume: 0.5 Volume: 0.5
Pitch: 1.7 Pitch: 1.7
CustomSoundId: ''
TIRED: TIRED:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 1.7 Pitch: 1.7
CustomSoundId: ''
BLEED: BLEED:
Enable: true Enable: true
Volume: 2.0 Volume: 2.0
Pitch: 2.0 Pitch: 2.0
CustomSoundId: ''
CRIPPLE: CRIPPLE:
Enable: true Enable: true
Volume: 1.0 Volume: 1.0
Pitch: 0.5 Pitch: 0.5
CustomSoundId: ''

View File

@@ -296,3 +296,11 @@ Hylian_Luck:
Standard_Mode: 0 Standard_Mode: 0
Retro_Mode: 0 Retro_Mode: 0
Drops_From: [Pots] Drops_From: [Pots]
COPPER_NUGGET:
Amount: 1
XP: 5
Drop_Chance: 100.0
Level_Requirement:
Standard_Mode: 0
Retro_Mode: 0
Drops_From: [Pots]

View File

@@ -0,0 +1,258 @@
package com.gmail.nossr50.events.items;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
class McMMOModifyBlockDropItemEventTest {
private BlockDropItemEvent blockDropItemEvent;
private Item itemEntity;
private ItemStack itemStack;
private Player player;
private Block block;
private BlockState blockState;
@BeforeEach
void setUp() {
// Mocks for delegate passthroughs
player = mock(Player.class, RETURNS_DEEP_STUBS);
block = mock(Block.class, RETURNS_DEEP_STUBS);
blockState = mock(BlockState.class, RETURNS_DEEP_STUBS);
// Primary Bukkit event mock
blockDropItemEvent = mock(BlockDropItemEvent.class, RETURNS_DEEP_STUBS);
when(blockDropItemEvent.getPlayer()).thenReturn(player);
when(blockDropItemEvent.getBlock()).thenReturn(block);
when(blockDropItemEvent.getBlockState()).thenReturn(blockState);
// Item + ItemStack mock
itemStack = mock(ItemStack.class);
when(itemStack.getAmount()).thenReturn(3); // original count
itemEntity = mock(Item.class);
when(itemEntity.getItemStack()).thenReturn(itemStack);
}
private McMMOModifyBlockDropItemEvent newEvent(int bonus) {
return new McMMOModifyBlockDropItemEvent(blockDropItemEvent, itemEntity, bonus);
}
@Nested
@DisplayName("Constructor & validation")
class ConstructorValidation {
@Test
void ctorNullEventThrows() {
assertThrows(NullPointerException.class,
() -> new McMMOModifyBlockDropItemEvent(null, itemEntity, 1));
}
@Test
void ctorNullItemThrows() {
assertThrows(NullPointerException.class,
() -> new McMMOModifyBlockDropItemEvent(blockDropItemEvent, null, 1));
}
@Test
void ctorZeroBonusThrows() {
assertThrows(IllegalArgumentException.class,
() -> new McMMOModifyBlockDropItemEvent(blockDropItemEvent, itemEntity, 0));
}
@Test
void ctorNegativeBonusThrows() {
assertThrows(IllegalArgumentException.class,
() -> new McMMOModifyBlockDropItemEvent(blockDropItemEvent, itemEntity, -5));
}
@Test
void ctorSetsOriginalsAndModifiedCorrectly() {
// original amount = 3, bonus = 2
McMMOModifyBlockDropItemEvent ev = newEvent(2);
assertEquals(3, ev.getOriginalItemStackQuantity());
assertEquals(2, ev.getOriginalBonusAmountToAdd());
assertEquals(5, ev.getModifiedItemStackQuantity());
assertFalse(ev.isCancelled());
assertFalse(ev.isEffectivelyNoBonus());
}
}
@Nested
@DisplayName("Cancellable contract")
class Cancellation {
@Test
void cancelAndUncancel() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertFalse(ev.isCancelled());
ev.setCancelled(true);
assertTrue(ev.isCancelled());
ev.setCancelled(false);
assertFalse(ev.isCancelled());
}
}
@Nested
@DisplayName("Delta & absolute quantity semantics")
class DeltaAndAbsolute {
@Test
void getBonusAmountToAddReflectsDifferenceFromOriginal() {
// original 3, bonus 4 => modified 7
McMMOModifyBlockDropItemEvent ev = newEvent(4);
assertEquals(4, ev.getBonusAmountToAdd());
assertEquals(7, ev.getModifiedItemStackQuantity());
}
@Test
void setBonusAmountToAddUpdatesModifiedQuantity() {
McMMOModifyBlockDropItemEvent ev = newEvent(2); // original 3 -> modified 5
ev.setBonusAmountToAdd(10); // new modified should be 13
assertEquals(13, ev.getModifiedItemStackQuantity());
assertEquals(10, ev.getBonusAmountToAdd());
assertFalse(ev.isEffectivelyNoBonus());
}
@Test
void setBonusAmountToAddNegativeThrows() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertThrows(IllegalArgumentException.class, () -> ev.setBonusAmountToAdd(-1));
}
@Test
void setModifiedItemStackQuantityEqualToOriginalIsNoBonus() {
McMMOModifyBlockDropItemEvent ev = newEvent(2); // 3 -> 5
ev.setModifiedItemStackQuantity(3); // back to original => no bonus
assertEquals(3, ev.getModifiedItemStackQuantity());
assertEquals(0, ev.getBonusAmountToAdd());
assertTrue(ev.isEffectivelyNoBonus());
}
@Test
void setModifiedItemStackQuantityLessThanOriginalThrows() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertThrows(IllegalArgumentException.class, () -> ev.setModifiedItemStackQuantity(2)); // original is 3
}
@Test
void setModifiedItemStackQuantityGreaterThanOriginalUpdatesBonus() {
McMMOModifyBlockDropItemEvent ev = newEvent(1); // original 3 -> modified 4
ev.setModifiedItemStackQuantity(12);
assertEquals(12, ev.getModifiedItemStackQuantity());
assertEquals(9, ev.getBonusAmountToAdd()); // 12 - 3
assertFalse(ev.isEffectivelyNoBonus());
}
}
@Nested
@DisplayName("Delegate passthroughs")
class Delegates {
@Test
void getPlayerPassthrough() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertSame(player, ev.getPlayer());
verify(blockDropItemEvent, atLeastOnce()).getPlayer();
}
@Test
void getBlockPassthrough() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertSame(block, ev.getBlock());
verify(blockDropItemEvent, atLeastOnce()).getBlock();
}
@Test
void getBlockStatePassthrough() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertSame(blockState, ev.getBlockState());
verify(blockDropItemEvent, atLeastOnce()).getBlockState();
}
@Test
void getItemReturnsOriginalItemEntity() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
assertSame(itemEntity, ev.getItem());
}
}
@Nested
@DisplayName("HandlerList plumbing")
class HandlerListTests {
@Test
void handlerList_isNonNull_andShared() {
McMMOModifyBlockDropItemEvent ev = newEvent(1);
HandlerList fromInstance = ev.getHandlers();
HandlerList fromStatic = McMMOModifyBlockDropItemEvent.getHandlerList();
assertNotNull(fromInstance);
assertNotNull(fromStatic);
// Bukkit convention: same static instance
assertSame(fromStatic, fromInstance);
}
}
@Nested
@DisplayName("Object contracts")
class ObjectContracts {
@Test
void toStringContainsKeyFields() {
McMMOModifyBlockDropItemEvent ev = newEvent(2);
String s = ev.toString();
assertNotNull(s);
assertTrue(s.contains("originalBonusAmountToAdd=2"));
assertTrue(s.contains("modifiedItemStackQuantity=5"));
}
@Test
void equalsAndHashCodeReflectState() {
// Same inputs => equal (mocks are same instances)
McMMOModifyBlockDropItemEvent a = newEvent(2);
McMMOModifyBlockDropItemEvent b = newEvent(2);
assertEquals(a, b);
assertEquals(a.hashCode(), b.hashCode());
// Change cancellation and modified quantity => not equal
McMMOModifyBlockDropItemEvent c = newEvent(2);
c.setCancelled(true);
assertNotEquals(a, c);
McMMOModifyBlockDropItemEvent d = newEvent(2);
d.setModifiedItemStackQuantity(99);
assertNotEquals(a, d);
// Different underlying mocks => not equal
BlockDropItemEvent otherEvent = mock(BlockDropItemEvent.class, RETURNS_DEEP_STUBS);
when(otherEvent.getPlayer()).thenReturn(player);
when(otherEvent.getBlock()).thenReturn(block);
when(otherEvent.getBlockState()).thenReturn(blockState);
ItemStack otherStack = mock(ItemStack.class);
when(otherStack.getAmount()).thenReturn(3);
Item otherItem = mock(Item.class);
when(otherItem.getItemStack()).thenReturn(otherStack);
McMMOModifyBlockDropItemEvent e = new McMMOModifyBlockDropItemEvent(otherEvent, otherItem, 2);
assertNotEquals(a, e);
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More