1
0
mirror of https://github.com/mcMMO-Dev/mcMMO.git synced 2026-02-21 19:22:59 +01:00

Compare commits

...

575 Commits

Author SHA1 Message Date
Shane Freeder
483553b89d add translation badge
is pretti?
2020-02-27 20:41:15 +00:00
Shane Freeder
6047a5579b Translated using Weblate (English (United States))
Currently translated at 100.0% (1021 of 1021 strings)

Translation: mcmmo/mcmmo-master
Translate-URL: https://translate.mcmmo.org/projects/mcmmo/mcmmo-master/en_US/
2020-02-27 20:26:56 +00:00
Shane Freeder
a94db1b88a Listen to me 2020-02-27 19:56:07 +00:00
Shane Freeder
f5a397d2d2 Translated using Weblate (English (United States))
Currently translated at 100.0% (1021 of 1021 strings)

Translation: mcmmo/mcmmo-master
Translate-URL: https://translate.mcmmo.org/projects/mcmmo/mcmmo-master/en_US/
2020-02-27 19:56:07 +00:00
Shane Freeder
05af15c06b Translated using Weblate (English (United States))
Currently translated at 100.0% (1021 of 1021 strings)

Translation: mcmmo/mcmmo-master
Translate-URL: https://translate.mcmmo.org/projects/mcmmo/mcmmo-master/en_US/
2020-02-27 19:56:07 +00:00
nossr50
0a59b79ef9 Dev mode 2020-02-27 10:50:56 -08:00
nossr50
441125dbd1 2.1.117 2020-02-27 07:36:41 -08:00
nossr50
eff1ce102f Merge branch 'master' of github.com:mcMMO-Dev/mcmmo 2020-02-24 16:01:18 -08:00
nossr50
705b57a30b dev mode 2020-02-24 16:01:10 -08:00
Shane Freeder
d4ba9d7605 Reduce mojang profile API call limit (Fixes #4121) 2020-02-22 11:12:52 +00:00
nossr50
4cd91350db 2.1.116 2020-02-20 17:35:33 -08:00
nossr50
6168309ec9 2.1.115 2020-02-19 17:41:47 -08:00
nossr50
95c403a467 More tweaks to GT 2020-02-19 17:31:00 -08:00
nossr50
a598796c99 More tweaks to GT 2020-02-19 17:20:05 -08:00
nossr50
a333f36fd8 Fix sneak check on GT 2020-02-19 16:19:19 -08:00
nossr50
7c6d5c476d Green Thumb requires a hoe, sneak to break with a hoe 2020-02-19 16:14:21 -08:00
nossr50
e2073ff9f7 Immature crop replanting, green thumb tweaks, replant accidental break
protection
2020-02-19 15:58:53 -08:00
nossr50
8f26544188 Immature plants will be replanted if weilding a hoe 2020-02-19 13:51:10 -08:00
nossr50
4e21f1a200 tweak and fix salvage result chance 2020-02-19 13:27:21 -08:00
nossr50
ab6dbe306d Fix potential NPE for salvage 2020-02-19 11:38:48 -08:00
Shane Freeder
38d64f207d Fix default permission for Critical Strikes 2020-02-12 02:06:49 +00:00
Shane Freeder
8e8024e3e1 update changelog 2020-02-09 22:50:28 +00:00
Shane Freeder
4f161812aa Use minimum level of salvagable properly 2020-02-09 22:47:20 +00:00
Shane Freeder
11ca0d9ff1 Fix 1.13.x archery compat 2020-02-04 23:36:54 +00:00
Shane Freeder
4eef4a3e41 Fix CCE from spectral arrows (Fixes #4114) 2020-02-04 23:29:51 +00:00
Shane Freeder
816b64cb70 Track spectral arrows for combat 2020-01-28 16:37:02 +00:00
Shane Freeder
dceee5554d Fix CombatUtils NPE due to arrows from unloaded players 2020-01-28 16:33:30 +00:00
nossr50
8094be46c8 Dev mode 2020-01-27 19:01:08 -08:00
nossr50
2525ce9abe 2.1.114 2020-01-27 18:53:39 -08:00
nossr50
ea70c937f2 Fix rank for new versions of MySQL 2020-01-27 18:45:19 -08:00
Shane Freeder
550a3df616 place SnowGolemExcavation exploit fix under the correct section 2020-01-28 00:12:50 +00:00
apachezy
657abb76a7 "EndermanEndermiteFarms" does not work. (#4111)
This error causes the "ExploitFix.EndermanEndermiteFarms" option in ExperienceConfig to not work.
2020-01-28 00:11:57 +00:00
Shane Freeder
0ffcff53b3 Further address locale issues (Targets #4083) 2020-01-26 17:48:14 +00:00
nossr50
33f4ac14b5 Add toggle for snow golem exploit to experience.yml - SnowGolemExcavation 2020-01-24 18:28:41 -08:00
nossr50
15d3119627 Berserk now breaks a soft block if it was used to activate it 2020-01-24 01:25:55 -08:00
nossr50
4fd94bfe29 2.1.113 2020-01-24 01:11:23 -08:00
nossr50
ac731258c7 Berserk now breaks glass and makes noise when doing so 2020-01-24 01:09:19 -08:00
nossr50
7b8c90d362 BlockCracker fix for infested stone bricks 2020-01-24 00:56:16 -08:00
nossr50
055391e908 Hacky fix for spigot bug 2020-01-24 00:43:18 -08:00
nossr50
cd6ce5a19d Correct changelog 2020-01-23 20:34:54 -08:00
nossr50
7441d2d8d6 Merge branch 'master' of github.com:mcMMO-Dev/mcmmo 2020-01-23 20:34:13 -08:00
nossr50
7b941baa1c Update changelog 2020-01-23 20:34:00 -08:00
Lane
0c1fa07079 Fixed typo in config for potato (#4096) 2020-01-17 07:23:28 +00:00
andrewkm
539cd7290e Retro mode documentation. (#4104)
This commit will save lives, believe me.
2020-01-17 07:21:31 +00:00
Shane Freeder
406429f4e3 Use ThreadedLocalRandom for RNG utils 2020-01-16 18:21:35 +00:00
t00thpick1
421a394f68 Another check for PTP exploit 2020-01-15 13:49:11 -08:00
t00thpick1
d4adb490e2 Fixing PTP exploit 2020-01-15 13:32:10 -08:00
nossr50
de5a8babc5 dev mode 2020-01-15 13:21:33 -08:00
nossr50
d892bfe83a 2.1.112 2020-01-14 20:10:33 -08:00
nossr50
ceaff0c862 SkillShot tweaks 2020-01-14 20:09:41 -08:00
nossr50
a118d8465e Sweet Berry Bush nerf 2020-01-14 19:57:38 -08:00
nossr50
7c156319be Skill Shot is now multiplicative instead of additive 2020-01-14 19:53:37 -08:00
nossr50
24b3bf1100 NPE fix for combat on unloaded profiles 2020-01-14 19:44:17 -08:00
nossr50
41bdca948a Update POM for 1.15.1 2020-01-13 19:28:28 -08:00
Shane Freeder
3cbbf1bee0 Move valid check higher up, no need to set additional metadata 2019-12-31 12:17:03 +00:00
Shane Freeder
8fd1af4cbf Don't cache mob infomation in the updater task 2019-12-31 12:16:12 +00:00
Shane Freeder
601297799f Enforce locale usage for enums to ensure correct casing (Fixes #4086) 2019-12-16 01:05:47 +00:00
nossr50
da98be88ad Update changelog 2019-12-10 21:51:41 -08:00
nossr50
1104f48ad5 2.1.111 2019-12-10 21:46:09 -08:00
nossr50
af50699de1 1.15 changes 2019-12-10 21:35:44 -08:00
Shane Freeder
1c71f1daf5 Update changelog 2019-11-13 19:56:07 +00:00
Shane Freeder
b7dd491c01 Prevent nesting of bleed damage
This commit prevents the nesting of damage event processing in general in
regards to bleed, health related stuff will need a further glance over down
the line, however; This will fix a major problematic area
2019-11-13 19:53:02 +00:00
nossr50
3ce0d7b972 dev mode 2019-11-10 19:51:47 -08:00
Robert Alan Chapton
9dcbccb010 Merge pull request #4078 from Ineusia/master
Missing Section Error Messages (Repair & Salvage Config)
2019-11-10 18:18:12 -08:00
Ineusia
c5cbab39b6 Update RepairConfig.java
Removed accidental whitespace
2019-11-10 11:56:32 -06:00
Ineusia
ca1906fbc5 Added error message for missing Salvageables section (rather than throw NPE) 2019-11-08 01:15:32 -06:00
Ineusia
7eab20ef56 Added error message for missing Repairables section (rather than throw NPE) 2019-11-08 01:11:29 -06:00
nossr50
188b0f9813 2.1.110 2019-10-18 15:48:53 -07:00
nossr50
e6c9cc6fdd Actually fixed BlockCracker + One more type of block can be cracked 2019-10-18 15:48:12 -07:00
nossr50
76ca7cc88f Additional dupe failsafes 2019-10-18 15:37:36 -07:00
nossr50
335d708848 Bump version 2019-10-18 15:24:46 -07:00
nossr50
b4179cb9a6 Fixed a dupe bug 2019-10-18 15:23:15 -07:00
Robert Alan Chapton
8bbf95e9da Merge pull request #4065 from Vyciokazz/master
locale_lt_LT.properties
2019-10-18 01:10:09 -07:00
nossr50
dc805825de 2.1.109 2019-10-17 20:16:01 -07:00
Robert Alan Chapton
871ca744d9 Merge pull request #4070 from Fabrimat/patch-4
Update locale_it.properties
2019-10-17 10:01:26 -07:00
Fabrizio La Rosa
1b091bdbd5 Update locale_it.properties
Fixed definetly /mctop and fixed special characters.
2019-10-17 13:37:00 +02:00
Robert Alan Chapton
110d9a633b Update FUNDING.yml 2019-10-02 13:26:34 -07:00
Robert Alan Chapton
584859318b Create FUNDING.yml 2019-10-02 13:06:56 -07:00
Robert A. C
1eb2c7b2d7 Merge pull request #4068 from ethernetcat/master
Update locale_ja_JP.properties
2019-10-01 14:37:21 -04:00
SNAKE
3310a12a95 Update locale_ja_JP.properties 2019-10-02 01:43:51 +09:00
Shane Freeder
6125b3fbd2 Don't spam incompatible WG error 2019-09-27 18:57:25 +01:00
Robert A. C
0d6b5e2530 Merge pull request #4064 from Fabrimat/patch-3
Update locale_it.properties
2019-09-23 10:46:29 -07:00
Fabrizio La Rosa
d679101cfb Update locale_it.properties
Spaces doesn't work in commands like "/mctop Tiro con l'arco"
2019-09-23 18:40:56 +02:00
Shane Freeder
122c8b0faa Added missing 1.14 blocks to ability/tool activation blacklists (Fixes #4050) 2019-09-22 04:30:24 +01:00
nossr50
08d1ad4f6c Dev mode 2019-09-19 18:45:09 -07:00
nossr50
8e19e1de15 2.1.108 2019-09-19 18:33:33 -07:00
nossr50
101b0671fe compatibility with FAWE ( :| ) 2019-09-19 18:31:18 -07:00
nossr50
e14c53d3ca Load after worlds 2019-09-19 18:02:23 -07:00
nossr50
28c0215a93 Catch more exceptions when doing WG reflection checks 2019-09-19 17:21:25 -07:00
nossr50
51a373db4f Fixing an Acrobatics exploit 2019-09-17 18:59:44 -07:00
Vyciokazz
1b889b8177 locale_lt_LT.properties
I translated in Lithuanian language manny required info for player and player skils, in time i update this translation.
2019-09-18 00:14:14 +03:00
nossr50
4a4124d09f 2.1.107 2019-09-14 16:08:20 -07:00
nossr50
ceaf3d46cb Update changelog 2019-09-14 16:06:14 -07:00
Robert A. C
260d0f9b4a Merge pull request #4051 from Shrek5InTheatres2019/master
McMMOPlayerProfileLoadEvent for the api
2019-09-14 16:05:26 -07:00
Shane Freeder
d3a7ff8e8c Correctly encode Russian translation file (#4058) 2019-09-14 23:58:46 +01:00
nossr50
9154b3f083 Fixes #4056 2019-09-14 15:44:58 -07:00
Shrek5InTheatres2019
c3548be380 deleting one character variables for good 2019-09-09 17:56:06 -07:00
Shrek5InTheatres2019
67bfb40dd5 fixing the things 2019-09-09 16:50:05 -07:00
Robert A. C
777a9d4185 Merge pull request #4052 from andris155/patch-1
Update locale_hu_HU.properties
2019-09-09 15:06:02 -06:00
András Marczinkó
fcd45f3bc1 Update locale_hu_HU.properties 2019-09-07 13:24:05 +02:00
Shrek5InTheatres2019
478d542981 removing this task that i once thought i needed and now realize that it is completely unnecessary 2019-09-06 16:46:38 -07:00
Shrek5InTheatres2019
c6c1c39a98 player profile load event from issue request #4045 2019-09-06 16:44:58 -07:00
nossr50
0d6165c0f4 dev mode 2019-09-06 15:37:54 -06:00
nossr50
f45983949a 2.1.106 2019-09-06 15:21:13 -06:00
nossr50
cca0524441 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-09-05 18:59:08 -06:00
nossr50
e84e9a7dc8 more blacklisted blocks 2019-09-05 18:58:50 -06:00
Robert A. C
a3600e11a9 Merge pull request #4048 from ethernetcat/master
Update locale_ja_JP.properties
2019-09-03 14:10:50 -06:00
Robert A. C
483579503a Merge pull request #4047 from 89009332/patch-10
Update locale_zh_CN.properties
2019-09-03 14:10:37 -06:00
SNAKE
d89ff8b238 Update locale_ja_JP.properties 2019-09-04 01:05:33 +09:00
89009332
582ff48b6f Update locale_zh_CN.properties 2019-09-03 19:50:02 +08:00
nossr50
d6e14ca431 Dev mode 2019-09-02 17:10:40 -06:00
nossr50
0961351ba2 2.1.105 2019-09-02 16:56:16 -06:00
Robert A. C
0b93a74652 Merge pull request #4041 from Shrek5InTheatres2019/master
Implementing request from issue #3918
2019-09-02 16:53:50 -06:00
Robert A. C
2bc2e5bb32 Merge pull request #4042 from QuantumToasted/master
Support jump strength stats for horses in Beast Lore
2019-09-02 15:18:10 -06:00
Daniel Jarski
98f8e049f3 Update to Beast Lore
Removed movement speed information for llamas, and added jump strength info for horses. Also added another locale string to display this information.
2019-08-30 23:14:39 -05:00
Shrek5InTheatres2019
e27d299132 removing unnecessary code 2019-08-29 23:16:26 -07:00
Shrek5InTheatres2019
7cf40d9dbf Implementing request from issue #3918 2019-08-29 18:51:48 -07:00
Daniel Jarski
d6eefac065 Merge pull request #1 from mcMMO-Dev/master
update
2019-08-29 19:53:42 -05:00
nossr50
3036c4ef80 Update locale 2019-08-28 14:29:14 -06:00
Robert A. C
a81468ccfc Merge pull request #4040 from Leomixer17/patch-1
Update locale_it.properties
2019-08-28 14:00:05 -06:00
Leomixer17
2a2a4479ca Update locale_it.properties 2019-08-27 17:17:34 +02:00
Leomixer17
289276d987 Update locale_it.properties 2019-08-27 17:06:20 +02:00
Leomixer17
f771b777b9 Update locale_it.properties 2019-08-27 04:38:35 +02:00
Robert A. C
e4d081f14b Merge pull request #4039 from Mixpa/master
simply if code
2019-08-26 14:34:36 -06:00
nossr50
bba35f8a4e Set player scoreboards to main server scoreboard upon entering a blacklisted world 2019-08-26 14:15:42 -06:00
Shane Freeder
8a4410cde8 Add a configuration to print jdbc exceptions
By default, mcmmo tries to pretty print errors, which is fine for many cases,
however; deeper nested errors can lack information, e.g. networking related issues,
while the pretty print is less intimitating and provides useful information to users,
surpressing the trace can prevent debugging these deeper issues, this config option serves
as a compromise between scaring users and having a means to find these deeper issues.
2019-08-26 05:29:29 +01:00
Shane Freeder
8951c1fd21 Back in dev 2019-08-26 05:28:21 +01:00
nossr50
1f7f71e8b5 2.1.104 2019-08-25 12:06:07 -06:00
Robert A. C
88b056c38f Merge pull request #4035 from andris155/patch-2
Update locale_hu_HU.properties
2019-08-25 12:03:34 -06:00
Robert A. C
d408782acf Merge pull request #4037 from ethernetcat/master
Update locale_ja_JP.properties
2019-08-25 12:03:24 -06:00
Mixpa
dfeab6b558 simply if code 2019-08-25 21:51:19 +08:00
SNAKE
f4fe25009d Convert to UTF16 2019-08-25 05:37:58 +09:00
SNAKE
905010aacd Update locale_ja_JP.properties 2019-08-25 04:01:17 +09:00
Shane Freeder
5ea2c493e8 Don't process mcmmo damage for invuln (#4028) 2019-08-24 17:40:46 +01:00
András Marczinkó
734c6f9c62 Update locale_hu_HU.properties 2019-08-24 10:23:10 +02:00
nossr50
44a3238c79 Dev mode 2019-08-23 21:14:23 -06:00
nossr50
139975958f 2.1.103 2019-08-23 21:00:50 -06:00
nossr50
52f9273fa8 Fishing drops are no longer random amounts 2019-08-23 20:51:32 -06:00
nossr50
77ffee2515 Fixed a bug where Tree Feller only rewarded 1 XP per block 2019-08-23 13:08:04 -06:00
nossr50
40118d570c Update notes 2019-08-23 12:19:52 -06:00
Robert A. C
8109ecb0e0 Merge pull request #4032 from Leomixer17/patch-1
Update locale_it.properties
2019-08-22 19:17:28 -06:00
Leomixer17
1147dff4c3 Update locale_it.properties 2019-08-23 03:02:15 +02:00
Leomixer17
c274b21af1 Update locale_it.properties 2019-08-23 02:51:20 +02:00
nossr50
2b72e8e69f Making Limit Break code clearer to understand 2019-08-22 14:54:47 -06:00
Robert A. C
ca511ca0f5 Merge pull request #4029 from QuantumToasted/master
Fix spelling error in Guilds.Salvage.Section.0
2019-08-22 14:20:56 -06:00
Daniel Jarski
cafacc05ab Fix spelling error in Guilds.Salvage.Section.0
"...use an gold block" -> "...use a gold block"
2019-08-22 13:05:54 -05:00
Shane Freeder
2974ed0993 correct item salvage level check 2019-08-22 00:38:29 +01:00
Robert A. C
861552bcd8 Merge pull request #4027 from QuantumToasted/master
Add additional info about horse speed in Beast Lore
2019-08-21 14:06:15 -07:00
nossr50
7095ddb611 Dev mode 2019-08-21 14:17:27 -06:00
Daniel Jarski
f70f2321f2 Add additional info about horse speed in Beast Lore
An additional string containing info about the horse's movement speed (in blocks per second) is now concat'd to the end of the Beast Lore info. Also, added a Combat.BeastLoreHorseSpeed locale string to service this info.
2019-08-21 13:10:43 -05:00
nossr50
4bb8e20b59 2.1.102 2019-08-21 04:57:02 -07:00
Shane Freeder
e8165321e1 Fix bleed tasks invoking ruptures
Also, made the mcmmo custom damage checks handle nested calls
2019-08-21 01:05:01 +01:00
nossr50
4f6706b664 Test 2019-08-19 15:01:45 -07:00
Robert Chapton
665a31fc85 Players moving to a blacklisted world will have scoreboards removed 2019-08-19 14:49:21 -07:00
nossr50
1221069854 Dev mode 2019-08-11 23:58:13 -04:00
Robert A. C
054f8ffe0a Merge pull request #4021 from ethernetcat/master
Update locale_ja_JP.properties
2019-08-11 23:57:22 -04:00
Shane Freeder
dbecd289b2 Check configuration for fishing spam prevention (#4010) 2019-08-12 03:54:45 +01:00
Shane Freeder
bb7989449e Do not allow additions of timer tasks while iterating
Follow up on:
e4d980b135
Should help debug #4019 (and let us know when this actually occurs)
2019-08-12 02:31:51 +01:00
SNAKE0053
296c2e99f7 Update locale_ja_JP.properties 2019-08-12 02:35:23 +09:00
nossr50
4246f59d44 2.1.101 2019-08-09 17:18:26 -04:00
nossr50
87ff69d5c4 Add fix to changelog 2019-08-07 15:30:48 -07:00
Shane Freeder
84cb40521b Don't unmark herbalism blocks early (Fixes #4015) 2019-08-06 00:52:23 +01:00
nossr50
dda894dd9a dev mode 2019-08-05 10:46:26 -04:00
nossr50
7853efc63d 2.1.100 2019-08-05 10:43:05 -04:00
nossr50
11409c07c0 Fixed a bug with herbalism double drops 2019-08-05 10:39:33 -04:00
Robert A. C
7c17126ffb Merge pull request #4012 from myfbone/master
Another portion of Russian translation
2019-08-04 19:19:59 -07:00
myfbone
05e19b2122 Small correction of xp desc 2019-08-03 08:25:57 +03:00
myfbone
3b8fee5134 Some color corrections and added missing translation 2019-08-03 08:10:31 +03:00
Shane Freeder
4735b2ff8f Use the full GPLv3 license file 2019-08-02 16:02:07 +01:00
Shane Freeder
ac29c51d6e Fixed an NPE that may occur with random chances on a player without loaded data
Also correct changelog version
2019-08-02 03:34:26 +01:00
myfbone
ad9fa2dd9f Add some missing translations 2019-08-01 14:51:14 +03:00
Robert A. C
1e2f11f4f9 Merge pull request #4009 from myfbone/master
some russian translation corrections
2019-07-31 06:26:34 -07:00
myfbone
3a1f297618 new available version message now points to spigot instead of bukkit 2019-07-30 02:37:58 +03:00
myfbone
8af3f41f12 Стрельба (shooting) was renamed to Луки (bows) to reflect that this skill is about bows, but not about tridens and crossbows 2019-07-30 02:36:01 +03:00
Shane Freeder
e4d980b135 Fixed some concurrency concerns around BleedTasks 2019-07-29 17:41:57 +01:00
Shane Freeder
62ce98c8a5 validate that mcnotify isn't being ran by the console 2019-07-29 17:23:21 +01:00
myfbone
31a1fd4ece Fixed records translation in fishing extra and drop rate 2019-07-28 20:04:56 +03:00
nossr50
51e22f7904 Dev mode 2019-07-27 18:47:38 -07:00
Robert A. C
106fd84b7f Merge pull request #4006 from myfbone/master
Small corrections. Also shorted two word skill names to one word in order to be able running /skillname command
2019-07-26 20:13:59 -07:00
myfbone
5f99a6cf19 Merge branch 'master' of https://github.com/myfbone/mcMMO 2019-07-26 21:46:45 +03:00
myfbone
aba465e1a8 Small corrections. Alse shorted two word skill names to one word in order to be able running /skillname command 2019-07-26 21:46:24 +03:00
nossr50
73500aae90 2.1.99 2019-07-25 21:53:45 -07:00
nossr50
c3ec6a0b80 Debug message color tweaks 2019-07-25 21:50:17 -07:00
nossr50
509ca5ae7f 毎日... 2019-07-25 21:47:11 -07:00
nossr50
9b3091add4 Debug mode will now dump info about XP perks and how they are modifying
incoming XP gains
2019-07-25 21:43:19 -07:00
nossr50
b503cb5d80 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-07-25 21:26:31 -07:00
Robert A. C
a631388e5a Merge pull request #4003 from myfbone/master
Updated Russian translation up to the last version
2019-07-25 20:15:25 -07:00
myfbone
d64b869695 Updated Russian translation up to the last version 2019-07-26 06:09:24 +03:00
nossr50
8e1c1c9ef4 2.1.98 2019-07-24 20:11:54 -07:00
nossr50
952ee9556a Fixing Taming XP 2019-07-24 19:57:58 -07:00
nossr50
3155550931 Dev Mode again 2019-07-23 23:04:11 -07:00
nossr50
7242a171dd Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-07-22 20:12:35 -07:00
nossr50
0dac5f6b3f 2.1.97 2019-07-22 20:12:10 -07:00
Robert A. C
ff3bbad68c Merge pull request #3991 from andris155/patch-7
Update locale_hu_HU.properties
2019-07-22 20:09:53 -07:00
Robert A. C
5cc473fd96 Merge pull request #3996 from Yukiiro-Nite/close-files-after-world-unload
Close all the files after unload instead of before
2019-07-22 20:08:51 -07:00
Yukiiro-Nite
c03907b5a3 Close all the files after unload instead of before
- This ensures that all file handles are closed after a world is
unloaded, since the unloadChunk function calls saveChunk, which
opens files.
- Should resolve issue #3995
2019-07-21 01:01:42 -04:00
András Marczinkó
f9c257b73a Update locale_hu_HU.properties 2019-07-13 12:43:07 +02:00
Robert A. C
308e3a4b1f Merge pull request #3988 from EvilOlaf/patch-6
Update locale_de.properties
2019-07-11 08:33:47 -07:00
Werner
99f8f34529 Update locale_de.properties 2019-07-11 16:27:14 +02:00
nossr50
5f7f6fc55a Fixed a NPE with taming. 2019-07-10 05:03:33 -07:00
nossr50
36932e397d 2.1.96 2019-07-08 07:57:07 -07:00
nossr50
732e29f0a5 Add missing 's' to Nether_Bricks 2019-07-08 03:53:00 -07:00
nossr50
cd0ed4b385 Dev mode 2019-07-07 06:13:33 -07:00
nossr50
03fd558e1b Add toggle to allow piston cheating 2019-07-07 06:11:15 -07:00
nossr50
6bc57f184a 2.1.95 2019-07-07 02:48:17 -07:00
nossr50
6c58e8a243 Limit Break Nerfs 2019-07-07 02:33:39 -07:00
nossr50
c818bf82b0 Cap how much XP can be given for Roll based on damage 2019-07-07 02:07:55 -07:00
nossr50
67a687ee40 Fix Ender Pearls not preventing XP gains in offhand 2019-07-07 01:55:23 -07:00
nossr50
ec44c99076 Many Herbalism bug fixes 2019-07-07 01:42:57 -07:00
nossr50
39a1a07a7d Add missing Chorus_Flower xp entry for Herbalism to experience.yml 2019-07-05 06:20:44 -07:00
nossr50
0b2d0fa332 Make the last bug fix compatible with 1.13 2019-07-05 06:14:54 -07:00
nossr50
304a942f51 Fixed a bug preventing wandering traders from granting XP 2019-07-05 05:51:41 -07:00
nossr50
02c1ce749c 2.1.94 2019-07-02 17:29:57 -07:00
nossr50
1307169d8b Debug Stick is now replaced by /mmodebug 2019-07-02 17:29:33 -07:00
nossr50
8eeebf63e9 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-07-02 16:23:14 -07:00
nossr50
f7c0c9beb7 Add new mcMMO devs to readme.md and plugin.yml 2019-07-02 16:22:56 -07:00
Robert A. C
9ec4f64c70 Merge pull request #3978 from snake0053/master
Fix spelling
2019-07-02 15:09:15 -07:00
SNAKE0053
9667eaf045 Fix spelling 2019-07-03 06:51:06 +09:00
nossr50
51ade5113f Adjust changelog 2019-07-02 14:50:34 -07:00
nossr50
0af3c82612 Fixed a bug that could prevent a Tree from being removed by Tree Feller
if 2 or more players were using Tree Feller simultaneously
2019-07-02 14:46:55 -07:00
Robert A. C
4c13c0ec31 Merge pull request #3977 from andris155/patch-1
Update locale_hu_HU.properties
2019-07-02 14:46:33 -07:00
Robert A. C
8ca5a5cdec Merge pull request #3976 from snake0053/update_japanese_local
Update locale_ja_JP.properties
2019-07-02 14:46:22 -07:00
András Marczinkó
43819605fa Update locale_hu_HU.properties 2019-07-02 23:44:23 +02:00
SNAKE0053
6e00f7eaa2 Update locale_ja_JP.properties 2019-07-03 06:41:29 +09:00
nossr50
5d0ce407b7 2.1.93 2019-07-02 13:47:37 -07:00
nossr50
bf70a42f6a Fix breeding sending incorrect messages 2019-07-02 12:45:25 -07:00
nossr50
6e70258f9a 2.1.92 2019-07-02 01:44:01 -07:00
nossr50
1ae9e80d96 Prevent spam from breeding events 2019-07-02 01:31:49 -07:00
nossr50
444edb209c Remove summoned entities on server shutdown 2019-07-02 01:14:11 -07:00
nossr50
8a9c836065 More locale tweaks for COTW 2019-07-02 00:45:08 -07:00
nossr50
a19ddb46b6 Fixing some bugs, tweaking some strings for COTW 2019-07-02 00:32:38 -07:00
nossr50
53d6065185 Numerous COTW tweaks 2019-07-01 23:50:30 -07:00
nossr50
a66940b2b8 Unarmed no longer uses a serverwide cooldown for all players for bonus
damage
2019-06-30 12:19:45 -07:00
nossr50
9092e70544 Check the projectile type instead of main hand item 2019-06-25 22:44:14 -07:00
nossr50
517ca6568f Increase compatiblility with crazy enchants 2019-06-25 22:29:02 -07:00
nossr50
3368625dde 2.1.90 2019-06-25 18:21:14 -07:00
nossr50
2eb330f070 Mining XP values tweaked 2019-06-25 18:20:56 -07:00
nossr50
74a2485cff Multiple tweaks to how salvaged items travel towards a player 2019-06-25 18:02:16 -07:00
nossr50
03efd14ff4 2.1.89 2019-06-24 23:33:17 -07:00
nossr50
e71c95139d RetroMode is now the default mode. 2019-06-24 23:31:31 -07:00
nossr50
d9b84b0ab3 Check mining rank before processing double drops 2019-06-24 23:25:15 -07:00
nossr50
421d6cff3b Tweak archaeology numbers 2019-06-24 22:48:22 -07:00
nossr50
ccb86264d9 Update excavation command 2019-06-24 22:31:21 -07:00
nossr50
ee2a1b332e tweak Archaeology rewards 2019-06-24 22:30:20 -07:00
nossr50
2dda0bf27a Fix some WG logic + Archaeology stat display 2019-06-24 21:25:51 -07:00
nossr50
d347fa9512 Add information about Archaeology to /excavation and tweak some locale
strings related to excavation
2019-06-24 20:54:26 -07:00
nossr50
913323245c Archaeology now does something 2019-06-24 20:27:50 -07:00
nossr50
68ad507be3 Skills which used to unlock at level 5 now unlock at level 1 and some
tweaks to  ranks of other skills, and length scaling for super
abilities. Early game boost has also been modified.
2019-06-24 20:17:35 -07:00
nossr50
764b4c20f5 Tools with durability enchant will be damaged properly by super
abilities again (at a reduced rated)
2019-06-24 17:49:02 -07:00
nossr50
a135e08e12 Improved WG compatibility + Tree Feller will now damage unbreaking
enchant tools again
2019-06-24 17:32:05 -07:00
Robert A. C
214974e3a3 Merge pull request #3968 from snake0053/master
Update locale_ja_JP.properties
2019-06-23 12:01:53 -07:00
nossr50
3673d3fb7b Tree Feller bug fix 2019-06-23 12:00:49 -07:00
nossr50
f6ad530660 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-06-23 11:56:41 -07:00
SNAKE0053
046daa43fa Update locale_ja_JP.properties 2019-06-24 00:11:24 +09:00
Robert A. C
cc1c5239dc Merge pull request #3967 from EvilOlaf/patch-5
Update locale_de.properties
2019-06-23 01:26:09 -07:00
Werner
4fafb5731e Update locale_de.properties 2019-06-23 10:00:07 +02:00
nossr50
9ab4d59cca mcMMO will ignore damage triggers for events with a value of zero 2019-06-22 22:35:25 -07:00
nossr50
68864dae2d 2.1.87 2019-06-22 15:06:24 -07:00
nossr50
ae6d377abb Fixing a mistake when grabbing level cap 2019-06-22 15:03:51 -07:00
nossr50
b479d45f14 Level Cap bugfixes and tweaks 2019-06-22 14:48:16 -07:00
nossr50
e17afe31a5 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-06-22 13:05:58 -07:00
Robert A. C
5f115d5e4a Merge pull request #3966 from EvilOlaf/patch-1
Update locale_de.properties
2019-06-22 08:28:33 -07:00
Werner
1984131874 Update locale_de.properties 2019-06-22 13:33:03 +02:00
nossr50
0b4e2b48c9 Dev mode 2019-06-21 12:45:31 -07:00
nossr50
6aa53823f1 Small changelog edits 2019-06-21 09:10:53 -07:00
nossr50
7f567585e2 2.1.86 2019-06-21 08:12:00 -07:00
nossr50
c6d604bbbc Inspect, Salvage, and Locale fixes 2019-06-21 08:05:57 -07:00
nossr50
5698d8282c 2.1.85 2019-06-20 00:02:48 -07:00
nossr50
83636644b1 2.1.84 2019-06-18 15:28:56 -07:00
nossr50
fa6995b9fd You can no longer set fire to party members 2019-06-18 14:04:42 -07:00
nossr50
c83d38b5c2 Arrow Retrieval will no longer work with piercing enchant 2019-06-18 13:06:26 -07:00
Robert A. C
31e9abd8eb Merge pull request #3960 from andris155/patch-1
Update locale_hu_HU.properties
2019-06-18 09:00:34 -07:00
András Marczinkó
43b7abafe7 Update locale_hu_HU.properties 2019-06-18 16:29:06 +02:00
András Marczinkó
483134df10 Update locale_hu_HU.properties 2019-06-18 16:22:48 +02:00
nossr50
b612a599de 2.1.82 2019-06-17 08:26:21 -07:00
nossr50
2cecc91026 WG Hardcore penalty flag 'mcmmo-hardcore' 2019-06-17 08:25:37 -07:00
nossr50
38bc60ba86 Inspecting offline players no longer requires permissions + fixing
errors when using mcrank on an offline player
2019-06-17 08:19:15 -07:00
nossr50
4e4d798b1d Add proper error handling to file loading 2019-06-17 07:38:30 -07:00
nossr50
218b2a1a75 Double check that a Player is not an NPC when loading profiles 2019-06-17 07:00:39 -07:00
Robert A. C
73ce7e729c Merge pull request #3958 from 89009332/patch-9
Update locale_zh_CN.properties
2019-06-16 06:15:34 -07:00
89009332
d67cbe2861 Update locale_zh_CN.properties 2019-06-16 21:09:34 +08:00
nossr50
c3f38cdabd A few typos in javdocs 2019-06-15 21:22:21 -07:00
nossr50
8f55a6277a Fix Repair enchant logic 2019-06-14 20:44:33 -07:00
nossr50
ef71661db1 2.1.81 2019-06-14 20:39:57 -07:00
nossr50
adefda42df Dev mode 2019-06-12 14:43:13 -07:00
nossr50
9c04054017 2.1.80 2019-06-12 12:23:58 -07:00
nossr50
7ab70ba597 2.1.79 2019-06-12 11:05:16 -07:00
Robert A. C
0abccd105d Merge pull request #3953 from snake0053/master
Update locale_ja_JP.properties
2019-06-12 10:43:08 -07:00
SNAKE0053
15b34e2056 Update locale_ja_JP.properties 2019-06-13 02:35:39 +09:00
nossr50
ae551a6bc1 2.1.78 2019-06-12 10:22:20 -07:00
nossr50
98f6eac50c Super Abilities don't do extra durability damage to tools with the
unbreaking enchantment
2019-06-12 10:18:43 -07:00
nossr50
963d0a1897 Fixed a bug where shovels took too many materials to repair 2019-06-12 06:20:20 -07:00
nossr50
705285878f Diagnosing myself with dyslexia 2019-06-11 03:57:28 -07:00
nossr50
e1dcb65888 Add back in the comment about min quantity 2019-06-11 03:52:45 -07:00
nossr50
9062dbcaae Add minimum quantity back to the repair config 2019-06-11 03:50:13 -07:00
nossr50
97c98969ff 2.1.76 2019-06-10 22:49:47 -07:00
nossr50
3fe47c939a You can not salvage without 1 rank in Scrap Collector now (unlocks at
level 2)
2019-06-10 22:46:03 -07:00
nossr50
46dee3c9b6 Numerous tweaks to salvage + fixing repair bugs 2019-06-10 22:37:20 -07:00
nossr50
8e67e2d158 Merge branch 'master' of github.com:mcMMO-Dev/mcMMO 2019-06-10 16:33:30 -07:00
nossr50
f5f4182a90 2.1.75 2019-06-10 16:14:24 -07:00
Robert A. C
05087e569a Merge pull request #3950 from 89009332/patch-8
Update locale_zh_CN.properties
2019-06-09 20:16:38 -07:00
89009332
77bde61f4b Update locale_zh_CN.properties 2019-06-10 09:17:07 +08:00
nossr50
1297b45ef8 2.1.74 2019-06-09 07:08:26 -07:00
nossr50
83b55db4f8 2.1.73 2019-06-09 05:53:39 -07:00
nossr50
caec01e9fa 2.1.72 2019-06-09 05:12:56 -07:00
nossr50
2be67bae19 Fixed a NPE that could occur if Roll was disabled in coreskills.yml 2019-06-09 05:10:30 -07:00
nossr50
a677450d50 Fix NPE on server shutdown with no user data 2019-06-09 05:07:34 -07:00
nossr50
1d7919c050 2.1.71 2019-06-08 10:21:12 -07:00
nossr50
a132172507 You can no longer repair/salvage item stacks with more than one item 2019-06-08 10:20:22 -07:00
nossr50
549ef5734e Repair now always requires confirmation 2019-06-07 10:32:55 -07:00
nossr50
77fbf7f51e Salvage always asks for confirmation before breaking an item 2019-06-07 10:26:49 -07:00
nossr50
e37820d25e 2.1.70 2019-06-07 05:14:51 -07:00
nossr50
00bee60151 Prevent tool ready messages on shulker boxes 2019-06-07 05:13:37 -07:00
nossr50
7679afd3e0 Add new DatabaseAPI 2019-06-06 23:15:18 -07:00
nossr50
0b0408ef98 2.1.70 dev mode 2019-06-06 21:42:12 -07:00
nossr50
58cde322f5 Add shoutout to changelog 2019-06-06 01:53:59 -07:00
nossr50
0638f4c437 2.1.69 2019-06-05 23:50:39 -07:00
nossr50
426b2d27e7 Fix NPE for new data tracker 2019-06-05 21:43:07 -07:00
nossr50
3ce3ac5350 mcMMO should no longer lose a few minutes of player data from shutting
down the server
2019-06-05 21:11:44 -07:00
nossr50
4048ecc764 Fixing some imports 2019-06-02 22:42:03 -07:00
nossr50
f93a1aa151 2.1.68 - You can use food in the off hand with the diet abilities now. 2019-06-02 22:41:13 -07:00
nossr50
f6dc76719a Update changelog 2019-06-02 20:10:40 -07:00
Robert A. C
3035af97a4 Merge pull request #3940 from snake0053/master
Update locale_ja_JP.properties
2019-06-02 20:08:26 -07:00
SNAKE0053
3832ef3547 Update locale_ja_JP.properties 2019-06-02 05:50:26 +09:00
nossr50
8b4cea5dab Chimaera Wing should not be disabled by default 2019-06-01 12:26:11 -07:00
nossr50
9111590dc2 2.1.67 2019-05-31 19:46:14 -07:00
nossr50
ff1bb0deed 2.1.66 2019-05-29 11:01:02 -07:00
nossr50
4795143fca Fixed a memory leak in MySQL that would cause errors if users were
removed from the DB
2019-05-29 10:14:04 -07:00
nossr50
54eca5b8ba Fixed a bug where RetroMode would always use Linear formula 2019-05-27 20:13:22 -07:00
nossr50
11f669f8f4 2.1.64 2019-05-27 19:27:35 -07:00
nossr50
1cda612e86 Fixed a bug that would spam other players when someone used an ability 2019-05-27 19:25:36 -07:00
nossr50
50e4e971d9 Standard level scaling now mirrors RetroMode in a true 1:10 parity 2019-05-27 17:37:54 -07:00
nossr50
33dd34931c Add missing credits to snake for ja_JP 2019-05-21 15:24:45 -07:00
nossr50
ce230bf403 2.1.63 2019-05-21 13:28:22 -07:00
Robert A. C
d7b2a98723 Merge pull request #3934 from andris155/patch-6
Update locale_hu_HU.properties
2019-05-21 13:27:34 -07:00
nossr50
bfb48ccea3 Buffed Impact durability damage and fixed it 2019-05-21 13:13:17 -07:00
András Marczinkó
8cd39301a3 Update locale_hu_HU.properties 2019-05-21 19:11:28 +02:00
nossr50
321684e5f6 Fixed a bug where creative players could gain XP if they qualified for
early game XP boosts
2019-05-19 17:34:51 -07:00
Robert A. C
0b247dfae7 Merge pull request #3932 from snake0053/japanese-translate
Update locale_ja_JP.properties
2019-05-18 11:55:19 -07:00
SNAKE0053
d46fae2d1a Update locale_ja_JP.properties 2019-05-19 03:46:48 +09:00
nossr50
5d6690fc1a 2.1.62 2019-05-18 11:06:48 -07:00
nossr50
66425ba48d Add UUID to admin notifications 2019-05-18 10:59:52 -07:00
nossr50
3b3a36c64d Updating changelog 2019-05-18 10:51:21 -07:00
nossr50
2433ef5db7 Move admin notification toggle check 2019-05-18 10:47:37 -07:00
nossr50
663757352a Tweak xp rate admin notification messages 2019-05-18 10:45:50 -07:00
nossr50
1ced5d8ffc Confirmation messages for admin commands are now moved into the
convenience methods in NotificationManager
2019-05-18 10:40:06 -07:00
nossr50
04c6bd8750 Admin notifications convenience methods handled by NotificationManager 2019-05-18 10:09:45 -07:00
nossr50
b0dc41b4d9 Encapsulate admin notifications + add prefix 2019-05-18 08:12:32 -07:00
nossr50
92e6cedb14 This is why you don't program when you haven't slept in 20 hours 2019-05-18 08:04:55 -07:00
nossr50
447ce97f24 Send message to correct player 2019-05-18 08:03:39 -07:00
nossr50
2a471e409c Fix mistake in new admin notification locale 2019-05-18 08:02:16 -07:00
nossr50
08223bd320 Hotfix for repairing diamond, nerf guardian xp rate 2019-05-18 08:01:15 -07:00
nossr50
90480ca626 Add missing Magma_Block xp value 2019-05-17 15:45:07 -07:00
Robert A. C
56b031b99d Merge pull request #3930 from andris155/patch-1
Update locale_hu_HU.properties
2019-05-17 04:28:15 -07:00
nossr50
f3cbd450d0 Admin chat now sends useful information to admins/adminchat permissible
players
2019-05-17 04:27:27 -07:00
András Marczinkó
b176fd9bca Update locale_hu_HU.properties 2019-05-17 13:08:49 +02:00
nossr50
1c130aad42 2.1.61 - Some fixes + Exploit prevention 2019-05-16 13:30:43 -07:00
nossr50
734dfcdec5 Add toggle to disable event information on player join 2019-05-16 11:40:47 -07:00
nossr50
c8a32b8b38 Add toggle for event broadcasts - General.EventBroadcasts 2019-05-16 11:34:26 -07:00
nossr50
ed3ec3aa40 Add note about JP locale update 2019-05-16 11:29:45 -07:00
nossr50
88d8d0e6bb Fix the Double Drop string in the mining command 2019-05-16 11:20:51 -07:00
Robert A. C
a763f7f025 Merge pull request #3928 from snake0053/translate
Update locale_ja_JP.properties
2019-05-15 09:52:54 -07:00
SNAKE0053
357e9cc08f Update locale_ja_JP.properties 2019-05-16 01:11:25 +09:00
nossr50
2746bac86a 2.1.60 2019-05-14 16:16:24 -07:00
nossr50
95652efbaa Fix bonus drops on multi-block crops 2019-05-14 16:14:01 -07:00
nossr50
e70e5b04b5 Remove unecessary parameter 2019-05-14 15:29:15 -07:00
nossr50
34869914c4 Wolfs no longer kill themselves + tamed mob heart death message bug 2019-05-14 15:14:30 -07:00
nossr50
a53505ee0b Raised overfishing limit + improved tips 2019-05-13 08:53:22 -07:00
nossr50
ed1831da78 Fixed the wrong locale string being used for Mining DD 2019-05-11 12:45:00 -07:00
nossr50
ad550759e6 Fixed an incredibly rare and difficult to perform dupe bug 2019-05-08 10:24:34 -07:00
Robert A. C
984518d9f5 Merge pull request #3925 from SpiderRobotMan/patch-1
Fix small grammar mistake in README
2019-05-07 06:40:19 -07:00
Daniel Bethel
e0055eeead Fix small grammar mistake in README 2019-05-07 09:37:08 -04:00
nossr50
fe07261846 Very large update to the chinese language 2.1.56 2019-05-06 03:52:22 -07:00
Robert A. C
0cbb9b22a5 Merge pull request #3922 from 89009332/patch-7
Update locale_zh_CN.properties
2019-05-06 00:29:28 -07:00
89009332
31ccf2ca02 Update locale_zh_CN.properties 2019-05-06 15:25:41 +08:00
nossr50
23b7e11dd1 Fixed bugs that could occur while updating old DBs to have UUIDs 2019-05-05 16:41:42 -07:00
nossr50
588b6f3692 Fixed the furnace XP bug 2019-05-04 04:08:56 -07:00
nossr50
cdf6e607de 2.1.53 - Fixed critical XP bug 2019-05-03 15:04:40 -07:00
nossr50
f61917e8fe 2.1.52 2019-05-03 01:08:29 -07:00
Robert A. C
661564df36 Merge pull request #3914 from snake0053/master
Update locale_ja_JP.properties
2019-05-01 14:39:56 -07:00
SNAKE0053
0a7c852d89 Update locale_ja_JP.properties 2019-05-01 16:57:58 +09:00
nossr50
c1379f7ac6 2.1.51 - mikroskeem patch 2019-04-30 17:26:14 -07:00
nossr50
22ef134c84 Update changelog 2019-04-30 17:20:23 -07:00
Robert A. C
7f95956a01 Merge pull request #3911 from mikroskeem/feature/locale-reload-command
Add a command to reload locale
2019-04-30 11:33:08 -07:00
Mark Vainomaa
40ea101bf6 Add a command to reload locale 2019-04-30 21:19:55 +03:00
Robert A. C
0c8b001d05 Merge pull request #3910 from mikroskeem/feature/locales-in-plugin-data-folder
Try to load locale from plugin data folder first
2019-04-30 10:33:28 -07:00
Mark Vainomaa
5dc9c3f732 Note user that locale is loaded from locales directory 2019-04-30 20:14:42 +03:00
Mark Vainomaa
ec574a6b63 Cache raw messages from resource bundles
Should speed things up a bit as next message lookups are from single
hashmap instead
2019-04-30 17:58:37 +03:00
Mark Vainomaa
1ca48051ad Dedicated directory for locales 2019-04-30 14:08:43 +03:00
Mark Vainomaa
0f2e1ea740 Fall back to locale loaded from JAR when filesystem one doesn't have requested key 2019-04-30 09:29:04 +03:00
Mark Vainomaa
c2d4aeaf85 Try to load locale from plugin data folder first 2019-04-30 09:29:04 +03:00
nossr50
a496b1fd71 Dev mode 2019-04-29 18:54:00 -07:00
nossr50
ac8042f5d8 update gitignore 2019-04-28 06:52:16 -07:00
nossr50
f7eb06e80b 2.1.50 2019-04-27 06:39:06 -07:00
nossr50
f4214e2031 changelog update 2019-04-27 00:00:52 -07:00
Robert A. C
fd8712ee61 Merge pull request #3905 from Zed-I/patch-6
Added some missing blocks to Herbalism/Mining
2019-04-26 23:50:43 -07:00
BuildTools
f904ac7019 Fixing 1.13.2 bamboo material errors 2019-04-26 23:26:00 -07:00
Robert A. C
3c08af363f Merge pull request #3904 from OverCrave/master
Minor German Locale Update
2019-04-26 14:17:54 -07:00
Robert A. C
8295355a5d Merge pull request #3906 from Zed-I/patch-7
Added bamboo to the non-2 high plant blocks
2019-04-26 14:17:36 -07:00
Zed-I
aee81f87f5 Added bamboo to the non-2 high plant blocks 2019-04-26 18:16:42 +02:00
Zed-I
43d08ec21d Added some missing blocks to Herbalism/Mining
Added some missing entries to herbalism mining and one to combat.
Reasoning for each xp below:

bamboo - 10 Cant grow nearly as tall as kelp
cornflower - 150 same as the other 1 high tall flowers (excluding poppy, dandelion and allium)
lily_of_the_valley - 150 same as the other 1 high tall flowers (excluding poppy, dandelion and allium)
wither_rose - 500. Quite hard to harvest. You need a wither to kill a mob and have the block not get destroyed by the wither blast. If the block where to get destroyed the flower just drops instead and you dont get any xp.

The whole stone brick family get the same xp as nether brick, 50
stone_bricks
cracked_stone_bricks
mossy_stone_bricks
chiseled_stone_bricks

The rest of the prismarine family continue with the same xp as their main block, 70
prismarine_bricks
dark_prismarine
sea_lantern

wandering_trader  - 1.0 same as normal villagers
2019-04-26 18:08:12 +02:00
OverCrave
15e3ad8876 add missing translations 2019-04-26 17:58:23 +02:00
OverCrave
a583f557d7 remove unused translations 2019-04-26 17:49:35 +02:00
nossr50
0949931a61 2.1.49 2019-04-25 18:56:49 -07:00
nossr50
8efee39f7e Add sweet berrys to Herbalism XP tables (update configs) 2019-04-25 18:54:41 -07:00
Robert A. C
307b807b38 Merge pull request #3788 from LogGits/patch-5
Herbalism compatibility with PlayerAnimationEvent
2019-04-25 18:50:27 -07:00
nossr50
be8a2a4b07 Fixes #3902 - NPE in Inventory Listener 2019-04-25 18:49:18 -07:00
nossr50
30df57fa35 Fix async tool lower 2019-04-25 18:46:49 -07:00
nossr50
467025888c Fixed #3858 - Falling blocks in water not getting tracked 2019-04-25 18:28:24 -07:00
nossr50
21ecf959ea updating pom 2019-04-24 22:12:49 -07:00
nossr50
d1401d0cba change targetted API 2019-04-24 21:11:27 -07:00
Robert A. C
b5930fc35d Merge pull request #3897 from Zed-I/patch-4
Added excavation treasure to coarse dirt
2019-04-24 18:23:29 -07:00
Robert A. C
9a74ab77f4 Merge pull request #3900 from Leomixer17/patch-1
Update locale_it.properties
2019-04-24 18:22:45 -07:00
nossr50
18d698aad2 2.1.48 2019-04-24 16:40:28 -07:00
Leomixer17
3329a6c49e Update locale_it.properties 2019-04-24 23:09:03 +02:00
nossr50
c07a29ba86 mcMMO should work on both 1.13 and 1.14 now 2019-04-23 08:20:00 -07:00
nossr50
b36c4b56c3 first 5 levels in all skills are now much easier to level 2019-04-23 04:21:25 -07:00
nossr50
cee0025147 Bonus XP for early combat levels 2019-04-23 03:52:48 -07:00
nossr50
372ad1fac3 Experience settings for 114 are now under Experience_114 in experience.yml 2019-04-23 03:37:43 -07:00
nossr50
09cba965d3 Switch to GSON since mojang lib does not exist in 1.14 2019-04-23 02:12:22 -07:00
nossr50
d862f7f779 Tool lower task sync 2019-04-23 01:13:21 -07:00
nossr50
0adaa0ba66 PlayerNotification now marked async 2019-04-23 01:10:09 -07:00
nossr50
432a4aa330 1.14 is required for this version of mcMMO 2019-04-23 00:54:49 -07:00
nossr50
1c490cd463 1.14 Compatibility (this build won't run on 1.13 anymore) 2019-04-22 23:54:02 -07:00
nossr50
b41637fbf8 2.1.47 2019-04-21 17:08:58 -07:00
nossr50
7506646862 Party NPE fix 2019-04-21 16:56:26 -07:00
Zed-I
570ab49e55 Added excavation treasure to coarse dirt
Added coarse dirt to all drops that dirt can drop.
Also added grass block to the quartz drop since there is no reason not to.
2019-04-20 16:35:01 +02:00
nossr50
227fb49dec 2.1.46 2019-04-19 17:59:00 -07:00
nossr50
78fdfc1c35 Made improvements to the Party member list from /party 2019-04-19 17:56:59 -07:00
nossr50
0b26d6c72c Fixed error related to Bleed, fixed missing default XP values for Herbalism and Woodcutting 2019-04-19 14:55:07 -07:00
nossr50
cae722e8c7 Changelog upd 2019-04-19 14:34:21 -07:00
Robert A. C
0eed1a6c5a Merge pull request #3892 from Zed-I/patch-3
Fixed bug where you couldn't shake zombie/creeper heads
2019-04-19 13:06:00 -07:00
Zed-I
bbf7ce9c57 Fixed bug where skeleton heads would drop in instead of zombie/creeper heads on successful shake
Creeper/zombie heads are now their own items and data is no longer used
2019-04-19 20:35:06 +02:00
Robert A. C
1fa21823a4 Merge pull request #3891 from Zed-I/patch-2
Fixed axe salvage bug
2019-04-19 10:12:37 -07:00
Zed-I
4b34299648 Fixed axe salvage bug
Changes max quantity to 3 from 2 on all axes since they are crafted with 3 resources not 2
2019-04-19 14:36:29 +02:00
nossr50
45841218e6 dev mode 2019-04-18 16:34:19 -07:00
Robert A. C
c509daff9f Merge pull request #3890 from OverCrave/master
Fix adminchat returning too early if send by the console
2019-04-18 15:13:21 -07:00
OverCrave
ce92329705 fix it for real now 2019-04-18 22:59:52 +02:00
OverCrave
817b5364cf fix adminchat returning too early if send by console 2019-04-18 22:58:50 +02:00
nossr50
820c3260c8 2.1.45 - mcMMO will check for outdated software and provide tips 2019-04-17 11:51:13 -07:00
Robert A. C
54a1475fef Merge pull request #3878 from andris155/patch-2
Update locale_hu_HU.properties
2019-04-15 10:43:12 -07:00
András Marczinkó
bd0204a09e Update locale_hu_HU.properties 2019-04-15 10:10:33 +02:00
nossr50
31c1bd52bc 2.1.44 2019-04-14 05:39:23 -07:00
nossr50
0f8c0f97d9 Fixing another NPE for brewing 2019-04-14 05:27:31 -07:00
nossr50
5a56b27ea8 Fix AlchemyBrew NPE 2019-04-14 04:55:37 -07:00
nossr50
273dfbbdce 2.1.43 2019-04-14 04:23:28 -07:00
nossr50
138b109ff5 Correct display error when successfully salvaging enchantments 2019-04-13 22:04:35 -07:00
Robert A. C
908ac7c541 Update README.md 2019-04-13 15:56:00 -07:00
Robert A. C
e7e13d990a Update README.md 2019-04-13 15:55:38 -07:00
Robert A. C
ea9f79291e Update readme.md
Adjusting the team information to represent the current state of the project
2019-04-13 15:51:03 -07:00
nossr50
4b13cbeb43 2.1.42 2019-04-13 13:20:49 -07:00
nossr50
d542098f8a New salvage enchant bypass permission node 2019-04-13 13:17:28 -07:00
nossr50
f6e01ea910 UserManager::getPlayer returns null again (oopsie) 2019-04-13 12:58:32 -07:00
nossr50
2a053a0be2 Fixing logic error in mcrank CD msg 2019-04-12 15:34:33 -07:00
nossr50
b5cbfc7f66 Commands.Database.CooldownMS - new locale string 2019-04-12 15:29:37 -07:00
nossr50
8c0076ff80 2.1.41 2019-04-12 15:24:57 -07:00
nossr50
6e3c2fcb76 Fix mcrank cd display 2019-04-12 15:24:01 -07:00
nossr50
33a68daa9c mcMMO now checks in all places for a loaded profile before executing processing on said profile 2019-04-12 15:17:05 -07:00
nossr50
00cc5f0845 Move Fall data to AcrobaticsManager 2019-04-11 04:09:00 -07:00
nossr50
8b0a580505 Fixing Party Chat Bug 2019-04-11 03:49:13 -07:00
nossr50
87bf3a5b40 fixing an oopsie 2019-04-11 00:00:22 -07:00
nossr50
426b1304e2 Numerous tweaks + failsafes added to Loading/Saving of players 2019-04-10 01:52:34 -07:00
nossr50
f1204f8a2a 2.1.39 - Added Seagrass/Tall_Seagrass to experience tables
Salvage should sound a bit different to Repair now
Fixes #3863 #3862
2019-04-09 16:34:38 -07:00
nossr50
f7b07899c1 2.1.38 2019-04-08 17:58:44 -07:00
nossr50
e5de240eb4 Reduced Roll XP CD from 60s - > 10s 2019-04-08 17:58:06 -07:00
Robert A. C
0ba3d7bd68 Update README.md 2019-04-08 03:17:36 -07:00
Robert A. C
79d5c6192f Update README.md 2019-04-08 03:17:16 -07:00
Robert A. C
b8ae8438de Merge pull request #3861 from FabioZumbi12/patch-4
Update locale_pt_BR.properties
2019-04-07 00:26:53 -07:00
FabioZumbi12
974106f983 Update locale_pt_BR.properties 2019-04-07 04:03:08 -03:00
nossr50
d599db2897 2.1.37 - Fixes #3859 2019-04-06 05:14:52 -07:00
Robert A. C
3f89f91f42 Merge pull request #3857 from andris155/patch-1
Update locale_hu_HU.properties
2019-04-05 01:45:12 -07:00
András Marczinkó
2fca0963d7 Update locale_hu_HU.properties
Improve AbilityGateRequirementFail translation.
Translated new translation lines.
Update and fix Guides.Mining.Section.4
2019-04-05 10:44:01 +02:00
nossr50
b63db1981c 2.1.36 2019-04-04 19:08:20 -07:00
nossr50
af744fa088 Villagers give XP now 2019-04-04 18:55:25 -07:00
nossr50
8538ac4e50 mcnotify will now squelch notifications from mcMMO & players who are squelched will be reminded of their squelch status at least once an hour (you can disable this in advanced.yml) 2019-04-04 17:27:17 -07:00
Robert A. C
cabc5977d9 Merge pull request #3856 from OverCrave/master
German Locale Update
2019-04-04 04:30:44 -07:00
OverCrave
43dd382541 fix concoction name inconsistency 2019-04-04 13:12:55 +02:00
OverCrave
cdb81e961e fix herbalism name inconsistency 2019-04-04 13:11:24 +02:00
OverCrave
51ced83301 mining guide update 2019-04-04 13:09:57 +02:00
OverCrave
09bca96af3 Merge remote-tracking branch 'upstream/master' 2019-04-04 13:05:37 +02:00
nossr50
f1d9f787f4 2.1.35 2019-04-04 00:39:00 -07:00
nossr50
b8b0be71b1 2.1.34 2019-04-03 22:01:45 -07:00
nossr50
ac10261803 Blast Mining uses Pickaxe + Missing Taming XP entries 2019-04-03 21:54:49 -07:00
OverCrave
dc018be6bb overhaul part 2
- fixed/changed punctuation and grammar in some of the skills
- fixed some skills commands not having the same name as their shown name
2019-04-03 22:20:59 +02:00
OverCrave
832b653a88 change usage of word 'wahrscheinlichkeit/chance' for consistency 2019-04-03 21:50:38 +02:00
OverCrave
1fddaf15cc add last missing new translations 2019-04-03 21:49:16 +02:00
nossr50
b68feb6992 rogue import spotted 2019-04-02 23:07:52 -07:00
nossr50
f3837265db 2.1.33 2019-04-02 23:03:48 -07:00
nossr50
ae551e17cd 2.1.32 2019-04-01 10:16:43 -07:00
nossr50
c6d055cb48 Completely remove Fireworks from mcMMO 2019-04-01 10:04:45 -07:00
nossr50
68e34d682c 2.1.31 2019-03-30 17:45:03 -07:00
nossr50
b125600dac Fixing an issue with mmoedit triggering notifications for skills already unlocked 2019-03-30 17:44:06 -07:00
Robert A. C
57b31b60b3 Merge pull request #3843 from Ineusia/master
Minor API fix
2019-03-30 17:09:27 -07:00
nossr50
7757e187be Fixed a bug involving SubSkill notifications
Fixes #3808, also fixed the notification timer
2019-03-30 16:56:00 -07:00
Robert A. C
5ce360d443 Merge pull request #3844 from OverCrave/master
German Locale Overhaul
2019-03-30 10:21:44 -07:00
OverCrave
d44b6e0afb readd other locales 2019-03-30 17:59:25 +01:00
OverCrave
629d882831 Merge remote-tracking branch 'upstream/master' 2019-03-30 17:57:14 +01:00
OverCrave
947018c0f1 remove other languages temporarily 2019-03-30 17:56:40 +01:00
BuildTools
ca2e1c11e6 Don't load the players profile just to get their name 2019-03-29 23:56:40 -05:00
nossr50
69e5d3e1b5 2.1.30 2019-03-29 18:21:07 -07:00
nossr50
b7d33f0227 Adding missing Double Drop entries for Woodcutting 2019-03-29 18:11:32 -07:00
nossr50
28c7fdd4e2 Add missing Herbalism entries to config 2019-03-29 17:57:48 -07:00
nossr50
53534e0f1d Fixing Mining Double Drops (update configs) 2019-03-29 17:44:54 -07:00
nossr50
8d477a5cf5 unused imports 2019-03-29 11:33:40 -07:00
nossr50
74908cdcf5 2.1.29 - Double Drop Fix 2019-03-29 11:27:49 -07:00
Robert A. C
39b22d0ee8 Merge pull request #3841 from Fabrimat/patch-3
Update locale_it.properties
2019-03-28 08:05:57 -07:00
Fabrizio La Rosa
74e62ab08c Update locale_it.properties 2019-03-28 16:01:21 +01:00
OverCrave
f1cc745de8 fully translate party stuff 2019-03-28 13:41:39 +01:00
OverCrave
7654e78fbe Update locale_de.properties 2019-03-28 12:44:00 +01:00
OverCrave
558c727136 change color code usage style 2019-03-28 12:35:08 +01:00
OverCrave
18097fa1a5 Update locale_de.properties 2019-03-28 12:26:15 +01:00
nossr50
e2b8d940d3 2.1.28 2019-03-28 04:22:26 -07:00
OverCrave
5093c37efb Update locale_de.properties
so much done so much still missing .-.
2019-03-28 12:10:11 +01:00
OverCrave
610e1a6bf4 Merge remote-tracking branch 'upstream/master' 2019-03-28 11:25:56 +01:00
OverCrave
99843f2735 update en_US to upstream version 2019-03-28 11:25:41 +01:00
nossr50
732726bbd3 2.1.27 - Fixed an exploit that allowed players to dupe torches, rails, etc 2019-03-27 21:05:57 -07:00
nossr50
65687ca603 2.1.26 - Combat Skills are MUCH more deadly 2019-03-27 16:40:08 -07:00
nossr50
658382dba2 Added Limit Break to Archery, Axes, Swords, Unarmed 2019-03-27 16:30:29 -07:00
nossr50
404a876d6b Compiler made an oopsie 2019-03-27 12:36:46 -07:00
nossr50
c4a383c4fb Removed PVP requirement on Stab, added info about Stab to /swords 2019-03-27 12:33:04 -07:00
nossr50
e0341f7ae7 Added new subskill to Swords, Stab 2019-03-27 12:11:11 -07:00
nossr50
018c6fc96b 2.1.26 Dev Version 2019-03-27 11:27:27 -07:00
nossr50
d324aa9589 Rescale Iron Arm Damage 2019-03-27 11:27:05 -07:00
OverCrave
cc1c73cb17 Update locale_de.properties
stopped at Fishing.Exhausting
2019-03-26 22:33:44 +01:00
OverCrave
d6dc8bb04c Update locale_da.properties
generated by the eclipse property tool
2019-03-26 21:35:01 +01:00
OverCrave
88ef6b0984 Update locale_de.properties 2019-03-26 21:34:31 +01:00
OverCrave
624299602d Update locale_de.properties 2019-03-26 21:14:30 +01:00
OverCrave
8fe8db2353 Update locale_de.properties 2019-03-26 20:21:11 +01:00
OverCrave
159cf7c0d4 remove unused translations
this change removes every translation in every locale that does not exist in locale_en_US anymore, to keep everything up to date
2019-03-26 20:05:46 +01:00
OverCrave
947cdc91a4 Update locale_de.properties 2019-03-26 19:52:36 +01:00
OverCrave
ff55cbb946 Update locale_de.properties 2019-03-26 19:40:47 +01:00
OverCrave
fdb151083d Update locale_de.properties 2019-03-26 19:33:18 +01:00
nossr50
7a3d608f36 2.1.25 2019-03-26 08:36:13 -07:00
nossr50
719283177e Shake has an upper limit of 10 damage (will be configurable in the near future), alchemy ranks adjusted 2019-03-26 08:22:39 -07:00
nossr50
55fb3ed74f 2.1.24 - Critical Exploit Fix 2019-03-25 15:12:17 -07:00
nossr50
363ea66335 2.1.23 - Read the changelog, configs need to be updated. 2019-03-24 19:02:08 -07:00
nossr50
7ee65a7e65 Fixing a 7 year old damage bug. 2019-03-24 14:20:20 -07:00
nossr50
aa25ba6338 Fixed DoubleDrops for Mining, MANY nerfs to Rupture (PVP balance tweaks coming soon) 2019-03-23 22:57:44 -07:00
nossr50
b68bbad766 Eject players from Minecarts if they cast a fishing rod (Anti-AFK) 2019-03-23 21:01:40 -07:00
nossr50
6d19239db7 Don't add drops for items with a quantity of zero 2019-03-23 18:09:29 -07:00
nossr50
faab64864a Fixing Double Drops for Mining -- READ THE FULL COMMIT MSG
This fix is very similar to what was deployed for Herbalism in 2.1.22

NOTE: Here's what your Double_Drop entries in Config.yml for Mining should look like

https://paste.gg/p/anonymous/dcd06f1215844311b4f2225f200090d1

IMPORTANT: Version 2.1.22 which came before this had a similar fix for Herbalism, instructions on how to fix your Herbalism Double Drops can be found here
        https://www.spigotmc.org/resources/official-mcmmo.64348/update?update=269868
2019-03-23 18:07:23 -07:00
nossr50
b1f4ea8cba 2.1.22 release 2019-03-23 16:35:05 -07:00
nossr50
df6315dd62 Fixed Repair Mastery using incorrect numbers during calculations 2019-03-23 16:23:38 -07:00
nossr50
255f7bf335 Fixes #3832 - Resolved issue with double drops & herbalism, similar fixes coming to woodcutting/mining soon. Reminder to update config.yml, read changelog for instructions.
If you harvest crops with a Hoe it does not require seeds to replant on successful Green Thumb
2019-03-23 16:21:25 -07:00
nossr50
ce6553d857 Fixing Double Drops for Herbalism (Update your configs) see changelog for instructions 2019-03-23 13:34:14 -07:00
Robert A. C
df1497924c Merge pull request #3830 from andris155/patch-1
Added Fishing.LowResources translation to Hungarian locale file
2019-03-22 08:56:52 -07:00
András Marczinkó
aeed0cf6ad Added Fishing.LowResources translation to Hungarian locale file 2019-03-22 16:38:04 +01:00
nossr50
e40a7bb4e1 XP Gain from Roll has a CD now (60 seconds) 2019-03-21 14:32:01 -07:00
nossr50
d59dbe7630 update log 2019-03-20 07:08:39 -07:00
nossr50
dece43429d Added an option to turn off fishing exploit detection as a band-aid fix until the config update is done 2019-03-20 07:04:05 -07:00
Robert A. C
14f900aa83 Merge pull request #3828 from andris155/patch-1
Update Hungarian locale file
2019-03-19 01:36:02 -07:00
András Marczinkó
53848d3fd3 Update Hungarian locale file 2019-03-19 09:33:55 +01:00
nossr50
c8d95dc711 2.1.19 2019-03-18 03:12:00 -07:00
nossr50
bb118607ce Less aggressive detection 2019-03-18 02:40:19 -07:00
nossr50
2d849f55e5 Smaller bounds on fishing scarcity 2019-03-18 00:43:14 -07:00
nossr50
fef9058e16 Fishing is now more aggressive about over casting, added messages about fishing, removed vanilla rewards for exploiters 2019-03-18 00:26:49 -07:00
nossr50
e3d2526939 Improve Fishing AFK detection 2019-03-18 00:11:27 -07:00
nossr50
2f0a58b968 2.1.18 - It turns out Kelp is actually made up of 2 blocks mixed together 2019-03-16 20:26:26 -07:00
nossr50
8994594ed4 2.1.17 - Fix drowned mob spawner logic 2019-03-14 16:52:15 -07:00
nossr50
bb46b2a6ac Drowned Transformation will no longer enabled XP on mob spawners, Kelp will now count the whole block for XP 2019-03-13 13:27:16 -07:00
nossr50
7296deb149 2.1.15 Release - Fixing Fuel Efficiency Max Rank Benefits 2019-03-09 18:10:01 -08:00
nossr50
ef5cd3ec60 2.1.14 release 2019-03-09 17:36:20 -08:00
nossr50
f9f6d1550e Silk Touch toggle in advanced.yml for double drops 2019-03-09 17:31:45 -08:00
nossr50
68e43e3641 Mycellium removed from XP tables for woodcutting 2019-03-09 17:23:17 -08:00
nossr50
93458aa355 Kelp added to Herbalism XP tables 2019-03-09 17:18:04 -08:00
nossr50
e80e771e9d mcMMO now tracks blocks moved by pistons and flags them as unnatural, even if they were natural to combat automated xp farming 2019-03-09 17:12:34 -08:00
nossr50
af9b631ee2 kill flux mining 2019-03-09 16:44:55 -08:00
nossr50
ca5a46508d fixing a bug with setting ranks for fuel efficiency 2019-03-09 16:35:23 -08:00
nossr50
7703cafa34 fixing compile error 2019-03-09 16:25:51 -08:00
nossr50
437fe29112 Fuel Efficiency now uses a rank system, also fixed some bugs with it 2019-03-09 16:22:20 -08:00
nossr50
28b71804a2 Fixed display bug w/ Fish Diet, added Tropical, Raw Cod/Salmon to eligible foods 2019-03-09 15:48:29 -08:00
nossr50
6f15cd4005 2.1.13 Release 2019-03-08 15:34:35 -08:00
LogGits
3ed4228b72 Added imports 2019-02-16 05:40:49 +10:00
nossr50
ba88831c88 2.1.12 2019-02-15 10:21:39 -08:00
LogGits
93fefa031b Herbalism compatibility with PlayerAnimationEvent
This change in theory should make McMMO herbalism compatible with plugins that utilise PlayerAnimationEvent. The main reason that I want to add this is to fix `no swing` false positives in `AAC` (though didn't get to test this). 

I would appreciate if someone could test this PR and verify that its working without any issues. (I am busy for the next few days so I haven't been able to test it. In theory it looks like it should work. I could have checked if the event `isCancelled()` however, this doesn't seem necessary quite yet. Though, if it is needed I can add it 👍 

Please don't merge this unless it's confirmed completely working. I will find some time to test it out within the next few days.
2019-02-12 13:26:03 +10:00
210 changed files with 13971 additions and 4952 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [nossr50] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: nossr50 # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://paypal.me/nossr50 # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
# bash stuff
*.sh
# Eclipse stuff
/.classpath
/.project

11
1 Normal file
View File

@@ -0,0 +1,11 @@
SkillShot tweaks
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
# modified: src/main/java/com/gmail/nossr50/skills/archery/Archery.java
# modified: src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
#

View File

@@ -1,13 +1,952 @@
Changelog:
Versions without changelogs probably had very small misc fixes, like tweaks to the source code
Version 2.1.117
Fixed a rare http error when polling Mojang for UUIDs
Fixed a bug that allowed duping
Key:
+ Addition
= Fix
! Change
- Removal
Version 2.2.0
Version 2.1.116
Fixed directional plants not maintaining their direction when replanted
Version 2.1.115
Green Thumb now requires a hoe to activate
Hoes no longer give free replants
You can sneak to break plants with a hoe in your hand (or just put the hoe away)
Using a hoe on non-fully grown crops will replant them as a convenience feature
New sound option in sounds.yml called 'ITEM_CONSUMED', plays when eating seeds for Green Thumb
Cocoa plants now require GT of at least 2 to start at the second stage of growth
Green Terra now boosts growth on Green Thumb by 1 stage (doesn't go above the maximum value though)
There is now a feature in place to prevent breaking a newly automatically replanted (via green thumb) crop from being breakable for a few seconds after it appears
Fixed a bug where Salvage always gave the best results
Fixed an issue with arrows causing exceptions with players not yet having data loaded
Spectral arrows are now tracked by mcMMO
Use minimum level of salvageable properly
Fix Axes Critical Strikes default permissions ( new fixed permission: mcmmo.ability.axes.criticalstrikes )
Fix potential null pointer exception for salvage
Updated locale entry 'Herbalism.SubSkill.GreenTerra.Description'
Version 2.1.114
Fix some more locale usages, should aim to further prevent issues with oddball locales
Fixed a bug where newer versions of MySQL did not like our rank command
Added a new setting to turn off the Snow Golem Exploit prevention to experience.yml next to the other exploit fixes
Fixed a bug which stopped the optional Endermite XP exploit fix from working
Version 2.1.113
Activating Berserk on a soft block (glass, snow, dirts) will break that material right away instead of only breaking subsequent blocks hit by the player
Berserk will now break glass and glass pane blocks
Hitting glass with berserk readied will activate it
Added GLASS settings to sounds.yml for Berserk
Fixed bug where BlockCracker didn't work on infested_stone_bricks
Fixed a bug where beacons could be duplicated
Check player's PTP world permissions before executing a party teleport
Improved how mcMMO handles randomness
Version 2.1.112
Correct locale usage for enum access, now enforces using the english locale to prevent issues with oddball locales for configs/commands
Fixed a NPE that can occur if a player engages in combat with specific skills before their profile is loaded
mcMMO is now more compatible with certain mob stacking plugins
Improved behaviour for mob health bars
Archery's Skill Shot bonus damage is now multiplicative instead of additive (nerfing early game skill shot ranks)
Sweet Berry Bush's default Herbalism XP is now 50 instead of 300 (Update your experience.yml or delete it to generate a new one)
Version 2.1.111
mcMMO is compatible with the following versions of MC: 1.15 / 1.14.4 / 1.14.3 / 1.14.2 / 1.14.1 / 1.14 / 1.13.2
Further prevent nesting of bleed damage calls
Warn about reparable/salvage configs with missing sections
Added Bee combat experience modifier to experience.yml (Update your experience.yml file, see notes)
Breaking a Bee Nest will result in Herbalism XP (Update your experience.yml file, see notes)
Breeding bees will now result in Taming XP (Update your experience.yml file, see notes)
NOTES:
You will need to update your experience.yml by hand or delete it to get XP from new things in 1.15
The default version of mcMMO's experience.yml looks like this: https://paste.gg/p/anonymous/15c34df6e60d45d9a3508b379a5e6514
You'll want to add Bee to combat XP section, and Bee_Nest to Herbalism XP, and Bee to Taming XP section.
Version 2.1.110
Fixed a dupe bug
Actually fixed Block Cracker
You can now crack Infested Stone Bricks with Block Cracker
Added Lithuanian locale (thanks Vyciokazz)
Version 2.1.109
Block Cracker will now correctly crack stone_bricks during Berserk again
Added Lily_Of_The_Valley to the Bonus Drops list in config.yml (you'll probably want to add this manually) which enables it to double drop
Added missing 1.14 blocks to ability/tool activation blacklists
Fixed spamming of incompatible worldguard version message
Updated Italian locale (thanks Fabrimat)
Version 2.1.108
Fixed an amusing exploit for easy leveling in Acrobatics
mcMMO should no longer break if FAWE is being used in conjunction with WG on the server
Improved WG compatibility, mcMMO will now check if WG has loaded properly before hooking into it, which will prevent mcMMO from breaking if WG could not load properly.
mcMMO now loads after worlds do during start up (which is what it should be doing)
NOTES:
Mobs will now only reward Dodge XP a certain amount of times
You can turn off this exploit prevention by disabling ExploitFix.Acrobatics in experience.yml
Version 2.1.107
Fixed an exploit that allowed automated XP gain for Excavation
Fixed encoding of russian translation
New API event McMMOPlayerProfileLoadEvent (thanks Shrek5InTheatres2019)
Version 2.1.106
Added a few missing blocks to the ability blacklist tables (prevents readying/using abilities on certain blocks that have right click functionality)
Updated Japanese locale (thanks ethernetcat)
Updated Simplified Chinese locale (thanks Fu_Meng)
Version 2.1.105
mcMMO will reset players scoreboard to the main scoreboard if they move into a blacklisted world
Beast lore now shows max jump height and other tweaks (Thanks QuantumToasted)
If the server has enabled level caps (which are not on by default) players will be shown that they are at max level instead of seeing how much XP needed to reach an impossible level (thanks Shrek5InTheatres2019)
Large update to Italian locale (thanks Leomixer17)
NOTES:
The scoreboard change should result in mcMMO removing scoreboards from players properly when they enter a black listed world. This is a hacky band aid fix as our scoreboard code is archaic and needs to be rewritten in 2.2 and not 2.1. Expect a scoreboard overhaul sometime in the future.
Version 2.1.104
Fixed a bug resulting in many errors when using Rupture
Large update to the Japanese locale (thanks ethernetcat)
Updated Hungarian locale (thanks andris)
Version 2.1.103
Treasure item amount will default to 1 if not specified instead of breaking mcMMO
Fishing treasures will now return the amount defined in treasures config file, an option to randomize amounts will be coming in the future. See notes.
Fixed a bug where Tree Feller was only rewarding 1 XP per log broken no matter the circumstances
Fixed an issue with salvage checking the incorrect level requirement
Updated Italian locale (thanks Leomixer17)
Fixed grammar in one of the Salvage strings (thanks QuantumToasted)
NOTES:
Sometime in 2014 a decision was made that any fishing treasure over the amount of 1 will be randomized in its yield, while this is not necessarily a bad thing it means control over the drop is a bit random. I've removed this randomness temporarily, in the future you will be able to chose if the amount is randomized or static.
Version 2.1.102
Scoreboards will now be removed from players who teleport to a blacklisted world
Fixed a bug where Rupture could trigger itself
Version 2.1.101
Fixed an exploit where chorus plants could be used to gain automatic XP
Added blast furnace, cartography table, grindstone, lectern, loom, scaffolding, smoker, stonecutter, and sweet berry bush to the list of internal blocks that don't trigger tool readying
Version 2.1.100
Fixed a bug where plants could double drop when the skill was not yet unlocked
Fixed a bug where plants ALWAYS double dropped
mcnotify command now checks that it's being executed by a player
Fixed some concurrency concerns around BleedTasks
Fixed an NPE that may occur with random chances on a player without loaded data
Updated Russian locale (thanks myfbone!)
Version 2.1.99
MASSIVE update to the Russian locale (ru) credit to myfbone
Debug mode (/mmodebug) will now print info about XP perks and how they are modifying your incoming XP
Version 2.1.98
Fixed a bug that prevented Taming XP from combat
Version 2.1.97
mcMMO is compatible with 1.14.4 (Didn't require any changes)
Fixed a NPE that could occur if a pet participated in combat and its master's mcMMO data was not available
mcMMO now properly closes its region files as it creates them (thanks Yukiiro-Nite)
Updated Hungarian locale (thanks andris)
Version 2.1.96
Added the setting 'Skills.General.LimitBreak.AllowPVE' to advanced.yml to allow Limit Break damage bonus to apply in PVE again, defaults to false
Updated Limit Break locale strings
Fixed a few more places where 'Archaeology' was misspelled in the locale
Added the setting 'ExploitFix.PistonCheating' to experience.yml at the request of a user
Added a missing 's' to Nether_Bricks (thanks Sikatsu) in experience.yml
NOTES:
The Skill Tooltips are a bit limited right now, in the future they will be more flexible. In order to reflect that Limit Break doesn't always work in PVE (now up to server settings) I added a crappy note to its hover window tip. I'll be fixing this in the future.
You shouldn't need to update you config entry for Nether_Bricks, I believe that file updates automatically (the old config system is a bit janky, some stuff updates, some other stuff doesn't.)
PistonCheating prevents blocks from being marked "natural" once they've been moved, we've never had an option for this before.
A discord user requested it, its a strange request but I added it anyways.
Of course, it defaults to "true" which prevents cheating with pistons.
Version 2.1.95
Added missing Chorus_Fruit & Chorus_Plant entries to Herbalism's Bonus Drops in config.yml (See notes)
Limit Break now does dramatically less damage to players with lower grades of armor
Limit Break damage bonuses now only apply to Players
Updated in game text to reflect changes to Limit Break
Fixed a bug where opponents used your stats instead of their own to activate Iron Grip
Fixed a bug preventing Wandering Traders from granting XP
Fixed a bug that prevented Chorus Tree's from giving full XP if you broke anything other than the bottom block
Fixed a bug which could cause Large Fern's to reward less XP
Fixed a bug where certain herbalism crops could have fewer than intended bonus drops
Fixed a bug involving Ender Pearl and Acrobatics
Added some protection to Acrobatics to prevent gaining too much XP in one Roll.
Added 'Carrots, Cocoa, Potatoes, Wheat, Beetroots, Nether_Wart' to Herbalism in experience.yml (See notes)
Removed the _Ripe entries from experience.yml (no longer used)
Updated locale string 'Swords.SubSkill.SwordsLimitBreak.Description' & 'Swords.SubSkill.SwordsLimitBreak.Stat'
Added missing 'Chorus_Flower' entry to herbalism in experience.yml
Added some debug messages about XP gains if you are in debug mode
Added some debug messages for Acrobatics if you are in debug mode
Added some debug messages for Herbalism if you are in debug mode
NOTES:
Add 'Chorus_Fruit' and 'Chorus_Plant' under Bonus_Drops.Herbalism in config.yml or you will not be getting double drops for Chorus Fruit.
You shouldn't need to add "Chorus_Flower, Carrots, Cocoa, Potatoes, Wheat, Beetroots, Nether_Wart" to your experience file, it seems that config file updates automatically for missing entries.
Version 2.1.94
2 new devs have joined the mcMMO team (electronicboy, kashike), bringing the active dev team to 3 including myself! Strings relating to authors of mcMMO have been updated to reflect this
Fixed a bug where 2 people using Tree Feller could result in the tree being rejected for being too big
New command /mmodebug (or /mcmmodebugmode) - Prints useful information when players punch blocks while they are in debug mode
mcMMO no longer prints debug information when you attack stuff with the debug stick, use the new command (/mmodebug) instead
Added locale string 'mcMMO.Description.FormerDevs'
Added locale string 'mcMMO.Template.Prefix'
Added locale string 'Commands.Mmodebug.Toggle'
Added locale string 'Commands.Description.mmodebug'
Tweaked locale string 'mcMMO.Description'
Updated Japanese locale (thanks snake)
Updated hu_HU locale (thanks andris155)
Version 2.1.93
Fixed a bug where players would be told they could not breed summoned animals when the animals weren't summoned (bug didn't actually do anything besides send you a message)
Version 2.1.92
Call Of The Wild (COTW) no longer cares if entities of the same type are nearby when attempting to summon a new entity
Fixed a bug where COTW summon limit was global instead of per player
If you are playing in 1.14 mcMMO will now summon cats instead of ocelots
The default summon limit for COTW is now per player instead of global which is how it should be, for wolves this defaults to 2, for other entities it defaults to 1
The COTW setting named Summon_Max_Amount in config.yml has been renamed to Per_Player_Limit
By default players are no longer allowed to breed COTW summoned animals with other animals, you can turn this off (see the notes)
If a player tries to breed animals with a COTW animal and the server settings prevent this, they are informed via a message that it is not allowed
If the COTW summon has a lifespan, players are now informed about this lifespan when the entity is first summoned
COTW entities now send the player a message when they die, time out, or get removed through other means
COTW summons now have their name prefixed with some colored text to to make it easier to identify them.
COTW summons now despawn if their owner logs out
There is now a small 150ms window in which you cannot summon an entity via COTW to prevent accidentally summoning extra entities
COTW Horses, Cats, and Wolves now always spawn in as adults
Changed the sound effect for COTW (Fireworks -> Pop)
Most COTW messages have been tweaked and new COTW messages have been added
Added new setting to experience.yml 'ExploitFix.COTWBreeding' - Prevents breeding with COTW summoned entities when set to true, defaults to true
Removed the 'mcmmo.ability.taming.callofthewild.renamepets' permission node as it is seen as unnecessary
Removed locale strings
Taming.Summon.Fail.Ocelot
Taming.Summon.Fail.Wolf
Taming.Summon.Fail.Horse
Taming.Summon.Fail.TooMany
Taming.Summon.Lifespan
Added new locale strings
Taming.Summon.COTW.NeedMoreItems
Taming.Summon.COTW.BreedingDisallowed
Taming.Summon.COTW.Success.WithLifespan
Taming.Summon.COTW.Success.WithoutLifespan
Taming.Summon.COTW.Limit
Taming.Summon.COTW.TimeExpired
Tweaked locale string
Taming.Summon.Name.Format
NOTES:
I plan to rework Call of The Wild (COTW) significantly in the upcoming content patch, until then I have made several tweaks to it.
COTW Summoning Requirement Changes
It is intentional that you are not supposed to be able to COTW summon something that you already have tamed, but mcMMO was not checking this properly.
So previous to this patch, if you tried to summon a wolf and wolves were nearby, it would fail. This is not intentional behaviour and was a bug.
The correct behaviour is that if you try to summon a wolf and you already have wolves, it should fail.
I was fixing this bug when it occurred to me, why do we even care if nearby tamed wolves owned by you exist if you are trying to summon a temporary one?
As a result of this train of thought, I have removed this restriction on COTW and several other tweaks have been made as a result of this line of thinking.
There was also an issue involving how many COTW entities could be out at once, for some reason the limit was applied globally and defaulted to 10, so if 10 players had COTW entities out no one else would be able to summon anything. I have fixed this.
You can set the lifespan to 0 in the config to make it so that COTW entities last until a server restart or the player logs out.
COTW Breeding Change
It was never intentional for COTW summoned entities to be breedable, by default they will not be. You can change this by setting 'ExploitFix.COTWBreeding' to false in experience.yml
Version 2.1.91
mcMMO is now more compatible with plugins that spawn arrows in unexpected ways, this fixes some NPE in mcMMO when using certain plugins
Fixed a bug where Unarmed was using the same CD timer for every player in the server (thanks slop_me)
Version 2.1.90
Salvaged items now travel much slower towards the player
Books from salvage will now travel towards the player
Salvaged items travelling towards you will now have their speed adjusted based on distance
Common Materials found when mining have had their XP gains reduced and rare materials have had their XP gains increased
Diamond Ore has had its XP increased from 750 to 2400
Gold Ore has had its XP increased from 350 to 1300
Iron Ore has had its XP increased from 250 to 900
Lapis Ore has had its XP increased from 400 to 800
Nether Quartz Ore has had its XP increased from 100 to 300
Redstone Ore has had its XP increased from 150 to 600
Blue_Ice has had its default XP value reduced to 15
Packed_Ice has had its default XP value reduced to 15
Netherrack has had its default XP value reduced to 15
Coal Ore has had its XP increased from 100 to 400
Stone has had its XP decreased from 30 to 15
Granite has had its XP decreased from 30 to 15
Andesite has had its XP decreased from 30 to 15
Diorite has had its XP decreased from 30 to 15
End Stone has had its XP decreased from 30 to 15
Glow Stone has had its XP decreased from 30 to 15
End Bricks has had its XP decreased from 200 to 50
NOTES:
You can either apply the default XP changes manually to experience.yml or delete it to generate a new file
Sorry about salvaged items traveling too quickly, in testing on my LAN server with ideal conditions they always entered my inventory and never shot past me so the high speed of the items was not an apparent issue.
I've tested the new changes to how they travel towards you pretty thoroughly, they never go fast enough to go past you and they adjust their speed based on distance to you with some speed limitations.
In testing the new tweaks work well whether the salvage anvil is above, below, or at the same height as you.
I'll be tweaking XP values across all skills more carefully in the upcoming content patch due after 2.2. Some tweaks to XP gains will be applied for 2.2.
Version 2.1.89
Many changes were made to this version that affect default values in the config, read the notes carefully if you wish to apply these changes. They are optional.
mcMMO is compatible with the new 1.14.3, in addition to this it is still compatible with 1.14.2, 1.14.1, 1.14, and 1.13.2. This did not require any changes to be made to mcMMO, but I thought I'd add this to the notes for those wondering.
RetroMode is the default level scaling mode again
The default level for players has been changed back to 0 from 1 (you can change it back to 1 by editing 'Skills.General.StartingLevel' in advanced.yml) if you wish to apply this change read the notes
Super Abilities now scale in length up to level 100/1000 instead of 50/500 by default (you can edit this in advanced.yml under 'Skills.General.Ability.Length.xxx')
Early Game Boost now only applies when leveling from level 0 to level 1
Removed the config setting 'MaxLevelMultiplier' from experience.yml as it is no longer used.
When finding a treasure via Excavation players have a 1-8% chance to have a small amount vanilla experience orbs to be found alongside the treasure, the chance and number of orbs are based on the players Archaeology rank
Tweaked the locale string 'Excavation.SubSkill.Archaeology.Description'
Added locale string 'Excavation.SubSkill.Archaeology.Stat'
Added locale string 'Excavation.SubSkill.Archaeology.Stat.Extra'
Tweaked the locale string 'Fishing.SubSkill.MasterAngler.Stat'
The interval at which you can gain Acrobatics XP from fall damage has been reduced to 3 seconds from 10 seconds, this will be configurable in 2.2.
When using WorldGuard (WG) with mcMMO, mcMMO now examines WG more carefully to determine if it is a compatible version or not, see the notes. Keep in mind WG is optional and not needed to run mcMMO.
Fixed a bug that could result in Tree Feller failing to remove parts of a tree in snowy biomes. (This fix won't apply retroactively to old trees, see the notes)
Updated Japanese locale (thanks snake)
Tree Feller and other Super Abilities will damage tools with the Enchantment named 'Durability/Unbreaking' again, this does not apply to the NBT tag named Ubreakable (Unbreakable NBT tag is safe from damage however, try not to confuse them as they share similar names)
Added new setting 'ExploitFix.TreeFellerReducedXP' to experience.yml
Tree Feller will no longer give full XP for each block destroyed and instead give diminishing returns on XP for each block removed. You can turn this off by setting 'ExploitFix.TreeFellerReducedXP' in experience.yml to false
Many skills which used to unlock at level 5/50 now unlock at level 1 instead
Arrow Retrieval now unlocks at level 1 in both Standard and RetroMode
Skill Shot now unlocks at level 1 in both Standard and RetroMode
Dodge now unlocks at level 1 in both Standard and RetroMode
Critical Strikes now unlocks at level 1 in both Standard and RetroMode
Armor Impact now unlocks at level 1 in both Standard and RetroMode
Beast Lore now unlocks at level 1 in both Standard and RetroMode
Call Of The Wild now unlocks at level 1 in both Standard and RetroMode
Scrap Collector now unlocks at level 1 in both Standard and RetroMode
Treasure Hunter now unlocks at level 1 in both Standard and RetroMode
Rupture now unlocks at level 1 in both Standard and RetroMode
Iron Arm Style now unlocks at level 1 in both Standard and RetroMode
Harvest Lumber now unlocks at level 1 in both Standard and RetroMode
Archaeology now unlocks at level 1 in both Standard and RetroMode
Repair Mastery now unlocks at level 1 in both Standard and RetroMode
Double Drops (Herbalism and Mining) now have ranks and unlock at level 1 in both Standard and RetroMode
Concoctions rank 2 now unlocks at Level 1 for both Standard and RetroMode
Serrated Strikes now unlocks at levels 5/50 instead of 10/100
Berserk now unlocks at levels 5/50 instead of 10/100
NOTES:
I'm looking into adding 1.12.2 support sooner than expected.
Editing your config files is not required for this patch (and never will be), however I would highly recommend it. Read the notes below this line carefully.
If you want to update to this patch easily and you don't mind default config values, delete skillranks.yml, advanced.yml, and experience.yml before starting your server with 2.1.89 of mcMMO applied.
Many skills now unlock at level 1 and the default starting level is back to 0. It is recommended you change this number from 1 to 0 manually by editing 'Skills.General.StartingLevel' in advanced.yml or deleting advanced.yml and generating a new file when 2.1.89 starts.
It is recommended you make the manual edits to skillranks.yml to apply this change or delete skillranks.yml and a new one will be generated once you start 2.1.89.
Early Game Boost was used to help players get to level 5 quickly by boosting their XP until they got there, this caused some confusion as they appeared to be 'learning a skill' for multiple levels, on RetroMode this lasted until level 50.
I have changed Early Game Boost to only last from level 0-1 on both RetroMode and Standard, and now important skills are unlocked at level 1.
I was going to wait until 2.2 was done to deploy this change, but 2.2 is some time away and the previous system was causing some confusion.
Early Game Boost gives players extra XP for skills that are level 0, you can turn this system off by setting 'EarlyGameBoost.Enabled' in experience.yml to false
Early Game Boost will show 'Learning a new skill...' if XP bars are enabled
https://mcmmo.org/wiki/World_guard - A list of WG flags supported by mcMMO.
It is not necessary to have WG installed, but if you do have WG installed mcMMO hooks into it to provide some additional features.
Previously mcMMO used to determine if WG was compatible just by checking to see if it was version 7 of WG, however version 7 of WG is not guaranteed to be compatible as necessary classes that mcMMO hooks into were added during its development and some users are still running early dev versions of WG7.
In order to decrease the chance of error, mcMMO now uses reflection when checking to see if WG is compatible in addition to checking its version number, if its not compatible mcMMO will print a message and refrain from hooking into WG.
WG is an optional dependency for mcMMO, and unfortunately before this change if mcMMO thought you were running a compatible version of WG and it turned out you weren't then mcMMO would not function correctly.
Archaeology does something now, it will be tweaked again in the future. Previously rank 1 of Archaeology was required to find treasures but that was all it did, now each rank of Archaeology also adds a small chance to find experience orbs when a player finds treasure.
In a prior patch I removed damage on tools if they had Unbreakable NBT or Unbreaking Enchantment, at the time I made this change I did not realize they were different things and just shared the same name, this patch fixes this mistake. My intention was to prevent damage on tools with the NBT unbreakable tag which makes an item never suffer from durability loss.
mcMMO reduces damage to tools from super abilities if they have the "Durability/Unbreaking" enchantment already, this behaviour has been in mcMMO for a long time.
Tree Feller will now give reduced XP per block destroyed by Tree Feller and will never go below 1 XP per block, you can turn this off with 'ExploitFix.TreeFellerReducedXP' in experience.yml
There was a bug fixed in this patch that prevents an issue where Tree Feller was not removing all blocks left behind, unfortunately this will only affect new trees made in the world. The only trees that suffered from this bug were ones in snowy areas that had snow form on them.
RetroMode and Standard mode will be getting renamed in 2.2, probably to something like 1000-scale and 100-scale respectively.
Retro Mode was accidental genius is the short reason for the change to make it the default level scaling for mcMMO again.
Standard Mode is not going anywhere, it is just opt-in now instead of the default.
If you delete config.yml you will need to turn RetroMode off to use Standard mode as mcMMO doesn't keep track of what level scaling you are using outside of that.
Version 2.1.88
mcMMO is now more compatible with a plugin named Project Korra
mcMMO will no longer process combat triggers for damage at or below 0
Version 2.1.87
(Level caps are not on by default in mcMMO, this is something you can turn on)
Players who reach either the power level cap or skill level cap will now be informed that they have done so
XP Bars will no longer be sent to players who have reached the power level or skill level cap respectively
Level up messages will no longer be sent to players who have reached the power level or skill level cap respectively
Fixed a bug where mcMMO would send level up notifications to a player if the custom level up event from mcMMO was cancelled
New locale strings 'LevelCap.PowerLevel' & 'LevelCap.Skill'
Version 2.1.86
Players will no longer be told they got a perfect result when salvaging if they are below max skill level
Salvage results will now travel towards the player instead of moving in a random direction
(FIX) You cannot view stats of players who are offline if your server limits the range on inspect for you via permissions or settings
(FIX) Players will no longer be told they lack skill in salvage if they already qualify for the best possible result for the item
(FIX) Fixed a bug where arcane salvage was being used to calculate salvage results instead of scrap collector
(FIX) Added the missing locale color for 'Commands.Party.Commands'
Modified colors used in locale strings 'Salvage.Skills.Lottery.Normal', 'Salvage.Skills.Lottery.Perfect', and 'Profile.Loading.FailurePlayer'
When failing to load a profile mcMMO will increase the amount of time it waits before reattempting to load the profile for each failure
NOTES:
You can (and always have been able) to turn off the inspect range check by setting it to 0 in the config
2.2 is around the corner, most things are functional, still a lot of work left to do.
Version 2.1.85
Fixed a nearly 6 year old bug where Super Repair was not included as a child permission under Repair ability permission nodes (which meant some players would not have access to this skill)
Fixed a bug that could prevent salvage from working for certain players
Renamed the advanced salvage permission node to 'mcmmo.ability.salvage.scrapcollector'
Fixed a bug that would send players skill unlock notifications if they did not have the permission node for that skill
Dramatically increased the chance of receiving full materials when salvaging
Version 2.1.84
Added some code to make mcMMO more compatible with EpicSpawners
Version 2.1.83
You can no longer set party members on fire with your bow
(FIX) Arrow Retrieval will no longer work with piercing enchant on crossbows
WG Flags should now correctly recognize when a projectile belongs to a player and respect flag settings
Updated hu_HU locale (thanks andris155)
Version 2.1.82
Added new WG flag 'mcmmo-hardcore' if set to negative players will not be penalized by hardcore mode (if hardcore mode is enabled) it defaults to true
Added proper error handling when loading parties file
Fixed an error that could occur when using mcrank on an offline player
You can now use mcrank on offline players by default
You can now use inspect on offline players by default
Removed the offline inspect/mcrank permissions
Updated Chinese locale (thanks to the user named 89009332 from github)
Added some redundancy checks when loading profiles (NPC checks to be specific)
NOTES:
There were reasons to prevent inspecting offline players in the past, I don't see any reason for them anymore so I've removed the restriction.
Version 2.1.81
Fixed a bug where Arrow Deflect would never trigger outside of PVP
Fixed a bug where failing to salvage enchantments incorrectly colored the text
mcMMO no longer allows players to keep enchantments exceeding normal limitations by default when salvaging or repairing (you can turn this off in the config, see below)
Added new setting 'ExploitFix.UnsafeEnchantments' to experience.yml, turn this on to allow players to salvage/repair enchantments higher than normal game restrictions
NOTES:
If a player tries to salvage/repair an item with an illegal enchant (for example Sharpness X) it will downgrade that item to the highest legal version when calculating rewards
If you don't like this change you can turn it off in experience.yml under 'ExploitFix.UnsafeEnchantments'
Version 2.1.80
(Fix) mcMMO now respects the NBT "Unbreakable" tag and does not deal durability damage to items with that tag
Version 2.1.79
Updated Japanese locale (Thanks snake0053)
Fixed a NPE that could happen when using Tree Feller with an unenchanted Axe
Version 2.1.78
Shovels no longer take more than 1 diamond to repair
Tools with the unbreaking enchantment no longer take extra damage from ability usage, they are still subject to the normal durability damage from breaking blocks though.
Version 2.1.77
Added minimum quantity back to Repair config
NOTES: I removed this last patch because I did not consider that server admins might be allowing users to repair items without crafting recipes (as of last patch mcMMO determines minimum quantity via counting ingredients in a recipe)
If you do not define minimum quantity in the repair config, mcMMO will grab the minimum quantity automatically as I programmed it to do as of last patch, otherwise if it is defined, mcMMO will respect that and use that for calculations.
The minimum quanitty should be set to the number of ingredients used to craft the recipe, for example 8 for diamond chestplate etc, you do not need to define this unless you are allowing players to repair custom items.
Version 2.1.76
Advanced Salvage has been renamed to Scrap Collector
Scrap Collector has 8 ranks, the first rank is unlocked at level 2 (Level 20 in RetroMode)
You can not salvage without at least 1 rank in Scrap Collector now (formerly Advanced Salvage)
Fixed a bug where Repair was repairing too much
Fixed a bug where Arcane Salvage was used to determine how many materials a player could salvage from an item instead of Scrap Collector (formerly Advanced Salvage)
Fixed a bug where messages about an item being too damage to salvage were being sent twice
Removed the minimum quantity field from the repair config
Removed the item data (metadata) field from repair config as its not used anymore
Salvage will no longer return the max amount of materials possible, instead you are guaranteed one item and then some luck is involved on how many items are returned.
Updated Chinese locale (thanks to the user named 89009332 from github)
New locale strings
Salvage.Skills.Lottery.Normal
Salvage.Skills.Lottery.Perfect
Salvage.Skills.Lottery.Untrained
Salvage.SubSkill.ScrapCollector.Name
Salvage.SubSkill.ScrapCollector.Description
Salvage.SubSkill.ScrapCollector.Stat
(API) SALVAGE_ARCANE_SALVAGE in SubSkillType has been renamed to SALVAGE_SCRAP_COLLECTOR
NOTES:
You do not need to update your configs for this update.
How Salvage works
As an example, say you had enough skill to gain up to 5 items from salvaging something, and that item has enough durability to yield up to 5 materials, salvage will play out like this...
First off, you will be guaranteed 1 material, after this you have 80% chance to get the next material, if successful, another dice roll is conducted but lowers your odds by 20%, you chance to succeed will never fall below 33%
If you fail a dice roll, it will still conduct dice rolls for the remaining maximum amount of materials returned but your odds of success are only lowered upon a successful dice roll, the sum of the successful dice rolls is used to calculate how many items you are given back, the first item is guaranteed and has no dice rolls, which means for example the Diamond Shovel will always succeed.
Version 2.1.75
Fixed a bug that prevented Fortune from working correctly if a Double Drop was triggered
Version 2.1.74
Fixed a NPE that could occur during certain events if a skill was disabled in coreskills.yml (Sorry!)
Version 2.1.73
Fixed a NPE that could occur if an entire skill was disabled in coreskills.yml
Version 2.1.72
Fixed a NPE if a server shutdown with no player data needing to be saved (the error is harmless but spammy)
Fixed a NPE that could occur if Roll was disabled in coreskills.yml
Version 2.1.71
Salvage will now always ask for confirmation before breaking your items (instead of only asking for enchanted items)
Repair will now always ask for confirmation before repairing items (instead of only asking for enchanted items)
Gold & Iron Blocks will no longer trigger tool ready messages
Salvage & Repair anvils will no longer work on multi-item stacks
NOTES: You can still turn the confirmation off in config.yml
Version 2.1.70
Added new DatabaseAPI to the API package, has features relating to database operations
Fixed a bug where shulker boxes (without colors) would activate tool ready messages
Version 2.1.69
Fixed a few places where mcMMO would not save player data immediately which may cause players to lose a few minutes of progress
A big thanks to Sleepyflea for helping test this patch and report this bug.
Version 2.1.68
Updated Japanese locale (thanks Snake)
Fixed a bug where consuming food in the off hand did not trigger the Diet abilities
Version 2.1.67
The XP bar now reflects whether or not the player is receiving the early game boost
Players who are receiving an early game boost will be shown "Learning a skill..." as the title of the XP bar while gaining XP
New locale string 'XPBar.Template.EarlyGameBoost'
NOTES:
You can turn off this system in experience.yml 'EarlyGameBoost.Enabled'
The Early Game Boost is a system in which players receive drastically increased XP gains for the first few levels (until the first set of skills are unlocked)
With default settings, this means players will be receiving boosted XP for the first 5 levels (50 for Retro)
The Early Game Boost ends when players get the first skill in each ability under default settings
The main purpose of this system is to alleviate progression issues with a few skills where the first set of unlocked abilities drastically increase how fun it is to level the skill
The secondary purpose of this system is to alleviate any psychological issues when grinding towards the first set of unlocks by making the first set of unlocks happen quickly
This system has been in place for a few versions now, but without an in game indicator of what was going on.
If you have XP bars off there is still no indicator that this system is in place, I'll address that at some point.
Version 2.1.66
Fixed a bug that could happen if a player was removed from the DB when using MySQL/MariaDB when the user was offline
Fixed a minor memory leak for MySQL
Version 2.1.65
Corrected a bug that would cause RetroMode to use Linear formula regardless of setting
Version 2.1.64
Corrected how Standard mode (1-100 scaling) XP to next level was calculated, it is now a true 1:10 ratio with Retro (1-1000) scale, which is how it was intended to be to begin with
Fixed a bug that caused skill messages to spam nearby players
(API) method to get XP in FormulaManager has been renamed to getXPtoNextLevel(...), this shouldn't break anything as plugins should be using our Experience API methods instead of this
(API) Added method getLevel(Player player, PrimarySkillType primarySkillType) to ExperienceAPI.java
NOTE: The net result of this change is it will take a bit longer to level with Standard, but it should not be a drastic change. You might not even notice it.
Standard is meant to take the same amount of time to level from levels 1-100 as it takes Retro to do 1-1000, this change corrects from errors in the code that made Standard actually take less XP than Retro despite intending for it to be a cosmetic difference in progression.
I made a google sheet visualizing the difference between Standard and Retro Mode using default settings and Linear formula - https://docs.google.com/spreadsheets/d/1VlJtvNHlypACHyz_zulEdhgLwFjL01xMPkqlnu0XBSs/edit?usp=sharing
Version 2.1.63
Fixed Armor Impact not scaling by skill rank
Significantly Buffed the amount of durability damage incurred by a successful Armor Impact
Added new setting to advanced.yml 'Skills.Axes.ArmorImpact.DamagePerRank' which is multiplied against Armor Impact's skill level to determine damage done to armor
Fixed a bug that caused creative mode players to gain XP when qualifying for early game XP boosts
Removed the damage cap setting for Armor Impact, it is inherently capped now based on its max rank and damage setting
Updated hu_HU locale (thanks andris155)
Updated ja_JP locale (thanks snake)
NOTES:
Armor Impact only has a 25% chance to go off, and for it to only incur 20 durability damage seemed incredibly underwhelming, I've buffed it quite a bit.
You can change it back to its underwhelming self by setting DamagePerRank to 1.0
Based on feedback I may tweak the number again or other properties of this skill
Version 2.1.62
Added a new admin notification system, sensitive commands will print chat messages to "admins" (players with either Operator status or admin chat permission)
Added a setting to disable the new admin notifications to config.yml 'General.AdminNotifications' (this will be more configurable in 2.2)
OPs and players with the admin chat permission will now see details about XP rate event commands regardless of whether or not the XP rate event messages are enabled
Updated hu_HU locale (thanks andris155)
Added XP for mining Magma_Block (default 30 XP - Update your config, see notes)
Diamond tools & armor in the repair config now have a minimum level of 0 (Update your config, temporary hotfix, 2.2 addresses this issue, see notes)
Guardian default combat XP multiplier reduced from 3.0 to 1.0 (update config if you want this change)
New locale string - 'Server.ConsoleName' the name of the server console, this will be used in place of player names when sending admin notifications out if the command was used from console
New locale string - 'Notifications.Admin.Format.Others' style formatting + prefix for admin notifications used in the other new strings below
New locale string - 'Notifications.Admin.Format.Self' style formatting + prefix for admin command confirmations sent to the user who executed the command
New locale string - 'Notifications.Admin.XPRate.Start.Self' sent to the user who modifies the XP rate regardless of whether or not messages for the event are enabled
New locale string - 'Notifications.Admin.XPRate.Start.Others' details of who started an XP rate event are sent to players who have Operator status or admin chat permission when the command to start or modify XP of an event has been issued
New locale string - 'Notifications.Admin.XPRate.End.Self' sent to the user who ended the XP rate event regardless of whether or not messages for the event are enabled
New locale string - 'Notifications.Admin.XPRate.End.Others' details of who ended an XP rate event are sent to players who have Operator status or admin chat permission when the command to end the event has been issued
NOTES:
Admin notifications currently only reports use of the XP rate command, it will be expanded to support other commands in upcoming patches
Add an entry of 'Magma_Block: 30' under Mining in experience.yml section titled "Experience_Values" (or you can delete the file to generate a new one with default values, 2.2 is coming soon which will have brand new configs so you could just wait for that
2.2 is the config rewrite, in this rewrite Repair and Salvage configs have been partially rewritten, it is not intended for Diamond Repair to take until level 50 in Standard level scaling to be available, since it'd be redundant to fix this in 2.1.X when 2.2 fixes it and its about to come out, the minimum level has temporarily been changed to 0. You can either update your repair.vanilla.yml config manually or delete it to generate a new one.
Admin notifications are a step in the right direction for finding naughty admins in mcMMO, I will be changing which permission node is used for players to be considered an admin in the future as not everyone wants or uses admin chat.
I expect to add logging of admin commands which will be viewable in game via command, so you won't have to have access to the servers log files to view who has been executing what.
Version 2.1.61
Fixed the locale string formatting of 'Mining.SubSkill.DoubleDrops.Stat'
Updated the Japanese locale (thanks snake0053)
Added toggle to turn off event message broadcasts (XP rate) to config.yml - 'General.EventBroadcasts'
Added toggle to not inform players of events when they join (XP rate, etc) to config.yml 'General.EventInfoOnPlayerJoin'
Added anti-exploit protection for cobble/stone farms which can be automated, to turn this off you can toggle the new config options 'ExploitFix.LavaStoneAndCobbleFarming' in experience.yml
NOTE: The toggle for event message broadcasts is separate from the titles being shown, that's another config option (titles are the BIG TEXT in the middle of the screen)
NOTE: The new anti-stone/cobble automation will not prevent XP gains from obsidian, since Obsidian requires some effort to farm
Version 2.1.60
Fixed a NPE error if a LivingEntity's target was set to null
Fixed a bug where tamed mobs could kill themselves if their owner shot them once
Corrected a typo when naming entities summoned by COTW (Locale string - Taming.Summon.Name.Format)
Fixed a bug where tamed mobs could have hearts instead of their name in their own death messages
Fixed a bug where multi-block crops would fail to double/triple drop (Sugar Cane, Cactus, etc)
Optimized the bonus drop code to reduce overhead
Version 2.1.59
Raised the overfishing limit from 3 to 10
Improved the overfishing messages to be more clear about its mechanics
Overfishing locale keys renamed "Fishing.ScarcityTip" and "Fishing.LowResourcesTip"
NOTES: This and other exploit prevention measures are much more customizable in 2.2, which shouldn't be too far off.
Version 2.1.58
Fixed the wrong locale string being used for Mining Double Drops
Version 2.1.57
Fixed an incredibly rare dupe bug that only happened with VERY specific config options that was extremely difficult to pull off
Version 2.1.56
Very large update to the zh_CN Chinese language file (thanks Dream_m)
Version 2.1.55
Fixed a bug that could occur when adding UUIDs to old outdated DBs
Version 2.1.54
Fixed a bug where the Skill 'Understanding the Art' was preventing vanilla experience orbs from furnaces
Fixed 'Understanding the Art' not correctly boosting vanilla XP from furnaces
Version 2.1.53
Fixed a critical bug where players earned too much XP
Version 2.1.52
Updated Japanese locale (thanks snake0053)
Added a toggle for the early game XP boost to experience.yml 'EarlyGameBoost.Enabled'
Added a max level multiplier for determining early game boosts cutoff to experience.yml 'EarlyGameBoost.MaxLevelMultiplier'
Version 2.1.51
You can now customize a locale outside of the JAR! (Thanks mikroskeem)
Added a new locale reload command 'mmolocalereload' (Thanks mikroskeem)
Locales can now be overriden by placing a file with an appropriate name inside /plugins/mcMMO/locales/ (Thanks mikroskeem)
NOTES
You can find the up to date current en_US locale entries here: https://github.com/mcMMO-Dev/mcMMO/blob/master/src/main/resources/locale/locale_en_US.properties
You do NOT have to replace the whole locale, you can replace only the strings you want to!
Locales only support ASCII and UTF16 characters at the moment, so you'll need to run special characters through a UTF16 converter (google it) to get them to work, I'll be fixing this in the future!
The locale name must match the internal file you are overriding (ie: locale_en_US.properties)
Locale will first check for a users locale file, if it doesn't exist it will use internal resources (files inside the JAR)
If a locale is found, it will use locale entries from that file, if any entries are missing, it will use entries from en_US inside the JAR
The locale file names are structured like this 'locale_XX_XX.properties', replace XX with your country codes, if you are not overriding en_US you will have to change the targetted locale inside config.yml
Version 2.1.50
Fixed a bug where early game XP boost (level 1-5) didn't function in certain circumstances
Updated German locale (thanks OverCrave)
Added missing Herbalism XP values for: Bamboo, Cornflower, Lily of the valley, Wither rose (thanks Zed-I)
Added missing Mining XP values for: Stone Bricks, Cracked Stone Bricks, Mossy Stone Bricks, Chiseled Stone Bricks, Prismarine Bricks, Dark Prismarine, Sea Lantern (thanks Zed-I)
Added missing Combat XP multiplier for: Wandering Trader (thanks Zed-I)
Notes:
If you haven't upgraded mcMMO since version 2.1.47 or before you will not need to do these steps as the experience file will update once automatically.
You can either delete experience.yml to generate a new one or edit it manually
This is what the default experience.yml looks like
https://paste.gg/p/anonymous/946f62ce7dff4ab7a87cae70c0266313
Version 2.1.49
Added sweet berry bush to Herbalism XP (Update your experience.yml config or delete it to gen a new one)
Fixed a bug where falling blocks were not marked as unnatural in water
Fixed a bug where tool lower notifications were being called async when they are sync only
Fixed NPE when checking inventory location
Improved herbalism compatibility with anti-cheat (thanks LogGits)
NOTE: This is what the default herbalism XP table looks like
https://paste.gg/p/anonymous/1022088f20cf44298870930e9bc58e8a
Version 2.1.48
1.14 Support
Added Cats, Foxes, and Pandas to Taming XP rewards
Added Cats, Foxes, Pandas, Trader Llamas, Pillagers, and Ravagers to Combat XP rewards
"Experience" section of experience.yml has been renamed to "Experience_Values"
Dodge now gives 800 XP
Roll now gives 600 XP
Fall now gives 600 XP
The first 5/50 levels of skills now give large amounts of XP so players get key early skills much faster
Note: First 5 in Standard, first 50 in Retro
Dev Notes:
I will be making a write up soon explaining near future plans for mcMMO and what is going on with the config update, abstraction update, etc...
Currently this version of mcMMO will work on both 1.13 and 1.14, in the abstraction update I will expand compatible versions of mcMMO to include: 1.14 / 1.13.2 / 1.12.2 / 1.8.8 / Sponge 1.14
It is not necessary to update your configs if you are upgrading from 1.13 -> 1.14, however if you had custom XP values in your experience.yml you will want to update your config.
Acrobatics XP was buffed since many AFK counter-measures were put into place to prevent repetitive grinding.
Experience node in experience.yml was renamed to "automatically" update configs for the new stuff 1.14
There are 4 updates planned for mcMMO, including a patreon rewards update, a large content update, a config update, and backwards compatibility for 1.13/1.12/1.8.8 and support for Sponge
Version 2.1.47
Fix NPE when party leader is offline and players grab a party list
Version 2.1.46
Party member lists now show the whole party, including offline players again.
Party lists now have special markers for players who are in shared XP range
Party lists now have special markers for players who are offline
Party lists now have special markers for the party leader
Fixed an error where bleed was setting health outside minimum values
[See NOTE] Fixed a bug where Creepers and Zombies were not dropping the correct heads from Shake (thanks Zed-I)
[See NOTE] Fixed a bug where salvage was not returning the correct amount of materials for AXE items (thanks Zed-I)
[See NOTE] Added missing STRIPPED_WOOD entries to experience.yml for Woodcutting
[See NOTE] Added about 15-20 missing entries to experience.yml for coral to Herbalism
Fixed a bug where admin chat from console would fail to send (thanks OverCrave)
Reduced default XP values for DEAD_* coral plants from 30 -> 10
Updated hu_HU locale (thanks andris155)
NOTE: These bugfixes were related to default config values, to receive these changes you can either delete experience.yml, treasures.yml and salvage.vanilla.yml to generate new ones or make the necessary edits.
This is what the files should look like after being edited.
Experience Correct Default Config - https://paste.gg/p/anonymous/ff695df1417e4232957a3d176fd14ed4
Salvage Correct Default Config - https://paste.gg/p/anonymous/c4eb2f4e66ed444e872021051760f3be
Treasures Correct Default Config - https://paste.gg/p/anonymous/b0120210f8c149958ca0303c68c19ebd
Version 2.1.45
mcMMO will now check to see if the server version is incompatible and inform server admins on how to fix the problem.
Version 2.1.44
Fixed a NPE with Alchemy brewing
Version 2.1.43
Fixed a bug that would result in players being told they they failed to salvage enchantments when in reality they succeeded.
Version 2.1.42
Fixed McMMOPlayerNotFoundException being thrown instead of null
(API) UserManager.getPlayer() returns null again (oopsie)
Added new perk permission node `mcmmo.perks.bypass.salvageenchant` - guarantees full enchantment return for Salvage
Added alternative permission node `mcmmo.perks.bypass.repairenchant` - guarantees full enchantment return for Repair
Added new wildcard perk `mcmmo.perks.bypass.*` and `mcmmo.perks.bypass.all` (either of these will grant all new mcmmo.perks.bypass perk permissions)
NOTE: Sorry about that, when trying to improve Bungee Cord compatibility I made a big oopsie!
NOTE: Repair's new perk permission works in the exact same way as mcmmo.bypass.arcanebypass, bypass perk permissions will all eventually be moved to `mcmmo.perks.bypass`
NOTE: Expect perk permissions to all be moved to `mcmmo.perks.X` in the near future
Version 2.1.41
Fixed NullPointerException errors when trying to grab PlayerProfiles for players who have not loaded
Added new locale string Profile.PendingLoad
Added new locale string Commands.Database.CooldownMS
Fixed a display error preventing the remaining time on /mcrank from being shown if it was on cooldown
Version 2.1.40
(API) mcMMO will now return null in all cases for UserManager.getPlayerProfile() if they have not been loaded yet
(API) Roll stores exploit data in AcrobaticsManager now
Added new locale string "Profile.Loading.FailureNotice"
Added new locale string "Profile.Loading.FailurePlayer"
mcMMO no longer gives up forever if a player profile fails to load and the player is still online
mcMMO will attempt to save a profile up to 10 times now, previously it would only try one time.
Fixed an ArrayIndexOutOfBounds error with Party Chat
Player data for mcMMO is now loaded 3 seconds after a player connects in order to give any ongoing save tasks from other servers a small grace period to finish. This will mostly be useful to Bungee servers.
NOTES: I received reports from some users saying that saving and loading was failing could fail and not recover, I have implemented some fail safes to greatly reduce the the odds of that happening.
Version 2.1.39
Salvaging an item should now only play the item break sound (was playing the anvil sound simultaneously before)
Fixed bug where Tall_Grass was not giving full XP
Added Tall_Seagrass and Seagrass to experience.yml under Herbalism (update your configs)
NOTE: This is what your herbalism section in experience.yml should look like - https://paste.gg/p/anonymous/d5b03bd56e8442f2836f8a954d2974de
Version 2.1.38
Roll XP cooldown down from 60 seconds to 10
Updated pt_BR localization (thanks FabioZumbi12)
NOTE: The XP Cooldown will be configurable in 2.2 which is nearing the finish line
Version 2.1.37
Fixed a potential IndexOutOfBoundsException when informing a disconnected player that their Blast Mining was off CD
Updated hu_HU locale (thanks andris)
Version 2.1.36
Updated German locale (Thanks OverCrave)
Fixed a bug preventing Villagers from giving combat XP
The /mcnotify command will now squelch almost all chat messages or action bar notifications sent to the player from mcMMO
mcMMO will now remind players on an hourly basis that they are are not receiving notifications from mcMMO if they have run the mcnotify command and toggled squelch mode
Added a new setting to advanced.yml "Feedback.PlayerTips", when set to true this will allow mcMMO to send periodic helpful messages to players, currently this only affects mcnotify reminders.
Version 2.1.35
Readded the detonator config option
NOTE: I decided to make the detonator configurable again because 2.2 is some ways off. Sorry for the inconvenience.
NOTE: Pickaxes are now usable for blast mining, this is in addition to the detonator that you can specify in the config. This will be more configurable in the upcoming 2.2 update.
Version 2.1.34
Added Llama to taming XP tables
Added Parrot to taming XP tables
Pickaxes are now used to activate Blast Mining instead of Flint
The detonator for Blast Mining is no longer configurable
Fixed a bug where Blast Mining did not show cooldown length correctly
NOTE: You'll have to add these entries in yourself, this is what it should look like: https://paste.gg/p/anonymous/aadbcfde3eb3470fb13caebde4065a03
Alternatively you can delete the experience config file to generate a new one
Version 2.1.33
Renamed "Skills.Acrobatics.Prevent_AFK_Leveling" to "ExploitFix.Acrobatics"
ExploitFix.Acrobatics when set to false allows gaining XP in Acrobatics freely with no anti-grind measures
NOTE: The anti-grinding/exploit stuff is fully configurable in update 2.2 coming soon, this hotfix is to hold you over until that update comes out.
Version 2.1.32
Completely removed Fireworks from mcMMO because they lag
Added 'General.AprilFoolsEvent' setting to config.yml to turn off April Fools
NOTE: April Fools event has been in mcMMO for a long time, I did not write it so I didn't know it spawned fireworks like crazy.
Version 2.1.31
Fixed a bug where certain SubSkills did not properly send unlock or rank up notifications
Fixed a bug where unlock notifications would send simultaneously for a specific skill (still happens if mmoedit changes all skill levels on a player at once)
Fixed a bug where mmoedit triggered notifications for skills already gained
Fixed NPE with grabbing offline player skill ranks through certain API methods (thanks Ineusia)
Updated German language locale (thanks OverCrave)
Version 2.1.30
Fixed double drops behaving oddly
Double_Drop config table has been renamed to Bonus_Drops, this is to jankily auto-update everyones config
DoubleDrop config tables now must contain all things that can possibly be doubled, such as the Ore block, the ore itself, etc.
Added the following items to the Bonus_Drops tables for Mining: Coal, Diamond, Emerald, Glowstone_Dust, Iron_Ingot, Lapis_Lazuli, Nether_Quartz, Redstone, Cobblestone
Added the following items to the Bonus_Drops tables for Herbalism: Beetroot, Carrot, Cocoa_Beans, Melon_Slice, Potatoe
Added the following items to the Bonus_Drops tables for Woodcutting: Birch_Wood, Spruce_Wood, Jungle_Wood, Dark_Oak_Wood, Oak_Wood, Acacia_Wood
NOTE: You don't need to update your configs for this one unless you had custom entries in the Double_Drop tables, the renaming of the key will auto-insert default values and give everyone correct defaults
NOTE: I'm gonna have to blame Bukkit on this one, several API methods I used are actually unfinished and kind of janky. So I hacked something together to make them work.
Version 2.1.29
Fixed a bug where double drops and triple drops were not activating
Version 2.1.28
Fixed a bug where Archery could not gain XP
Version 2.1.27
Fixed an exploit that allowed players to duplicate torches, and rails
Version 2.1.26
Added new scaling damage buffs to all existing Combat Skills
Added a new subskill named Stab to Swords
Fixed a bug where Berserk was not adding 50% damage to attacks
Changed how Iron Arm damage is calculated (Rank 1 now effectively gives twice the damage bonus it used to, higher ranks have more damage)
NOTE: Combat skills will be completely configurable in the upcoming 2.2 update, be patient <3
New Permissions
- mcmmo.ability.unarmed.unarmedlimitbreak
- mcmmo.ability.axes.axeslimitbreak
- mcmmo.ability.archery.archerylimitbreak
- mcmmo.ability.swords.swordslimitbreak
- mcmmo.ability.swords.stab
Notes:
The new Limit Break subskills are intended to make Prot IV players less tanky and for you to feel more powerful for having high skill level.
Limit Break has 10 ranks, each rank gives 1 extra RAW damage, this is damage before reductions from armor and enchantments. The net result is you deal about 50% more damage with an end game skill compared to before.
With these new changes, most skills can 2 shot normal diamond armor, and it takes about 5 hits to kill someone in Prot IV Diamond Armor.
I'm not sure everyone will like these changes, the net result is players are a lot easier to kill now, whereas before you could take quite a beating before getting killed.
I collected several sets of data before making these changes, including damage to player with and without prot 4 diamond armor, damage to those players with and without enchanted weapons, damage with and without leveling your skills, and combinations of the previously mentioned things.
Version 2.1.25
Shake now has an upper limit of damage (10) - Will be configurable in 2.2 which is coming in the near future
Rank 1 of Catalysis & Concoctions are now available at level 0 by default (update skillranks.yml or delete it to regen a new one)
NOTE: The change to shake was to make mcMMO more compatible with plugins that spawn entities with large amounts of HP
Version 2.1.24
Fixed an exploit where you could clone inventories
Version 2.1.23
Fixed a bug with Double Drops for Mining (Update your configs instructions below)
Fixed a 7 year old bug where damage in mcMMO from SkillBs was potentially getting reduced by damage reduction TWICE
Fixed a bug where killing entities with Rupture would not properly credit you as the killer
Fixed a bug where Serrated Strikes was applying Rupture twice
Players will now be ejected from Minecarts if they cast their fishing rod (anti-afk)
Many nerfs to Rupture, its now much more reasonable and not very useful against Protection IV opponents
Rupture's strength is now related to your equipped Sword
Rupture will no longer be applied if the target is blocking, this doesn't prevent existing bleed damage from occurring though.
Wolf's Rupture has strength equivalent to a Stone Sword
Only Diamond swords will have bonus rupture damage at Rank 4
Rupture damage is cut in half for weapons below Diamond in quality, if the weapon is wooden, the damage is cut in half again.
Swords below Diamond quality will have their tick duration drastically reduced
Rupture damage is reduced by 25% on players if they are wearing Full Armor (can be any type)
Note: You'll need to add these entries to your config.yml manually, or wait for the upcoming config update where this will be fixed for you automatically.
NOTE: Here's what your Double_Drop entries in Config.yml for Mining should look like
https://paste.gg/p/anonymous/dcd06f1215844311b4f2225f200090d1
IMPORTANT: Version 2.1.22 which came before this had a similar fix for Herbalism, instructions on how to fix your Herbalism Double Drops can be found here
https://www.spigotmc.org/resources/official-mcmmo.64348/update?update=269868
NOTE: Due to the nature of these fixes, Fortune enchants now work with Double/Triple drops
Version 2.1.22
Less aggressive spam click protection on Fishing
Updated Hungarian file for missing entries related to Fishing messages (credit: andris155)
Added all missing flowers to Double Drop tables for Herbalism
Fixed bug where Repair Mastery was calculating player skill level incorrectly when determining bonuses
Fixed Double Drop entries for all farming crops for Herbalism
It no longer requires seeds to replant crops if you are harvesting crops with a hoe (will still consume seeds if you aren't)
NOTE: You'll need to add these entries to your config.yml manually, or wait for the upcoming config update where this will be fixed for you automatically.
NOTE: Here's what your Double_Drop entries in Config.yml for Herbalism should look like: https://paste.gg/p/anonymous/8d8db4ac69bd495fa48a7f5190484c5e
Version 2.1.21
Improved anti-farm/anti-grinding mechanics for Rolling
When you gain XP from Rolling there is a cooldown period (60~ seconds) for gaining XP again
This XP cooldown period extends if players are taking fall damage within the cooldown period
NOTE: Roll already has a few built in measures to prevent XP grinding / abuse, those are still the same.
NOTE: Rolls still happen in the cooldown period, you just won't gain XP.
Version 2.1.20
Added Hungarian localization (Locale code: hu_HU) (thanks andris155)
Players can now fish in the same spot about 3 times before mcMMO will mark the area as being over-fished (over-fishing is to prevent abuse)
Added a toggle to turn off the fishing exploit detection to experience.yml "ExploitFix.Fishing"
Note: The new config update is coming soon and will use a different setting, putting this out as a band-aid fix for people that don't like the new fishing exploit prevention stuff
Added a message to warn players that their next fishing attempt will result in over-fishing (Locale: Fishing.LowResources)
Version 2.1.19
Greatly Improved Fishing AFK/Exploit Detection
Fixed a bug where Fishing AFK detection did not work on a new exploit
Certain exploits for Fishing now result in players losing small amounts of hunger and durability
Players who get detected by Fishing's anti-exploit measures will no longer get vanilla rewards from Minecraft
**Note: Previously if mcMMO detected you abusing Fishing it just switched you over to vanilla Minecraft fishing rewards, this change is to help server admins who don't want players to get any kind of reward from AFK fishing
Fishing now drops several hints to players if they are triggering the exploit detection
**Note: Not all types of exploit detection will warn players, this is just to prevent legitimate fishers from being confused by the aggressive exploit detection.
Added messages to warn players about fishing in the same spot (Locale: Fishing.Scarcity)
Added messages to warn players who exploit in order to catch fish unusually fast (Locale: Fishing.Scared)
Added messages to warn players about casting the fishing rod too often (Locale: Fishing.Exhausting)
Version 2.1.18
You will need to add Kelp to your experience.yml file for this fix to be fully functional
Breaking Kelp will now properly count its XP
Added "Kelp" to experience.yml (Kelp is actually made up of two blocks mixed together)
It is recommended that Kelp and Kelp_Plant have the same XP value in experience.yml
mcMMO will now calculate XP for plants that are taller than naturally allowed (Cactus above 3 block height, etc)
Version 2.1.17
Fixed a logic error that resulted in Drowned giving no XP
Fixed a bug that resulted in mob spawner entities to not be marked for no xp after being transforming into Drowned
Version 2.1.16
Breaking Kelp should now count the whole plant for XP
Spawned Mobs that are not supposed to award XP will no longer reward XP once transformed (ie: drowned)
Version 2.1.15
Fixed a bug where a max rank of Fuel Efficiency would cause its benefits to be lost
Version 2.1.14
Added a config option to toggle double drops for Silk Touch pickaxes (advanced.yml "Skills.Mining.DoubleDrops.SilkTouch"
Mycelium removed from Woodcutting XP tables (because its soil!)
Kelp added to Herbalism XP tables
mcMMO now flags blocks moved by piston as not natural to prevent automated XP farms
Fixed a bug where Fuel Efficiency was way too good
Fixed a display issue with Fisherman's Diet
Fuel Efficiency now uses the rank system
Removed Fuel Efficiency config options in advanced.yml
Added Tropical Fish, Raw Cod, Raw Salmon to the list of foods that benefit from Fisherman's Diet
Version 2.1.13
Fixed a bug where Archery's Arrow Retrieval was using the wrong permission node
Version 2.1.12
Salvage config entries are no longer case sensitive
Fixed a bug where Fishing was not rewarding vanilla XP orbs

894
LICENSE
View File

@@ -1,346 +1,674 @@
TERMS AND CONDITIONS
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”.
“Licensees” and “recipients” may be individuals or organizations.
Preamble
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission,
other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work
“based on” the earlier work.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
A “covered work” means either the unmodified Program or a work based on the Program.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily
liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy.
Propagation includes copying, distribution (with or without modification), making available to the public, and in some
countries other activities as well.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction
with a user through a computer network, with no transfer of a copy, is not conveying.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and
prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no
warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this
License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any
non-source form of a work.
1. Source Code.
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or,
in the case of interfaces specified for a particular programming language, one that is widely used among developers
working in that language.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in
the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to
enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is
available to the public in source code form. A “Major Component”, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a
compiler used to produce the work, or an object code interpreter used to run it.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and
(for an executable work) run the object code and to modify the work, including scripts to control those activities.
However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs
which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding
Source includes interface definition files associated with source files for the work, and the source code for shared
libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data
communication or control flow between those subprograms and other parts of the work.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the
Corresponding Source.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source for a work in source code form is that same work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided
the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program.
The output from running a covered work is covered by this License only if the output, given its content, constitutes a
covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
The Corresponding Source for a work in source code form is that
same work.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license
otherwise remains in force. You may convey covered works to others for the sole purpose of having them make
modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do not control copyright. Those thus making or running
the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that
prohibit them from making any copies of your copyrighted material outside their relationship with you.
2. Basic Permissions.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not
allowed; section 10 makes it unnecessary.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling
obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or
restricting circumvention of such measures.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the
extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you
disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users,
your or third parties' legal rights to forbid circumvention of technological measures.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating
that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices
of the absence of any warranty; and give all recipients a copy of this License along with the Program.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for
a fee.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source
code under the terms of section 4, provided that you also meet all of these conditions:
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under
section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all
its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way,
but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has
interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of
the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or
distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the
access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other parts of the aggregate.
4. Conveying Verbatim Copies.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License, in one of these ways:
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied
by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied
by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for
that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all
the software in the product that is covered by this License, on a durable physical medium customarily used for software
interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2)
access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source.
This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an
offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent
access to the Corresponding Source in the same way through the same place at no further charge. You need not require
recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a
network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports
equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it
is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and
Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library,
need not be included in conveying the object code work.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used
for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In
determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a
particular product received by a particular user, “normally used” refers to a typical or common use of that class of
product, regardless of the status of the particular user or of the way in which the particular user actually uses, or
expects or is expected to use, the product. A product is a consumer product regardless of whether the product has
substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of
the product.
5. Conveying Modified Source Versions.
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information
required to install and execute modified versions of a covered work in that User Product from a modified version of its
Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code
is in no case prevented or interfered with solely because modification has been made.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the
conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to
the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding
Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not
apply if neither you nor any third party retains the ability to install modified object code on the User Product (for
example, the work has been installed in ROM).
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
The requirement to provide Installation Information does not include a requirement to continue to provide support
service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product
in which it has been modified or installed. Access to a network may be denied when the modification itself materially
and adversely affects the operation of the network or violates the rules and protocols for communication across the
network.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format
that is publicly documented (and with an implementation available to the public in source code form), and must require
no special password or key for unpacking, reading or copying.
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its
conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were
included in this License, to the extent that they are valid under applicable law. If additional permissions apply only
to part of the Program, that part may be used separately under those permissions, but the entire Program remains
governed by this License without regard to the additional permissions.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or
from any part of it. (Additional permissions may be written to require their own removal in certain cases when you
modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have
or can give appropriate copyright permission.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by
the copyright holders of that material) supplement the terms of this License with terms:
6. Conveying Non-Source Forms.
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the
Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be
marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified
versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual
assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the
Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with
a term that is a further restriction, you may remove that term. If a license document contains a further restriction but
permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of
that license document, provided that the further restriction does not survive such relicensing or conveying.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a
statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as
exceptions; the above requirements apply either way.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to
propagate or modify it is void, and will automatically terminate your rights under this License (including any patent
licenses granted under the third paragraph of section 11).
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated
(a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and
(b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days
after the cessation.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you
of the violation by some reasonable means, this is the first time you have received notice of violation of this License
(for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or
rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not
qualify to receive new licenses for the same material under section 10.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a
covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not
require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered
work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run,
modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third
parties with this License.
10. Automatic Licensing of Downstream Recipients.
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or
subdividing an organization, or merging organizations. If propagation of a covered work results from an entity
transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work
the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with
reasonable efforts.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For
example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License,
and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent
claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program
is based. The work thus licensed is called the contributor's “contributor version”.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already
acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or
selling its contributor version, but do not include claims that would be infringed only as a consequence of further
modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent
sublicenses in a manner consistent with the requirements of this License.
11. Patents.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential
patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its
contributor version.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to
enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To
“grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against
the party.
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not
available for anyone to copy, free of charge and under the terms of this License, through a publicly available network
server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available,
or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a
manner consistent with the requirements of this License, to extend the patent license to downstream recipients.
“Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in
a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in
that country that you have reason to believe are valid.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring
conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing
them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is
automatically extended to all recipients of the covered work and works based on it.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of,
or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You
may not convey a covered work if you are a party to an arrangement with a third party that is in the business of
distributing software, under which you make payment to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a
discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from
those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered
work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to
infringement that may otherwise be available to you under applicable patent law.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to
satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence
you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further
conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License
would be to refrain entirely from conveying the Program.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work
licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the
resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special
requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply
to the combination as such.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to
time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new
problems or concerns.
12. No Surrender of Others' Freedom.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the
GNU General Public License “or any later version” applies to it, you have the option of following the terms and
conditions either of that numbered version or of any later version published by the Free Software Foundation. If the
Program does not specify a version number of the GNU General Public License, you may choose any version ever published
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used,
that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the
Program.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed
on any author or copyright holder as a result of your choosing to follow a later version.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING
THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
15. Disclaimer of Warranty.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to
their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil
liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program
in return for a fee.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -1,41 +1,47 @@
# mcMMO
## The RPG lovers mod
## The #1 RPG Mod for Minecraft
[![Translation status](https://translate.mcmmo.org/widgets/mcmmo/-/svg-badge.svg)](https://translate.mcmmo.org/engage/mcmmo/?utm_source=widget)
## Website
I'm working on a brand new website for mcMMO
You can check it out here http://www.mcmmo.org
Spigot Resource: https://spigot.mcmmo.org
I plan to post links to our new wiki (its still under development), downloads, and dev blogs there.
### Builds
Currently, you can obtain our builds via the Spigot resource page: https://spigot.mcmmo.org
Currently, you can obtain our builds via the Spigot resource page: http://spigot.mcmmo.org
### Brief Description
The goal of mcMMO is to take core Minecraft game mechanics and expand them into add an extensive and quality RPG experience. Everything in mcMMO has been carefully thought out and is constantly being improved upon. Currently, mcMMO adds fourteen unique skills to train and level in. Each of these skills is highly customizable through our configuration files, allowing server admins to tweak mcMMO to best suit the needs of his or her server. Know that the mcMMO team is dedicated to providing an ever-evolving experience, and that we carefully read all feedback and bug reports in order to evaluate and balance the mechanics of mcMMO in every update.
The goal of mcMMO is to take core Minecraft game mechanics and expand them into an extensive and quality RPG experience. Everything in mcMMO has been carefully thought out and is constantly being improved upon. Currently, mcMMO adds fourteen unique skills to train and level in. Each of these skills is highly customizable through our configuration files, allowing server admins to tweak mcMMO to best suit the needs of his or her server. Know that the mcMMO team is dedicated to providing an ever-evolving experience, and that we carefully read all feedback and bug reports in order to evaluate and balance the mechanics of mcMMO in every update.
## About the Team
mcMMO is currently developed by a team of individuals from all over the world.
### Project Lead & Founder
In December 2018, the original author and creator of mcMMO (nossr50) returned and took over the role of project lead once again, to develop and improve mcMMO.
#### Project Lead & Founder
[![nossr50](http://www.gravatar.com/avatar/f2ee41eedfd645fb4a3a2c8f6cb1b18c.png)](https://github.com/nossr50)
### Former Lead
#### mcMMO Devs
[![nossr50](http://www.gravatar.com/avatar/f2ee41eedfd645fb4a3a2c8f6cb1b18c.png)](https://github.com/nossr50)
[![kashike](https://secure.gravatar.com/avatar/b5e86d6d443b957fd5cdee55501f3799.png)](https://github.com/kashike)
[![electronicboy](https://secure.gravatar.com/avatar/44759c38d311ce09596de6a2d5b88036.png)](https://github.com/electronicboy)
#### Classic Maintainer
[![t00thpick1](http://www.gravatar.com/avatar/ee23c7794a0c40120c3474287c7bce06.png)](https://github.com/t00thpick1)
## Former Team Members
### Former Lead & Awesome guy
[![gmcferrin](http://www.gravatar.com/avatar/b64c52daf25d206b27650788b5813b7b.png)](https://github.com/gmcferrin)
### Developers
### Former team members
[![bm01](http://www.gravatar.com/avatar/ec8146f5358177f12e9a252271bbc391.png)](https://github.com/bm01)
[![Glitchfinder](http://www.gravatar.com/avatar/5aa4cce22f72ae9c002ecec30f061d00.png)](https://github.com/Glitchfinder)
[![NuclearW](http://www.gravatar.com/avatar/90926bdcf1c8a75918df5ea5fa801ce6.png)](https://github.com/NuclearW)
[![shatteredbeam](http://www.gravatar.com/avatar/cad3b5d7d39cf5387afb87f494389610.png)](https://github.com/shatteredbeam)
[![TfT_02](http://www.gravatar.com/avatar/b8914f9970e1f6ffd5281ce4770e20a7.png)](https://github.com/TfT-02)
[![t00thpick1](http://www.gravatar.com/avatar/ee23c7794a0c40120c3474287c7bce06.png)](https://github.com/t00thpick1)
[![riking](https://1.gravatar.com/avatar/aca9f37e569ac3a63929920035a91ba4.png)](https://github.com/riking)
### Special thanks
[![EasyMFnE](https://www.gravatar.com/avatar/99c9a1fa3bbf957791ceac7b45daadb0.png)](https://github.com/EasyMFnE)
Added the Alchemy skill
[![TheYeti](https://i.imgur.com/tzFrxdo.png)](https://github.com/TheYeti)
## Compiling
@@ -44,7 +50,13 @@ mcMMO uses Maven 3 to manage dependencies, packaging, and shading of necessary c
The typical command used to build mcMMO is: `mvn clean package install`
Required Libraries:
* Bukkit
* Spigot
* JUnit
* WorldGuard 7
* bStats Bukkit
https://spigot.mcmmo.org for more up to date information.
Resource Page
https://www.spigotmc.org/resources/official-mcmmo-original-author-returns.64348/

View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.2.0-SNAPSHOT</version>
<version>2.1.118-SNAPSHOT</version>
<name>mcMMO</name>
<url>https://github.com/mcMMO-Dev/mcMMO</url>
<scm>
@@ -167,13 +167,13 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<version>1.15.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-core</artifactId>
<version>7.0.0-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>

View File

@@ -0,0 +1,30 @@
package com.gmail.nossr50.api;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.mcMMO;
import java.util.UUID;
public class DatabaseAPI {
/**
* Checks if a player exists in the mcMMO Database
* @param uuid player UUID
* @return true if the player exists in the DB, false if they do not
*/
public boolean doesPlayerExistInDB(String uuid) {
return doesPlayerExistInDB(UUID.fromString(uuid));
}
/**
* Checks if a player exists in the mcMMO Database
* @param uuid player UUID
* @return true if the player exists in the DB, false if they do not
*/
public boolean doesPlayerExistInDB(UUID uuid) {
PlayerProfile playerProfile = mcMMO.getDatabaseManager().loadPlayerProfile(uuid);
return playerProfile.isLoaded();
}
}

View File

@@ -649,11 +649,28 @@ public final class ExperienceAPI {
* @return the level of a given skill
*
* @throws InvalidSkillException if the given skill is not valid
* @deprecated Use getLevel(Player player, PrimarySkillType skillType) instead
*/
@Deprecated
public static int getLevel(Player player, String skillType) {
return getPlayer(player).getSkillLevel(getSkillType(skillType));
}
/**
* Get the level a player has in a specific skill.
* </br>
* This function is designed for API usage.
*
* @param player The player to get the level for
* @param skillType The skill to get the level for
* @return the level of a given skill
*
* @throws InvalidSkillException if the given skill is not valid
*/
public static int getLevel(Player player, PrimarySkillType skillType) {
return getPlayer(player).getSkillLevel(skillType);
}
/**
* Get the level an offline player has in a specific skill.
* </br>
@@ -783,7 +800,7 @@ public final class ExperienceAPI {
*/
@Deprecated
public static int getPlayerRankSkill(String playerName, String skillType) {
return mcMMO.getDatabaseManager().readRank(getOfflineProfile(playerName).getPlayerName()).get(getNonChildSkillType(skillType));
return mcMMO.getDatabaseManager().readRank(mcMMO.p.getServer().getOfflinePlayer(playerName).getName()).get(getNonChildSkillType(skillType));
}
/**
@@ -801,7 +818,7 @@ public final class ExperienceAPI {
* @return the position on the leaderboard
*/
public static int getPlayerRankSkill(UUID uuid, String skillType) {
return mcMMO.getDatabaseManager().readRank(getOfflineProfile(uuid).getPlayerName()).get(getNonChildSkillType(skillType));
return mcMMO.getDatabaseManager().readRank(mcMMO.p.getServer().getOfflinePlayer(uuid).getName()).get(getNonChildSkillType(skillType));
}
/**
@@ -817,7 +834,7 @@ public final class ExperienceAPI {
*/
@Deprecated
public static int getPlayerRankOverall(String playerName) {
return mcMMO.getDatabaseManager().readRank(getOfflineProfile(playerName).getPlayerName()).get(null);
return mcMMO.getDatabaseManager().readRank(mcMMO.p.getServer().getOfflinePlayer(playerName).getName()).get(null);
}
/**
@@ -832,7 +849,7 @@ public final class ExperienceAPI {
* @return the position on the power level leaderboard
*/
public static int getPlayerRankOverall(UUID uuid) {
return mcMMO.getDatabaseManager().readRank(getOfflineProfile(uuid).getPlayerName()).get(null);
return mcMMO.getDatabaseManager().readRank(mcMMO.p.getServer().getOfflinePlayer(uuid).getName()).get(null);
}
/**
@@ -995,7 +1012,7 @@ public final class ExperienceAPI {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level) {
return mcMMO.getFormulaManager().getCachedXpToLevel(level, ExperienceConfig.getInstance().getFormulaType());
return mcMMO.getFormulaManager().getXPtoNextLevel(level, ExperienceConfig.getInstance().getFormulaType());
}
/**
@@ -1009,7 +1026,7 @@ public final class ExperienceAPI {
* @throws InvalidFormulaTypeException if the given formulaType is not valid
*/
public static int getXpNeededToLevel(int level, String formulaType) {
return mcMMO.getFormulaManager().getCachedXpToLevel(level, getFormulaType(formulaType));
return mcMMO.getFormulaManager().getXPtoNextLevel(level, getFormulaType(formulaType));
}
/**
@@ -1085,7 +1102,7 @@ public final class ExperienceAPI {
PlayerProfile profile = getOfflineProfile(playerUniqueId);
profile.addXp(skill, XP);
profile.save();
profile.save(true);
}
@Deprecated
@@ -1158,6 +1175,13 @@ public final class ExperienceAPI {
return formulaType;
}
/**
* @deprecated Use UserManager::getPlayer(Player player) instead
* @param player target player
* @return McMMOPlayer for that player if the profile is loaded, otherwise null
* @throws McMMOPlayerNotFoundException
*/
@Deprecated
private static McMMOPlayer getPlayer(Player player) throws McMMOPlayerNotFoundException {
if (!UserManager.hasPlayerDataKey(player)) {
throw new McMMOPlayerNotFoundException(player);

View File

@@ -41,6 +41,9 @@ public final class PartyAPI {
* @return true if the player is in a party, false otherwise
*/
public static boolean inParty(Player player) {
if(UserManager.getPlayer(player) == null)
return false;
return UserManager.getPlayer(player).inParty();
}
@@ -79,6 +82,10 @@ public final class PartyAPI {
*/
@Deprecated
public static void addToParty(Player player, String partyName) {
//Check if player profile is loaded
if(UserManager.getPlayer(player) == null)
return;
Party party = PartyManager.getParty(partyName);
if (party == null) {
@@ -113,7 +120,12 @@ public final class PartyAPI {
* @param partyName The party to add the player to
* @param bypassLimit if true bypasses party size limits
*/
//TODO: bypasslimit not used?
public static void addToParty(Player player, String partyName, boolean bypassLimit) {
//Check if player profile is loaded
if(UserManager.getPlayer(player) == null)
return;
Party party = PartyManager.getParty(partyName);
if (party == null) {
@@ -131,6 +143,10 @@ public final class PartyAPI {
* @param player The player to remove
*/
public static void removeFromParty(Player player) {
//Check if player profile is loaded
if(UserManager.getPlayer(player) == null)
return;
PartyManager.removeFromParty(UserManager.getPlayer(player));
}

View File

@@ -6,6 +6,6 @@ public class McMMOPlayerNotFoundException extends RuntimeException {
private static final long serialVersionUID = 761917904993202836L;
public McMMOPlayerNotFoundException(Player player) {
super("McMMOPlayer object was not found for: " + player.getName() + " " + player.getUniqueId());
super("McMMOPlayer object was not found for [NOTE: This can mean the profile is not loaded yet!] : " + player.getName() + " " + player.getUniqueId());
}
}

View File

@@ -1,6 +1,7 @@
package com.gmail.nossr50.chat;
import com.gmail.nossr50.datatypes.party.Party;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.events.chat.McMMOChatEvent;
import com.gmail.nossr50.events.chat.McMMOPartyChatEvent;
import com.gmail.nossr50.locale.LocaleLoader;
@@ -46,12 +47,14 @@ public abstract class ChatManager {
McMMOPartyChatEvent partyChatEvent = (McMMOPartyChatEvent) event;
//Find the people with permissions
for(Player player : event.getPlugin().getServer().getOnlinePlayers())
for(McMMOPlayer mcMMOPlayer : UserManager.getPlayers())
{
Player player = mcMMOPlayer.getPlayer();
//Check for toggled players
if(UserManager.getPlayer(player).isPartyChatSpying())
if(mcMMOPlayer.isPartyChatSpying())
{
Party adminParty = UserManager.getPlayer(player).getParty();
Party adminParty = mcMMOPlayer.getParty();
//Only message admins not part of this party
if(adminParty != null)

View File

@@ -11,6 +11,7 @@ import org.bukkit.command.CommandSender;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class McImportCommand implements CommandExecutor {
int fileAmount;
@@ -129,7 +130,7 @@ public class McImportCommand implements CommandExecutor {
}
FileWriter out = null;
String type = modConfigType.name().toLowerCase();
String type = modConfigType.name().toLowerCase(Locale.ENGLISH);
for (String modName : materialNames.keySet()) {
File outputFile = new File(outputFilePath, modName + "." + type + ".yml");

View File

@@ -23,6 +23,7 @@ public class McmmoCommand implements CommandExecutor {
String description = LocaleLoader.getString("mcMMO.Description");
String[] mcSplit = description.split(",");
sender.sendMessage(mcSplit);
sender.sendMessage(LocaleLoader.getString("mcMMO.Description.FormerDevs"));
if (Config.getInstance().getDonateMessageEnabled()) {
sender.sendMessage(LocaleLoader.getString("MOTD.Donate"));

View File

@@ -2,6 +2,7 @@ package com.gmail.nossr50.commands;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.google.common.collect.ImmutableList;
import org.bukkit.command.Command;
@@ -14,10 +15,18 @@ import java.util.List;
public class McnotifyCommand implements TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
switch (args.length) {
case 0:
McMMOPlayer mcMMOPlayer = UserManager.getPlayer((Player) sender);
//Not Loaded yet
if(mcMMOPlayer == null)
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
sender.sendMessage(LocaleLoader.getString("Commands.Notifications." + (mcMMOPlayer.useChatNotifications() ? "Off" : "On")));
mcMMOPlayer.toggleChatNotifications();
return true;

View File

@@ -1,7 +1,9 @@
package com.gmail.nossr50.commands;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.notifications.SensitiveCommandType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Permissions;
@@ -44,8 +46,14 @@ public class XprateCommand implements TabExecutor {
10, 10*20, 20);
}
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop"));
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop.Subtitle"));
if(Config.getInstance().broadcastEventMessages())
{
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop"));
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Stop.Subtitle"));
}
//Admin notification
NotificationManager.processSensitiveCommandNotification(sender, SensitiveCommandType.XPRATE_END);
mcMMO.p.toggleXpEventEnabled();
}
@@ -83,20 +91,22 @@ public class XprateCommand implements TabExecutor {
ExperienceConfig.getInstance().setExperienceGainsGlobalMultiplier(newXpRate);
if (mcMMO.p.isXPEventEnabled()) {
if(AdvancedConfig.getInstance().useTitlesForXPEvent())
{
NotificationManager.broadcastTitle(mcMMO.p.getServer(),
LocaleLoader.getString("Commands.Event.Start"),
LocaleLoader.getString("Commands.Event.XP", newXpRate),
10, 10*20, 20);
}
if(AdvancedConfig.getInstance().useTitlesForXPEvent())
{
NotificationManager.broadcastTitle(mcMMO.p.getServer(),
LocaleLoader.getString("Commands.Event.Start"),
LocaleLoader.getString("Commands.Event.XP", newXpRate),
10, 10*20, 20);
}
if(Config.getInstance().broadcastEventMessages())
{
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.Start"));
mcMMO.p.getServer().broadcastMessage(LocaleLoader.getString("Commands.Event.XP", newXpRate));
}
else {
sender.sendMessage(LocaleLoader.getString("Commands.xprate.modified", newXpRate));
}
//Admin notification
NotificationManager.processSensitiveCommandNotification(sender, SensitiveCommandType.XPRATE_MODIFY, String.valueOf(newXpRate));
return true;

View File

@@ -0,0 +1,30 @@
package com.gmail.nossr50.commands.admin;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.Permissions;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
/**
* @author Mark Vainomaa
*/
public final class McmmoReloadLocaleCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 0:
if (!Permissions.reloadlocale(sender)) {
sender.sendMessage(command.getPermissionMessage());
return true;
}
LocaleLoader.reloadLocale();
sender.sendMessage(LocaleLoader.getString("Locale.Reloaded"));
return true;
default:
return false;
}
}
}

View File

@@ -0,0 +1,25 @@
package com.gmail.nossr50.commands.admin;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class PlayerDebugCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(sender instanceof Player) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer((Player) sender);
mcMMOPlayer.toggleDebugMode(); //Toggle debug mode
NotificationManager.sendPlayerInformationChatOnlyPrefixed(mcMMOPlayer.getPlayer(), "Commands.Mmodebug.Toggle", String.valueOf(mcMMOPlayer.isDebugMode()));
return true;
} else {
return false;
}
}
}

View File

@@ -55,14 +55,13 @@ public abstract class ChatCommand implements TabExecutor {
return true;
case 1:
if (!CommandUtils.hasPlayerDataKey(sender)) {
return true;
}
if (CommandUtils.shouldEnableToggle(args[0])) {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
if (!CommandUtils.hasPlayerDataKey(sender)) {
return true;
}
enableChatMode(UserManager.getPlayer(sender.getName()), sender);
return true;
@@ -72,6 +71,9 @@ public abstract class ChatCommand implements TabExecutor {
if (CommandUtils.noConsoleUsage(sender)) {
return true;
}
if (!CommandUtils.hasPlayerDataKey(sender)) {
return true;
}
disableChatMode(UserManager.getPlayer(sender.getName()), sender);
return true;

View File

@@ -22,6 +22,10 @@ public class PartyChatCommand extends ChatCommand {
String message;
if (sender instanceof Player) {
//Check if player profile is loaded
if(UserManager.getPlayer((Player) sender) == null)
return;
party = UserManager.getPlayer((Player) sender).getParty();
if (party == null) {

View File

@@ -5,6 +5,7 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.google.common.collect.ImmutableList;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@@ -12,6 +13,7 @@ import org.bukkit.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class McremoveCommand implements TabExecutor {
@Override
@@ -24,7 +26,13 @@ public class McremoveCommand implements TabExecutor {
return true;
}
if (mcMMO.getDatabaseManager().removeUser(playerName)) {
UUID uuid = null;
if(Bukkit.getPlayer(playerName) != null) {
uuid = Bukkit.getPlayer(playerName).getUniqueId();
}
if (mcMMO.getDatabaseManager().removeUser(playerName, uuid)) {
sender.sendMessage(LocaleLoader.getString("Commands.mcremove.Success", playerName));
}
else {

View File

@@ -30,7 +30,7 @@ public class AddlevelsCommand extends ExperienceCommand {
return;
}
EventUtils.handleLevelChangeEvent(player, skill, value, xpRemoved, true, XPGainReason.COMMAND);
EventUtils.tryLevelChangeEvent(player, skill, value, xpRemoved, true, XPGainReason.COMMAND);
}
@Override

View File

@@ -24,6 +24,10 @@ public class AddxpCommand extends ExperienceCommand {
@Override
protected void handleCommand(Player player, PlayerProfile profile, PrimarySkillType skill, int value) {
if (player != null) {
//Check if player profile is loaded
if(UserManager.getPlayer(player) == null)
return;
UserManager.getPlayer(player).applyXpGain(skill, value, XPGainReason.COMMAND, XPGainSource.COMMAND);
}
else {

View File

@@ -11,13 +11,15 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Locale;
public class ConvertExperienceCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
FormulaType previousType = mcMMO.getFormulaManager().getPreviousFormulaType();
FormulaType newType = FormulaType.getFormulaType(args[1].toUpperCase());
FormulaType newType = FormulaType.getFormulaType(args[1].toUpperCase(Locale.ENGLISH));
if (newType == FormulaType.UNKNOWN) {
sender.sendMessage(LocaleLoader.getString("Commands.mcconvert.Experience.Invalid"));

View File

@@ -51,6 +51,14 @@ public abstract class ExperienceCommand implements TabExecutor {
return true;
}
//Profile not loaded
if(UserManager.getPlayer(sender.getName()) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
editValues((Player) sender, UserManager.getPlayer(sender.getName()).getProfile(), skill, Integer.parseInt(args[1]));
return true;

View File

@@ -36,7 +36,7 @@ public class MmoeditCommand extends ExperienceCommand {
return;
}
EventUtils.handleLevelChangeEvent(player, skill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND);
EventUtils.tryLevelEditEvent(player, skill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND, skillLevel);
}
@Override

View File

@@ -126,7 +126,7 @@ public class SkillresetCommand implements TabExecutor {
return;
}
EventUtils.handleLevelChangeEvent(player, skill, levelsRemoved, xpRemoved, false, XPGainReason.COMMAND);
EventUtils.tryLevelChangeEvent(player, skill, levelsRemoved, xpRemoved, false, XPGainReason.COMMAND);
}
protected boolean permissionsCheckSelf(CommandSender sender) {

View File

@@ -15,8 +15,17 @@ public class PartyAcceptCommand implements CommandExecutor {
switch (args.length) {
case 1:
Player player = (Player) sender;
//Check if player profile is loaded
if(UserManager.getPlayer(player) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if (!mcMMOPlayer.hasPartyInvite()) {
sender.sendMessage(LocaleLoader.getString("mcMMO.NoInvites"));
return true;

View File

@@ -17,6 +17,13 @@ public class PartyChangeOwnerCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
//Check if player profile is loaded
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party playerParty = UserManager.getPlayer((Player) sender).getParty();
String targetName = CommandUtils.getMatchedPlayerName(args[1]);
OfflinePlayer target = mcMMO.p.getServer().getOfflinePlayer(targetName);

View File

@@ -11,6 +11,12 @@ import org.bukkit.entity.Player;
public class PartyChangePasswordCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party party = UserManager.getPlayer((Player) sender).getParty();
switch (args.length) {

View File

@@ -74,6 +74,12 @@ public class PartyCommand implements TabExecutor {
return true;
}
if(UserManager.getPlayer(player) == null)
{
player.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if (args.length < 1) {
@@ -197,6 +203,14 @@ public class PartyCommand implements TabExecutor {
if (matches.size() == 0) {
Player player = (Player) sender;
//Not Loaded
if(UserManager.getPlayer(player) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return ImmutableList.of();
}
Party party = UserManager.getPlayer(player).getParty();
playerNames = party.getOnlinePlayerNames(player);

View File

@@ -18,6 +18,12 @@ public class PartyCreateCommand implements CommandExecutor {
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if(UserManager.getPlayer(player) == null)
{
player.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
// Check to see if the party exists, and if it does cancel creating a new party
if (PartyManager.checkPartyExistence(player, args[1])) {
return true;

View File

@@ -15,6 +15,12 @@ public class PartyDisbandCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 1:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party playerParty = UserManager.getPlayer((Player) sender).getParty();
String partyName = playerParty.getName();

View File

@@ -23,6 +23,11 @@ public class PartyInfoCommand implements CommandExecutor {
switch (args.length) {
case 0:
case 1:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
Party party = mcMMOPlayer.getParty();

View File

@@ -25,6 +25,13 @@ public class PartyInviteCommand implements CommandExecutor {
}
Player target = mcMMOTarget.getPlayer();
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
String playerName = player.getName();

View File

@@ -14,9 +14,17 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Locale;
public class PartyItemShareCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party party = UserManager.getPlayer((Player) sender).getParty();
if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ITEM_SHARE)) {
@@ -26,7 +34,7 @@ public class PartyItemShareCommand implements CommandExecutor {
switch (args.length) {
case 2:
ShareMode mode = ShareMode.getShareMode(args[1].toUpperCase());
ShareMode mode = ShareMode.getShareMode(args[1].toUpperCase(Locale.ENGLISH));
if (mode == null) {
sender.sendMessage(LocaleLoader.getString("Commands.Usage.2", "party", "itemshare", "<NONE | EQUAL | RANDOM>"));
@@ -51,7 +59,7 @@ public class PartyItemShareCommand implements CommandExecutor {
}
try {
handleToggleItemShareCategory(party, ItemShareType.valueOf(args[1].toUpperCase()), toggle);
handleToggleItemShareCategory(party, ItemShareType.valueOf(args[1].toUpperCase(Locale.ENGLISH)), toggle);
}
catch (IllegalArgumentException ex) {
sender.sendMessage(LocaleLoader.getString("Commands.Usage.2", "party", "itemshare", "<loot | mining | herbalism | woodcutting | misc> <true | false>"));

View File

@@ -32,6 +32,13 @@ public class PartyJoinCommand implements CommandExecutor {
}
Player player = (Player) sender;
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
Party targetParty = mcMMOTarget.getParty();

View File

@@ -18,6 +18,12 @@ public class PartyKickCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party playerParty = UserManager.getPlayer((Player) sender).getParty();
String targetName = CommandUtils.getMatchedPlayerName(args[1]);

View File

@@ -54,6 +54,12 @@ public class PartyLockCommand implements CommandExecutor {
}
private void togglePartyLock(CommandSender sender, boolean lock) {
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return;
}
Party party = UserManager.getPlayer((Player) sender).getParty();
if (!Permissions.partySubcommand(sender, lock ? PartySubcommandType.LOCK : PartySubcommandType.UNLOCK)) {

View File

@@ -17,6 +17,13 @@ public class PartyQuitCommand implements CommandExecutor {
switch (args.length) {
case 1:
Player player = (Player) sender;
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
Party playerParty = mcMMOPlayer.getParty();

View File

@@ -16,6 +16,12 @@ public class PartyRenameCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer((Player) sender);
Party playerParty = mcMMOPlayer.getParty();

View File

@@ -16,6 +16,12 @@ import org.bukkit.entity.Player;
public class PartyXpShareCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Party party = UserManager.getPlayer((Player) sender).getParty();
if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.XP_SHARE)) {

View File

@@ -14,6 +14,11 @@ public class PartyAllianceAcceptCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);

View File

@@ -37,6 +37,12 @@ public class PartyAllianceCommand implements TabExecutor {
return true;
}
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);

View File

@@ -15,6 +15,11 @@ public class PartyAllianceDisbandCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
switch (args.length) {
case 2:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
Party party = mcMMOPlayer.getParty();

View File

@@ -24,6 +24,13 @@ public class PartyAllianceInviteCommand implements CommandExecutor {
}
Player target = mcMMOTarget.getPlayer();
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
String playerName = player.getName();

View File

@@ -20,6 +20,12 @@ public class PtpAcceptCommand implements CommandExecutor {
return true;
}
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
PartyTeleportRecord ptpRecord = UserManager.getPlayer(player).getPartyTeleportRecord();

View File

@@ -19,6 +19,7 @@ import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import com.google.common.collect.ImmutableList;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -59,6 +60,12 @@ public class PtpCommand implements TabExecutor {
return true;
}
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if (!mcMMOPlayer.inParty()) {
@@ -131,6 +138,12 @@ public class PtpCommand implements TabExecutor {
List<String> matches = StringUtil.copyPartialMatches(args[0], TELEPORT_SUBCOMMANDS, new ArrayList<String>(TELEPORT_SUBCOMMANDS.size()));
if (matches.size() == 0) {
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return ImmutableList.of();
}
Player player = (Player) sender;
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
@@ -156,6 +169,23 @@ public class PtpCommand implements TabExecutor {
McMMOPlayer mcMMOTarget = UserManager.getPlayer(targetName);
Player target = mcMMOTarget.getPlayer();
if (Config.getInstance().getPTPCommandWorldPermissions()) {
World targetWorld = target.getWorld();
World playerWorld = player.getWorld();
if (!Permissions.partyTeleportAllWorlds(player)) {
if (!Permissions.partyTeleportWorld(target, targetWorld)) {
player.sendMessage(LocaleLoader.getString("Commands.ptp.NoWorldPermissions", targetWorld.getName()));
return;
}
else if (targetWorld != playerWorld && !Permissions.partyTeleportWorld(player, targetWorld)) {
player.sendMessage(LocaleLoader.getString("Commands.ptp.NoWorldPermissions", targetWorld.getName()));
return;
}
}
}
PartyTeleportRecord ptpRecord = mcMMOTarget.getPartyTeleportRecord();
if (!ptpRecord.isConfirmRequired()) {
@@ -205,6 +235,18 @@ public class PtpCommand implements TabExecutor {
}
protected static void handleTeleportWarmup(Player teleportingPlayer, Player targetPlayer) {
if(UserManager.getPlayer(targetPlayer) == null)
{
targetPlayer.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return;
}
if(UserManager.getPlayer(teleportingPlayer) == null)
{
teleportingPlayer.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(teleportingPlayer);
McMMOPlayer mcMMOTarget = UserManager.getPlayer(targetPlayer);

View File

@@ -36,10 +36,6 @@ public class InspectCommand implements TabExecutor {
return true;
}
if (CommandUtils.inspectOffline(sender, profile, Permissions.inspectOffline(sender))) {
return true;
}
if (Config.getInstance().getScoreboardsEnabled() && sender instanceof Player && Config.getInstance().getInspectUseBoard()) {
ScoreboardManager.enablePlayerInspectScoreboard((Player) sender, profile);
@@ -70,10 +66,8 @@ public class InspectCommand implements TabExecutor {
Player target = mcMMOPlayer.getPlayer();
if (CommandUtils.hidden(sender, target, Permissions.inspectHidden(sender))) {
if (!Permissions.inspectOffline(sender)) {
sender.sendMessage(LocaleLoader.getString("Inspect.Offline"));
return true;
}
sender.sendMessage(LocaleLoader.getString("Inspect.Offline"));
return true;
}
else if (CommandUtils.tooFar(sender, target, Permissions.inspectFar(sender))) {
return true;

View File

@@ -38,6 +38,12 @@ public class MccooldownCommand implements TabExecutor {
}
}
if(UserManager.getPlayer(player) == null)
{
player.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
player.sendMessage(LocaleLoader.getString("Commands.Cooldowns.Header"));

View File

@@ -62,9 +62,6 @@ public class McrankCommand implements TabExecutor {
return true;
}
}
else if (CommandUtils.inspectOffline(sender, mcMMO.getDatabaseManager().loadPlayerProfile(playerName, false), Permissions.mcrankOffline(sender))) {
return true;
}
display(sender, playerName);
return true;
@@ -88,10 +85,17 @@ public class McrankCommand implements TabExecutor {
private void display(CommandSender sender, String playerName) {
if (sender instanceof Player) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(sender.getName());
long cooldownMillis = Math.max(Config.getInstance().getDatabasePlayerCooldown(), 1750);
if(mcMMOPlayer == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return;
}
long cooldownMillis = Math.min(Config.getInstance().getDatabasePlayerCooldown(), 1750);
if (mcMMOPlayer.getDatabaseATS() + cooldownMillis > System.currentTimeMillis()) {
sender.sendMessage(LocaleLoader.getString("Commands.Database.Cooldown"));
sender.sendMessage(LocaleLoader.getString("Commands.Database.CooldownMS", getCDSeconds(mcMMOPlayer, cooldownMillis)));
return;
}
@@ -110,4 +114,8 @@ public class McrankCommand implements TabExecutor {
new McrankCommandAsyncTask(playerName, sender, useBoard, useChat).runTaskAsynchronously(mcMMO.p);
}
private long getCDSeconds(McMMOPlayer mcMMOPlayer, long cooldownMillis) {
return ((mcMMOPlayer.getDatabaseATS() + cooldownMillis) - System.currentTimeMillis());
}
}

View File

@@ -26,6 +26,12 @@ public class McstatsCommand implements TabExecutor {
switch (args.length) {
case 0:
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
Player player = (Player) sender;
if (Config.getInstance().getStatsUseBoard() && Config.getInstance().getScoreboardsEnabled()) {

View File

@@ -30,6 +30,13 @@ public class AlchemyCommand extends SkillCommand {
}
protected String[] calculateAbilityDisplayValues(Player player) {
//TODO: Needed?
if(UserManager.getPlayer(player) == null)
{
player.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return new String[] {"DATA NOT LOADED", "DATA NOT LOADED"};
}
AlchemyManager alchemyManager = UserManager.getPlayer(player).getAlchemyManager();
String[] displayValues = new String[2];

View File

@@ -5,6 +5,7 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.archery.Archery;
import com.gmail.nossr50.util.TextComponentFactory;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
@@ -74,6 +75,11 @@ public class ArcheryCommand extends SkillCommand {
messages.add(getStatMessage(SubSkillType.ARCHERY_SKILL_SHOT, skillShotBonus));
}
if(canUseSubskill(player, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK)) {
messages.add(getStatMessage(SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK,
String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK, 1000))));
}
return messages;
}

View File

@@ -7,6 +7,7 @@ import com.gmail.nossr50.skills.axes.Axes;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory;
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.SkillActivationType;
import net.md_5.bungee.api.chat.TextComponent;
@@ -95,6 +96,11 @@ public class AxesCommand extends SkillCommand {
+ (hasEndurance ? LocaleLoader.getString("Perks.ActivationTime.Bonus", skullSplitterLengthEndurance) : ""));
}
if(canUseSubskill(player, SubSkillType.AXES_AXES_LIMIT_BREAK)) {
messages.add(getStatMessage(SubSkillType.AXES_AXES_LIMIT_BREAK,
String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, SubSkillType.AXES_AXES_LIMIT_BREAK, 1000))));
}
return messages;
}

View File

@@ -3,8 +3,10 @@ package com.gmail.nossr50.commands.skills;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.excavation.ExcavationManager;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
@@ -43,6 +45,8 @@ public class ExcavationCommand extends SkillCommand {
protected List<String> statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky) {
List<String> messages = new ArrayList<String>();
ExcavationManager excavationManager = UserManager.getPlayer(player).getExcavationManager();
if (canGigaDrill) {
messages.add(getStatMessage(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, gigaDrillBreakerLength)
+ (hasEndurance ? LocaleLoader.getString("Perks.ActivationTime.Bonus", gigaDrillBreakerLengthEndurance) : ""));
@@ -50,6 +54,14 @@ public class ExcavationCommand extends SkillCommand {
//messages.add(LocaleLoader.getString("Excavation.Effect.Length", gigaDrillBreakerLength) + (hasEndurance ? LocaleLoader.getString("Perks.ActivationTime.Bonus", gigaDrillBreakerLengthEndurance) : ""));
}
if(canUseSubskill(player, SubSkillType.EXCAVATION_ARCHAEOLOGY)) {
messages.add(getStatMessage(false, false, SubSkillType.EXCAVATION_ARCHAEOLOGY,
percent.format(excavationManager.getArchaelogyExperienceOrbChance() / 100.0D)));
messages.add(getStatMessage(true, false, SubSkillType.EXCAVATION_ARCHAEOLOGY,
String.valueOf(excavationManager.getExperienceOrbsReward())));
}
return messages;
}

View File

@@ -89,7 +89,7 @@ public class FishingCommand extends SkillCommand {
// FISHERMAN'S DIET
if (canFishermansDiet) {
fishermansDietRank = calculateRank(skillValue, Fishing.fishermansDietMaxLevel, Fishing.fishermansDietRankLevel1);
fishermansDietRank = RankUtils.getRank(player, SubSkillType.FISHING_FISHERMANS_DIET);
}
// MASTER ANGLER

View File

@@ -72,7 +72,7 @@ public class MiningCommand extends SkillCommand {
canBiggerBombs = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_BIGGER_BOMBS) && Permissions.biggerBombs(player);
canBlast = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_BLAST_MINING) && Permissions.remoteDetonation(player);
canDemoExpert = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_DEMOLITIONS_EXPERTISE) && Permissions.demolitionsExpertise(player);
canDoubleDrop = Permissions.isSubSkillEnabled(player, SubSkillType.MINING_DOUBLE_DROPS) && !skill.getDoubleDropsDisabled();
canDoubleDrop = canUseSubskill(player, SubSkillType.MINING_DOUBLE_DROPS);
canSuperBreaker = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_SUPER_BREAKER) && Permissions.superBreaker(player);
}
@@ -96,7 +96,7 @@ public class MiningCommand extends SkillCommand {
}
if (canDoubleDrop) {
messages.add(getStatMessage(SubSkillType.HERBALISM_DOUBLE_DROPS, doubleDropChance)
messages.add(getStatMessage(SubSkillType.MINING_DOUBLE_DROPS, doubleDropChance)
+ (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", doubleDropChanceLucky) : ""));
//messages.add(LocaleLoader.getString("Mining.Effect.DropChance", doubleDropChance) + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", doubleDropChanceLucky) : ""));
}

View File

@@ -86,7 +86,7 @@ public class RepairCommand extends SkillCommand {
canRepairString = Permissions.repairMaterialType(player, MaterialType.STRING);
canRepairLeather = Permissions.repairMaterialType(player, MaterialType.LEATHER);
canRepairWood = Permissions.repairMaterialType(player, MaterialType.WOOD);
arcaneBypass = Permissions.arcaneBypass(player);
arcaneBypass = (Permissions.arcaneBypass(player) || Permissions.hasRepairEnchantBypassPerk(player));
}
@Override

View File

@@ -15,7 +15,7 @@ import java.util.ArrayList;
import java.util.List;
public class SalvageCommand extends SkillCommand {
private boolean canAdvancedSalvage;
private boolean canScrapCollector;
private boolean canArcaneSalvage;
public SalvageCommand() {
@@ -30,7 +30,7 @@ public class SalvageCommand extends SkillCommand {
@Override
protected void permissionsCheck(Player player) {
canAdvancedSalvage = canUseSubskill(player, SubSkillType.SALVAGE_ADVANCED_SALVAGE);
canScrapCollector = canUseSubskill(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR);
canArcaneSalvage = canUseSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE);
}
@@ -39,9 +39,11 @@ public class SalvageCommand extends SkillCommand {
List<String> messages = new ArrayList<String>();
SalvageManager salvageManager = UserManager.getPlayer(player).getSalvageManager();
if (canAdvancedSalvage) {
messages.add(LocaleLoader.getString("Ability.Generic.Template", LocaleLoader.getString("Salvage.Ability.Bonus.0"),
LocaleLoader.getString("Salvage.Ability.Bonus.1", salvageManager.getSalvageableAmount())));
if (canScrapCollector) {
messages.add(getStatMessage(false, true,
SubSkillType.SALVAGE_SCRAP_COLLECTOR,
String.valueOf(RankUtils.getRank(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR)),
RankUtils.getHighestRankStr(SubSkillType.SALVAGE_SCRAP_COLLECTOR)));
}
if (canArcaneSalvage) {

View File

@@ -11,6 +11,7 @@ import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.TextComponentFactory;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
@@ -29,6 +30,7 @@ import org.bukkit.entity.Player;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public abstract class SkillCommand implements TabExecutor {
@@ -56,6 +58,12 @@ public abstract class SkillCommand implements TabExecutor {
return true;
}
if(UserManager.getPlayer((Player) sender) == null)
{
sender.sendMessage(LocaleLoader.getString("Profile.PendingLoad"));
return true;
}
switch (args.length) {
case 0:
Player player = (Player) sender;
@@ -127,7 +135,7 @@ public abstract class SkillCommand implements TabExecutor {
}
}
player.sendMessage(LocaleLoader.getString("Guides.Available", skillName, skillName.toLowerCase()));
player.sendMessage(LocaleLoader.getString("Guides.Available", skillName, skillName.toLowerCase(Locale.ENGLISH)));
}
private void sendSkillCommandHeader(Player player, McMMOPlayer mcMMOPlayer, int skillValue) {
@@ -262,19 +270,17 @@ public abstract class SkillCommand implements TabExecutor {
return LocaleLoader.getString(templateKey, LocaleLoader.getString(statDescriptionKey, vars));
else
{
String[] mergedList = addItemToFirstPositionOfArray(LocaleLoader.getString(statDescriptionKey), vars);
String[] mergedList = NotificationManager.addItemToFirstPositionOfArray(LocaleLoader.getString(statDescriptionKey), vars);
return LocaleLoader.getString(templateKey, mergedList);
}
}
public static String[] addItemToFirstPositionOfArray(String itemToAdd, String... existingArray) {
String[] newArray = new String[existingArray.length + 1];
newArray[0] = itemToAdd;
System.arraycopy(existingArray, 0, newArray, 1, existingArray.length);
return newArray;
protected String getLimitBreakDescriptionParameter() {
if(AdvancedConfig.getInstance().canApplyLimitBreakPVE()) {
return "(PVP/PVE)";
} else {
return "(PVP)";
}
}
protected abstract void dataCalculations(Player player, float skillValue);

View File

@@ -3,7 +3,6 @@ package com.gmail.nossr50.commands.skills;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.smelting.Smelting;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory;
import com.gmail.nossr50.util.player.UserManager;
@@ -35,7 +34,7 @@ public class SmeltingCommand extends SkillCommand {
protected void dataCalculations(Player player, float skillValue) {
// FUEL EFFICIENCY
if (canFuelEfficiency) {
burnTimeModifier = decimal.format(1 + ((skillValue / Smelting.burnModifierMaxLevel) * Smelting.burnTimeMultiplier));
burnTimeModifier = String.valueOf(UserManager.getPlayer(player).getSmeltingManager().getFuelEfficiencyMultiplier());
}
// FLUX MINING
@@ -57,7 +56,7 @@ public class SmeltingCommand extends SkillCommand {
protected void permissionsCheck(Player player) {
canFuelEfficiency = canUseSubskill(player, SubSkillType.SMELTING_FUEL_EFFICIENCY);
canSecondSmelt = canUseSubskill(player, SubSkillType.SMELTING_SECOND_SMELT);
canFluxMine = canUseSubskill(player, SubSkillType.SMELTING_FLUX_MINING);
//canFluxMine = canUseSubskill(player, SubSkillType.SMELTING_FLUX_MINING);
canUnderstandTheArt = Permissions.vanillaXpBoost(player, skill) && RankUtils.hasUnlockedSubskill(player, SubSkillType.SMELTING_UNDERSTANDING_THE_ART);
}

View File

@@ -7,6 +7,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory;
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.SkillActivationType;
import net.md_5.bungee.api.chat.TextComponent;
@@ -94,6 +95,17 @@ public class SwordsCommand extends SkillCommand {
+ (hasEndurance ? LocaleLoader.getString("Perks.ActivationTime.Bonus", serratedStrikesLengthEndurance) : ""));
}
if(canUseSubskill(player, SubSkillType.SWORDS_STAB))
{
messages.add(getStatMessage(SubSkillType.SWORDS_STAB,
String.valueOf(UserManager.getPlayer(player).getSwordsManager().getStabDamage())));
}
if(canUseSubskill(player, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK)) {
messages.add(getStatMessage(SubSkillType.SWORDS_SWORDS_LIMIT_BREAK,
String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK, 1000))));
}
return messages;
}

View File

@@ -6,6 +6,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.TextComponentFactory;
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.SkillActivationType;
import net.md_5.bungee.api.chat.TextComponent;
@@ -113,6 +114,11 @@ public class UnarmedCommand extends SkillCommand {
//messages.add(LocaleLoader.getString("Unarmed.Ability.Chance.IronGrip", ironGripChance) + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", ironGripChanceLucky) : ""));
}
if(canUseSubskill(player, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK)) {
messages.add(getStatMessage(SubSkillType.UNARMED_UNARMED_LIMIT_BREAK,
String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK, 1000))));
}
return messages;
}

View File

@@ -164,18 +164,10 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
reason.add("Skills.Axes.GreaterImpact.BonusDamage should be at least 1!");
}
if (getArmorImpactIncreaseLevel() < 1) {
reason.add("Skills.Axes.ArmorImpact.IncreaseLevel should be at least 1!");
}
if (getImpactChance() < 1) {
reason.add("Skills.Axes.ArmorImpact.Chance should be at least 1!");
}
if (getArmorImpactMaxDurabilityDamage() < 1) {
reason.add("Skills.Axes.ArmorImpact.MaxPercentageDurabilityDamage should be at least 1!");
}
if (getSkullSplitterModifier() < 1) {
reason.add("Skills.Axes.SkullSplitter.DamageModifier should be at least 1!");
}
@@ -438,10 +430,6 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
reason.add("Skills.Smelting.FuelEfficiency.MaxBonusLevel should be at least 1!");
}
if (getBurnTimeMultiplier() < 1) {
reason.add("Skills.Smelting.FuelEfficiency.Multiplier should be at least 1!");
}
if (getMaxBonusLevel(SubSkillType.SMELTING_SECOND_SMELT) < 1) {
reason.add("Skills.Smelting.SecondSmelt.MaxBonusLevel should be at least 1!");
}
@@ -648,8 +636,14 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
protected void loadKeys() {}
/* GENERAL */
public boolean canApplyLimitBreakPVE() { return config.getBoolean("Skills.General.LimitBreak.AllowPVE", false); }
public int getStartingLevel() { return config.getInt("Skills.General.StartingLevel", 1); }
public boolean allowPlayerTips() {
return config.getBoolean("Feedback.PlayerTips", true);
}
/**
* This returns the maximum level at which superabilities will stop lengthening from scaling alongside skill level.
* It returns a different value depending on whether or not the server is in retro mode
@@ -871,17 +865,8 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
public double getGreaterImpactModifier() { return config.getDouble("Skills.Axes.GreaterImpact.KnockbackModifier", 1.5D); }
public double getGreaterImpactBonusDamage() { return config.getDouble("Skills.Axes.GreaterImpact.BonusDamage", 2.0D); }
public int getArmorImpactIncreaseLevel() {
int increaseLevel = config.getInt("Skills.Axes.ArmorImpact.IncreaseLevel", 5);
if(mcMMO.isRetroModeEnabled())
return increaseLevel * 10;
return increaseLevel;
}
public double getImpactChance() { return config.getDouble("Skills.Axes.ArmorImpact.Chance", 25.0D); }
public double getArmorImpactMaxDurabilityDamage() { return config.getDouble("Skills.Axes.ArmorImpact.MaxPercentageDurabilityDamage", 20.0D); }
public double getImpactDurabilityDamageMultiplier() { return config.getDouble("Skills.Axes.ArmorImpact.DamagePerRank", 6.5D); }
public double getSkullSplitterModifier() { return config.getDouble("Skills.Axes.SkullSplitter.DamageModifier", 2.0D); }
@@ -907,6 +892,7 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
public int getGreenThumbStageChange() { return config.getInt("Skills.Herbalism.GreenThumb.StageChange", 200); }
/* MINING */
public boolean getDoubleDropSilkTouchEnabled() { return config.getBoolean("Skills.Mining.DoubleDrops.SilkTouch", true); }
public int getBlastMiningRankLevel(int rank) { return config.getInt("Skills.Mining.BlastMining.Rank_Levels.Rank_" + rank); }
public double getBlastDamageDecrease(int rank) { return config.getDouble("Skills.Mining.BlastMining.BlastDamageDecrease.Rank_" + rank); }
public double getOreBonus(int rank) { return config.getDouble("Skills.Mining.BlastMining.OreBonus.Rank_" + rank); }
@@ -939,8 +925,12 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
public double getArcaneSalvageExtractPartialEnchantsChance(int rank) { return config.getDouble("Skills.Salvage.ArcaneSalvage.ExtractPartialEnchant.Rank_" + rank); }
/* SMELTING */
public int getBurnModifierMaxLevel() { return config.getInt("Skills.Smelting.FuelEfficiency.MaxBonusLevel", 100); }
public double getBurnTimeMultiplier() { return config.getDouble("Skills.Smelting.FuelEfficiency.Multiplier", 3.0D); }
public int getBurnModifierMaxLevel() {
if(mcMMO.isRetroModeEnabled())
return config.getInt("Skills.Smelting.FuelEfficiency.RetroMode.MaxBonusLevel", 1000);
else
return config.getInt("Skills.Smelting.FuelEfficiency.Standard.MaxBonusLevel", 100);
}
/*public int getFluxMiningUnlockLevel() { return config.getInt("Skills.Smelting.FluxMining.UnlockLevel", 250); }*/
public double getFluxMiningChance() { return config.getDouble("Skills.Smelting.FluxMining.Chance", 33.0D); }

View File

@@ -9,10 +9,10 @@ import com.gmail.nossr50.util.StringUtils;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public class Config extends AutoUpdateConfigLoader {
@@ -186,10 +186,6 @@ public class Config extends AutoUpdateConfigLoader {
reason.add("Abilities.Fishing.Lure_Modifier should be at least 0!");
}
if (getDetonatorItem() == null) {
reason.add("Skills.Mining.Detonator_Item is invalid!");
}
if (getRepairAnvilMaterial() == null) {
reason.add("Skills.Repair.Anvil_Type is invalid!!");
}
@@ -202,41 +198,41 @@ public class Config extends AutoUpdateConfigLoader {
reason.add("Cannot use the same item for Repair and Salvage anvils!");
}
if (getTamingCOTWMaterial(EntityType.WOLF) == null) {
reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Material is invalid!!");
}
if (getTamingCOTWMaterial(EntityType.OCELOT) == null) {
reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Material is invalid!!");
}
if (getTamingCOTWMaterial(EntityType.HORSE) == null) {
reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Material is invalid!!");
}
if (getTamingCOTWCost(EntityType.WOLF) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Amount should be greater than 0!");
}
if (getTamingCOTWCost(EntityType.OCELOT) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Amount should be greater than 0!");
}
if (getTamingCOTWCost(EntityType.HORSE) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Amount should be greater than 0!");
}
if (getTamingCOTWAmount(EntityType.WOLF) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Summon_Amount should be greater than 0!");
}
if (getTamingCOTWAmount(EntityType.OCELOT) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Summon_Amount should be greater than 0!");
}
if (getTamingCOTWAmount(EntityType.HORSE) <= 0) {
reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Summon_Amount should be greater than 0!");
}
// if (getTamingCOTWMaterial(EntityType.WOLF) == null) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Material is invalid!!");
// }
//
// if (getTamingCOTWMaterial(EntityType.OCELOT) == null) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Material is invalid!!");
// }
//
// if (getTamingCOTWMaterial(EntityType.HORSE) == null) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Material is invalid!!");
// }
//
// if (getTamingCOTWCost(EntityType.WOLF) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Amount should be greater than 0!");
// }
//
// if (getTamingCOTWCost(EntityType.OCELOT) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Amount should be greater than 0!");
// }
//
// if (getTamingCOTWCost(EntityType.HORSE) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Amount should be greater than 0!");
// }
//
// if (getTamingCOTWAmount(EntityType.WOLF) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Summon_Amount should be greater than 0!");
// }
//
// if (getTamingCOTWAmount(EntityType.OCELOT) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Summon_Amount should be greater than 0!");
// }
//
// if (getTamingCOTWAmount(EntityType.HORSE) <= 0) {
// reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Summon_Amount should be greater than 0!");
// }
return noErrorsInConfig(reason);
}
@@ -245,6 +241,8 @@ public class Config extends AutoUpdateConfigLoader {
* GENERAL SETTINGS
*/
public boolean isAprilFoolsAllowed() { return config.getBoolean("General.AprilFoolsEvent", true); }
/* General Settings */
public boolean getIsMetricsEnabled() { return config.getBoolean("Metrics.bstats", true); }
@@ -280,7 +278,7 @@ public class Config extends AutoUpdateConfigLoader {
/* Mob Healthbar */
public MobHealthbarType getMobHealthbarDefault() {
try {
return MobHealthbarType.valueOf(config.getString("Mob_Healthbar.Display_Type", "HEARTS").toUpperCase().trim());
return MobHealthbarType.valueOf(config.getString("Mob_Healthbar.Display_Type", "HEARTS").toUpperCase(Locale.ENGLISH).trim());
}
catch (IllegalArgumentException ex) {
return MobHealthbarType.HEARTS;
@@ -344,6 +342,7 @@ public class Config extends AutoUpdateConfigLoader {
public int getMySQLMaxConnections(PoolIdentifier identifier) { return config.getInt("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()), 30); }
public int getMySQLMaxPoolSize(PoolIdentifier identifier) { return config.getInt("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()), 10); }
public boolean getMySQLSSL() { return config.getBoolean("MySQL.Server.SSL", true); }
public boolean getMySQLDebug() { return config.getBoolean("MySQL.Debug", false); }
private String getStringIncludingInts(String key) {
String str = config.getString(key);
@@ -405,7 +404,7 @@ public class Config extends AutoUpdateConfigLoader {
public boolean getCallOfTheWildEffectEnabled() { return config.getBoolean("Particles.Call_of_the_Wild", true); }
public boolean getLevelUpEffectsEnabled() { return config.getBoolean("Particles.LevelUp_Enabled", true); }
public int getLevelUpEffectsTier() { return config.getInt("Particles.LevelUp_Tier", 100); }
public boolean getLargeFireworks() { return config.getBoolean("Particles.LargeFireworks", true); }
// public boolean getLargeFireworks() { return config.getBoolean("Particles.LargeFireworks", true); }
/* PARTY SETTINGS */
public boolean getPartyFriendlyFire() { return config.getBoolean("Party.FriendlyFire", false);}
@@ -463,18 +462,18 @@ public class Config extends AutoUpdateConfigLoader {
/*
* SKILL SETTINGS
*/
public boolean getDoubleDropsEnabled(PrimarySkillType skill, Material material) { return config.getBoolean("Double_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_")); }
public boolean getDoubleDropsEnabled(PrimarySkillType skill, Material material) { return config.getBoolean("Bonus_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_")); }
public boolean getDoubleDropsDisabled(PrimarySkillType skill) {
String skillName = StringUtils.getCapitalized(skill.toString());
ConfigurationSection section = config.getConfigurationSection("Double_Drops." + skillName);
ConfigurationSection section = config.getConfigurationSection("Bonus_Drops." + skillName);
if (section == null)
return false;
Set<String> keys = section.getKeys(false);
boolean disabled = true;
for (String key : keys) {
if (config.getBoolean("Double_Drops." + skillName + "." + key)) {
if (config.getBoolean("Bonus_Drops." + skillName + "." + key)) {
disabled = false;
break;
}
@@ -503,7 +502,6 @@ public class Config extends AutoUpdateConfigLoader {
/* Mining */
public Material getDetonatorItem() { return Material.matchMaterial(config.getString("Skills.Mining.Detonator_Name", "FLINT_AND_STEEL")); }
public int getMiningGate() { return config.getInt("Skills.Mining.Ability_Activation_Level_Gate", 10); }
/* Excavation */
public int getExcavationGate() { return config.getInt("Skills.Excavation.Ability_Activation_Level_Gate", 10); }
@@ -532,21 +530,24 @@ public class Config extends AutoUpdateConfigLoader {
public int getSwordsGate() { return config.getInt("Skills.Swords.Ability_Activation_Level_Gate", 10); }
/* Taming */
public Material getTamingCOTWMaterial(EntityType type) { return Material.matchMaterial(config.getString("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Material")); }
public int getTamingCOTWCost(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Amount"); }
public int getTamingCOTWAmount(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Amount"); }
public int getTamingCOTWLength(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type)+ ".Summon_Length"); }
public int getTamingCOTWMaxAmount(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type)+ ".Summon_Max_Amount"); }
public double getTamingCOTWRange() { return config.getDouble("Skills.Taming.Call_Of_The_Wild.Range", 40.0D); }
// public Material getTamingCOTWMaterial(EntityType type) { return Material.matchMaterial(config.getString("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Material")); }
// public int getTamingCOTWCost(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Amount"); }
// public int getTamingCOTWAmount(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Amount"); }
// public int getTamingCOTWLength(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type)+ ".Summon_Length"); }
// public int getTamingCOTWMaxAmount(EntityType type) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type)+ ".Summon_Max_Amount"); }
public Material getTamingCOTWMaterial(String cotwEntity) { return Material.matchMaterial(config.getString("Skills.Taming.Call_Of_The_Wild." + cotwEntity + ".Item_Material")); }
public int getTamingCOTWCost(String cotwEntity) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + cotwEntity + ".Item_Amount"); }
public int getTamingCOTWAmount(String cotwEntity) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + cotwEntity + ".Summon_Amount"); }
public int getTamingCOTWLength(String cotwEntity) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + cotwEntity+ ".Summon_Length"); }
public int getTamingCOTWMaxAmount(String cotwEntity) { return config.getInt("Skills.Taming.Call_Of_The_Wild." + cotwEntity+ ".Per_Player_Limit", 1); }
/* Woodcutting */
public boolean getWoodcuttingDoubleDropsEnabled(BlockData material) { return config.getBoolean("Double_Drops.Woodcutting." + StringUtils.getFriendlyConfigBlockDataString(material)); }
public boolean getWoodcuttingDoubleDropsEnabled(BlockData material) { return config.getBoolean("Bonus_Drops.Woodcutting." + StringUtils.getFriendlyConfigBlockDataString(material)); }
public boolean getTreeFellerSoundsEnabled() { return config.getBoolean("Skills.Woodcutting.Tree_Feller_Sounds", true); }
public int getWoodcuttingGate() { return config.getInt("Skills.Woodcutting.Ability_Activation_Level_Gate", 10); }
/* AFK Leveling */
public boolean getAcrobaticsPreventAFK() { return config.getBoolean("Skills.Acrobatics.Prevent_AFK_Leveling", true); }
public int getAcrobaticsAFKMaxTries() { return config.getInt("Skills.Acrobatics.Max_Tries_At_Same_Location", 3); }
public boolean getHerbalismPreventAFK() { return config.getBoolean("Skills.Herbalism.Prevent_AFK_Leveling", true); }
/* Level Caps */
@@ -572,4 +573,9 @@ public class Config extends AutoUpdateConfigLoader {
public boolean getPVEEnabled(PrimarySkillType skill) { return config.getBoolean("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVE", true); }
//public float getMasterVolume() { return (float) config.getDouble("Sounds.MasterVolume", 1.0); }
public boolean broadcastEventMessages() { return config.getBoolean("General.EventBroadcasts", true);}
public boolean playerJoinEventInfo() { return config.getBoolean("General.EventInfoOnPlayerJoin", true);}
public boolean adminNotifications() { return config.getBoolean("General.AdminNotifications", true);}
}

View File

@@ -87,18 +87,18 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* Alchemy */
for (PotionStage potionStage : PotionStage.values()) {
if (getPotionXP(potionStage) < 0) {
reason.add("Experience.Alchemy.Potion_Stage_" + potionStage.toNumerical() + " should be at least 0!");
reason.add("Experience_Values.Alchemy.Potion_Stage_" + potionStage.toNumerical() + " should be at least 0!");
}
}
/* Archery */
if (getArcheryDistanceMultiplier() < 0) {
reason.add("Experience.Archery.Distance_Multiplier should be at least 0!");
reason.add("Experience_Values.Archery.Distance_Multiplier should be at least 0!");
}
/* Combat XP Multipliers */
if (getAnimalsXP() < 0) {
reason.add("Experience.Combat.Multiplier.Animals should be at least 0!");
reason.add("Experience_Values.Combat.Multiplier.Animals should be at least 0!");
}
if (getDodgeXPModifier() < 0) {
@@ -117,32 +117,43 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
// TODO: Add validation for each fish type once enum is available.
if (getFishingShakeXP() <= 0) {
reason.add("Experience.Fishing.Shake should be greater than 0!");
reason.add("Experience_Values.Fishing.Shake should be greater than 0!");
}
/* Repair */
if (getRepairXPBase() <= 0) {
reason.add("Experience.Repair.Base should be greater than 0!");
reason.add("Experience_Values.Repair.Base should be greater than 0!");
}
/* Taming */
if (getTamingXP(EntityType.WOLF) <= 0) {
reason.add("Experience.Taming.Animal_Taming.Wolf should be greater than 0!");
reason.add("Experience_Values.Taming.Animal_Taming.Wolf should be greater than 0!");
}
if (getTamingXP(EntityType.OCELOT) <= 0) {
reason.add("Experience.Taming.Animal_Taming.Ocelot should be greater than 0!");
reason.add("Experience_Values.Taming.Animal_Taming.Ocelot should be greater than 0!");
}
return noErrorsInConfig(reason);
}
public boolean isEarlyGameBoostEnabled() { return config.getBoolean("EarlyGameBoost.Enabled", true); }
/*
* FORMULA SETTINGS
*/
/* EXPLOIT TOGGLES */
public boolean isSnowExploitPrevented() { return config.getBoolean("ExploitFix.SnowGolemExcavation", true); }
public boolean isEndermanEndermiteFarmingPrevented() { return config.getBoolean("ExploitFix.EndermanEndermiteFarms", true); }
public boolean isPistonCheatingPrevented() { return config.getBoolean("ExploitFix.PistonCheating", true); }
public boolean isPistonExploitPrevented() { return config.getBoolean("ExploitFix.Pistons", false); }
public boolean allowUnsafeEnchantments() { return config.getBoolean("ExploitFix.UnsafeEnchantments", false); }
public boolean isCOTWBreedingPrevented() { return config.getBoolean("ExploitFix.COTWBreeding", true); }
public boolean isFishingExploitingPrevented() { return config.getBoolean("ExploitFix.Fishing", true); }
public boolean isAcrobaticsExploitingPrevented() { return config.getBoolean("ExploitFix.Acrobatics", true); }
public boolean isTreeFellerXPReduced() { return config.getBoolean("ExploitFix.TreeFellerReducedXP", true); }
/* Curve settings */
public FormulaType getFormulaType() { return FormulaType.getFormulaType(config.getString("Experience_Formula.Curve")); }
@@ -184,18 +195,18 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
*/
/* General Settings */
public boolean getExperienceGainsPlayerVersusPlayerEnabled() { return config.getBoolean("Experience.PVP.Rewards", true); }
public boolean getExperienceGainsPlayerVersusPlayerEnabled() { return config.getBoolean("Experience_Values.PVP.Rewards", true); }
/* Combat XP Multipliers */
public double getCombatXP(EntityType entity) { return config.getDouble("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); }
public double getAnimalsXP(EntityType entity) { return config.getDouble("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP()); }
public double getAnimalsXP() { return config.getDouble("Experience.Combat.Multiplier.Animals", 1.0); }
public boolean hasCombatXP(EntityType entity) {return config.contains("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); }
public double getCombatXP(EntityType entity) { return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); }
public double getAnimalsXP(EntityType entity) { return config.getDouble("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP()); }
public double getAnimalsXP() { return config.getDouble("Experience_Values.Combat.Multiplier.Animals", 1.0); }
public boolean hasCombatXP(EntityType entity) {return config.contains("Experience_Values.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); }
/* Materials */
public int getXp(PrimarySkillType skill, Material data)
{
String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + ".";
String explicitString = baseString + StringUtils.getExplicitConfigMaterialString(data);
if (config.contains(explicitString))
return config.getInt(explicitString);
@@ -211,7 +222,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* Materials */
public int getXp(PrimarySkillType skill, BlockData data)
{
String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + ".";
String explicitString = baseString + StringUtils.getExplicitConfigBlockDataString(data);
if (config.contains(explicitString))
return config.getInt(explicitString);
@@ -226,7 +237,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
public boolean doesBlockGiveSkillXP(PrimarySkillType skill, Material data)
{
String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + ".";
String explicitString = baseString + StringUtils.getExplicitConfigMaterialString(data);
if (config.contains(explicitString))
return true;
@@ -239,7 +250,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
public boolean doesBlockGiveSkillXP(PrimarySkillType skill, BlockData data)
{
String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
String baseString = "Experience_Values." + StringUtils.getCapitalized(skill.toString()) + ".";
String explicitString = baseString + StringUtils.getExplicitConfigBlockDataString(data);
if (config.contains(explicitString))
return true;
@@ -302,27 +313,29 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
}
/* Acrobatics */
public int getDodgeXPModifier() { return config.getInt("Experience.Acrobatics.Dodge", 120); }
public int getRollXPModifier() { return config.getInt("Experience.Acrobatics.Roll", 80); }
public int getFallXPModifier() { return config.getInt("Experience.Acrobatics.Fall", 120); }
public int getDodgeXPModifier() { return config.getInt("Experience_Values.Acrobatics.Dodge", 120); }
public int getRollXPModifier() { return config.getInt("Experience_Values.Acrobatics.Roll", 80); }
public int getFallXPModifier() { return config.getInt("Experience_Values.Acrobatics.Fall", 120); }
public double getFeatherFallXPModifier() { return config.getDouble("Experience.Acrobatics.FeatherFall_Multiplier", 2.0); }
public double getFeatherFallXPModifier() { return config.getDouble("Experience_Values.Acrobatics.FeatherFall_Multiplier", 2.0); }
/* Alchemy */
public double getPotionXP(PotionStage stage) { return config.getDouble("Experience.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D); }
public double getPotionXP(PotionStage stage) { return config.getDouble("Experience_Values.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D); }
/* Archery */
public double getArcheryDistanceMultiplier() { return config.getDouble("Experience.Archery.Distance_Multiplier", 0.025); }
public double getArcheryDistanceMultiplier() { return config.getDouble("Experience_Values.Archery.Distance_Multiplier", 0.025); }
public int getFishingShakeXP() { return config.getInt("Experience.Fishing.Shake", 50); }
public int getFishingShakeXP() { return config.getInt("Experience_Values.Fishing.Shake", 50); }
/* Repair */
public double getRepairXPBase() { return config.getDouble("Experience.Repair.Base", 1000.0); }
public double getRepairXP(MaterialType repairMaterialType) { return config.getDouble("Experience.Repair." + StringUtils.getCapitalized(repairMaterialType.toString())); }
public double getRepairXPBase() { return config.getDouble("Experience_Values.Repair.Base", 1000.0); }
public double getRepairXP(MaterialType repairMaterialType) { return config.getDouble("Experience_Values.Repair." + StringUtils.getCapitalized(repairMaterialType.toString())); }
/* Taming */
public int getTamingXP(EntityType type)
{
return config.getInt("Experience.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type));
return config.getInt("Experience_Values.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type));
}
public boolean preventStoneLavaFarming() { return config.getBoolean("ExploitFix.LavaStoneAndCobbleFarming", true);}
}

View File

@@ -5,10 +5,8 @@ import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.MaterialType;
import com.gmail.nossr50.skills.repair.repairables.Repairable;
import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
@@ -77,13 +75,6 @@ public class CustomArmorConfig extends ConfigLoader {
}
if (repairable) {
byte repairData = (byte) config.getInt(armorType + "." + armorName + ".Repair_Material_Data_Value", -1);
int repairQuantity = SkillUtils.getRepairAndSalvageQuantities(new ItemStack(armorMaterial), repairMaterial, repairData);
if (repairQuantity == 0) {
repairQuantity = config.getInt(armorType + "." + armorName + ".Repair_Material_Quantity", 2);
}
String repairItemName = config.getString(armorType + "." + armorName + ".Repair_Material_Pretty_Name");
int repairMinimumLevel = config.getInt(armorType + "." + armorName + ".Repair_MinimumLevel", 0);
double repairXpMultiplier = config.getDouble(armorType + "." + armorName + ".Repair_XpMultiplier", 1);
@@ -94,7 +85,7 @@ public class CustomArmorConfig extends ConfigLoader {
durability = (short) config.getInt(armorType + "." + armorName + ".Durability", 70);
}
repairables.add(RepairableFactory.getRepairable(armorMaterial, repairMaterial, repairData, repairItemName, repairMinimumLevel, repairQuantity, durability, ItemType.ARMOR, MaterialType.OTHER, repairXpMultiplier));
repairables.add(RepairableFactory.getRepairable(armorMaterial, repairMaterial, repairItemName, repairMinimumLevel, durability, ItemType.ARMOR, MaterialType.OTHER, repairXpMultiplier));
}
materialList.add(armorMaterial);

View File

@@ -6,10 +6,8 @@ import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.MaterialType;
import com.gmail.nossr50.skills.repair.repairables.Repairable;
import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashMap;
@@ -85,13 +83,6 @@ public class CustomToolConfig extends ConfigLoader {
}
if (repairable) {
byte repairData = (byte) config.getInt(toolType + "." + toolName + ".Repair_Material_Data_Value", -1);
int repairQuantity = SkillUtils.getRepairAndSalvageQuantities(new ItemStack(toolMaterial), repairMaterial, repairData);
if (repairQuantity == 0) {
repairQuantity = config.getInt(toolType + "." + toolName + ".Repair_Material_Quantity", 2);
}
String repairItemName = config.getString(toolType + "." + toolName + ".Repair_Material_Pretty_Name");
int repairMinimumLevel = config.getInt(toolType + "." + toolName + ".Repair_MinimumLevel", 0);
double repairXpMultiplier = config.getDouble(toolType + "." + toolName + ".Repair_XpMultiplier", 1);
@@ -102,7 +93,7 @@ public class CustomToolConfig extends ConfigLoader {
durability = (short) config.getInt(toolType + "." + toolName + ".Durability", 60);
}
repairables.add(RepairableFactory.getRepairable(toolMaterial, repairMaterial, repairData, repairItemName, repairMinimumLevel, repairQuantity, durability, ItemType.TOOL, MaterialType.OTHER, repairXpMultiplier));
repairables.add(RepairableFactory.getRepairable(toolMaterial, repairMaterial, repairItemName, repairMinimumLevel, durability, ItemType.TOOL, MaterialType.OTHER, repairXpMultiplier));
}
double multiplier = config.getDouble(toolType + "." + toolName + ".XP_Modifier", 1.0);

View File

@@ -5,6 +5,7 @@ import com.gmail.nossr50.util.StringUtils;
import org.bukkit.Material;
import java.util.HashSet;
import java.util.Locale;
public class ItemWeightConfig extends ConfigLoader {
private static ItemWeightConfig instance;
@@ -29,7 +30,7 @@ public class ItemWeightConfig extends ConfigLoader {
HashSet<Material> miscItems = new HashSet<Material>();
for (String item : config.getStringList("Party_Shareables.Misc_Items")) {
Material material = Material.getMaterial(item.toUpperCase());
Material material = Material.getMaterial(item.toUpperCase(Locale.ENGLISH));
if (material != null) {
miscItems.add(material);

View File

@@ -3,10 +3,10 @@ package com.gmail.nossr50.config.skills.repair;
import com.gmail.nossr50.config.ConfigLoader;
import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.MaterialType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.repair.repairables.Repairable;
import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
@@ -27,6 +27,11 @@ public class RepairConfig extends ConfigLoader {
protected void loadKeys() {
repairables = new ArrayList<Repairable>();
if (!config.isConfigurationSection("Repairables")) {
mcMMO.p.getLogger().severe("Could not find Repairables section in " + fileName);
return;
}
ConfigurationSection section = config.getConfigurationSection("Repairables");
Set<String> keys = section.getKeys(false);
@@ -126,7 +131,6 @@ public class RepairConfig extends ConfigLoader {
}
}
byte repairMetadata = (byte) config.getInt("Repairables." + key + ".RepairMaterialMetadata", -1);
int minimumLevel = config.getInt("Repairables." + key + ".MinimumLevel");
double xpMultiplier = config.getDouble("Repairables." + key + ".XpMultiplier", 1);
@@ -135,18 +139,14 @@ public class RepairConfig extends ConfigLoader {
}
// Minimum Quantity
int minimumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), repairMaterial, repairMetadata) : config.getInt("Repairables." + key + ".MinimumQuantity", 2));
int minimumQuantity = config.getInt("Repairables." + key + ".MinimumQuantity");
if (minimumQuantity <= 0 && itemMaterial != null) {
minimumQuantity = config.getInt("Repairables." + key + ".MinimumQuantity", 2);
}
if (minimumQuantity <= 0) {
reason.add("Minimum quantity of " + key + " must be greater than 0!");
if(minimumQuantity == 0) {
minimumQuantity = -1;
}
if (noErrorsInRepairable(reason)) {
Repairable repairable = RepairableFactory.getRepairable(itemMaterial, repairMaterial, repairMetadata, minimumLevel, minimumQuantity, maximumDurability, repairItemType, repairMaterialType, xpMultiplier);
Repairable repairable = RepairableFactory.getRepairable(itemMaterial, repairMaterial, null, minimumLevel, maximumDurability, repairItemType, repairMaterialType, xpMultiplier, minimumQuantity);
repairables.add(repairable);
}
}

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.config.skills.salvage;
import com.gmail.nossr50.config.ConfigLoader;
import com.gmail.nossr50.datatypes.skills.ItemType;
import com.gmail.nossr50.datatypes.skills.MaterialType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.salvage.salvageables.Salvageable;
import com.gmail.nossr50.skills.salvage.salvageables.SalvageableFactory;
import com.gmail.nossr50.util.ItemUtils;
@@ -13,6 +14,7 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public class SalvageConfig extends ConfigLoader {
@@ -27,6 +29,11 @@ public class SalvageConfig extends ConfigLoader {
protected void loadKeys() {
salvageables = new ArrayList<Salvageable>();
if (!config.isConfigurationSection("Salvageables")) {
mcMMO.p.getLogger().severe("Could not find Salvageables section in " + fileName);
return;
}
ConfigurationSection section = config.getConfigurationSection("Salvageables");
Set<String> keys = section.getKeys(false);
@@ -72,7 +79,7 @@ public class SalvageConfig extends ConfigLoader {
}
else {
try {
salvageMaterialType = MaterialType.valueOf(salvageMaterialTypeString.replace(" ", "_").toUpperCase());
salvageMaterialType = MaterialType.valueOf(salvageMaterialTypeString.replace(" ", "_").toUpperCase(Locale.ENGLISH));
}
catch (IllegalArgumentException ex) {
reason.add(key + " has an invalid MaterialType of " + salvageMaterialTypeString);
@@ -106,14 +113,13 @@ public class SalvageConfig extends ConfigLoader {
}
else {
try {
salvageItemType = ItemType.valueOf(salvageItemTypeString.replace(" ", "_").toUpperCase());
salvageItemType = ItemType.valueOf(salvageItemTypeString.replace(" ", "_").toUpperCase(Locale.ENGLISH));
}
catch (IllegalArgumentException ex) {
reason.add(key + " has an invalid ItemType of " + salvageItemTypeString);
}
}
byte salvageMetadata = (byte) config.getInt("Salvageables." + key + ".SalvageMaterialMetadata", -1);
int minimumLevel = config.getInt("Salvageables." + key + ".MinimumLevel");
double xpMultiplier = config.getDouble("Salvageables." + key + ".XpMultiplier", 1);
@@ -122,7 +128,7 @@ public class SalvageConfig extends ConfigLoader {
}
// Maximum Quantity
int maximumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), salvageMaterial, salvageMetadata) : config.getInt("Salvageables." + key + ".MaximumQuantity", 2));
int maximumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(itemMaterial, salvageMaterial) : config.getInt("Salvageables." + key + ".MaximumQuantity", 2));
if (maximumQuantity <= 0 && itemMaterial != null) {
maximumQuantity = config.getInt("Salvageables." + key + ".MaximumQuantity", 1);
@@ -139,7 +145,7 @@ public class SalvageConfig extends ConfigLoader {
}
if (noErrorsInSalvageable(reason)) {
Salvageable salvageable = SalvageableFactory.getSalvageable(itemMaterial, salvageMaterial, salvageMetadata, minimumLevel, maximumQuantity, maximumDurability, salvageItemType, salvageMaterialType, xpMultiplier);
Salvageable salvageable = SalvageableFactory.getSalvageable(itemMaterial, salvageMaterial, minimumLevel, maximumQuantity, maximumDurability, salvageItemType, salvageMaterialType, xpMultiplier);
salvageables.add(salvageable);
}
}

View File

@@ -150,7 +150,7 @@ public class TreasureConfig extends ConfigLoader {
}
if (amount <= 0) {
reason.add("Amount of " + treasureName + " must be greater than 0! " + amount);
amount = 1;
}
if (material != null && material.isBlock() && (data > 127 || data < -128)) {

View File

@@ -30,9 +30,17 @@ public interface DatabaseManager {
* Remove a user from the database.
*
* @param playerName The name of the user to remove
* @param uuid player UUID, can be null
* @return true if the user was successfully removed, false otherwise
*/
public boolean removeUser(String playerName);
public boolean removeUser(String playerName, UUID uuid);
/**
* Removes any cache used for faster lookups
* Currently only used for SQL
* @param uuid target UUID to cleanup
*/
public void cleanupUser(UUID uuid);
/**
* Save a user to the database.

View File

@@ -185,7 +185,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().info("Purged " + removedPlayers + " users from the database.");
}
public boolean removeUser(String playerName) {
public boolean removeUser(String playerName, UUID uuid) {
//NOTE: UUID is unused for FlatFile for this interface implementation
boolean worked = false;
BufferedReader in = null;
@@ -240,6 +241,11 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
return worked;
}
@Override
public void cleanupUser(UUID uuid) {
//Not used in FlatFile
}
public boolean saveUser(PlayerProfile profile) {
String playerName = profile.getPlayerName();
UUID uuid = profile.getUniqueId();

View File

@@ -31,6 +31,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
private DataSource loadPool;
private DataSource savePool;
private boolean debug = false;
private ReentrantLock massUpdateLock = new ReentrantLock();
protected SQLDatabaseManager() {
@@ -56,6 +58,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
//throw e; // aborts onEnable() Riking if you want to do this, fully implement it.
}
debug = Config.getInstance().getMySQLDebug();
PoolProperties poolProperties = new PoolProperties();
poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
@@ -172,7 +176,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().info("Purged " + purged + " users from the database.");
}
public boolean removeUser(String playerName) {
public boolean removeUser(String playerName, UUID uuid) {
boolean success = false;
Connection connection = null;
PreparedStatement statement = null;
@@ -200,12 +204,20 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
if (success) {
if(uuid != null)
cleanupUser(uuid);
Misc.profileCleanup(playerName);
}
return success;
}
public void cleanupUser(UUID uuid) {
if(cachedUserIDs.containsKey(uuid))
cachedUserIDs.remove(uuid);
}
public boolean saveUser(PlayerProfile profile) {
boolean success = true;
PreparedStatement statement = null;
@@ -335,7 +347,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
public List<PlayerStat> readLeaderboard(PrimarySkillType skill, int pageNumber, int statsPerPage) {
List<PlayerStat> stats = new ArrayList<PlayerStat>();
String query = skill == null ? ALL_QUERY_VERSION : skill.name().toLowerCase();
String query = skill == null ? ALL_QUERY_VERSION : skill.name().toLowerCase(Locale.ENGLISH);
ResultSet resultSet = null;
PreparedStatement statement = null;
Connection connection = null;
@@ -379,9 +391,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
connection = getConnection(PoolIdentifier.MISC);
for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
String skillName = primarySkillType.name().toLowerCase();
String skillName = primarySkillType.name().toLowerCase(Locale.ENGLISH);
// Get count of all users with higher skill level than player
String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
String sql = "SELECT COUNT(*) AS 'rank' FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
"AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE user = ?)";
@@ -415,7 +427,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.close();
}
String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
String sql = "SELECT COUNT(*) AS 'rank' FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE " + ALL_QUERY_VERSION + " > 0 " +
"AND " + ALL_QUERY_VERSION + " > " +
"(SELECT " + ALL_QUERY_VERSION + " " +
@@ -899,7 +911,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
int cap = Config.getInstance().getLevelCap(skill);
if (cap != Integer.MAX_VALUE) {
statement = connection.prepareStatement("UPDATE `" + tablePrefix + "skills` SET `" + skill.name().toLowerCase() + "` = " + cap + " WHERE `" + skill.name().toLowerCase() + "` > " + cap);
statement = connection.prepareStatement("UPDATE `" + tablePrefix + "skills` SET `" + skill.name().toLowerCase(Locale.ENGLISH) + "` = " + cap + " WHERE `" + skill.name().toLowerCase(Locale.ENGLISH) + "` > " + cap);
statement.executeUpdate();
tryClose(statement);
}
@@ -939,7 +951,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
break;
}
if (connection == null) {
throw new RuntimeException("getConnection() for " + identifier.name().toLowerCase() + " pool timed out. Increase max connections settings.");
throw new RuntimeException("getConnection() for " + identifier.name().toLowerCase(Locale.ENGLISH) + " pool timed out. Increase max connections settings.");
}
return connection;
}
@@ -1140,6 +1152,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
private void printErrors(SQLException ex) {
if (debug) {
ex.printStackTrace();
}
StackTraceElement element = ex.getStackTrace()[0];
mcMMO.p.getLogger().severe("Location: " + element.getClassName() + " " + element.getMethodName() + " " + element.getLineNumber());
mcMMO.p.getLogger().severe("SQLException: " + ex.getMessage());
@@ -1246,7 +1262,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases");
for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
String skill_name = skill.name().toLowerCase();
String skill_name = skill.name().toLowerCase(Locale.ENGLISH);
try {
statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_" + skill_name + "` (`" + skill_name + "`) USING BTREE");

View File

@@ -0,0 +1,30 @@
package com.gmail.nossr50.datatypes;
import org.bukkit.Material;
import org.bukkit.block.Block;
/**
* Contains a snapshot of a block at a specific moment in time
* Used to check before/after type stuff
*/
public class BlockSnapshot {
private final Material oldType;
private Block blockRef;
public BlockSnapshot(Material oldType, Block blockRef) {
this.oldType = oldType;
this.blockRef = blockRef;
}
public Material getOldType() {
return oldType;
}
public Block getBlockRef() {
return blockRef;
}
public boolean hasChangedType() {
return oldType != blockRef.getState().getType();
}
}

View File

@@ -20,6 +20,7 @@ public enum NotificationType {
SUPER_ABILITY("SuperAbilityInteraction"),
SUPER_ABILITY_ALERT_OTHERS("SuperAbilityAlertOthers"),
ITEM_MESSAGE("ItemMessage"),
CHAT_ONLY("ChatOnly"),
PARTY_MESSAGE("PartyMessage");
final String niceName;

View File

@@ -0,0 +1,14 @@
package com.gmail.nossr50.datatypes.meta;
import com.gmail.nossr50.mcMMO;
import org.bukkit.metadata.FixedMetadataValue;
/**
* Stores how many bonus drops a block should give
*/
public class BonusDropMeta extends FixedMetadataValue {
public BonusDropMeta(int value, mcMMO plugin) {
super(plugin, value);
}
}

View File

@@ -12,4 +12,5 @@ public class OldName extends FixedMetadataValue {
{
super(plugin, oldName);
}
}

View File

@@ -0,0 +1,17 @@
package com.gmail.nossr50.datatypes.meta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.Plugin;
public class RecentlyReplantedCropMeta extends FixedMetadataValue {
/**
* Initializes a FixedMetadataValue with an Object
*
* @param owningPlugin the {@link Plugin} that created this metadata value
*/
public RecentlyReplantedCropMeta(Plugin owningPlugin, Boolean recentlyPlanted) {
super(owningPlugin, recentlyPlanted);
}
}

View File

@@ -0,0 +1,7 @@
package com.gmail.nossr50.datatypes.notifications;
public enum SensitiveCommandType {
XPRATE_MODIFY,
XPRATE_END,
MMOEDIT
}

View File

@@ -3,12 +3,16 @@ package com.gmail.nossr50.datatypes.party;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.experience.FormulaType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -18,8 +22,15 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class Party {
// private static final String ONLINE_PLAYER_PREFIX = "★";
// private static final String ONLINE_PLAYER_PREFIX = "●" + ChatColor.RESET;
private static final String ONLINE_PLAYER_PREFIX = "";
// private static final String OFFLINE_PLAYER_PREFIX = "☆";
private static final String OFFLINE_PLAYER_PREFIX = "";
// private static final String OFFLINE_PLAYER_PREFIX = "⭕" + ChatColor.RESET;
private final LinkedHashMap<UUID, String> members = new LinkedHashMap<UUID, String>();
private final List<Player> onlineMembers = new ArrayList<Player>();
@@ -192,7 +203,7 @@ public class Party {
public int getXpToLevel() {
FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType();
return (mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType)) * (getOnlineMembers().size() + Config.getInstance().getPartyXpCurveMultiplier());
return (mcMMO.getFormulaManager().getXPtoNextLevel(level, formulaType)) * (getOnlineMembers().size() + Config.getInstance().getPartyXpCurveMultiplier());
}
public String getXpToLevelPercentage() {
@@ -324,36 +335,203 @@ public class Party {
return this.getMembers().keySet().contains(uuid);
}
/**
* Makes a formatted list of party members based on the perspective of a target player
* Players that are hidden will be shown as offline (formatted in the same way)
* Party leader will be formatted a specific way as well
* @param player target player to use as POV
* @return formatted list of party members from the POV of a player
*/
public String createMembersList(Player player) {
StringBuilder memberList = new StringBuilder();
for (Player otherPlayer : this.getVisibleMembers(player)) {
String memberName = otherPlayer.getName();
List<UUID> onlineMembers = members.keySet().stream()
.filter(x -> Bukkit.getOfflinePlayer(x).isOnline())
.collect(Collectors.toList());
if (this.getLeader().getUniqueId().equals(otherPlayer.getUniqueId())) {
memberList.append(ChatColor.GOLD);
List<UUID> offlineMembers = members.keySet().stream()
.filter(x -> !Bukkit.getOfflinePlayer(x).isOnline())
.collect(Collectors.toList());
if (otherPlayer == null) {
memberName = memberName.substring(0, 1) + ChatColor.GRAY + ChatColor.ITALIC + "" + memberName.substring(1);
}
}
else if (otherPlayer != null) {
memberList.append(ChatColor.WHITE);
}
else {
memberList.append(ChatColor.GRAY);
}
ArrayList<UUID> visiblePartyList = new ArrayList<>();
boolean isPartyLeaderOfflineOrHidden = false;
ArrayList<UUID> offlineOrHiddenPartyList = new ArrayList<>();
if (player.getName().equalsIgnoreCase(otherPlayer.getName())) {
memberList.append(ChatColor.ITALIC);
}
for(UUID onlineMember : onlineMembers)
{
Player onlinePlayer = Bukkit.getPlayer(onlineMember);
memberList.append(memberName).append(ChatColor.RESET).append(" ");
if(!isNotSamePerson(player.getUniqueId(), onlineMember) || player.canSee(onlinePlayer))
{
visiblePartyList.add(onlineMember);
} else {
//Party leader and cannot be seen by this player
if(isNotSamePerson(leader.getUniqueId(), player.getUniqueId()) && onlineMember == leader.getUniqueId())
isPartyLeaderOfflineOrHidden = true;
offlineOrHiddenPartyList.add(onlineMember);
}
}
if(offlineMembers.contains(leader.getUniqueId()))
isPartyLeaderOfflineOrHidden = true;
//Add all the actually offline members
offlineOrHiddenPartyList.addAll(offlineMembers);
/* BUILD THE PARTY LIST WITH FORMATTING */
String partyLeaderPrefix =
/*ChatColor.WHITE
+ "["
+*/ ChatColor.GOLD
+ ""
/*+ ChatColor.WHITE
+ "]"*/
+ ChatColor.RESET;
//First add the party leader
memberList.append(partyLeaderPrefix);
List<Player> nearbyPlayerList = getNearMembers(UserManager.getPlayer(player));
boolean useDisplayNames = Config.getInstance().getPartyDisplayNames();
if(isPartyLeaderOfflineOrHidden)
{
if(isNotSamePerson(player.getUniqueId(), leader.getUniqueId()))
applyOnlineAndRangeFormatting(memberList, false, false);
memberList.append(ChatColor.GRAY)
.append(leader.getPlayerName());
}
else {
if(isNotSamePerson(leader.getUniqueId(), player.getUniqueId()))
applyOnlineAndRangeFormatting(memberList, true, nearbyPlayerList.contains(Bukkit.getPlayer(leader.getUniqueId())));
if(useDisplayNames) {
memberList.append(leader.getPlayerName());
} else {
memberList.append(ChatColor.GOLD)
.append(Bukkit.getOfflinePlayer(leader.getUniqueId()));
}
}
//Space
memberList.append(" ");
//Now do online members
for(UUID onlinePlayerUUID : visiblePartyList)
{
if(onlinePlayerUUID == leader.getUniqueId())
continue;
if(isNotSamePerson(onlinePlayerUUID, player.getUniqueId()))
applyOnlineAndRangeFormatting(memberList, true, nearbyPlayerList.contains(Bukkit.getPlayer(onlinePlayerUUID)));
if(useDisplayNames)
{
memberList.append(Bukkit.getPlayer(onlinePlayerUUID).getDisplayName());
}
else
{
//Color allies green, players dark aqua
memberList.append(ChatColor.GREEN)
.append(Bukkit.getPlayer(onlinePlayerUUID).getName());
}
memberList.append(" ").append(ChatColor.RESET);
}
for(UUID offlineOrHiddenPlayer : offlineOrHiddenPartyList)
{
if(offlineOrHiddenPlayer == leader.getUniqueId())
continue;
applyOnlineAndRangeFormatting(memberList, false, false);
memberList.append(ChatColor.GRAY)
.append(Bukkit.getOfflinePlayer(offlineOrHiddenPlayer).getName())
.append(" ").append(ChatColor.RESET);
}
// for (Player otherPlayer : this.getVisibleMembers(player)) {
// String memberName = otherPlayer.getName();
//
// if (this.getLeader().getUniqueId().equals(otherPlayer.getUniqueId())) {
// memberList.append(ChatColor.GOLD);
//
// if (otherPlayer == null) {
// memberName = memberName.substring(0, 1) + ChatColor.GRAY + ChatColor.ITALIC + "" + memberName.substring(1);
// }
// }
// else if (otherPlayer != null) {
// memberList.append(ChatColor.WHITE);
// }
// else {
// memberList.append(ChatColor.GRAY);
// }
//
// if (player.getName().equalsIgnoreCase(otherPlayer.getName())) {
// memberList.append(ChatColor.ITALIC);
// }
//
// memberList.append(memberName).append(ChatColor.RESET).append(" ");
// }
return memberList.toString();
}
private boolean isNotSamePerson(UUID onlinePlayerUUID, UUID uniqueId) {
return onlinePlayerUUID != uniqueId;
}
private void applyOnlineAndRangeFormatting(StringBuilder stringBuilder, boolean isVisibleOrOnline, boolean isNear)
{
if(isVisibleOrOnline)
{
if(isNear)
{
stringBuilder.append(ChatColor.GREEN);
} else {
stringBuilder.append(ChatColor.GRAY);
}
// stringBuilder.append(ChatColor.BOLD);
stringBuilder.append(ONLINE_PLAYER_PREFIX);
} else {
stringBuilder.append(ChatColor.GRAY);
stringBuilder.append(OFFLINE_PLAYER_PREFIX);
}
stringBuilder.append(ChatColor.RESET);
}
/**
* Get the near party members.
*
* @param mcMMOPlayer The player to check
* @return the near party members
*/
public List<Player> getNearMembers(McMMOPlayer mcMMOPlayer) {
List<Player> nearMembers = new ArrayList<Player>();
Party party = mcMMOPlayer.getParty();
if (party != null) {
Player player = mcMMOPlayer.getPlayer();
double range = Config.getInstance().getPartyShareRange();
for (Player member : party.getOnlineMembers()) {
if (!player.equals(member) && member.isValid() && Misc.isNear(player.getLocation(), member.getLocation(), range)) {
nearMembers.add(member);
}
}
}
return nearMembers;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {

View File

@@ -81,6 +81,7 @@ public class McMMOPlayer {
private boolean partyChatMode;
private boolean adminChatMode;
private boolean displaySkillNotifications = true;
private boolean debugMode;
private boolean abilityUse = true;
private boolean godMode;
@@ -100,9 +101,10 @@ public class McMMOPlayer {
private boolean isUsingUnarmed;
private final FixedMetadataValue playerMetadata;
private String playerName;
public McMMOPlayer(Player player, PlayerProfile profile) {
String playerName = player.getName();
this.playerName = player.getName();
UUID uuid = player.getUniqueId();
this.player = player;
@@ -138,6 +140,12 @@ public class McMMOPlayer {
}
experienceBarManager = new ExperienceBarManager(this);
debugMode = false; //Debug mode helps solve support issues, players can toggle it on or off
}
public String getPlayerName() {
return playerName;
}
/*public void hideXpBar(PrimarySkillType primarySkillType)
@@ -145,8 +153,15 @@ public class McMMOPlayer {
experienceBarManager.hideExperienceBar(primarySkillType);
}*/
public void processPostXpEvent(XPGainReason xpGainReason, PrimarySkillType primarySkillType, Plugin plugin, XPGainSource xpGainSource)
public void processPostXpEvent(PrimarySkillType primarySkillType, Plugin plugin, XPGainSource xpGainSource)
{
//Check if they've reached the power level cap just now
if(hasReachedPowerLevelCap()) {
NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.PowerLevel", String.valueOf(Config.getInstance().getPowerLevelCap()));
} else if(hasReachedLevelCap(primarySkillType)) {
NotificationManager.sendPlayerInformationChatOnly(player, "LevelCap.Skill", String.valueOf(Config.getInstance().getLevelCap(primarySkillType)), primarySkillType.getName());
}
//Updates from Party sources
if(xpGainSource == XPGainSource.PARTY_MEMBERS && !ExperienceConfig.getInstance().isPartyExperienceBarsEnabled())
return;
@@ -425,6 +440,18 @@ public class McMMOPlayer {
public void togglePartyChatSpying() { chatSpy = !chatSpy;}
/*
* Debug Mode Flags
*/
public boolean isDebugMode() {
return debugMode;
}
public void toggleDebugMode() {
debugMode = !debugMode;
}
/*
* Skill notifications
*/
@@ -454,6 +481,28 @@ public class McMMOPlayer {
return powerLevel;
}
/**
* Whether or not a player is level capped
* If they are at the power level cap, this will return true, otherwise it checks their skill level
* @param primarySkillType
* @return
*/
public boolean hasReachedLevelCap(PrimarySkillType primarySkillType) {
if(hasReachedPowerLevelCap())
return true;
return getSkillLevel(primarySkillType) >= Config.getInstance().getLevelCap(primarySkillType);
}
/**
* Whether or not a player is power level capped
* Compares their power level total to the current set limit
* @return true if they have reached the power level cap
*/
public boolean hasReachedPowerLevelCap() {
return this.getPowerLevel() >= Config.getInstance().getPowerLevelCap();
}
/**
* Begins an experience gain. The amount will be affected by skill modifiers, global rate, perks, and may be shared with the party
*
@@ -495,6 +544,9 @@ public class McMMOPlayer {
* @param xp Experience amount to process
*/
public void beginUnsharedXpGain(PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
if(player.getGameMode() == GameMode.CREATIVE)
return;
applyXpGain(skill, modifyXpGain(skill, xp), xpGainReason, xpGainSource);
if (party == null) {
@@ -541,8 +593,11 @@ public class McMMOPlayer {
* @param primarySkillType The skill to check
*/
private void checkXp(PrimarySkillType primarySkillType, XPGainReason xpGainReason, XPGainSource xpGainSource) {
if(hasReachedLevelCap(primarySkillType))
return;
if (getSkillXpLevelRaw(primarySkillType) < getXpToLevel(primarySkillType)) {
UserManager.getPlayer(player).processPostXpEvent(xpGainReason, primarySkillType, mcMMO.p, xpGainSource);
processPostXpEvent(primarySkillType, mcMMO.p, xpGainSource);
return;
}
@@ -559,8 +614,7 @@ public class McMMOPlayer {
levelsGained++;
}
if (!EventUtils.handleLevelChangeEvent(player, primarySkillType, levelsGained, xpRemoved, true, xpGainReason)) {
UserManager.getPlayer(player).processPostXpEvent(xpGainReason, primarySkillType, mcMMO.p, xpGainSource);
if (EventUtils.tryLevelChangeEvent(player, primarySkillType, levelsGained, xpRemoved, true, xpGainReason)) {
return;
}
@@ -572,10 +626,10 @@ public class McMMOPlayer {
* Check to see if the player unlocked any new skills
*/
NotificationManager.sendPlayerLevelUpNotification(UserManager.getPlayer(player), primarySkillType, levelsGained, profile.getSkillLevel(primarySkillType));
NotificationManager.sendPlayerLevelUpNotification(this, primarySkillType, levelsGained, profile.getSkillLevel(primarySkillType));
//UPDATE XP BARS
UserManager.getPlayer(player).processPostXpEvent(xpGainReason, primarySkillType, mcMMO.p, xpGainSource);
processPostXpEvent(primarySkillType, mcMMO.p, xpGainSource);
}
/*
@@ -750,7 +804,7 @@ public class McMMOPlayer {
* @return Modified experience
*/
private float modifyXpGain(PrimarySkillType primarySkillType, float xp) {
if (player.getGameMode() == GameMode.CREATIVE || (primarySkillType.getMaxLevel() <= getSkillLevel(primarySkillType)) || (Config.getInstance().getPowerLevelCap() <= getPowerLevel())) {
if ((primarySkillType.getMaxLevel() <= getSkillLevel(primarySkillType)) || (Config.getInstance().getPowerLevelCap() <= getPowerLevel())) {
return 0;
}
@@ -795,7 +849,6 @@ public class McMMOPlayer {
return;
}
//TODO: This is hacky and temporary solution until skills are move to the new system
//Potential problems with this include skills with two super abilities (ie mining)
if(!skill.isSuperAbilityUnlocked(getPlayer()))
@@ -910,7 +963,7 @@ public class McMMOPlayer {
}
setToolPreparationMode(tool, true);
new ToolLowerTask(this, tool).runTaskLaterAsynchronously(mcMMO.p, 4 * Misc.TICK_CONVERSION_FACTOR);
new ToolLowerTask(this, tool).runTaskLater(mcMMO.p, 4 * Misc.TICK_CONVERSION_FACTOR);
}
}
@@ -926,10 +979,6 @@ public class McMMOPlayer {
return (int) (((deactivatedTimestamp + (PerksUtils.handleCooldownPerks(player, ability.getCooldown()) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
}
private boolean hasReachedLevelCap(PrimarySkillType skill) {
return (skill.getMaxLevel() < getSkillLevel(skill) + 1) || (Config.getInstance().getPowerLevelCap() < getPowerLevel() + 1);
}
/*
* These functions are wrapped from PlayerProfile so that we don't always have to store it alongside the McMMOPlayer object.
*/
@@ -988,11 +1037,11 @@ public class McMMOPlayer {
*/
public void logout(boolean syncSave) {
Player thisPlayer = getPlayer();
resetAbilityMode();
BleedTimerTask.bleedOut(thisPlayer);
BleedTimerTask.bleedOut(getPlayer());
cleanup();
if (syncSave) {
getProfile().save();
getProfile().save(true);
} else {
getProfile().scheduleAsyncSave();
}
@@ -1005,5 +1054,19 @@ public class McMMOPlayer {
if (inParty()) {
party.removeOnlineMember(thisPlayer);
}
//Remove user from cache
mcMMO.getDatabaseManager().cleanupUser(thisPlayer.getUniqueId());
}
/**
* Cleanup various things related to this player
* Such as temporary summons..
* Turning off abilities...
* Etc...
*/
public void cleanup() {
resetAbilityMode();
getTamingManager().cleanupAllSummons();
}
}

View File

@@ -29,6 +29,7 @@ public class PlayerProfile {
/* HUDs */
private MobHealthbarType mobHealthbarType;
private int scoreboardTipsShown;
private int saveAttempts = 0;
/* Skill Data */
private final Map<PrimarySkillType, Integer> skills = new HashMap<PrimarySkillType, Integer>(); // Skill & Level
@@ -36,7 +37,7 @@ public class PlayerProfile {
private final Map<SuperAbilityType, Integer> abilityDATS = new HashMap<SuperAbilityType, Integer>(); // Ability & Cooldown
private final Map<UniqueDataType, Integer> uniquePlayerData = new HashMap<>(); //Misc data that doesn't fit into other categories (chimaera wing, etc..)
// Store previous XP gains for deminished returns
// Store previous XP gains for diminished returns
private DelayQueue<SkillXpGain> gainedSkillsXp = new DelayQueue<SkillXpGain>();
private HashMap<PrimarySkillType, Float> rollingSkillsXp = new HashMap<PrimarySkillType, Float>();
@@ -91,11 +92,25 @@ public class PlayerProfile {
}
public void scheduleAsyncSave() {
new PlayerProfileSaveTask(this).runTaskAsynchronously(mcMMO.p);
new PlayerProfileSaveTask(this, false).runTaskAsynchronously(mcMMO.p);
}
public void save() {
public void scheduleSyncSave() {
new PlayerProfileSaveTask(this, true).runTask(mcMMO.p);
}
public void scheduleAsyncSaveDelay() {
new PlayerProfileSaveTask(this, false).runTaskLaterAsynchronously(mcMMO.p, 20);
}
@Deprecated
public void scheduleSyncSaveDelay() {
new PlayerProfileSaveTask(this, true).runTaskLater(mcMMO.p, 20);
}
public void save(boolean useSync) {
if (!changed || !loaded) {
saveAttempts = 0;
return;
}
@@ -104,7 +119,33 @@ public class PlayerProfile {
changed = !mcMMO.getDatabaseManager().saveUser(profileCopy);
if (changed) {
mcMMO.p.getLogger().warning("PlayerProfile saving failed for player: " + playerName + " " + uuid);
mcMMO.p.getLogger().severe("PlayerProfile saving failed for player: " + playerName + " " + uuid);
if(saveAttempts > 0)
{
mcMMO.p.getLogger().severe("Attempted to save profile for player "+getPlayerName()
+ " resulted in failure. "+saveAttempts+" have been made so far.");
}
if(saveAttempts < 10)
{
saveAttempts++;
if(useSync)
scheduleSyncSave(); //Execute sync saves immediately
else
scheduleAsyncSaveDelay();
return;
} else {
mcMMO.p.getLogger().severe("mcMMO has failed to save the profile for "
+getPlayerName()+" numerous times." +
" mcMMO will now stop attempting to save this profile." +
" Check your console for errors and inspect your DB for issues.");
}
} else {
saveAttempts = 0;
}
}
@@ -117,7 +158,7 @@ public class PlayerProfile {
}
public void setUniqueId(UUID uuid) {
changed = true;
markProfileDirty();
this.uuid = uuid;
}
@@ -135,17 +176,24 @@ public class PlayerProfile {
}
public void setMobHealthbarType(MobHealthbarType mobHealthbarType) {
changed = true;
markProfileDirty();
this.mobHealthbarType = mobHealthbarType;
}
/**
* Marks the profile as "dirty" which flags a profile to be saved in the next save operation
*/
public void markProfileDirty() {
changed = true;
}
public int getScoreboardTipsShown() {
return scoreboardTipsShown;
}
public void setScoreboardTipsShown(int scoreboardTipsShown) {
changed = true;
markProfileDirty();
this.scoreboardTipsShown = scoreboardTipsShown;
}
@@ -161,12 +209,12 @@ public class PlayerProfile {
public int getChimaerWingDATS() { return uniquePlayerData.get(UniqueDataType.CHIMAERA_WING_DATS);}
protected void setChimaeraWingDATS(int DATS) {
changed = true;
markProfileDirty();
uniquePlayerData.put(UniqueDataType.CHIMAERA_WING_DATS, DATS);
}
public void setUniqueData(UniqueDataType uniqueDataType, int newData) {
changed = true;
markProfileDirty();
uniquePlayerData.put(uniqueDataType, newData);
}
@@ -189,7 +237,7 @@ public class PlayerProfile {
* @param DATS the DATS of the ability
*/
protected void setAbilityDATS(SuperAbilityType ability, long DATS) {
changed = true;
markProfileDirty();
abilityDATS.put(ability, (int) (DATS * .001D));
}
@@ -198,7 +246,7 @@ public class PlayerProfile {
* Reset all ability cooldowns.
*/
protected void resetCooldowns() {
changed = true;
markProfileDirty();
for (SuperAbilityType ability : abilityDATS.keySet()) {
abilityDATS.put(ability, 0);
@@ -226,7 +274,7 @@ public class PlayerProfile {
return;
}
changed = true;
markProfileDirty();
skillsXp.put(skill, xpLevel);
}
@@ -234,7 +282,7 @@ public class PlayerProfile {
protected float levelUp(PrimarySkillType skill) {
float xpRemoved = getXpToLevel(skill);
changed = true;
markProfileDirty();
skills.put(skill, skills.get(skill) + 1);
skillsXp.put(skill, skillsXp.get(skill) - xpRemoved);
@@ -253,7 +301,7 @@ public class PlayerProfile {
return;
}
changed = true;
markProfileDirty();
skillsXp.put(skill, skillsXp.get(skill) - xp);
}
@@ -263,7 +311,7 @@ public class PlayerProfile {
return;
}
changed = true;
markProfileDirty();
skillsXp.put(skill, skillsXp.get(skill) - xp);
}
@@ -279,7 +327,7 @@ public class PlayerProfile {
return;
}
changed = true;
markProfileDirty();
//Don't allow levels to be negative
if(level < 0)
@@ -306,7 +354,7 @@ public class PlayerProfile {
* @param xp Number of experience to add
*/
public void addXp(PrimarySkillType skill, float xp) {
changed = true;
markProfileDirty();
if (skill.isChildSkill()) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);
@@ -370,7 +418,7 @@ public class PlayerProfile {
int level = (ExperienceConfig.getInstance().getCumulativeCurveEnabled()) ? UserManager.getPlayer(playerName).getPowerLevel() : skills.get(primarySkillType);
FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType();
return mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType);
return mcMMO.getFormulaManager().getXPtoNextLevel(level, formulaType);
}
private int getChildSkillLevel(PrimarySkillType primarySkillType) {

View File

@@ -22,7 +22,6 @@ import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.google.common.collect.ImmutableList;
import org.bukkit.Color;
@@ -35,24 +34,39 @@ import java.util.Collections;
import java.util.List;
public enum PrimarySkillType {
ACROBATICS(AcrobaticsManager.class, Color.WHITE, ImmutableList.of(SubSkillType.ACROBATICS_DODGE, SubSkillType.ACROBATICS_ROLL)),
ALCHEMY(AlchemyManager.class, Color.FUCHSIA, ImmutableList.of(SubSkillType.ALCHEMY_CATALYSIS, SubSkillType.ALCHEMY_CONCOCTIONS)),
ARCHERY(ArcheryManager.class, Color.MAROON, ImmutableList.of(SubSkillType.ARCHERY_DAZE, SubSkillType.ARCHERY_ARROW_RETRIEVAL, SubSkillType.ARCHERY_SKILL_SHOT)),
AXES(AxesManager.class, Color.AQUA, SuperAbilityType.SKULL_SPLITTER, ToolType.AXE, ImmutableList.of(SubSkillType.AXES_SKULL_SPLITTER, SubSkillType.AXES_ARMOR_IMPACT, SubSkillType.AXES_AXE_MASTERY, SubSkillType.AXES_CRITICAL_STRIKES, SubSkillType.AXES_GREATER_IMPACT)),
EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), SuperAbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL, ImmutableList.of(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, SubSkillType.EXCAVATION_ARCHAEOLOGY)),
FISHING(FishingManager.class, Color.NAVY, ImmutableList.of(SubSkillType.FISHING_FISHERMANS_DIET, SubSkillType.FISHING_TREASURE_HUNTER, SubSkillType.FISHING_ICE_FISHING, SubSkillType.FISHING_MAGIC_HUNTER, SubSkillType.FISHING_MASTER_ANGLER, SubSkillType.FISHING_SHAKE)),
HERBALISM(HerbalismManager.class, Color.GREEN, SuperAbilityType.GREEN_TERRA, ToolType.HOE, ImmutableList.of(SubSkillType.HERBALISM_GREEN_TERRA, SubSkillType.HERBALISM_FARMERS_DIET, SubSkillType.HERBALISM_GREEN_THUMB, SubSkillType.HERBALISM_DOUBLE_DROPS, SubSkillType.HERBALISM_HYLIAN_LUCK, SubSkillType.HERBALISM_SHROOM_THUMB)),
MINING(MiningManager.class, Color.GRAY, SuperAbilityType.SUPER_BREAKER, ToolType.PICKAXE, ImmutableList.of(SubSkillType.MINING_SUPER_BREAKER, SubSkillType.MINING_DEMOLITIONS_EXPERTISE, SubSkillType.MINING_BIGGER_BOMBS, SubSkillType.MINING_BLAST_MINING, SubSkillType.MINING_DOUBLE_DROPS)),
REPAIR(RepairManager.class, Color.SILVER, ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR)),
SALVAGE(SalvageManager.class, Color.ORANGE, ImmutableList.of(SubSkillType.SALVAGE_ADVANCED_SALVAGE, SubSkillType.SALVAGE_ARCANE_SALVAGE)),
SMELTING(SmeltingManager.class, Color.YELLOW, ImmutableList.of(SubSkillType.SMELTING_UNDERSTANDING_THE_ART, SubSkillType.SMELTING_FLUX_MINING, SubSkillType.SMELTING_FUEL_EFFICIENCY, SubSkillType.SMELTING_SECOND_SMELT)),
SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbilityType.SERRATED_STRIKES, ToolType.SWORD, ImmutableList.of(SubSkillType.SWORDS_SERRATED_STRIKES, SubSkillType.SWORDS_RUPTURE, SubSkillType.SWORDS_COUNTER_ATTACK)),
TAMING(TamingManager.class, Color.PURPLE, ImmutableList.of(SubSkillType.TAMING_BEAST_LORE, SubSkillType.TAMING_CALL_OF_THE_WILD, SubSkillType.TAMING_ENVIRONMENTALLY_AWARE, SubSkillType.TAMING_FAST_FOOD_SERVICE, SubSkillType.TAMING_GORE, SubSkillType.TAMING_HOLY_HOUND, SubSkillType.TAMING_SHARPENED_CLAWS, SubSkillType.TAMING_SHOCK_PROOF, SubSkillType.TAMING_THICK_FUR, SubSkillType.TAMING_PUMMEL)),
UNARMED(UnarmedManager.class, Color.BLACK, SuperAbilityType.BERSERK, ToolType.FISTS, ImmutableList.of(SubSkillType.UNARMED_BERSERK, SubSkillType.UNARMED_BLOCK_CRACKER, SubSkillType.UNARMED_ARROW_DEFLECT, SubSkillType.UNARMED_DISARM, SubSkillType.UNARMED_IRON_ARM_STYLE, SubSkillType.UNARMED_IRON_GRIP)),
WOODCUTTING(WoodcuttingManager.class, Color.OLIVE, SuperAbilityType.TREE_FELLER, ToolType.AXE, ImmutableList.of(SubSkillType.WOODCUTTING_LEAF_BLOWER, SubSkillType.WOODCUTTING_TREE_FELLER, SubSkillType.WOODCUTTING_HARVEST_LUMBER));
ACROBATICS(AcrobaticsManager.class, Color.WHITE,
ImmutableList.of(SubSkillType.ACROBATICS_DODGE, SubSkillType.ACROBATICS_ROLL)),
ALCHEMY(AlchemyManager.class, Color.FUCHSIA,
ImmutableList.of(SubSkillType.ALCHEMY_CATALYSIS, SubSkillType.ALCHEMY_CONCOCTIONS)),
ARCHERY(ArcheryManager.class, Color.MAROON,
ImmutableList.of(SubSkillType.ARCHERY_DAZE, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK, SubSkillType.ARCHERY_ARROW_RETRIEVAL, SubSkillType.ARCHERY_SKILL_SHOT)),
AXES(AxesManager.class, Color.AQUA, SuperAbilityType.SKULL_SPLITTER, ToolType.AXE,
ImmutableList.of(SubSkillType.AXES_SKULL_SPLITTER, SubSkillType.AXES_AXES_LIMIT_BREAK, SubSkillType.AXES_ARMOR_IMPACT, SubSkillType.AXES_AXE_MASTERY, SubSkillType.AXES_CRITICAL_STRIKES, SubSkillType.AXES_GREATER_IMPACT)),
EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), SuperAbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL,
ImmutableList.of(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, SubSkillType.EXCAVATION_ARCHAEOLOGY)),
FISHING(FishingManager.class, Color.NAVY,
ImmutableList.of(SubSkillType.FISHING_FISHERMANS_DIET, SubSkillType.FISHING_TREASURE_HUNTER, SubSkillType.FISHING_ICE_FISHING, SubSkillType.FISHING_MAGIC_HUNTER, SubSkillType.FISHING_MASTER_ANGLER, SubSkillType.FISHING_SHAKE)),
HERBALISM(HerbalismManager.class, Color.GREEN, SuperAbilityType.GREEN_TERRA, ToolType.HOE,
ImmutableList.of(SubSkillType.HERBALISM_GREEN_TERRA, SubSkillType.HERBALISM_FARMERS_DIET, SubSkillType.HERBALISM_GREEN_THUMB, SubSkillType.HERBALISM_DOUBLE_DROPS, SubSkillType.HERBALISM_HYLIAN_LUCK, SubSkillType.HERBALISM_SHROOM_THUMB)),
MINING(MiningManager.class, Color.GRAY, SuperAbilityType.SUPER_BREAKER, ToolType.PICKAXE,
ImmutableList.of(SubSkillType.MINING_SUPER_BREAKER, SubSkillType.MINING_DEMOLITIONS_EXPERTISE, SubSkillType.MINING_BIGGER_BOMBS, SubSkillType.MINING_BLAST_MINING, SubSkillType.MINING_DOUBLE_DROPS)),
REPAIR(RepairManager.class, Color.SILVER,
ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR)),
SALVAGE(SalvageManager.class, Color.ORANGE,
ImmutableList.of(SubSkillType.SALVAGE_SCRAP_COLLECTOR, SubSkillType.SALVAGE_ARCANE_SALVAGE)),
SMELTING(SmeltingManager.class, Color.YELLOW,
ImmutableList.of(SubSkillType.SMELTING_UNDERSTANDING_THE_ART, /*SubSkillType.SMELTING_FLUX_MINING,*/ SubSkillType.SMELTING_FUEL_EFFICIENCY, SubSkillType.SMELTING_SECOND_SMELT)),
SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbilityType.SERRATED_STRIKES, ToolType.SWORD,
ImmutableList.of(SubSkillType.SWORDS_SERRATED_STRIKES, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK, SubSkillType.SWORDS_STAB, SubSkillType.SWORDS_RUPTURE, SubSkillType.SWORDS_COUNTER_ATTACK)),
TAMING(TamingManager.class, Color.PURPLE,
ImmutableList.of(SubSkillType.TAMING_BEAST_LORE, SubSkillType.TAMING_CALL_OF_THE_WILD, SubSkillType.TAMING_ENVIRONMENTALLY_AWARE, SubSkillType.TAMING_FAST_FOOD_SERVICE, SubSkillType.TAMING_GORE, SubSkillType.TAMING_HOLY_HOUND, SubSkillType.TAMING_SHARPENED_CLAWS, SubSkillType.TAMING_SHOCK_PROOF, SubSkillType.TAMING_THICK_FUR, SubSkillType.TAMING_PUMMEL)),
UNARMED(UnarmedManager.class, Color.BLACK, SuperAbilityType.BERSERK, ToolType.FISTS,
ImmutableList.of(SubSkillType.UNARMED_BERSERK, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK, SubSkillType.UNARMED_BLOCK_CRACKER, SubSkillType.UNARMED_ARROW_DEFLECT, SubSkillType.UNARMED_DISARM, SubSkillType.UNARMED_IRON_ARM_STYLE, SubSkillType.UNARMED_IRON_GRIP)),
WOODCUTTING(WoodcuttingManager.class, Color.OLIVE, SuperAbilityType.TREE_FELLER, ToolType.AXE,
ImmutableList.of(SubSkillType.WOODCUTTING_LEAF_BLOWER, SubSkillType.WOODCUTTING_TREE_FELLER, SubSkillType.WOODCUTTING_HARVEST_LUMBER));
private Class<? extends SkillManager> managerClass;
private Color runescapeColor;
private Color skillColor;
private SuperAbilityType ability;
private ToolType tool;
private List<SubSkillType> subSkillTypes;
@@ -96,13 +110,13 @@ public enum PrimarySkillType {
NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
}
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color runescapeColor, List<SubSkillType> subSkillTypes) {
this(managerClass, runescapeColor, null, null, subSkillTypes);
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, List<SubSkillType> subSkillTypes) {
this(managerClass, skillColor, null, null, subSkillTypes);
}
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color runescapeColor, SuperAbilityType ability, ToolType tool, List<SubSkillType> subSkillTypes) {
private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, SuperAbilityType ability, ToolType tool, List<SubSkillType> subSkillTypes) {
this.managerClass = managerClass;
this.runescapeColor = runescapeColor;
this.skillColor = skillColor;
this.ability = ability;
this.tool = tool;
this.subSkillTypes = subSkillTypes;
@@ -228,9 +242,9 @@ public enum PrimarySkillType {
return Permissions.skillEnabled(player, this);
}
public void celebrateLevelUp(Player player) {
ParticleEffectUtils.fireworkParticleShower(player, runescapeColor);
}
/* public void celebrateLevelUp(Player player) {
ParticleEffectUtils.fireworkParticleShower(player, skillColor);
}*/
public boolean shouldProcess(Entity target) {
return (target instanceof Player || (target instanceof Tameable && ((Tameable) target).isTamed())) ? getPVPEnabled() : getPVEEnabled();

View File

@@ -3,6 +3,8 @@ package com.gmail.nossr50.datatypes.skills;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.StringUtils;
import java.util.Locale;
public enum SubSkillType {
/* !! Warning -- Do not let subskills share a name with any existing PrimarySkillType as it will clash with the static import !! */
@@ -18,10 +20,12 @@ public enum SubSkillType {
ARCHERY_ARROW_RETRIEVAL(1),
ARCHERY_DAZE,
ARCHERY_SKILL_SHOT(20),
ARCHERY_ARCHERY_LIMIT_BREAK(10),
/* Axes */
AXES_ARMOR_IMPACT(20),
AXES_AXE_MASTERY(4),
AXES_AXES_LIMIT_BREAK(10),
AXES_CRITICAL_STRIKES(1),
AXES_GREATER_IMPACT(1),
AXES_SKULL_SPLITTER(1),
@@ -39,7 +43,7 @@ public enum SubSkillType {
FISHING_SHAKE(1),
/* Herbalism */
HERBALISM_DOUBLE_DROPS,
HERBALISM_DOUBLE_DROPS(1),
HERBALISM_FARMERS_DIET(5),
HERBALISM_GREEN_TERRA(1),
HERBALISM_GREEN_THUMB(4),
@@ -50,7 +54,7 @@ public enum SubSkillType {
MINING_BIGGER_BOMBS(1),
MINING_BLAST_MINING(8),
MINING_DEMOLITIONS_EXPERTISE(1),
MINING_DOUBLE_DROPS,
MINING_DOUBLE_DROPS(1),
MINING_SUPER_BREAKER(1),
/* Repair */
@@ -59,12 +63,11 @@ public enum SubSkillType {
REPAIR_SUPER_REPAIR(1),
/* Salvage */
SALVAGE_ADVANCED_SALVAGE(1),
SALVAGE_SCRAP_COLLECTOR(8),
SALVAGE_ARCANE_SALVAGE(8),
/* Smelting */
SMELTING_FLUX_MINING(1),
SMELTING_FUEL_EFFICIENCY,
SMELTING_FUEL_EFFICIENCY(3),
SMELTING_SECOND_SMELT,
SMELTING_UNDERSTANDING_THE_ART(8),
@@ -72,6 +75,8 @@ public enum SubSkillType {
SWORDS_COUNTER_ATTACK(1),
SWORDS_RUPTURE(4),
SWORDS_SERRATED_STRIKES(1),
SWORDS_STAB(2),
SWORDS_SWORDS_LIMIT_BREAK(10),
/* Taming */
TAMING_BEAST_LORE(1),
@@ -92,6 +97,7 @@ public enum SubSkillType {
UNARMED_DISARM(1),
UNARMED_IRON_ARM_STYLE(5),
UNARMED_IRON_GRIP(1),
UNARMED_UNARMED_LIMIT_BREAK(10),
/* Woodcutting */
/* WOODCUTTING_BARK_SURGEON(3),*/
@@ -153,7 +159,7 @@ public enum SubSkillType {
public String getPermissionNodeAddress()
{
//TODO: This could be optimized
return "mcmmo.ability." + getParentSkill().toString().toLowerCase() + "." + getConfigName(toString()).toLowerCase();
return "mcmmo.ability." + getParentSkill().toString().toLowerCase(Locale.ENGLISH) + "." + getConfigName(toString()).toLowerCase(Locale.ENGLISH);
}
/**

View File

@@ -1,6 +1,7 @@
package com.gmail.nossr50.datatypes.skills;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
@@ -198,7 +199,7 @@ public enum SuperAbilityType {
public boolean blockCheck(BlockState blockState) {
switch (this) {
case BERSERK:
return (BlockUtils.affectedByGigaDrillBreaker(blockState) || blockState.getType() == Material.SNOW);
return (BlockUtils.affectedByGigaDrillBreaker(blockState) || blockState.getType() == Material.SNOW || mcMMO.getMaterialMapStore().isGlass(blockState.getType()));
case GIGA_DRILL_BREAKER:
return BlockUtils.affectedByGigaDrillBreaker(blockState);

View File

@@ -1,9 +1,7 @@
package com.gmail.nossr50.datatypes.skills.subskills.acrobatics;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.LimitedSizeList;
import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
@@ -12,6 +10,7 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
@@ -34,14 +33,13 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Locale;
public class Roll extends AcrobaticsSubSkill {
protected HashMap<Player, LimitedSizeList> fallLocationMap;
public Roll() {
super("Roll", EventPriority.HIGHEST, SubSkillType.ACROBATICS_ROLL);
fallLocationMap = new HashMap<>();
}
/**
@@ -73,6 +71,9 @@ public class Roll extends AcrobaticsSubSkill {
//Grab the player
McMMOPlayer mcMMOPlayer = EventUtils.getMcMMOPlayer(entityDamageEvent.getEntity());
if(mcMMOPlayer == null)
break;
/*
* Check for success
*/
@@ -101,7 +102,7 @@ public class Roll extends AcrobaticsSubSkill {
*/
@Override
public String getPermissionNode() {
return ("mcmmo.ability."+getPrimaryKeyName()+"."+getConfigKeyName()).toLowerCase();
return ("mcmmo.ability."+getPrimaryKeyName()+"."+getConfigKeyName()).toLowerCase(Locale.ENGLISH);
}
/**
@@ -210,7 +211,7 @@ public class Roll extends AcrobaticsSubSkill {
//player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
//if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
if(!isExploiting(player))
if(!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
//}
@@ -219,7 +220,7 @@ public class Roll extends AcrobaticsSubSkill {
}
else if (!isFatal(player, damage)) {
//if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
if(!isExploiting(player))
if(!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
//}
}
@@ -249,14 +250,14 @@ public class Roll extends AcrobaticsSubSkill {
{
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc");
SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F);
if(!isExploiting(player))
if(!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
addFallLocation(player);
return modifiedDamage;
}
else if (!isFatal(player, damage)) {
if(!isExploiting(player))
if(!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
addFallLocation(player);
@@ -272,36 +273,35 @@ public class Roll extends AcrobaticsSubSkill {
* @return true if exploits are detected, false otherwise
*/
private boolean isExploiting(Player player) {
if (!Config.getInstance().getAcrobaticsPreventAFK()) {
if (!ExperienceConfig.getInstance().isAcrobaticsExploitingPrevented()) {
return false;
}
if (player.getInventory().getItemInMainHand().getType() == Material.ENDER_PEARL || player.isInsideVehicle()) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if (ItemUtils.hasItemInEitherHand(player, Material.ENDER_PEARL) || player.isInsideVehicle()) {
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage("Acrobatics XP Prevented: Ender Pearl or Inside Vehicle");
}
return true;
}
if(fallLocationMap.get(player) == null)
fallLocationMap.put(player, new LimitedSizeList(50));
if(UserManager.getPlayer(player).getAcrobaticsManager().hasFallenInLocationBefore(getBlockLocation(player)))
{
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage("Acrobatics XP Prevented: Fallen in location before");
}
LimitedSizeList fallLocations = fallLocationMap.get(player);
if(fallLocations.contains(getBlockLocation(player)))
return true;
}
return false; //NOT EXPLOITING
/*
Location fallLocation = player.getLocation();
int maxTries = Config.getInstance().getAcrobaticsAFKMaxTries();
boolean sameLocation = (lastFallLocation != null && Misc.isNear(lastFallLocation, fallLocation, 2));
fallTries = sameLocation ? Math.min(fallTries + 1, maxTries) : Math.max(fallTries - 1, 0);
lastFallLocation = fallLocation;
return fallTries + 1 > maxTries;*/
}
private float calculateRollXP(Player player, double damage, boolean isRoll) {
//Clamp Damage to account for insane DRs
damage = Math.min(40, damage);
ItemStack boots = player.getInventory().getBoots();
float xp = (float) (damage * (isRoll ? ExperienceConfig.getInstance().getRollXPModifier() : ExperienceConfig.getInstance().getFallXPModifier()));
@@ -426,13 +426,7 @@ public class Roll extends AcrobaticsSubSkill {
public void addFallLocation(Player player)
{
if(fallLocationMap.get(player) == null)
fallLocationMap.put(player, new LimitedSizeList(50));
LimitedSizeList fallLocations = fallLocationMap.get(player);
Location loc = getBlockLocation(player);
fallLocations.add(loc);
UserManager.getPlayer(player).getAcrobaticsManager().addLocationToFallMap(getBlockLocation(player));
}
public Location getBlockLocation(Player player)

View File

@@ -0,0 +1,26 @@
package com.gmail.nossr50.datatypes.skills.subskills.taming;
import com.gmail.nossr50.util.StringUtils;
import org.bukkit.entity.EntityType;
public enum CallOfTheWildType {
WOLF,
CAT,
HORSE;
//TODO: This is a hacky fix to make the COTW code in 2.1 more bearable, this will be removed upon the rework planned for COTW
public String getConfigEntityTypeEntry() {
switch(this) {
case CAT:
return StringUtils.getPrettyEntityTypeString(EntityType.OCELOT); //Even though cats will be summoned in 1.14, we specify Ocelot here. This will be gone in 2.2
case WOLF:
return StringUtils.getPrettyEntityTypeString(EntityType.WOLF);
case HORSE:
return StringUtils.getPrettyEntityTypeString(EntityType.HORSE);
}
return null;
}
}

View File

@@ -0,0 +1,87 @@
package com.gmail.nossr50.datatypes.skills.subskills.taming;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
/**
* Data Container for properties used in summoning an entity via COTW
*/
public class TamingSummon {
private Material itemType;
private int itemAmountRequired;
private int entitiesSummoned;
private int summonLifespan;
private int summonCap;
private CallOfTheWildType callOfTheWildType;
private EntityType entityType;
public TamingSummon(CallOfTheWildType callOfTheWildType, Material itemType, int itemAmountRequired, int entitiesSummoned, int summonLifespan, int summonCap) {
this.callOfTheWildType = callOfTheWildType;
this.itemType = itemType;
this.itemAmountRequired = Math.max(itemAmountRequired, 1);
this.entitiesSummoned = Math.max(entitiesSummoned, 1);
this.summonLifespan = summonLifespan;
this.summonCap = Math.max(summonCap, 1);
initEntityType();
}
private void initEntityType() {
switch(callOfTheWildType) {
case WOLF:
entityType = EntityType.WOLF;
break;
case HORSE:
entityType = EntityType.HORSE;
break;
case CAT:
if(shouldSpawnCatInsteadOfOcelot()) {
//Server is on 1.14 or above
entityType = EntityType.CAT;
} else {
//Server is not on 1.14 or above
entityType = EntityType.OCELOT;
}
}
}
private boolean shouldSpawnCatInsteadOfOcelot() {
try {
Class<?> clazz = Class.forName("org.bukkit.entity.Panda");
//Panda exists which means this is at least 1.14, so we should spawn a cat instead of ocelot
return true;
} catch (ClassNotFoundException e) {
/*e.printStackTrace();*/
return false;
}
}
public EntityType getEntityType() {
return entityType;
}
public Material getItemType() {
return itemType;
}
public int getItemAmountRequired() {
return itemAmountRequired;
}
public int getEntitiesSummoned() {
return entitiesSummoned;
}
public int getSummonLifespan() {
return summonLifespan;
}
public int getSummonCap() {
return summonCap;
}
public CallOfTheWildType getCallOfTheWildType() {
return callOfTheWildType;
}
}

View File

@@ -0,0 +1,44 @@
package com.gmail.nossr50.events.players;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class McMMOPlayerProfileLoadEvent extends Event implements Cancellable {
private boolean cancelled;
private PlayerProfile profile;
private Player player;
public McMMOPlayerProfileLoadEvent(Player player, PlayerProfile profile){
super(!Bukkit.isPrimaryThread());
this.cancelled = false;
this.profile = profile;
this.player = player;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
public PlayerProfile getProfile(){return this.profile;}
private static final HandlerList handlers = new HandlerList();
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() {return player;}
}

View File

@@ -5,13 +5,13 @@ import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
* This event is sent for when mcMMO informs a player about various important information
*/
public class McMMOPlayerNotificationEvent extends PlayerEvent implements Cancellable {
public class McMMOPlayerNotificationEvent extends Event implements Cancellable {
private boolean isCancelled;
/*
* Messages can be sent to both places, as configured in advanced.yml
@@ -27,7 +27,7 @@ public class McMMOPlayerNotificationEvent extends PlayerEvent implements Cancell
protected final NotificationType notificationType;
public McMMOPlayerNotificationEvent(Player who, NotificationType notificationType, TextComponent notificationTextComponent, ChatMessageType chatMessageType, boolean isMessageAlsoBeingSentToChat) {
super(who);
super(false);
this.notificationType = notificationType;
this.notificationTextComponent = notificationTextComponent;
this.chatMessageType = chatMessageType;

View File

@@ -4,6 +4,7 @@ import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.config.WorldBlacklist;
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.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
@@ -13,7 +14,6 @@ import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.alchemy.Alchemy;
import com.gmail.nossr50.skills.excavation.ExcavationManager;
import com.gmail.nossr50.skills.herbalism.Herbalism;
import com.gmail.nossr50.skills.herbalism.HerbalismManager;
import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.repair.Repair;
@@ -29,22 +29,18 @@ import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import java.util.HashSet;
import java.util.List;
public class BlockListener implements Listener {
@@ -54,6 +50,66 @@ public class BlockListener implements Listener {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockDropItemEvent(BlockDropItemEvent event)
{
//Track how many "things" are being dropped
HashSet<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
int blockCount = 0;
for(Item item : event.getItems()) {
//Track unique materials
uniqueMaterials.add(item.getItemStack().getType());
//Count blocks as a second failsafe
if(item.getItemStack().getType().isBlock())
blockCount++;
}
if(uniqueMaterials.size() > 1) {
//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
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(blockCount <= 1) {
for(Item item : event.getItems())
{
ItemStack is = new ItemStack(item.getItemStack());
if(is.getAmount() <= 0)
continue;
//TODO: Ignore this abomination its rewritten in 2.2
if(!Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.MINING, is.getType())
&& !Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.HERBALISM, is.getType())
&& !Config.getInstance().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, is.getType()))
continue;
//If we suspect TEs might be duped only reward block
if(dontRewardTE) {
if(!is.getType().isBlock()) {
continue;
}
}
if (event.getBlock().getMetadata(mcMMO.BONUS_DROPS_METAKEY).size() > 0) {
BonusDropMeta bonusDropMeta = (BonusDropMeta) event.getBlock().getMetadata(mcMMO.BONUS_DROPS_METAKEY).get(0);
int bonusCount = bonusDropMeta.asInt();
for (int i = 0; i < bonusCount; i++) {
event.getBlock().getWorld().dropItemNaturally(event.getBlockState().getLocation(), is);
}
}
}
}
if(event.getBlock().hasMetadata(mcMMO.BONUS_DROPS_METAKEY))
event.getBlock().removeMetadata(mcMMO.BONUS_DROPS_METAKEY, plugin);
}
/**
* Monitor BlockPistonExtend events.
*
@@ -65,12 +121,16 @@ public class BlockListener implements Listener {
if(WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld()))
return;
if(!ExperienceConfig.getInstance().isPistonCheatingPrevented()) {
return;
}
BlockFace direction = event.getDirection();
Block movedBlock = event.getBlock();
movedBlock = movedBlock.getRelative(direction, 2);
for (Block b : event.getBlocks()) {
if (BlockUtils.shouldBeWatched(b.getState()) && mcMMO.getPlaceStore().isTrue(b)) {
if (BlockUtils.shouldBeWatched(b.getState())) {
movedBlock = b.getRelative(direction);
mcMMO.getPlaceStore().setTrue(movedBlock);
}
@@ -88,6 +148,10 @@ public class BlockListener implements Listener {
if(WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld()))
return;
if(!ExperienceConfig.getInstance().isPistonCheatingPrevented()) {
return;
}
// Get opposite direction so we get correct block
BlockFace direction = event.getDirection();
Block movedBlock = event.getBlock().getRelative(direction);
@@ -111,39 +175,28 @@ public class BlockListener implements Listener {
if(WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld()))
return;
if(BlockUtils.shouldBeWatched(event.getBlock().getState()))
BlockState blockState = event.getNewState();
if(ExperienceConfig.getInstance().isSnowExploitPrevented() && BlockUtils.shouldBeWatched(blockState))
{
mcMMO.getPlaceStore().setTrue(event.getBlock());
mcMMO.getPlaceStore().setTrue(blockState.getBlock());
}
}
/**
* Monitor falling blocks.
*
* @param event The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onFallingBlock(EntityChangeBlockEvent event) {
public void onBlockFormEvent(BlockFormEvent event)
{
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld()))
return;
if (BlockUtils.shouldBeWatched(event.getBlock().getState()) && event.getEntityType().equals(EntityType.FALLING_BLOCK)) {
if (event.getTo().equals(Material.AIR) && mcMMO.getPlaceStore().isTrue(event.getBlock())) {
event.getEntity().setMetadata("mcMMOBlockFall", new FixedMetadataValue( plugin, event.getBlock().getLocation()));
} else {
List<MetadataValue> values = event.getEntity().getMetadata( "mcMMOBlockFall" );
if (!values.isEmpty()) {
if (values.get(0).value() == null) return;
Block spawn = ((org.bukkit.Location) values.get(0).value()).getBlock();
mcMMO.getPlaceStore().setTrue( event.getBlock() );
mcMMO.getPlaceStore().setFalse( spawn );
}
if(ExperienceConfig.getInstance().preventStoneLavaFarming())
{
if(event.getNewState().getType() != Material.OBSIDIAN
&& BlockUtils.shouldBeWatched(event.getNewState())
&& ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, event.getNewState().getBlockData()))
{
mcMMO.getPlaceStore().setTrue(event.getNewState());
}
}
}
@@ -176,6 +229,9 @@ public class BlockListener implements Listener {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if(mcMMOPlayer == null)
return;
if (blockState.getType() == Repair.anvilMaterial && PrimarySkillType.REPAIR.getPermissions(player)) {
mcMMOPlayer.getRepairManager().placedAnvilCheck();
}
@@ -269,6 +325,11 @@ public class BlockListener implements Listener {
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Check if profile is loaded
if(mcMMOPlayer == null)
return;
ItemStack heldItem = player.getInventory().getItemInMainHand();
/* HERBALISM */
@@ -285,8 +346,13 @@ public class BlockListener implements Listener {
* Instead, we check it inside the drops handler.
*/
if (PrimarySkillType.HERBALISM.getPermissions(player)) {
herbalismManager.herbalismBlockCheck(blockState);
herbalismManager.processHerbalismBlockBreakEvent(event);
}
/*
* We return here so that we don't unmark any affected blocks
* due to special checks managing this on their own:
*/
return;
}
/* MINING */
@@ -348,14 +414,15 @@ public class BlockListener implements Listener {
return;
}
BlockState blockState = event.getBlock().getState();
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (Herbalism.isRecentlyRegrown(blockState)) {
event.setCancelled(true);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
BlockState blockState = event.getBlock().getState();
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (ItemUtils.isSword(heldItem)) {
HerbalismManager herbalismManager = UserManager.getPlayer(player).getHerbalismManager();
@@ -413,6 +480,12 @@ public class BlockListener implements Listener {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Profile not loaded
if(mcMMOPlayer == null)
{
return;
}
/*
* ABILITY PREPARATION CHECKS
*
@@ -433,8 +506,23 @@ public class BlockListener implements Listener {
else if (mcMMOPlayer.getToolPreparationMode(ToolType.SHOVEL) && ItemUtils.isShovel(heldItem) && BlockUtils.affectedByGigaDrillBreaker(blockState) && Permissions.gigaDrillBreaker(player)) {
mcMMOPlayer.checkAbilityActivation(PrimarySkillType.EXCAVATION);
}
else if (mcMMOPlayer.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockUtils.affectedByGigaDrillBreaker(blockState) || blockState.getType() == Material.SNOW || BlockUtils.affectedByBlockCracker(blockState) && Permissions.berserk(player))) {
else if (mcMMOPlayer.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockUtils.affectedByGigaDrillBreaker(blockState)
|| mcMMO.getMaterialMapStore().isGlass(blockState.getType())
|| blockState.getType() == Material.SNOW
|| BlockUtils.affectedByBlockCracker(blockState) && Permissions.berserk(player))) {
mcMMOPlayer.checkAbilityActivation(PrimarySkillType.UNARMED);
if(mcMMOPlayer.getAbilityMode(SuperAbilityType.BERSERK)) {
if (SuperAbilityType.BERSERK.blockCheck(blockState) && EventUtils.simulateBlockBreak(blockState.getBlock(), player, true)) {
event.setInstaBreak(true);
if(blockState.getType().getKey().getKey().contains("glass")) {
SoundManager.worldSendSound(player.getWorld(), blockState.getLocation(), SoundType.GLASS);
} else {
SoundManager.sendSound(player, blockState.getLocation(), SoundType.POP);
}
}
}
}
}
@@ -487,6 +575,13 @@ public class BlockListener implements Listener {
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
ItemStack heldItem = player.getInventory().getItemInMainHand();
Block block = event.getBlock();
BlockState blockState = block.getState();
@@ -497,20 +592,25 @@ public class BlockListener implements Listener {
* We don't need to check permissions here because they've already been checked for the ability to even activate.
*/
if (mcMMOPlayer.getAbilityMode(SuperAbilityType.GREEN_TERRA) && BlockUtils.canMakeMossy(blockState)) {
if (mcMMOPlayer.getHerbalismManager().processGreenTerra(blockState)) {
if (mcMMOPlayer.getHerbalismManager().processGreenTerraBlockConversion(blockState)) {
blockState.update(true);
}
}
else if (mcMMOPlayer.getAbilityMode(SuperAbilityType.BERSERK) && heldItem.getType() == Material.AIR) {
if (SuperAbilityType.BERSERK.blockCheck(block.getState()) && EventUtils.simulateBlockBreak(block, player, true)) {
event.setInstaBreak(true);
SoundManager.sendSound(player, block.getLocation(), SoundType.POP);
}
else if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && BlockUtils.affectedByBlockCracker(blockState) && EventUtils.simulateBlockBreak(block, player, true)) {
if (mcMMOPlayer.getUnarmedManager().blockCrackerCheck(blockState)) {
else if (mcMMOPlayer.getAbilityMode(SuperAbilityType.BERSERK) && (heldItem.getType() == Material.AIR || Config.getInstance().getUnarmedItemsAsUnarmed())) {
if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && BlockUtils.affectedByBlockCracker(blockState)) {
if (EventUtils.simulateBlockBreak(block, player, true) && mcMMOPlayer.getUnarmedManager().blockCrackerCheck(blockState)) {
blockState.update();
}
}
else if (!event.getInstaBreak() && SuperAbilityType.BERSERK.blockCheck(blockState) && EventUtils.simulateBlockBreak(block, player, true)) {
event.setInstaBreak(true);
if(blockState.getType().getKey().getKey().contains("glass")) {
SoundManager.worldSendSound(player.getWorld(), block.getLocation(), SoundType.GLASS);
} else {
SoundManager.sendSound(player, block.getLocation(), SoundType.POP);
}
}
}
else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && BlockUtils.isLeaves(blockState) && EventUtils.simulateBlockBreak(block, player, true)) {
event.setInstaBreak(true);
@@ -522,6 +622,14 @@ public class BlockListener implements Listener {
public void onBlockDamageCleanup(BlockDamageEvent event) {
Player player = event.getPlayer();
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
BlockState blockState = event.getBlock().getState();
ItemStack heldItem = player.getInventory().getItemInMainHand();
@@ -531,8 +639,16 @@ public class BlockListener implements Listener {
debugStickDump(player, blockState);
}
public void debugStickDump(Player player, BlockState blockState) {
if(player.getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK)
//TODO: Rewrite this
//TODO: Convert into locale strings
private void debugStickDump(Player player, BlockState blockState) {
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
if(UserManager.getPlayer(player).isDebugMode())
{
if(mcMMO.getPlaceStore().isTrue(blockState))
player.sendMessage("[mcMMO DEBUG] This block is not natural and does not reward treasures/XP");
@@ -573,10 +689,12 @@ public class BlockListener implements Listener {
if(ExperienceConfig.getInstance().isExperienceBarsEnabled())
player.sendMessage("[mcMMO DEBUG] XP bars are enabled, however you should check per-skill settings to make sure those are enabled.");
player.sendMessage(ChatColor.RED+"You can turn this debug info off by typing "+ChatColor.GOLD+"/mmodebug");
}
}
public void cleanupAbilityTools(Player player, McMMOPlayer mcMMOPlayer, BlockState blockState, ItemStack heldItem) {
private void cleanupAbilityTools(Player player, McMMOPlayer mcMMOPlayer, BlockState blockState, ItemStack heldItem) {
if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
if ((ItemUtils.isPickaxe(heldItem) && !mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER)) || (ItemUtils.isShovel(heldItem) && !mcMMOPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER))) {
SkillUtils.removeAbilityBuff(heldItem);

View File

@@ -4,7 +4,6 @@ import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.WorldBlacklist;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.meta.OldName;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.InteractType;
@@ -14,16 +13,19 @@ import com.gmail.nossr50.events.fake.FakeEntityTameEvent;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.skills.archery.Archery;
import com.gmail.nossr50.skills.fishing.Fishing;
import com.gmail.nossr50.skills.mining.BlastMining;
import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.taming.Taming;
import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.Material;
@@ -31,22 +33,19 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.*;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.*;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
import java.util.List;
public class EntityListener implements Listener {
private final mcMMO plugin;
@@ -54,16 +53,35 @@ public class EntityListener implements Listener {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityTransform(EntityTransformEvent event)
{
//Transfer metadata keys from mob-spawned mobs to new mobs
if(event.getEntity().getMetadata(mcMMO.entityMetadataKey) != null || event.getEntity().getMetadata(mcMMO.entityMetadataKey).size() >= 1)
{
for(Entity entity : event.getTransformedEntities())
{
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityTargetEntity(EntityTargetLivingEntityEvent event)
{
if(!ExperienceConfig.getInstance().isEndermanEndermiteFarmingPrevented())
return;
//It's rare but targets can be null sometimes
if(event.getTarget() == null)
{
return;
}
//Prevent entities from giving XP if they target endermite
if(event.getTarget() instanceof Endermite)
{
if(event.getEntity().getMetadata(mcMMO.entityMetadataKey) == null || event.getEntity().getMetadata(mcMMO.entityMetadataKey).size() <= 0)
if(!event.getEntity().hasMetadata(mcMMO.entityMetadataKey))
event.getEntity().setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
}
@@ -94,7 +112,8 @@ public class EntityListener implements Listener {
ItemStack bow = event.getBow();
if (bow != null && bow.containsEnchantment(Enchantment.ARROW_INFINITE)) {
if (bow != null
&& bow.containsEnchantment(Enchantment.ARROW_INFINITE)) {
projectile.setMetadata(mcMMO.infiniteArrowKey, mcMMO.metadataValue);
}
@@ -108,9 +127,9 @@ public class EntityListener implements Listener {
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
if(event.getEntity() instanceof Player)
if(event.getEntity().getShooter() instanceof Player)
{
Player player = (Player) event.getEntity();
Player player = (Player) event.getEntity().getShooter();
/* WORLD GUARD MAIN FLAG CHECK */
if(WorldGuardUtils.isWorldGuardLoaded())
@@ -118,16 +137,24 @@ public class EntityListener implements Listener {
if(!WorldGuardManager.getInstance().hasMainFlag(player))
return;
}
Projectile projectile = event.getEntity();
if(!(projectile instanceof Arrow))
return;
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, 1.0));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
for(Enchantment enchantment : player.getInventory().getItemInMainHand().getEnchantments().keySet()) {
if(enchantment.getName().equalsIgnoreCase("piercing"))
return;
}
if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {
projectile.setMetadata(mcMMO.trackedArrow, mcMMO.metadataValue);
}
}
Projectile projectile = event.getEntity();
if (!(projectile instanceof Arrow) || projectile.hasMetadata(mcMMO.bowForceKey)) {
return;
}
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, 1.0));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
}
/**
@@ -147,7 +174,9 @@ public class EntityListener implements Listener {
// When the event is fired for the falling block that changes back to a
// normal block
// event.getBlock().getType() returns AIR
if (!BlockUtils.shouldBeWatched(block.getState()) && block.getType() != Material.AIR) {
if (!BlockUtils.shouldBeWatched(block.getState())
&& block.getState().getType() != Material.WATER
&& block.getType() != Material.AIR) {
return;
}
@@ -158,6 +187,7 @@ public class EntityListener implements Listener {
if (mcMMO.getPlaceStore().isTrue(block) && !isTracked) {
mcMMO.getPlaceStore().setFalse(block);
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
else if (isTracked) {
@@ -173,6 +203,76 @@ public class EntityListener implements Listener {
}
}
/*@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityDamageDebugLowest(EntityDamageEvent event)
{
if(event instanceof FakeEntityDamageByEntityEvent)
return;
if(event instanceof FakeEntityDamageEvent)
return;
Bukkit.broadcastMessage(ChatColor.DARK_AQUA+"DMG Before Events: "
+ChatColor.RESET+event.getDamage());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityDamageDebugMonitor(EntityDamageEvent event)
{
if(event instanceof FakeEntityDamageByEntityEvent)
return;
if(event instanceof FakeEntityDamageEvent)
return;
if(!(event.getEntity() instanceof LivingEntity))
return;
LivingEntity entity = (LivingEntity) event.getEntity();
double rawDamage = event.getDamage();
double dmgAfterReduction = event.getFinalDamage();
Bukkit.broadcastMessage(ChatColor.GOLD+"DMG After Events: "
+ event.getEntity().getName()+ChatColor.RESET
+"RawDMG["+rawDamage+"], "
+"FinalDMG=["+dmgAfterReduction+"]");
Bukkit.broadcastMessage(
event.getEntity().getName()
+ChatColor.GREEN
+" HP "
+ChatColor.RESET
+entity.getHealth()
+ChatColor.YELLOW
+" -> "
+ChatColor.RESET
+(entity.getHealth()-event.getFinalDamage()));
Bukkit.broadcastMessage("");
}*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityCombustByEntityEvent(EntityCombustByEntityEvent event) {
//Prevent players from setting fire to each other if they are in the same party
if(event.getEntity() instanceof Player) {
Player defender = (Player) event.getEntity();
if(event.getCombuster() instanceof Projectile) {
Projectile projectile = (Projectile) event.getCombuster();
if(projectile.getShooter() instanceof Player) {
Player attacker = (Player) projectile.getShooter();
if(checkParties(event, defender, attacker))
return;
}
} else if(event.getCombuster() instanceof Player) {
Player attacker = (Player) event.getCombuster();
if(checkParties(event, defender, attacker))
return;
}
}
}
/**
* Handle EntityDamageByEntity events that involve modifying the event.
*
@@ -181,6 +281,29 @@ public class EntityListener implements Listener {
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
double damage = event.getFinalDamage();
Entity defender = event.getEntity();
Entity attacker = event.getDamager();
if(WorldGuardUtils.isWorldGuardLoaded())
{
if(attacker instanceof Player) {
if(!WorldGuardManager.getInstance().hasMainFlag((Player) attacker))
return;
} else if(attacker instanceof Projectile) {
Projectile projectile = (Projectile) attacker;
if(projectile.getShooter() instanceof Player) {
if(!WorldGuardManager.getInstance().hasMainFlag((Player) projectile.getShooter()))
return;
}
}
}
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
@@ -189,6 +312,17 @@ public class EntityListener implements Listener {
return;
}
// Don't process this event for marked entities, for players this is handled above,
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes
// properly
if (defender.getMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY).size() > 0) {
return;
}
if (CombatUtils.isProcessingNoInvulnDamage()) {
return;
}
if (event.getEntity() instanceof ArmorStand) {
return;
}
@@ -199,49 +333,7 @@ public class EntityListener implements Listener {
return;
}
double damage = event.getFinalDamage();
Entity defender = event.getEntity();
Entity attacker = event.getDamager();
if(attacker instanceof Player)
{
Player player = (Player) attacker;
/* WORLD GUARD MAIN FLAG CHECK */
if(WorldGuardUtils.isWorldGuardLoaded())
{
if(!WorldGuardManager.getInstance().hasMainFlag(player))
return;
}
}
if (damage <= 0) {
if (defender instanceof Player && attacker instanceof Player) {
Player defendingPlayer = (Player) defender;
Player attackingPlayer = (Player) attacker;
if (event.getDamage(DamageModifier.ABSORPTION) > 0) {
//If friendly fire is off don't allow players to hurt one another
if(!Config.getInstance().getPartyFriendlyFire())
if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
event.setCancelled(true);
return;
}
}
}
return;
}
/*
As far as I can tell at one point we registered meta-data about custom damage and we no longer do that.
if (defender.hasMetadata(mcMMO.customDamageKey)) {
defender.removeMetadata(mcMMO.customDamageKey, plugin);
return;
}
*/
if (Misc.isNPCEntity(defender) || !defender.isValid() || !(defender instanceof LivingEntity)) {
if (Misc.isNPCEntityExcludingVillagers(defender) || !defender.isValid() || !(defender instanceof LivingEntity)) {
return;
}
@@ -251,20 +343,11 @@ public class EntityListener implements Listener {
return;
}
if (Misc.isNPCEntity(attacker)) {
if (Misc.isNPCEntityExcludingVillagers(attacker)) {
return;
}
if (attacker instanceof Projectile) {
ProjectileSource projectileSource = ((Projectile) attacker).getShooter();
if (projectileSource instanceof LivingEntity) {
attacker = (LivingEntity) projectileSource;
}
}
else if (attacker instanceof Tameable) {
if (attacker instanceof Tameable) {
AnimalTamer animalTamer = ((Tameable) attacker).getOwner();
if (animalTamer != null && ((OfflinePlayer) animalTamer).isOnline()) {
@@ -277,26 +360,66 @@ public class EntityListener implements Listener {
}
}
if (defender instanceof Player && attacker instanceof Player) {
//Friendly fire checks
if (defender instanceof Player) {
Player defendingPlayer = (Player) defender;
Player attackingPlayer = (Player) attacker;
Player attackingPlayer;
if (!UserManager.hasPlayerDataKey(defendingPlayer) || !UserManager.hasPlayerDataKey(attackingPlayer)) {
return;
}
//If the attacker is a Player or a projectile beloning to a player
if(attacker instanceof Projectile || attacker instanceof Player) {
if(attacker instanceof Projectile) {
Projectile projectile = (Projectile) attacker;
if(((Projectile) attacker).getShooter() instanceof Player) {
attackingPlayer = (Player) projectile.getShooter();
// We want to make sure we're not gaining XP or applying abilities
// when we hit ourselves
if (defendingPlayer.equals(attackingPlayer)) {
return;
}
//Check for party friendly fire and cancel the event
if (checkParties(event, defendingPlayer, attackingPlayer))
{
return;
}
//Party Friendly Fire
if(!Config.getInstance().getPartyFriendlyFire())
if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
event.setCancelled(true);
return;
}
//Deflect checks
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(defendingPlayer);
if (mcMMOPlayer != null) {
UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager();
if (unarmedManager.canDeflect()) {
if (unarmedManager.deflectCheck()) {
event.setCancelled(true);
return;
}
}
}
} else {
attackingPlayer = (Player) attacker;
//Check for party friendly fire and cancel the event
if (checkParties(event, defendingPlayer, attackingPlayer))
return;
}
}
}
//Required setup for processCombatAttack
if(attacker instanceof Projectile) {
ProjectileSource shooter = ((Projectile) attacker).getShooter();
if(shooter instanceof LivingEntity) {
attacker = (LivingEntity) shooter;
}
}
/*
* This was put here to solve a plugin conflict with a mod called Project Korra
* Project Korra sends out a damage event with exactly 0 damage
* mcMMO does some calculations for the damage in an event and it ends up dividing by zero,
* as a result of the modifiers for the event being 0 and the damage set for this event being 0.
*
* Surprising this kind of thing
*
*/
if(damage <= 0) {
return;
}
CombatUtils.processCombatAttack(event, attacker, target);
@@ -305,23 +428,39 @@ public class EntityListener implements Listener {
/**
* This sets entity names back to whatever they are supposed to be
*/
if(!(attacker instanceof Player) && defender instanceof Player)
if(event.getFinalDamage() >= target.getHealth())
{
if(event.getFinalDamage() >= ((LivingEntity) defender).getHealth())
if(attacker instanceof LivingEntity)
{
List<MetadataValue> metadataValue = attacker.getMetadata("mcMMO_oldName");
if(metadataValue.size() <= 0)
return;
if(metadataValue != null)
{
OldName oldName = (OldName) metadataValue.get(0);
attacker.setCustomName(oldName.asString());
attacker.setCustomNameVisible(false);
}
CombatUtils.fixNames((LivingEntity) attacker);
}
CombatUtils.fixNames(target);
}
}
public boolean checkParties(Cancellable event, Player defendingPlayer, Player attackingPlayer) {
if (!UserManager.hasPlayerDataKey(defendingPlayer) || !UserManager.hasPlayerDataKey(attackingPlayer)) {
return true;
}
// We want to make sure we're not gaining XP or applying abilities
// when we hit ourselves
if (defendingPlayer.equals(attackingPlayer)) {
return true;
}
//Party Friendly Fire
if(!Config.getInstance().getPartyFriendlyFire())
if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer)
|| PartyManager.areAllies(defendingPlayer, attackingPlayer))
&& !(Permissions.friendlyFire(attackingPlayer)
&& Permissions.friendlyFire(defendingPlayer))) {
event.setCancelled(true);
return true;
}
return false;
}
/**
@@ -377,7 +516,7 @@ public class EntityListener implements Listener {
}
*/
if (Misc.isNPCEntity(entity) || !entity.isValid() || !(entity instanceof LivingEntity)) {
if (Misc.isNPCEntityExcludingVillagers(entity) || !entity.isValid() || !(entity instanceof LivingEntity)) {
return;
}
@@ -398,6 +537,10 @@ public class EntityListener implements Listener {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Profile not loaded
if(mcMMOPlayer == null)
return;
/* Check for invincibility */
if (mcMMOPlayer.getGodMode()) {
event.setCancelled(true);
@@ -429,6 +572,12 @@ public class EntityListener implements Listener {
Player player = (Player) owner;
Wolf wolf = (Wolf) pet;
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
TamingManager tamingManager = UserManager.getPlayer(player).getTamingManager();
switch (cause) {
@@ -504,7 +653,7 @@ public class EntityListener implements Listener {
LivingEntity entity = event.getEntity();
if (Misc.isNPCEntity(entity)) {
if (Misc.isNPCEntityExcludingVillagers(entity)) {
return;
}
@@ -529,7 +678,7 @@ public class EntityListener implements Listener {
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(ignoreCancelled = true)
public void onEntityDeath(EntityDeathEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
@@ -537,7 +686,7 @@ public class EntityListener implements Listener {
LivingEntity entity = event.getEntity();
if (Misc.isNPCEntity(entity)) {
if (Misc.isNPCEntityExcludingVillagers(entity)) {
return;
}
@@ -550,7 +699,7 @@ public class EntityListener implements Listener {
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@EventHandler(priority = EventPriority.MONITOR)
public void onCreatureSpawn(CreatureSpawnEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
@@ -580,6 +729,28 @@ public class EntityListener implements Listener {
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityBreed(EntityBreedEvent event) {
if(ExperienceConfig.getInstance().isCOTWBreedingPrevented()) {
if(event.getFather().hasMetadata(mcMMO.COTW_TEMPORARY_SUMMON) || event.getMother().hasMetadata(mcMMO.COTW_TEMPORARY_SUMMON)) {
event.setCancelled(true);
Animals mom = (Animals) event.getMother();
Animals father = (Animals) event.getFather();
//Prevent love mode spam
mom.setLoveModeTicks(0);
father.setLoveModeTicks(0);
//Inform the player
if(event.getBreeder() instanceof Player) {
Player player = (Player) event.getBreeder();
NotificationManager.sendPlayerInformationChatOnly(player, "Taming.Summon.COTW.BreedingDisallowed");
}
}
}
}
/**
* Handle ExplosionPrime events that involve modifying the event.
*
@@ -606,6 +777,12 @@ public class EntityListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
/* WORLD GUARD MAIN FLAG CHECK */
if(WorldGuardUtils.isWorldGuardLoaded())
{
@@ -653,6 +830,12 @@ public class EntityListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
MiningManager miningManager = UserManager.getPlayer(player).getMiningManager();
if (miningManager.canUseBlastMining()) {
@@ -661,27 +844,6 @@ public class EntityListener implements Listener {
}
}
/**
* Handle EntityExplode events that involve modifying the event.
*
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityExplodeMonitor(EntityExplodeEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
Entity entity = event.getEntity();
if (!(entity instanceof TNTPrimed) || !entity.hasMetadata(mcMMO.tntsafeMetadataKey)) {
return;
}
event.blockList().clear();
}
/**
* Handle FoodLevelChange events that involve modifying the event.
*
@@ -702,6 +864,12 @@ public class EntityListener implements Listener {
Player player = (Player) entity;
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
/* WORLD GUARD MAIN FLAG CHECK */
if(WorldGuardUtils.isWorldGuardLoaded())
{
@@ -721,12 +889,24 @@ public class EntityListener implements Listener {
return;
}
//Determine which hand is eating food
//The main hand is used over the off hand if they both have food, so check the main hand first
Material foodInHand;
if(mcMMO.getMaterialMapStore().isFood(player.getInventory().getItemInMainHand().getType())) {
foodInHand = player.getInventory().getItemInMainHand().getType();
} else if(mcMMO.getMaterialMapStore().isFood(player.getInventory().getItemInOffHand().getType())) {
foodInHand = player.getInventory().getItemInOffHand().getType();
} else {
return; //Not Food
}
/*
* Some foods have 3 ranks Some foods have 5 ranks The number of ranks
* is based on how 'common' the item is We can adjust this quite easily
* if we find something is giving too much of a bonus
*/
switch (player.getInventory().getItemInMainHand().getType()) {
switch (foodInHand) {
case BAKED_POTATO: /*
* RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @
* 1000
@@ -765,19 +945,14 @@ public class EntityListener implements Listener {
event.setFoodLevel(UserManager.getPlayer(player).getHerbalismManager().farmersDiet(newFoodLevel));
}
return;
case COD:
case SALMON:
case TROPICAL_FISH:
case COOKED_COD:
case COOKED_SALMON:
case COOKED_SALMON: /*
* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @
* 1000
*/
if (Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_FISHERMANS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel1, newFoodLevel));
}
return;
case SALMON: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
if (Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_FISHERMANS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel2, newFoodLevel));
event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(newFoodLevel));
}
return;
@@ -813,11 +988,18 @@ public class EntityListener implements Listener {
LivingEntity entity = event.getEntity();
if (!UserManager.hasPlayerDataKey(player) || Misc.isNPCEntity(entity) || entity.hasMetadata(mcMMO.entityMetadataKey)) {
if (!UserManager.hasPlayerDataKey(player) || Misc.isNPCEntityExcludingVillagers(entity) || entity.hasMetadata(mcMMO.entityMetadataKey)) {
return;
}
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
UserManager.getPlayer(player).getTamingManager().awardTamingXP(entity);
}

View File

@@ -9,18 +9,14 @@ import org.bukkit.event.Event;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class InteractionManager {
private static HashMap<InteractType, ArrayList<Interaction>> interactRegister;
private static HashMap<String, AbstractSubSkill> subSkillNameMap; //Used for mmoinfo optimization
private static ArrayList<AbstractSubSkill> subSkillList;
/**
* Registers subskills with the Interaction registration
* @param abstractSubSkill the target subskill to register
*/
public static void registerSubSkill(AbstractSubSkill abstractSubSkill)
{
public static void initMaps() {
/* INIT MAPS */
if(interactRegister == null)
interactRegister = new HashMap<>();
@@ -30,7 +26,14 @@ public class InteractionManager {
if(subSkillNameMap == null)
subSkillNameMap = new HashMap<>();
}
/**
* Registers subskills with the Interaction registration
* @param abstractSubSkill the target subskill to register
*/
public static void registerSubSkill(AbstractSubSkill abstractSubSkill)
{
//Store a unique copy of each subskill
if(!subSkillList.contains(abstractSubSkill))
subSkillList.add(abstractSubSkill);
@@ -45,7 +48,7 @@ public class InteractionManager {
//Register skill
arrayRef.add(abstractSubSkill);
String lowerCaseName = abstractSubSkill.getConfigKeyName().toLowerCase();
String lowerCaseName = abstractSubSkill.getConfigKeyName().toLowerCase(Locale.ENGLISH);
//Register in name map
if(subSkillNameMap.get(lowerCaseName) == null)
@@ -62,7 +65,7 @@ public class InteractionManager {
*/
public static AbstractSubSkill getAbstractByName(String name)
{
return subSkillNameMap.get(name.toLowerCase());
return subSkillNameMap.get(name.toLowerCase(Locale.ENGLISH));
}
/**
@@ -73,6 +76,9 @@ public class InteractionManager {
*/
public static void processEvent(Event event, mcMMO plugin, InteractType curInteractType)
{
if(interactRegister.get(curInteractType) == null)
return;
for(Interaction interaction : interactRegister.get(curInteractType))
{
interaction.doInteraction(event, plugin);

View File

@@ -57,6 +57,12 @@ public class InventoryListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer((Player) player) == null)
{
return;
}
if(!furnaceBlock.hasMetadata(mcMMO.furnaceMetadataKey) && furnaceBlock.getMetadata(mcMMO.furnaceMetadataKey).size() == 0)
furnaceBlock.setMetadata(mcMMO.furnaceMetadataKey, UserManager.getPlayer((Player) player).getPlayerMetadata());
}
@@ -109,6 +115,12 @@ public class InventoryListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
event.setBurnTime(UserManager.getPlayer(player).getSmeltingManager().fuelEfficiency(event.getBurnTime()));
}
@@ -138,6 +150,12 @@ public class InventoryListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
event.setResult(UserManager.getPlayer(player).getSmeltingManager().smeltProcessing(smelting, event.getResult()));
}
@@ -166,7 +184,14 @@ public class InventoryListener implements Listener {
return;
}
int exp = UserManager.getPlayer(player).getSmeltingManager().vanillaXPBoost(event.getExpToDrop());
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
int xpToDrop = event.getExpToDrop();
int exp = UserManager.getPlayer(player).getSmeltingManager().vanillaXPBoost(xpToDrop);
event.setExpToDrop(exp);
}
@@ -188,6 +213,12 @@ public class InventoryListener implements Listener {
if (furnaceBlock.getMetadata(mcMMO.furnaceMetadataKey).size() > 0)
furnaceBlock.removeMetadata(mcMMO.furnaceMetadataKey, mcMMO.p);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
furnaceBlock.setMetadata(mcMMO.furnaceMetadataKey, UserManager.getPlayer(player).getPlayerMetadata());
}
}
@@ -367,8 +398,10 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getSource().getLocation().getWorld()))
return;
if(event.getSource().getLocation() != null)
if(WorldBlacklist.isWorldBlacklisted(event.getSource().getLocation().getWorld()))
return;
Inventory inventory = event.getDestination();

View File

@@ -10,6 +10,9 @@ import com.gmail.nossr50.datatypes.chat.ChatMode;
import com.gmail.nossr50.datatypes.party.Party;
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.datatypes.skills.subskills.taming.CallOfTheWildType;
import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.party.ShareHandler;
@@ -24,25 +27,32 @@ import com.gmail.nossr50.skills.salvage.SalvageManager;
import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.PoweredMinecart;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.Locale;
public class PlayerListener implements Listener {
private final mcMMO plugin;
@@ -62,8 +72,16 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld()))
if(WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
//Remove scoreboards
ScoreboardManager.teardownPlayer(event.getPlayer());
return;
} else if(WorldBlacklist.isWorldBlacklisted(event.getFrom().getWorld())) {
//This only fires if they are traveling to a non-blacklisted world from a blacklisted world
//Setup scoreboards
ScoreboardManager.setupPlayer(event.getPlayer());
}
Player player = event.getPlayer();
@@ -78,9 +96,14 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
UserManager.getPlayer(player).actualizeTeleportATS();
}
/**
* Handle PlayerDeathEvents at the lowest priority.
* <p>
@@ -183,6 +206,12 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
mcMMOPlayer.checkGodMode();
@@ -248,6 +277,12 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
switch (event.getState()) {
@@ -255,7 +290,7 @@ public class PlayerListener implements Listener {
//TODO Update to new API once available! Waiting for case CAUGHT_TREASURE:
Item fishingCatch = (Item) event.getCaught();
if (Config.getInstance().getFishingOverrideTreasures() &&
if (Config.getInstance(). getFishingOverrideTreasures() &&
fishingCatch.getItemStack().getType() != Material.SALMON &&
fishingCatch.getItemStack().getType() != Material.COD &&
fishingCatch.getItemStack().getType() != Material.TROPICAL_FISH &&
@@ -319,10 +354,37 @@ public class PlayerListener implements Listener {
return;
}
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
Entity caught = event.getCaught();
//event.setExpToDrop(event.getExpToDrop()); //Redundant?
FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager();
//Track the hook
if(ExperienceConfig.getInstance().isFishingExploitingPrevented())
{
if(event.getHook().getMetadata(mcMMO.FISH_HOOK_REF_METAKEY).size() == 0)
{
fishingManager.setFishHookReference(event.getHook());
}
//Spam Fishing
if(event.getState() == PlayerFishEvent.State.CAUGHT_FISH && fishingManager.isFishingTooOften())
{
event.setExpToDrop(0);
if(caught instanceof Item)
{
Item caughtItem = (Item) caught;
caughtItem.remove();
}
return;
}
}
switch (event.getState()) {
case FISHING:
@@ -331,21 +393,29 @@ public class PlayerListener implements Listener {
fishingManager.setFishingTarget();
}
return;
case CAUGHT_FISH:
if(fishingManager.exploitPrevention(event.getHook().getBoundingBox()))
return;
if(ExperienceConfig.getInstance().isFishingExploitingPrevented())
{
if(fishingManager.isExploitingFishing(event.getHook().getLocation().toVector()))
{
player.sendMessage(LocaleLoader.getString("Fishing.ScarcityTip", 3));
event.setExpToDrop(0);
Item caughtItem = (Item) caught;
caughtItem.remove();
return;
}
}
fishingManager.handleFishing((Item) caught);
fishingManager.setFishingTarget();
//fishingManager.setFishHookReference(null);
return;
case CAUGHT_ENTITY:
if (fishingManager.canShake(caught)) {
fishingManager.shakeCheck((LivingEntity) caught);
fishingManager.setFishingTarget();
}
return;
default:
return;
}
@@ -380,11 +450,22 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
Item drop = event.getItem();
ItemStack dropStack = drop.getItemStack();
//Remove tracking
if(drop.hasMetadata(mcMMO.trackedArrow)) {
drop.removeMetadata(mcMMO.trackedArrow, mcMMO.p);
}
if (drop.hasMetadata(mcMMO.disarmedItemKey)) {
if (!player.getName().equals(drop.getMetadata(mcMMO.disarmedItemKey).get(0).asString())) {
event.setCancelled(true);
@@ -432,8 +513,16 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
mcMMOPlayer.logout(false);
//There's an issue with using Async saves on player quit
//Basically there are conditions in which an async task does not execute fast enough to save the data if the server shutdown shortly after this task was scheduled
mcMMOPlayer.logout(true);
}
/**
@@ -449,17 +538,14 @@ public class PlayerListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (Misc.isNPCEntity(player)) {
return;
}
new PlayerProfileLoadingTask(player).runTaskLaterAsynchronously(mcMMO.p, 1); // 1 Tick delay to ensure the player is marked as online before we begin loading
//Delay loading for 3 seconds in case the player has a save task running, its hacky but it should do the trick
new PlayerProfileLoadingTask(player).runTaskLaterAsynchronously(mcMMO.p, 60);
if (Config.getInstance().getMOTDEnabled() && Permissions.motd(player)) {
Motd.displayAll(player);
}
if (plugin.isXPEventEnabled()) {
if (plugin.isXPEventEnabled() && Config.getInstance().playerJoinEventInfo()) {
player.sendMessage(LocaleLoader.getString("XPRate.Event", ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier()));
}
}
@@ -481,6 +567,12 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
UserManager.getPlayer(player).actualizeRespawnATS();
}
@@ -508,6 +600,12 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
MiningManager miningManager = mcMMOPlayer.getMiningManager();
Block block = event.getClickedBlock();
@@ -519,27 +617,34 @@ public class PlayerListener implements Listener {
if (!Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() || player.isSneaking()) {
/* REPAIR CHECKS */
if (type == Repair.anvilMaterial && PrimarySkillType.REPAIR.getPermissions(player) && mcMMO.getRepairableManager().isRepairable(heldItem)) {
if (type == Repair.anvilMaterial
&& PrimarySkillType.REPAIR.getPermissions(player)
&& mcMMO.getRepairableManager().isRepairable(heldItem)
&& heldItem.getAmount() <= 1) {
RepairManager repairManager = mcMMOPlayer.getRepairManager();
event.setCancelled(true);
// Make sure the player knows what he's doing when trying to repair an enchanted item
if (!(heldItem.getEnchantments().size() > 0) || repairManager.checkConfirmation(true)) {
if (repairManager.checkConfirmation(true)) {
repairManager.handleRepair(heldItem);
player.updateInventory();
}
}
/* SALVAGE CHECKS */
else if (type == Salvage.anvilMaterial && PrimarySkillType.SALVAGE.getPermissions(player) && mcMMO.getSalvageableManager().isSalvageable(heldItem)) {
SalvageManager salvageManager = UserManager.getPlayer(player).getSalvageManager();
event.setCancelled(true);
else if (type == Salvage.anvilMaterial
&& PrimarySkillType.SALVAGE.getPermissions(player)
&& RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR)
&& mcMMO.getSalvageableManager().isSalvageable(heldItem)
&& heldItem.getAmount() <= 1) {
SalvageManager salvageManager = UserManager.getPlayer(player).getSalvageManager();
event.setCancelled(true);
// Make sure the player knows what he's doing when trying to salvage an enchanted item
if (!(heldItem.getEnchantments().size() > 0) || salvageManager.checkConfirmation(true)) {
SkillUtils.handleAbilitySpeedDecrease(player);
salvageManager.handleSalvage(block.getLocation(), heldItem);
player.updateInventory();
}
// Make sure the player knows what he's doing when trying to salvage an enchanted item
if (salvageManager.checkConfirmation(true)) {
SkillUtils.handleAbilitySpeedDecrease(player);
salvageManager.handleSalvage(block.getLocation(), heldItem);
player.updateInventory();
}
}
}
/* BLAST MINING CHECK */
@@ -611,9 +716,31 @@ public class PlayerListener implements Listener {
return;
}
//Profile not loaded
if(UserManager.getPlayer(player) == null)
{
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
ItemStack heldItem = player.getInventory().getItemInMainHand();
//Spam Fishing Detection
if(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR)
{
if(ExperienceConfig.getInstance().isFishingExploitingPrevented()
&& (heldItem.getType() == Material.FISHING_ROD || player.getInventory().getItemInOffHand().getType() == Material.FISHING_ROD))
{
if(player.isInsideVehicle() && (player.getVehicle() instanceof Minecart || player.getVehicle() instanceof PoweredMinecart))
{
player.getVehicle().eject();
player.setVelocity(player.getEyeLocation().getDirection().multiply(10));
}
mcMMOPlayer.getFishingManager().setFishingRodCastTimestamp();
}
}
switch (event.getAction()) {
case RIGHT_CLICK_BLOCK:
if(player.getInventory().getItemInOffHand().getType() != Material.AIR && !player.isInsideVehicle() && !player.isSneaking()) {
@@ -656,16 +783,17 @@ public class PlayerListener implements Listener {
}
}
FakePlayerAnimationEvent fakeSwing = new FakePlayerAnimationEvent(event.getPlayer()); //PlayerAnimationEvent compat
if (herbalismManager.canGreenThumbBlock(blockState)) {
Bukkit.getPluginManager().callEvent(fakeSwing);
player.getInventory().setItemInMainHand(new ItemStack(Material.WHEAT_SEEDS, heldItem.getAmount() - 1));
if (herbalismManager.processGreenThumbBlocks(blockState) && EventUtils.simulateBlockBreak(block, player, false)) {
blockState.update(true);
}
}
/* SHROOM THUMB CHECK */
else if (herbalismManager.canUseShroomThumb(blockState)) {
Bukkit.getPluginManager().callEvent(fakeSwing);
event.setCancelled(true);
if (herbalismManager.processShroomThumb(blockState) && EventUtils.simulateBlockBreak(block, player, false)) {
blockState.update(true);
@@ -711,13 +839,13 @@ public class PlayerListener implements Listener {
Material type = heldItem.getType();
TamingManager tamingManager = mcMMOPlayer.getTamingManager();
if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.WOLF)) {
if (type == Config.getInstance().getTamingCOTWMaterial(CallOfTheWildType.WOLF.getConfigEntityTypeEntry())) {
tamingManager.summonWolf();
}
else if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.OCELOT)) {
else if (type == Config.getInstance().getTamingCOTWMaterial(CallOfTheWildType.CAT.getConfigEntityTypeEntry())) {
tamingManager.summonOcelot();
}
else if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.HORSE)) {
else if (type == Config.getInstance().getTamingCOTWMaterial(CallOfTheWildType.HORSE.getConfigEntityTypeEntry())) {
tamingManager.summonHorse();
}
@@ -737,7 +865,7 @@ public class PlayerListener implements Listener {
public void onPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
if (Misc.isNPCEntity(player) || !UserManager.hasPlayerDataKey(player)) {
if (Misc.isNPCEntityExcludingVillagers(player) || !UserManager.hasPlayerDataKey(player)) {
return;
}
@@ -783,12 +911,12 @@ public class PlayerListener implements Listener {
if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
String message = event.getMessage();
String command = message.substring(1).split(" ")[0];
String lowerCaseCommand = command.toLowerCase();
String lowerCaseCommand = command.toLowerCase(Locale.ENGLISH);
// Do these ACTUALLY have to be lower case to work properly?
for (PrimarySkillType skill : PrimarySkillType.values()) {
String skillName = skill.toString().toLowerCase();
String localizedName = skill.getName().toLowerCase();
String skillName = skill.toString().toLowerCase(Locale.ENGLISH);
String localizedName = skill.getName().toLowerCase(Locale.ENGLISH);
if (lowerCaseCommand.equals(localizedName)) {
event.setMessage(message.replace(command, skillName));

View File

@@ -9,8 +9,10 @@ import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
import com.gmail.nossr50.events.experience.McMMOPlayerXpGainEvent;
import com.gmail.nossr50.events.skills.abilities.McMMOPlayerAbilityActivateEvent;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.player.PlayerLevelUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.entity.Player;
@@ -40,6 +42,9 @@ public class SelfListener implements Listener {
UserManager.getPlayer(player).processUnlockNotifications(plugin, event.getSkill(), previousLevelGained);
}
//Reset the delay timer
RankUtils.resetUnlockDelayTimer();
if(Config.getInstance().getScoreboardsEnabled())
ScoreboardManager.handleLevelUp(player, skill);
@@ -47,9 +52,9 @@ public class SelfListener implements Listener {
return;
}
if ((event.getSkillLevel() % Config.getInstance().getLevelUpEffectsTier()) == 0) {
/*if ((event.getSkillLevel() % Config.getInstance().getLevelUpEffectsTier()) == 0) {
skill.celebrateLevelUp(player);
}
}*/
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@@ -70,6 +75,11 @@ public class SelfListener implements Listener {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
PrimarySkillType primarySkillType = event.getSkill();
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage(event.getSkill().toString() + " XP Gained");
mcMMOPlayer.getPlayer().sendMessage("Incoming Raw XP: "+event.getRawXpGained());
}
//WorldGuard XP Check
if(event.getXpGainReason() == XPGainReason.PVE ||
event.getXpGainReason() == XPGainReason.PVP ||
@@ -82,6 +92,10 @@ public class SelfListener implements Listener {
{
event.setRawXpGained(0);
event.setCancelled(true);
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage("No WG XP Flag - New Raw XP: "+event.getRawXpGained());
}
}
}
}
@@ -91,15 +105,30 @@ public class SelfListener implements Listener {
return;
}
if(ExperienceConfig.getInstance().isEarlyGameBoostEnabled())
{
int earlyGameBonusXP = 0;
//Give some bonus XP for low levels
if(PlayerLevelUtils.qualifiesForEarlyGameBoost(mcMMOPlayer, primarySkillType))
{
earlyGameBonusXP += (mcMMOPlayer.getXpToLevel(primarySkillType) * 0.05);
event.setRawXpGained(event.getRawXpGained() + earlyGameBonusXP);
}
}
int threshold = ExperienceConfig.getInstance().getDiminishedReturnsThreshold(primarySkillType);
if (threshold <= 0 || !ExperienceConfig.getInstance().getDiminishedReturnsEnabled()) {
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage("Final Raw XP: "+event.getRawXpGained());
}
// Diminished returns is turned off
return;
}
final float rawXp = event.getRawXpGained();
if (rawXp < 0) {
if (event.getRawXpGained() <= 0) {
// Don't calculate for XP subtraction
return;
}
@@ -108,6 +137,8 @@ public class SelfListener implements Listener {
return;
}
final float rawXp = event.getRawXpGained();
float guaranteedMinimum = ExperienceConfig.getInstance().getDiminishedReturnsCap() * rawXp;
float modifiedThreshold = (float) (threshold / primarySkillType.getXpModifier() * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
@@ -137,5 +168,11 @@ public class SelfListener implements Listener {
}
}
if(mcMMOPlayer.isDebugMode()) {
mcMMOPlayer.getPlayer().sendMessage("Final Raw XP: "+event.getRawXpGained());
}
}
}

View File

@@ -2,7 +2,6 @@ package com.gmail.nossr50.listeners;
import com.gmail.nossr50.config.WorldBlacklist;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.blockmeta.conversion.BlockStoreConversionMain;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.BlockState;
@@ -62,7 +61,7 @@ public class WorldListener implements Listener {
plugin.getLogger().info("Converting block storage for " + world.getName() + " to a new format.");
new BlockStoreConversionMain(world).run();
//new BlockStoreConversionMain(world).run();
}
/**

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