Compare commits

...

492 Commits

Author SHA1 Message Date
3440c117be Aktualizovat MMOCore-API/pom.xml 2024-09-12 14:30:00 +02:00
edae411983 revert 480ceb18f8
revert Aktualizovat pom.xml
2024-09-12 14:26:03 +02:00
480ceb18f8 Aktualizovat pom.xml 2024-09-12 12:53:49 +02:00
Jules
0e365c58c8 Fixed quest GUI showing dupes 2024-09-07 18:21:26 +02:00
Jules
88760db078 Fixes Parties throwing an error when players log out 2024-09-07 18:07:53 +02:00
Jules
cdfbb6ef09 Fixes times-claimed not being properly cleared when using /mmocore admin reset all <player> 2024-09-07 17:52:18 +02:00
Jules
6d71c775f6 Fixes 'hide-flags' not working in GUI's 2024-08-27 18:39:45 -07:00
Jules
22e5947112 Fixed an issue with player loading when guild data file is missing 2024-08-26 12:56:00 -07:00
Jules
ed9a9353aa Support for MM 5.7.1 2024-08-14 15:00:27 -07:00
Jules
d792b84219 Fixes custom model data of skill icons in 1.20.6+ 2024-08-14 13:48:58 -07:00
Jules
84e587ba0b Fixes skill tree points consumption dupe bug 2024-08-14 11:36:10 -07:00
Jules
15e759a70b Improves default skill tree node lore 2024-08-14 11:21:57 -07:00
Jules
cba1631d44 Fixes points spent in skill tree not updating when unlocking a node. 2024-08-14 11:21:55 -07:00
Jules
62e1ace7b5 Fixed loot chests not loading. Requires latest ML 2024-07-27 20:59:07 -07:00
Jules
cb92620b1b Skill config files now only generate once and never again 2024-07-27 15:01:27 -07:00
Jules
d0b27c84b2 Fixed MythicDungeons throwing an error message 2024-07-26 16:39:15 -07:00
Jules
fa40f3707d Fixed default skill configs not loading 2024-07-26 16:05:31 -07:00
Jules
25ca6e32a4 Fixed log stripping giving no exp (woodcutting professions) 2024-07-26 15:47:35 -07:00
Jules
61efa519c2 Minor performance improvement for custom mining 2024-07-26 15:32:48 -07:00
Jules
b80cda490c New capacity and shuffle option for block/fishing drop tables 2024-07-26 15:03:40 -07:00
Jules
5759f78924 Fixed plugin crash when inputting an invalid party module 2024-07-26 14:15:41 -07:00
Jules
44f846f591 New config folders for storing and organizing skills, waypoints, loot chests, exp tables, attributes. 2024-07-26 14:03:51 -07:00
Jules
d248f11a0e Support for MythicDungeons & Heroes party systems 2024-07-26 14:02:50 -07:00
Jules
25509be21b Compiles again on Java 8 2024-07-26 12:12:33 -07:00
Jules
dcd1b55099 More 1.21 fixes 2024-07-25 21:06:32 -07:00
Jules
d7ff655c86 Added 1.20+ attributes to default configs 2024-07-25 18:12:25 -07:00
Jules
94139bbe75 Option to hide tooltips from GUI items 2024-07-24 19:15:13 -07:00
Jules
6398872a9e Console warnings changed to info 2024-07-13 01:47:05 -07:00
Jules
0553f0bfe5 Fixed an issue with chest tier rolls 2024-07-13 01:12:30 -07:00
Jules
040e7360df Fixed vanilla-exp in fishing drop tables. experience is no longer necessary 2024-06-20 19:27:09 -07:00
Jules
ee2793d04d Fixed party buffs stacking when using /mmocore reload 2024-06-20 19:14:19 -07:00
Jules
1c415c0511 Fixed player attribute data not loading from SQL database 2024-06-19 20:44:48 -07:00
Jules
1661b8d6eb Fixed passive skills being castable thru combos 2024-06-14 00:43:30 -07:00
Jules
e17a8f903a Now built against Paper 1.20.6 2024-06-13 01:02:36 -07:00
Jules
151eebcde4 Changed placeholders in default player-stats.yml to reduce possible confusion 2024-06-13 00:19:41 -07:00
Jules
2f70c86b7e Fixed collecting stats applying even when a block cannot be broken 2024-06-13 00:10:50 -07:00
Jules
e2c9074084 /mmocore admin reset all now properly resets skills 2024-06-04 01:05:51 -07:00
Jules
fb84e2f96e Fixed NPE when clicking certain skill tree nodes 2024-06-03 22:48:11 -07:00
Jules
5c2bd9b637 Removed use of deprecated API 2024-05-24 20:02:56 -07:00
Jules
b150817964 Default configs no longer use %player% 2024-05-24 19:42:08 -07:00
Jules
7edd17962c Improved some config error messages 2024-05-24 19:41:49 -07:00
Jules
daa052cabd Fixed harmless NPE in the party UI 2024-05-24 18:51:58 -07:00
Jules
bded64d44a Fixed level_skill_tree_node sound not working 2024-05-24 18:46:40 -07:00
Jules
da0e16f1b3 Fixed skill buffs temporarily not working on login 2024-05-24 16:27:00 -07:00
Jules
93317c3e39 New %mmocore_id_bound_<slot>% PAPI placeholder 2024-05-24 14:50:02 -07:00
Jules
2a17aa1a58 Fixed quest triggers for the next objective not triggering 2024-05-23 23:47:13 -07:00
Jules
6e739b3787 Fixed some exp sources working across some classes/professions 2024-05-23 23:34:39 -07:00
Jules
0e5ac9ce3a Fixed damagedealt{} exp source crashing the server when giving a cookie to a parrot 2024-05-23 18:33:05 -07:00
Jules
dad9db0edd Fixed colors not working on profession/class holograms 2024-05-23 16:43:06 -07:00
Jules
bbe7d2b9b8 Fixed exp holograms always showing for certain professions 2024-05-23 16:22:01 -07:00
Jules
d9fa24a730 Fixed custom fishing not taking into account Unbreaking enchant 2024-05-23 15:59:10 -07:00
Jules
caf6b38363 New placeholder for getting parameter value of bound skill 2024-05-23 15:13:54 -07:00
Jules
4f832195e5 Support for latest ML math formula parser 2024-05-13 22:49:17 -07:00
Jules
a8e5a3eaec New features for skill combos: new sound, key to quit casting, ability to keep casting after a combo 2024-05-09 22:09:15 -07:00
Jules
3df5676304 Fixed permanent skills not triggering when locked/unlocked 2024-05-09 18:01:36 -07:00
Jules
952b543b45 Can no longer bind passive permanent skills 2024-05-09 17:17:19 -07:00
Jules
2d08d4403b Compatibility with new MythicDungeons API 2024-05-01 22:42:29 -07:00
Jules
be62d73fcb Fixed a bug with '/mmocore admin exportdata' 2024-04-25 19:49:48 -07:00
Jules
7593226610 Fixed waypoint default warp time not working. Waypoint warp time bypass permission is no longer a default op permission. 2024-04-25 17:55:48 -07:00
Jules
974dbe1eac Default backstab lore now includes skill cooldown 2024-04-24 22:49:07 -07:00
Jules
9546a95a59 Debug messages duh 2024-04-24 21:59:27 -07:00
Jules
3248ffe541 Fixed /skills not working when a class has too many slots configured 2024-04-23 22:54:49 -07:00
Jules
176657e3fd Changed outdated config.yml comment 2024-04-18 17:55:12 -07:00
Jules
991397606f Fixed MMOInv health buffs not working on login 2024-04-18 15:15:24 -07:00
Jules
3962c73515 Reduced confusion in default fishing profession config 2024-04-17 23:46:01 -07:00
Jules
a33d4061cd Fixed %mmocore_attribute_points_spent_<attr>% 2024-04-14 14:14:18 -07:00
Jules
8a017a6109 Fixed waypoint lore not working in UI 2024-04-10 07:13:21 -07:00
Jules
3b1ab33e2f Fixed Profile API version 2024-04-07 00:01:39 -07:00
Jules
558a5f5a01 Added one option to prevent players from upgrading skills using the skill UI 2024-04-06 23:31:27 -07:00
Jules
d4bea3dba7 Fixed /rpg reload increasing player skill levels when using skill trees 2024-04-06 23:15:33 -07:00
Jules
3231a69bf3 Removed <message_empty_...> user feedback on empty config message 2024-04-06 21:48:29 -07:00
Jules
8a8ec67f14 Fixed an on-login issue with non-vanilla resources 2024-03-29 00:47:03 +01:00
Jules
79d763718d More default settings for SQL data storage 2024-02-21 18:07:11 +01:00
Jules
5e466dd8c2 Improved handling of async tasks (autosave, on server shutdown) 2024-02-21 13:11:23 +01:00
Jules
1e370864cd Improved handling of async tasks (autosave, on server shutdown) 2024-02-21 13:05:14 +01:00
Jules
223a8fadb7 Added missing message to default messages.yml 2024-02-20 17:54:37 +01:00
Jules
13e808ba37 Fixed on-login health issue 2024-02-20 13:37:29 +01:00
Jules
0fd1f6bbce Removed use of deprecated methods 2024-02-20 00:27:54 +01:00
Jules
a653ffbfe1 Fixed resources not saving 2024-02-19 17:05:18 +01:00
Jules
1a1346d3bc Fixed NPE with guild gui 2024-02-19 12:52:44 +01:00
Jules
d5ffd04117 Fixed health issue on login 2024-02-11 23:36:21 +01:00
Jules
68fbfc3576 Support for Uclans API 7 2024-02-11 17:17:35 +01:00
Jules
e4f1400a31 Hotfix for on-login issue 2023-11-27 11:25:56 +01:00
Jules
47cd5c15c9 Fixed login trigger type not working on class skills & scripts 2023-11-27 00:11:12 +01:00
Jules
947637127e Fixed attributes not reseting with /mmocore reload 2023-11-26 17:42:45 +01:00
Jules
f6d094fb6e Fixed DROP forcing a left click with key combo casting 2023-11-25 16:56:06 +01:00
Jules
36b5be13be Fixed empty messages sent to chat/action bar 2023-11-25 15:23:34 +01:00
Jules
c211c05a67 Fixed item repair exp dupe glitch 2023-11-25 15:07:09 +01:00
Jules
22744b181b Fixed 1.20+ skull texture application 2023-11-06 02:56:07 +01:00
Jules
3c043babd5 Fixed stuck player messages 2023-11-06 00:37:20 +01:00
Jules
7d93031aeb Better handling of fake events 2023-11-06 00:28:03 +01:00
Jules
44d0785f73 Increased event priorities of exp sources 2023-11-05 23:21:58 +01:00
Jules
c8f1f9fefd Update README.md 2023-11-04 15:29:34 +01:00
Jules
76b0d51b2a Fixed a bug when logging off while in combat 2023-10-27 20:29:42 +02:00
Jules
71d0f7219f Fixed placeholders with proxy-based profiles 2023-10-22 02:11:45 +02:00
Jules
f79a66df80 Merge remote-tracking branch 'origin/master' 2023-10-22 01:07:11 +02:00
Jules
29a88a59fe Fixed skill upgrading gui 2023-10-22 01:06:57 +02:00
Jules
ede2991066 Fixed skill scroller, added option for action bar format 2023-10-22 01:03:28 +02:00
Jules
e784230ce7 Combos now ignore unused keys 2023-10-22 00:42:39 +02:00
Jules
88d02f140f Skill casting timeout, fixed casting particles 2023-10-22 00:03:35 +02:00
Jules
6565d7106b Fixed skill buffs not applying on cooldown & other mods 2023-10-16 01:40:38 +02:00
Jules
160c5d5699 Fixed exp resetting on death 2023-10-15 18:43:06 +02:00
Jules
dbe5aa5fab Fixed attributes not reloading when switching profiles 2023-10-14 15:30:36 +02:00
Jules
7810e3695b Fixed attributes not reseting 2023-10-14 12:42:27 +02:00
Jules
bc9f5ac6f8 Tree node will get latest level lore available 2023-10-08 01:48:36 +02:00
Jules
6bcfc0aad8 Added 'name' placeholder to skill tree nodes 2023-10-08 01:25:10 +02:00
Jules
90706ae97c Default color for skill tree node names 2023-10-08 01:22:44 +02:00
Jules
35484b5893 Removed "size" from skill trees 2023-10-08 00:36:07 +02:00
Jules
2d779d19bf Fixed an issue w/ casting mode on logout 2023-10-02 00:01:49 +02:00
Jules
d6ec76573c Fixed issue with quest list custom model data 2023-10-01 16:17:51 +02:00
Jules
5c185476dd Enter/quit combat skill triggers 2023-09-30 15:28:37 +02:00
Jules
b8e02c945f 1.20.2 support 2023-09-30 13:11:30 +02:00
Jules
760f7f6b0b Commented out nonsense 2023-09-18 13:06:09 +02:00
Taner
ed97665e27
Update example-drop-tables.yml to remove ;period= 2023-09-10 22:25:24 +00:00
Ka0rX
c04d46d662 Fixed issue #909 & #926 related to a bug when making a friend request. Make sure to reload messages.yml to fix this bug ! 2023-09-07 11:41:07 +01:00
Ka0rX
36f99a6cb4 Bug Fixing 2023-09-07 11:38:36 +01:00
Ka0rX
2f91a58a26 Fixed issue #922 related to stats related to class/profession being lost when reloading/quitting. 2023-09-06 21:48:58 +01:00
Ka0rX
09ea9ab3a9 Fixed issue #917 about a bug when unbinding a skill from a slot while being in a key combo. 2023-09-06 18:13:42 +01:00
Ka0rX
a794f81a5f Fixed issue #920 about placeholder API placeholders not working in skill-list.yml & fixed other bugs related to selected item in skill-list 2023-09-06 16:37:40 +01:00
Ka0rX
40b59e4b70 Added the possibilty to have force a specific item to appear when a skill is bound to a slot for the skill UI. 2023-09-06 15:18:25 +01:00
Ka0rX
1607b0f773 Fix for subclass select UI 2023-09-06 15:17:28 +01:00
Ka0rX
2a802e40bf Fixed issue #932 about Out of Mana message not being sent when it should. 2023-09-05 21:56:52 +01:00
Ka0rX
3fa278a920 Bug Fix 2023-09-05 21:07:30 +01:00
Ka0rX
55953d41ce Fixed issue #931 related to waypoints lore being inverted in the UI. Now you can use the placeholder {lore} in the UI config to display the waypoint specific lore. 2023-09-05 19:32:08 +01:00
Ka0rX
7b45b54793 Little enhancement for class select GUI. 2023-09-05 18:59:28 +01:00
Jules
3efc5b86fb More proxy profiles fixing 2023-08-27 22:26:04 +02:00
Jules
d050b708cc Changed player data setup event priority 2023-08-27 19:31:12 +02:00
Jules
730dd80418 Updated dependency nb 2023-08-27 18:20:06 +02:00
Jules
c0a27f5cc0 Fixed force-class-selection when using proxy-based profiles 2023-08-27 18:16:13 +02:00
Jules
b12c6142a3 Clarified default config.yml 2023-08-27 17:44:00 +02:00
Jules
e854663cff Updates to ProfileAPI 1.1 2023-08-27 16:55:09 +02:00
Jules
e98a31bdbc Useless import 2023-08-26 20:42:55 +02:00
Jules
10fb433291 Fixed NPE when repairing null item 2023-08-16 22:56:46 +02:00
Jules
13ada015c9 Fixes player combat updating on fake damage events 2023-07-24 11:25:45 +02:00
Ka0rX
3d48a7e7c0 Merge remote-tracking branch 'origin/master' 2023-07-16 13:58:36 +01:00
Ka0rX
1dc2d31360 Skill Tree Display Fix. 2023-07-14 17:35:52 +01:00
Jules
fadb7d7762 Hopefully fixed compile issue 2023-07-11 19:49:28 +02:00
Jules
c859c0d2e0 Support for latest MythicLib 2023-07-11 19:44:06 +02:00
Ka0rX
65d18509d0 Fix skilltree GUI. 2023-07-09 22:41:50 +01:00
Ka0rX
694ca2cac9 Removed debugging log. 2023-07-09 22:20:27 +01:00
Ka0rX
a76d77fe47 Added placeholder %mmocore_cooldown_bound_<slot>% according to issue #890. 2023-07-09 22:05:22 +01:00
Ka0rX
65d6047017 Fixed issue #897 about a bug in max party players placeholder. 2023-07-09 20:54:37 +01:00
Ka0rX
4a22e0a357 Fixed issue #892 regarding path issues for skill trees. 2023-07-09 20:33:06 +01:00
Ka0rX
83dcba2c0a Reformat 2023-07-09 19:18:06 +01:00
Ka0rX
070c725712 Added the possibility to open specific skill tree GUI and customize the GUI differently for each skill tree through specific-skill-tree/ folder. 2023-07-09 19:17:25 +01:00
Ka0rX
05180a4acc Version 1.12.1-SNAPSHOT* 2023-07-09 17:26:43 +01:00
Ka0rX
91491b2d18 Version 1.12.1 2023-07-09 16:27:42 +01:00
Ka0rX
e0bdfa2000 Merge remote-tracking branch 'origin/master' 2023-07-09 16:10:34 +01:00
Jules
1a976c6aa0 Cannot enter combos with no skills bound 2023-06-27 00:10:08 +02:00
Jules
2708dd2072 Fixed killmob not giving exp with flame & fire aspect 2023-06-26 22:54:03 +02:00
Jules
00f1581707 Removed debug message :D 2023-06-26 00:34:22 +02:00
Jules
f1366a584d Fixed key combos casting 2023-06-26 00:16:08 +02:00
Ka0rX
c3c461f777 Added the {display-type} placeholder to debug for skill tree node/paths. Added the possibility to add a lore to skill tree paths in skill tree GUI. 2023-06-25 22:48:49 +01:00
Ka0rX
e53e9db3d7 Merge remote-tracking branch 'origin/master' 2023-06-25 22:19:10 +01:00
Ka0rX
4a45f7abb3 Fixed issue #880 related to a casting issue. 2023-06-25 22:18:16 +01:00
Ka0rX
3f0ca4856e Fixed issue #828 about a bug when dying and then logging out. 2023-06-25 22:15:45 +01:00
Jules
5042f78fa3 Fixed respawn issue when using YAML 2023-06-25 23:15:05 +02:00
Jules
fdd1234d68 Merge remote-tracking branch 'origin/master' 2023-06-25 23:06:02 +02:00
Jules
8d1714f886 'can-mine' is now optional for tool restricts 2023-06-25 23:05:28 +02:00
Ka0rX
59ad3259cc Fixed issue #869 about health not syncing between servers. 2023-06-25 21:41:05 +01:00
Jules
7767e51534 Fixed issue with item damage application 2023-06-25 22:39:38 +02:00
Jules
f98d78959f Fishing conditions now apply on hook 2023-06-25 19:50:15 +02:00
Jules
75988f23f0 Merge remote-tracking branch 'origin/master' 2023-06-25 17:22:45 +02:00
Ka0rX
a7af0e1ca7 Changed default skill config. 2023-06-25 15:13:47 +01:00
Ka0rX
49b699b54b Added possibility to specify decimal format for each skill parameter regarding issue #866. 2023-06-25 15:13:04 +01:00
Ka0rX
892b04cd3a Fixed Issue #870 about skill tree triggers being applied 2 times when using force-class. 2023-06-25 11:14:47 +01:00
Ka0rX
004a2b8673 Fixed Issue related to custom sound being case sensitive. 2023-06-25 11:14:15 +01:00
Ka0rX
c0f3ac0638 Merge branch 'master' of https://gitlab.com/phoenix-dvpmt/mmocore 2023-06-25 10:10:21 +01:00
Guillaume
6a1fb8473d Merge branch 'casting-events-enter-exit' into 'master'
Casting Enter/Exit Events!

Closes #857 and #860

See merge request phoenix-dvpmt/mmocore!27
2023-06-25 08:24:00 +00:00
Ka0rX
77ecc005b4 Merge branch 'master' into casting-events-enter-exit
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerEnterCastingModeEvent.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/event/PlayerExitCastingModeEvent.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/KeyCombos.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillScroller.java
2023-06-25 10:23:32 +01:00
Ka0rX
066dc44a4f Merge branch 'master' into casting-events-enter-exit 2023-06-25 10:08:53 +01:00
Guillaume
6cd8c50ffa Merge branch 'revert-a0ec9542' into 'master'
Revert "Merge branch 'custom-sound-case-sensitivity-fix' into 'master'"

See merge request phoenix-dvpmt/mmocore!29
2023-06-25 08:05:00 +00:00
Guillaume
f8758ebe74 Revert "Merge branch 'custom-sound-case-sensitivity-fix' into 'master'"
This reverts merge request !28
2023-06-25 08:04:42 +00:00
Guillaume
a0ec9542fd Merge branch 'custom-sound-case-sensitivity-fix' into 'master'
Custom sound case sensitivity fix (#878)

Closes #878

See merge request phoenix-dvpmt/mmocore!28
2023-06-25 08:04:25 +00:00
Jules
611272e5bb Catch malformed json errors on class loading 2023-06-25 02:32:35 +02:00
Jules
dc9f1bc1aa Support for latest ML 2023-06-25 02:22:55 +02:00
Jules
be82279540 Permission to skip waypoint waiting time 2023-06-25 02:22:50 +02:00
Jules
441cea0208 Merge branch 'weather-time-conditions' into 'master'
feat(conditions): Add Weather and Time conditions

See merge request phoenix-dvpmt/mmocore!22
2023-06-25 00:19:03 +00:00
Ka0rX
9b7d0c35b7 Added the possibility to give vanilla exp with fishing drop items. 2023-06-24 22:46:45 +01:00
Ka0rX
8000bc9b89 Skill Tree refactor & enabled to translate the skill tree node states. 2023-06-24 22:46:05 +01:00
Rosenthalk0
51f4f7be1b Cleaning up the events, removing lambok from events, and making leaveCastingMode and setCastingMode as booleans to reflect the events they fire! 2023-06-24 15:06:17 -05:00
Rosenthalk0
a40e7b119c Fix for case insensitivity 2023-06-23 16:48:27 -05:00
Rosenthalk0
09e1241735 Fix for case insensitivity 2023-06-23 16:48:13 -05:00
Rosenthalk0
e90a1cea28 Fix for case insensitivity 2023-06-23 16:47:49 -05:00
Rosenthalk0
96ac7a9c00 API method for leaveSkillCasting to fire event! 2023-06-23 14:00:48 -05:00
Rosenthalk0
839ccd4942 Use MMOCore PlayerDataEvent 2023-06-23 13:39:28 -05:00
Rosenthalk0
6088c8b343 Fix of small bugs relate to the events! 2023-06-18 15:36:00 -05:00
Jules
74a170e66c !Use of newest methods of ML for data saving 2023-06-18 16:51:08 +02:00
Jules
59816c163d Update license 2023-06-18 15:53:07 +02:00
Rosenthalk0
222fbfc833 Events for Casting Mode 2023-06-12 13:06:57 -05:00
Ka0rX
df78c21aa3 Added the needs-bound option in class skills section in order to set which passive skills need to be bound and which don't. 2023-06-05 22:14:09 +01:00
Ka0rX
2b6f00d7fa Fixed issue #860 about a comp bug with KingdomsX. 2023-06-05 21:29:20 +01:00
Ka0rX
9af5c358dd . 2023-06-04 21:42:10 +01:00
Ka0rX
72f14547d9 Fixed issue #857 about progress not being properly saved for skill trees with skill modifier. (Skill modifier is now the name we will give to skill buffs. mana, delay... are now called skill parameters). 2023-06-04 21:23:06 +01:00
Ka0rX
90e0c349a4 Fixed a bug related to lore parsing in skill-list.yml 2023-06-01 08:41:55 +01:00
Ka0rX
fb0dbad80f Bug Fixing related to Skill Tree not working properly with MMOProfiles. 2023-06-01 08:41:30 +01:00
Ka0rX
178bb35d59 Added the status unlockable for path in skill-tree.yml (Check wiki), make sure to reload gui/skill-tree.yml to benefit from this modification. 2023-05-31 17:54:24 +01:00
Ka0rX
4065737f35 Added the possibility to redefine the display section inside of skill-tree folder in order to have different display for each skill-tree. (Check wiki) 2023-05-31 17:25:32 +01:00
Ka0rX
38065a1120 Added up,down,left & right type for nodes in the display section of skill-tree.yml. Make sure to reload this file to have everything working properly. 2023-05-31 17:24:20 +01:00
Ka0rX
c73ee476da Fixed a bug related to %mmocore_skill_parameter_<parameter>:<skill-name>% placeholder. 2023-05-31 16:36:49 +01:00
Ka0rX
f130f2aac9 Added {skill-lore} placeholder for SlotItem in gui/skill-list.yml acccodring to issue #854 2023-05-31 16:15:18 +01:00
Ka0rX
034200f021 Change for passive-skill-need-bound in config.yml 2023-05-31 06:46:03 +01:00
Ka0rX
bcc501176f Fixed issue #833 about console spamming when using /mmocore reload 2023-05-29 11:29:49 +01:00
Ka0rX
b093d325dd Refactored MMOCore skill modifiers to call them skill parameters as in MythicLib, Fixed issue #834. 2023-05-29 10:25:04 +01:00
Ka0rX
1282d18934 Added default config for all the default skills ! 2023-05-29 09:28:42 +01:00
Ka0rX
b87de32bbb Fixed issue #849 about some data not saving properly for MySQL. 2023-05-29 09:25:11 +01:00
Ka0rX
4812a48b3c Fixed issue #837 &838 about key combos being offset of 1 skill slot. 2023-05-29 09:23:22 +01:00
Ka0rX
0acff060eb Fixed issue #847 related to "selected" item not showing the right model data in the skill GUI. 2023-05-29 09:22:06 +01:00
Ka0rX
0f1ced9744 Fixed issue #841 related to SubclassSelect showing subclasses despite not having the required level. 2023-05-29 09:21:13 +01:00
Ka0rX
ddf041aa30 Fixed issue related to wrong display for skill tree paths. 2023-05-28 06:59:08 +01:00
Ka0rX
54bb1f2632 Added the option skill-tree-scroll-step-x/y in config.yml to control the scroll speed in skill tree GUI. 2023-05-28 06:39:38 +01:00
Ka0rX
4d98b8b307 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java
2023-05-19 20:10:18 +01:00
Jules
c0373750cd Fixed compile errors 2023-05-15 00:10:06 +02:00
Jules
f1d90589a4 Update lib 2023-05-15 00:07:54 +02:00
Jules
2ba9c1f0ec Removed unused sound 2023-05-15 00:06:34 +02:00
Jules
ac36e3eaa1 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java
#	MMOCore-Dist/src/main/resources/config.yml
2023-05-15 00:06:02 +02:00
Jules
7e134aac1d Force class on profile selection 2023-05-14 23:27:11 +02:00
Jules
651e46697e force-class-selection fixes 2023-05-14 16:34:43 +02:00
Ka0rX
0627c73378 Added placeholder for skill modifiers relative to ticket #829. 2023-05-13 11:46:29 +01:00
Ka0rX
15a8e6e796 Fixed README.md 2023-05-09 09:07:35 +01:00
Ka0rX
7bf3b9ace7 Bug Fixing for Issue#802 about passive-skill-need-bound not working. 2023-05-09 08:32:48 +01:00
Jules
e939b6e868 Merge remote-tracking branch 'origin/jules' into jules 2023-05-08 11:43:07 +02:00
Jules
a09c23ecf5 Fixed NoClassDefFound 2023-05-08 11:43:01 +02:00
Ka0rX
1a1371b5f9 Little debug for placeholders 2023-05-08 09:12:44 +01:00
Ka0rX
27d5c93ba7 Heavy debugging and refactor for skill trees. 2023-05-07 19:15:28 +01:00
Ka0rX
a18a42ea2f Heavy debugging and refactor for skill trees. 2023-05-07 18:12:37 +01:00
Jules
2bcd505bf8 Support for profile placeholders 2023-05-07 18:29:31 +02:00
Ka0rX
a64faa02fd Bug Fixing for Skill Tree 2023-05-07 16:50:43 +01:00
Ka0rX
8e504e1a10 Implemented feature associated to ticket #824 by adding incompatible-parents field in skill tree node config. 2023-05-07 16:28:18 +01:00
Ka0rX
a125320dd0 Fixed a bug related to SubClassSelect GUI. 2023-05-07 16:26:37 +01:00
Ka0rX
aa6a1d7101 Fixed issue #820 about skills not being locked when reallocating skill tree. 2023-05-07 15:11:20 +01:00
Ka0rX
13440600a8 Fixed issue #821 about skill tree nodes not loading properly. 2023-05-07 14:29:27 +01:00
Jules
c5dbf21694 Update repo URL 2023-05-07 15:24:41 +02:00
Jules
09d76dab1b API method to force into skill casting 2023-05-07 09:33:18 +02:00
Ka0rX
fe0996b01b Little modifications for the formula parser. 2023-05-05 11:18:40 +01:00
Ka0rX
5523e875cf Permission requirement for skill tree node according to ticket #801.
Check the wiki for further info. Make sure to reload messages.yml.
2023-05-04 11:21:11 +01:00
Ka0rX
528606628d Removed HotbarSwap option because of a dupe bug that has been found. 2023-05-04 10:46:19 +01:00
Ka0rX
b0cab10da2 Fixed issue #811. 2023-05-04 10:05:38 +01:00
Ka0rX
1cdbd08d6b Fixed issue #818 about decimal format not being applied to some placeholders. 2023-05-04 09:48:54 +01:00
Ka0rX
d2d03e322c Fixed issue #809 about passive skill being shown in the skill casting bar. 2023-05-04 09:40:25 +01:00
Ka0rX
edc873a6c7 Fixed issue #804 about custom display not working properly for the status fully-locked. 2023-05-04 09:34:22 +01:00
Ka0rX
9344ff99a6 Fixed issue #805 about placeholders not being parsed in the profile GUI. 2023-05-04 09:30:16 +01:00
Ka0rX
4b2cc5ea61 Fixed issue #810 about %mmocore_bound_<int>% placeholder bug. 2023-05-04 09:14:34 +01:00
Ka0rX
fc91ace143 Fixed issue #806 about skill slot lore not displaying on GUI and modified slightly skill-list.yml GUI for that. 2023-05-04 09:12:26 +01:00
Ka0rX
f3aa07288f Fixed issue #812 about a bug with slot_unlock trigger. 2023-05-04 09:11:17 +01:00
Ka0rX
061ced2207 Better error handling for slot lock command. 2023-05-04 09:10:36 +01:00
Ka0rX
fa9c24589b Fixed issue #817 about skill tree path not working as intented in GUI. 2023-05-04 09:10:16 +01:00
Starmism
71b7727a15 feat(conditions): Add Weather and Time conditions 2023-04-24 14:40:23 -06:00
Ka0rX
79b007f144 Merge remote-tracking branch 'origin/master' 2023-04-24 07:24:53 +01:00
Jules
590801203d Fixed NPE with yaml data loading 2023-04-23 22:08:30 +02:00
Jules
41617f722c Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
2023-04-23 21:42:10 +02:00
Jules
4bfbaac8fb Fixed default config for party module 2023-04-22 17:00:31 +02:00
Jules
f4b2147226 Basic support for DungeonParties 2023-04-22 16:54:55 +02:00
Jules
966cd333c1 Basic support for OBTeam 2023-04-22 15:59:54 +02:00
Ka0rX
a37287cf0c Refactor /typo 2023-04-22 11:39:40 +01:00
Ka0rX
523f910113 Bug Fixing for the specific display associated to each node. 2023-04-21 08:07:08 +01:00
Ka0rX
5fdfc36fcc Renaming for skill tree GUI. 2023-04-21 08:06:40 +01:00
Ka0rX
ad6b7fa0ff Enabled each skillTreeNode to have its own display by filling item & custom-model-data in its config. 2023-04-21 07:22:59 +01:00
Ka0rX
50f2de287c Fixed a bug linked to perm stats not being modified when changing class. 2023-04-20 21:27:28 +01:00
Ka0rX
f4be0ab409 Fixed issue #796. 2023-04-20 20:54:15 +01:00
Ka0rX
4d8df79dc2 Removed debugging message. 2023-04-20 20:45:34 +01:00
Ka0rX
ebed0d3983 Fixed issue #795 about bugs linked to the party GUI. 2023-04-20 20:33:03 +01:00
Ka0rX
d1be5cbce7 Fixed issue #794 about passive-skill-need-bound being disabled. 2023-04-20 20:12:03 +01:00
Ka0rX
c99caff22d Passive skill bug fixing. 2023-04-20 20:01:17 +01:00
Ka0rX
8b3d553183 Big modification for the skilltree GUI. Make sure to reload gui/skilltree.yml and look at the wiki. 2023-04-20 19:52:09 +01:00
Ka0rX
77f543f347 Added placeholder %mmocore_attribute_points_spent_<attribute_id>%. 2023-04-16 21:32:53 +01:00
Ka0rX
f9fdbfa127 Fixed bug #782. 2023-04-16 21:13:43 +01:00
Ka0rX
021cd960da Bug Fix 2023-04-16 20:09:49 +01:00
Ka0rX
048ed1364d Fixed issue #788. 2023-04-16 20:09:35 +01:00
Ka0rX
4de49070a0 Fixed issue #792 by adding the possibility to put a "custom-model-data" for skill trees. 2023-04-16 18:29:39 +01:00
Ka0rX
56a84015ac Bug fixing related to the "selected" item. 2023-04-16 18:28:23 +01:00
Ka0rX
a1e817f22c Added a "selected" item that replicates the skill that is selected in skill list GUI. 2023-04-16 18:15:24 +01:00
Jules
baf664a608 SQL Update commit 1 2023-04-16 00:56:17 +02:00
Jules
547775a33e Removed debug msg 2023-04-15 00:27:58 +02:00
Jules
afe3eec3fb New placeholders 2023-04-14 17:57:49 +02:00
Jules
039baed3d3 New triggers for skill management 2023-04-14 17:32:02 +02:00
Jules
39f95634a0 Fixed skills not unregistering on logout/changing class 2023-04-14 16:39:58 +02:00
Jules
0bcd11cf68 Fixed guild loading NPE 2023-04-14 15:45:04 +02:00
Jules
99f83a722a Reduced risk of confusion in default main config 2023-04-13 20:05:41 +02:00
Jules
f9a4f65860 Fixed subclass confirmation 2023-04-13 19:43:43 +02:00
Jules
3904b9a8b7 Skill bar now displays correct ints 2023-04-13 19:16:46 +02:00
Jules
f92e4410a1 Where did my commits go :( 2023-04-11 01:00:32 +02:00
Jules
634eda113b Added fixed level for exp tables!! 2023-04-11 00:49:18 +02:00
Jules
8c0e571194 Improved default class yml's 2023-04-11 00:49:04 +02:00
Jules
e4637194c3 Improved implementation of boundSkills 2023-04-11 00:48:54 +02:00
Jules
d020673105 Fixed bound skills not saving for yaml 2023-04-10 23:49:25 +02:00
Jules
7a336cab27 Fixed skill buffs 2023-04-10 17:42:12 +02:00
Jules
bb73fb57df Fixed skills not updating when using /mmocore reload 2023-04-10 17:30:50 +02:00
Jules
f13957b119 Fixed /skills when having no skill 2023-04-10 17:30:02 +02:00
Jules
c104c8230d Last cleanup 2023-04-10 16:46:05 +02:00
Jules
2c9a6773f5 Skill slots now use icon from bound skill 2023-04-10 16:46:00 +02:00
Jules
9b2c972ca4 More cleaning up 2023-04-10 16:12:57 +02:00
Jules
b694cf8cf4 Fixed skill binding offset 2023-04-10 16:12:48 +02:00
Jules
dff176042b Newest commits 2023-04-10 13:36:01 +02:00
Jules
1cbf0f0ea1 Resuming cleanup 2023-04-10 13:11:11 +02:00
Jules
b6600245ad Fixed default class configs 2023-04-10 13:03:19 +02:00
Jules
1a5f5986aa Refactor before dev build 2023-04-09 15:09:47 +02:00
Jules
786d1881bf Merging skill update 1 2023-04-09 11:31:08 +02:00
Jules
841264df95 Started cleaning up 2023-04-08 14:31:05 +02:00
Jules
c8932e3a5d Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
#	README.md
2023-04-08 14:28:40 +02:00
Jules
2746d7cda9 Merge remote-tracking branch 'origin/Skills-update'
# Conflicts:
#	MMOCore-API/pom.xml
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java
#	MMOCore-Dist/pom.xml
#	pom.xml
2023-04-08 14:20:55 +02:00
Jules
33d137f308 Merge remote-tracking branch 'origin/master' 2023-04-07 16:36:41 +02:00
Jules
2a4e509a8b Fixed /mmocore admin exportdata 2023-04-07 16:34:41 +02:00
Ka0rX
34d4cd4658 Changed the messages & gui/skill trees files to have better messages regarding that feature. Make sure to reload them. 2023-04-06 16:08:10 +01:00
Ka0rX
ac3d348a96 Modified default skill trees config to mention that feature. 2023-04-06 16:07:20 +01:00
Ka0rX
0d950bcd48 Bug Fixing for "point-consumed" field for skill Trees. You can now set the number of points that are consumed each time you level up a node. 2023-04-06 16:06:37 +01:00
Ka0rX
6fd15725bb The skill buffs associated to a slot will only trigger if the item bound matches the corresponding formula. 2023-04-06 12:08:06 +01:00
Ka0rX
8e93c83c0d Fixed SQL bug. 2023-04-06 12:07:37 +01:00
Ka0rX
816fbc5722 Added default config for class-confirm GUI and made the subclass-select.yml GUI as the class-select GUI. 2023-04-06 09:57:19 +01:00
Ka0rX
333ffe08d5 Merge branch 'master' into Skills-update
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/command/SkillsCommand.java
2023-04-04 21:11:49 +01:00
Ka0rX
2cbc1666f2 Merge remote-tracking branch 'origin/master' 2023-04-04 21:10:53 +01:00
Ka0rX
520516ded8 Possibility to select a bound skill and thus upgrade it even if it is not unlocked. 2023-04-04 21:10:44 +01:00
Ka0rX
943553632b can-manually-bind option for SkillSlots and possibility to bind/unbind a skill to a slot through /mmocore admin slot bind <slot> <skill>. 2023-04-04 14:58:14 +01:00
Ka0rX
08b8239291 Added option to have more than 1 skill tree point required for a certain some skill tree. 2023-04-04 13:05:27 +01:00
Jules
c94795fc89 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java
2023-04-04 13:04:44 +02:00
Ka0rX
a54bfc03a0 Added permission associated with every MMOCore command. 2023-04-04 07:11:16 +01:00
Ka0rX
015f4544ce Made all the slots Unlockable with an associated command & trigger. 2023-04-03 17:25:50 +01:00
Taner
e6cfde3ce7 Update Crowdin configuration file 2023-04-03 15:11:40 +00:00
Ka0rX
8f2da7a865 . 2023-04-03 07:28:36 +01:00
Ka0rX
e62c13f849 Merge remote-tracking branch 'origin/master' 2023-04-03 06:03:26 +01:00
Ka0rX
8192d6caa8 Test 2023-04-02 23:41:22 +01:00
Ka0rX
d7db3f6d68 Fixed bug related to fetching player health when he is offline. 2023-04-02 23:23:11 +01:00
Ka0rX
c31a3fcec1 Fixed the bug where player die when joining server. 2023-04-02 23:09:37 +01:00
Ka0rX
cedc6ae6c8 Bug Fixing 2023-04-02 21:15:39 +01:00
Ka0rX
c6b9372026 Fixed bug when class doesn't have any skills. 2023-04-02 20:20:55 +01:00
Ka0rX
c64b88e36d Fixed error message when the class doesn't have any skills. 2023-04-02 20:02:56 +01:00
Ka0rX
8ce90c3363 Merge branch 'master' into Skills-update 2023-04-02 19:55:55 +01:00
Ka0rX
7bd7dcc2d7 Merge fixes. 2023-04-02 19:55:45 +01:00
Ka0rX
395844c25a Better error handling & console messages for the new class-confirm GUI. 2023-04-02 19:47:58 +01:00
Ka0rX
3a9b3b6f56 Fixed health issue when changing class. 2023-04-02 19:47:30 +01:00
Ka0rX
9e98cd0640 Made it possible to have SkillBuffs associated to a SkillSlot. 2023-04-02 19:18:13 +01:00
Ka0rX
2f17d56c40 Fixed bug #772 about trigger at the end of a quest to launch a new one. 2023-04-02 18:29:14 +01:00
Ka0rX
3bc0ba515b Merge remote-tracking branch 'origin/master' 2023-04-02 18:13:16 +01:00
Ka0rX
253e2c38e0 Fixed bug #771 that made people die when changing class under some conditions. 2023-04-02 18:13:05 +01:00
Ka0rX
de5bfd5ed1 . 2023-04-02 18:10:29 +01:00
Jules
06fbd52c55 Fixed stat placeholders.. again 2023-04-02 16:24:39 +02:00
Jules
77f436200a Stat placeholder now more lenient 2023-04-01 23:00:46 +02:00
Jules
de011349a1 Updated poms 2023-04-01 20:00:56 +02:00
Jules
8a2a7c6381 Update license 2023-03-31 15:31:34 +02:00
Ka0rX
af2c68054e Merge branch 'master' into Skills-update
# Conflicts:
#	MMOCore-API/pom.xml
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/mysql/MySQLDataProvider.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/YAMLPlayerDataManager.java
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/player/DefaultPlayerData.java
#	MMOCore-Dist/pom.xml
#	README.md
#	pom.xml
2023-03-31 09:18:33 +01:00
Ka0rX
739f958d5a Refactor of the ClassSelect & ClassConfirmation GUI. Now you can fully customize the GUI depending on each class. Reload the GUI folder & add a class-confirm/... gui for each new class you created. 2023-03-31 09:04:58 +01:00
Ka0rX
b2982a9ffb Made CastableSkill.getModifier() take MMOPlayerData to enable it to check player buffs. 2023-03-31 07:35:47 +01:00
Ka0rX
d19da5f1cc Made it possible to unlock a skill that is not defined in the class. 2023-03-30 21:56:46 +01:00
Ka0rX
13b8b86b7b Bug Fixing 2023-03-30 21:47:07 +01:00
Ka0rX
b6ef6cd4de Bug Fixing 2023-03-30 21:28:42 +01:00
Ka0rX
1908b1d83e Debug for SkillBuffs. 2023-03-30 18:47:05 +01:00
Ka0rX
ddd3034584 . 2023-03-30 18:46:20 +01:00
Ka0rX
7f07f9e349 Transferred the categories formulaEvaluation from SkillSlot to RegisteredSkill. 2023-03-30 18:45:43 +01:00
Ka0rX
0f4699fbea Creation of SkillBuffTrigger. 2023-03-30 18:45:03 +01:00
Ka0rX
14f1a7fcc2 Version 1.12.0 2023-03-30 18:44:36 +01:00
Ka0rX
41aad7b6a1 Transfered unlockedItems from MythicLib to MMOCore. 2023-03-29 23:35:47 +01:00
Ka0rX
dca44b232d Added a fully detailed description and default modifiers for all the default registered skills. 2023-03-29 11:43:16 +01:00
Ka0rX
fc5b34a352 Debug by removing skills from SkillSlots when the skills gets locked.Done by creating a Listener for ItemLockedEvent. 2023-03-28 16:11:54 +01:00
Ka0rX
b62b0e89e9 Reindent 2023-03-28 16:10:51 +01:00
Ka0rX
9facd8d3df Improved Tab Completion for Skill Unlocking 2023-03-28 16:10:43 +01:00
Ka0rX
9544745cb4 Removed / Modified verbose 2023-03-28 14:30:21 +01:00
Jules
fda62fca84 Update ver nb 2023-03-27 01:10:13 +02:00
Ka0rX
3138f81e43 Fixed issue #691 by adding compatibilty with other party plugins for party buffs. 2023-03-27 00:06:55 +01:00
Jules
4de00ffe67 Merge remote-tracking branch 'origin/master' 2023-03-27 00:08:03 +02:00
Jules
e8fe24ba73 Merge remote-tracking branch 'origin/master' 2023-03-26 23:56:54 +02:00
Ka0rX
0bc1837460 Fixed issue #765 about stellium saving issues when switching server. 2023-03-26 21:14:52 +01:00
Ka0rX
c59473502f Fixed issue #750 about custom model data in Atribute view. 2023-03-26 21:14:29 +01:00
Ka0rX
fbe4314649 Transfer of Unlockable to MythicLib 2023-03-26 20:53:21 +01:00
Jules
8b5a94bf3a Fixed data sync health issue 2023-03-26 10:50:25 +02:00
Jules
588665f0b7 Fixed 'main-exp-split' 2023-03-24 23:34:59 +01:00
Jules
cec44d1647 Fixed default party buffs 2023-03-24 22:16:04 +01:00
Ka0rX
77d4f8e4e4 Command to lock/unlock skill manually. It is better to use triggers as it enables the unlocking.. to go to its initial state after a reallocation. 2023-03-21 21:20:14 +01:00
Ka0rX
713146d9dd Handling of unlockedItems on MySQLPlayerDataManager when loading/saving playerData. 2023-03-21 21:03:35 +01:00
Ka0rX
1deed752f4 Handling of unlockedItems on YamlPlayerDataManager when loading/saving playerData. 2023-03-21 21:01:43 +01:00
Ka0rX
a7231d948e Made unlockedItems class based. 2023-03-21 20:58:50 +01:00
Ka0rX
bbab36ca1b Added unlockedItems in ClassDataContainer. 2023-03-21 20:58:14 +01:00
Ka0rX
e518cafc85 Modifications to make UnlockSkillTrigger work with the rest of MMOCore. 2023-03-21 20:41:30 +01:00
Ka0rX
b1b1a6eddd UnlockSkillTrigger 2023-03-21 20:39:07 +01:00
Ka0rX
aaa777267d Skill Unlocking Mechanic. 2023-03-21 16:49:17 +01:00
Jules
d02418ea12 Merge branch 'Bug_Fix' into 'master'
Bug fixing

See merge request phoenix-dvpmt/mmocore!19
2023-03-21 14:07:07 +00:00
Ka0rX
6b91315b57 Class based Ressources that are also saved/set when quitting & connecting to the server. 2023-03-20 16:55:13 +01:00
Ka0rX
4d89fa8fd9 Class based Ressources that are also saved/set when quitting & connecting to the server. 2023-03-19 22:23:33 +01:00
Ka0rX
37bb719381 Buf Fix 2023-03-19 20:46:42 +01:00
Ka0rX
b05ced2660 Added passive & active categories by default 2023-03-19 20:42:43 +01:00
Ka0rX
5edc6ac999 Debug unbinding passive skill. 2023-03-19 20:42:28 +01:00
Ka0rX
10cfc48c9a Removed debug messages 2023-03-19 20:21:47 +01:00
Ka0rX
1d1d28958f Bug Fixing 2023-03-19 20:20:24 +01:00
Ka0rX
5db6ae79dc Modifications to support bound skills in default config 2023-03-19 20:20:10 +01:00
Ka0rX
d1a78ad83f Coming back to old pom.xml version bc of a strange bug 2023-03-19 20:19:49 +01:00
Ka0rX
0f16c987f0 Bug Fix 2023-03-19 18:20:56 +01:00
Ka0rX
6c89e78f54 Bug Fix 2023-03-19 17:56:23 +01:00
Ka0rX
374ac34f3c Bug Fix 2023-03-19 17:21:10 +01:00
Ka0rX
7bf8a4ee24 Version 2023-03-19 14:21:55 +01:00
Ka0rX
cddda1b6eb Version 2023-03-19 14:17:21 +01:00
Ka0rX
f17b9f2ace MMOCoreDataSynchronizer fix for Bounded Skills. 2023-03-19 14:16:34 +01:00
Ka0rX
1205dd773b ResetCommand fix for Bounded Skills. 2023-03-19 14:14:37 +01:00
Ka0rX
f7a6d92fc8 Saves Bound Skills in MySQLPlayerDataManager 2023-03-19 14:12:33 +01:00
Ka0rX
ca7ee79c73 Saves Bound Skills in YamlPlayerDataManager 2023-03-19 14:07:57 +01:00
Ka0rX
9e16e63bf5 Reformat for mapBoundSkills method. 2023-03-19 14:04:06 +01:00
Ka0rX
c618b0267e Reformat for mapBoundSkills method. 2023-03-19 14:03:48 +01:00
Ka0rX
4244bdbe3c Allowed GenericTypes in addJsonObject method 2023-03-19 14:02:50 +01:00
Ka0rX
037fb131ec Merge branch 'master' into Skills-update
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java
2023-03-19 13:57:20 +01:00
Ka0rX
8fc13a70b9 Adapted YamlDataStorage to the new formatting for boundSkills. 2023-03-19 13:51:29 +01:00
Ka0rX
8fc5b5a51c Map representation for BoundSkill in SavedClassInformation.java 2023-03-19 13:43:35 +01:00
Ka0rX
7538b66673 Modification to have the skillSlots seen has as a Map<Integer,ClassSkill> rather than a List<ClassSkill> 2023-03-19 13:42:21 +01:00
Ka0rX
ae9c396c25 Fixed Multiple Servers Skill Tree Bug 2023-03-19 13:33:13 +01:00
Ka0rX
57fe9f1f1b Blocks MMOCore party commands when another Module has been loaded. 2023-03-19 13:15:45 +01:00
Jules
54b67f6b1c Fixed ci/cd 2023-03-19 13:15:35 +01:00
Jules
4a719ad9b1 Changed MythicLib dep name 2023-03-19 12:58:05 +01:00
Ka0rX
2ec66e92ef Skill Slots Update 2023-03-19 10:53:40 +01:00
Jules
68fe326035 Using new debug methods 2023-03-18 23:23:40 +01:00
Jules
a3166b1049 Fixed combat placeholders 2023-03-18 21:56:14 +01:00
Jules
e1011d449f Fixed %mmocore_in_combat% 2023-03-18 21:20:43 +01:00
Ka0rX
1718e04ba5 Removed reference to passive/active skills. 2023-03-16 14:36:07 +01:00
Ka0rX
f5b312691f Modif for SkillSlots (skillSlot map in PlayerClass) 2023-03-16 14:35:18 +01:00
Ka0rX
3b40b2ef30 Removed SkillSlotLimit in PlayerData. 2023-03-16 14:31:51 +01:00
Ka0rX
456ecb9da1 SkillSlot modifications 2023-03-16 14:31:16 +01:00
Jules
a84d240a4e Placeholder for invulnerability 2023-03-11 18:52:58 +01:00
Jules
e5743a7011 Max combat level difference 2023-03-11 18:39:59 +01:00
Jules
b8624733da Messages for combat level restriction 2023-03-11 18:32:46 +01:00
Jules
5c9b73e3ec Fixed merge 2023-03-11 18:02:30 +01:00
Jules
fe2340f8cb Min combat level 2023-03-11 17:59:01 +01:00
Jules
482eeb9e8b Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/ConfigManager.java
2023-03-11 17:45:16 +01:00
Ka0rX
81f245a4ce Removed passive skill from the skill list GUI 2023-03-09 23:10:49 +01:00
Ka0rX
b7d3aa07eb Removed all references to passiveBoundSkill in playerData 2023-03-09 19:03:20 +01:00
Ka0rX
8e6ac3755d Removed references to PassiveBoundSlots in SavedClassInformation.java 2023-03-09 19:01:38 +01:00
Ka0rX
8e37898d33 Changed PlayerClass to make it compatible with SkillSlots 2023-03-09 19:00:38 +01:00
Ka0rX
e9a7097a8d Removed the boundPassiveSkill method in DataContainer 2023-03-09 18:59:29 +01:00
Ka0rX
ef173a2336 Added categories to registeredSkills 2023-03-09 18:58:17 +01:00
Ka0rX
4dce534d74 Creation of skillSlot class 2023-03-09 18:57:07 +01:00
Jules
42f583ac8d Merge remote-tracking branch 'origin/master' 2023-03-09 17:54:01 +01:00
Jules
3239b9ca17 Test push 2023-03-09 17:53:54 +01:00
Ka0rX
25e3b478d5 test 2023-03-09 17:50:41 +01:00
Ka0rX
8b6e31651f Fixed bug for ressources + class based ressource system 2023-03-09 17:49:55 +01:00
Ka0rX
e338c0fd25 Fixed bug for ressources + class based ressource system 2023-03-09 17:22:58 +01:00
Ka0rX
825473c8c6 Debug ressources loading. 2023-03-03 21:59:47 +01:00
Jules
bbd3708393 Removed default exp holos for the exp trigger. 2023-03-03 16:12:37 +01:00
Jules
393fddf497 Cleanup 2023-03-03 16:00:45 +01:00
Jules
5e73e41fa8 Cleanup 2023-03-03 15:22:54 +01:00
Jules
46ea648414 Moved close script to party module listener 2023-03-03 14:55:29 +01:00
Jules
8c0d8da483 Moved "class-confirmation-gui-name" option from class-select to class-confirm GUI 2023-03-03 14:22:43 +01:00
Jules
8ac6af34af Cleanup 2023-03-03 14:20:56 +01:00
Ka0rX
2b5932756f Debug Model Data Skill Tree GUI. 2023-03-03 10:27:45 +01:00
Ka0rX
5499979567 Debug config de base MMOCore 2023-03-02 22:37:02 +01:00
Ka0rX
3754a88880 Default GUI config to show how it works. 2023-03-02 22:13:16 +01:00
Ka0rX
a9ebca0f4d Enabled to have customizable ClassConfirmation GUI names. 2023-03-02 22:03:03 +01:00
Ka0rX
6ac3267059 Fixed bug that occured w/ perm stats when changing to a new class. 2023-03-02 21:31:42 +01:00
Ka0rX
b3c3218d87 Fixed bug that occured w perm stats when doing /mmocore reload 2023-03-02 21:09:31 +01:00
Ka0rX
d847049e90 Merge remote-tracking branch 'origin/master' 2023-03-02 21:08:37 +01:00
Jules
9ae2b3e661 Fixed UClans comp 2023-02-28 18:05:45 +01:00
Jules
ff75a08e42 Fixed DungeonsXL comp 2023-02-28 18:05:24 +01:00
Jules
79e26086ae Combat registers when logging in/changing world 2023-02-28 10:50:15 +01:00
Jules
f750326fe3 Added messages for guild/party module hook 2023-02-23 00:07:14 +01:00
Jules
deffae106a Updated KingdomsX dep 2023-02-23 00:07:02 +01:00
Jules
b966508c2d Messages sent only when dmg > 0 2023-02-22 23:59:00 +01:00
Jules
afa4a0467e Final commit for combat mode 2023-02-22 23:56:51 +01:00
Jules
14c015645d Reduced confusion for guild module 2023-02-22 23:40:37 +01:00
Jules
05355688e2 Fixed support for Kingdomsx 2023-02-22 22:53:27 +01:00
Jules
fb270bf1b6 Placeholder for pvp mode 2023-02-22 22:31:01 +01:00
Jules
83b9c37c6a Disabled combat mode by default 2023-02-22 17:38:38 +01:00
Jules
cebbfcf5c8 New options for combat mode 2023-02-22 17:33:22 +01:00
Ka0rX
b37c461092 Fixed prefix bug for stat triggers. 2023-02-21 22:02:50 +01:00
Ka0rX
b44283abcb Bug Fixing for Skill Trees. 2023-02-21 21:23:09 +01:00
Jules
07a61b900e Added invulnerability when using /pvpmode inside of region 2023-02-21 14:56:25 +01:00
Jules
9bd830efb7 Fixed pvp mode 2023-02-21 14:29:15 +01:00
Jules
9e8daf4842 Fixed party exp splitting + new option 2023-02-18 15:17:45 +01:00
Jules
4ae7fa4387 Fixed pvp mode 2023-02-17 15:37:48 +01:00
Jules
f23e520635 Fixed stat trigger issue with multiple players 2023-02-16 19:52:03 +01:00
Jules
25391039bc Fixed ints in exp source 2023-02-16 19:41:33 +01:00
Jules
c32bbdefdb Fixed NPE with exp 2023-02-14 11:44:41 +01:00
Jules
0fa680ae2f Fixed action bar time out 2023-02-02 16:15:35 +01:00
Jules
568ead3eca Annotations 2023-02-02 11:33:15 +01:00
Jules
5258c6114a PvP Mode 2023-02-02 11:17:09 +01:00
Jules
13669d8394 Added repo to main pom 2023-02-01 21:24:58 +01:00
Jules
e5ff3489ab Merge remote-tracking branch 'origin/master' 2023-02-01 21:23:00 +01:00
Jules
84f6019ced Removed use of lumine repo 2023-02-01 21:22:53 +01:00
Jules
7c6fc86f22 update ver nb 2023-01-31 21:16:38 +00:00
Jules
7c60d3687b Deprecated placeholder 2023-01-31 21:54:50 +01:00
Jules
c720e73f90 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	MMOCore-API/src/main/java/net/Indyuce/mmocore/party/MMOCoreTargetRestriction.java
2023-01-27 19:29:49 +01:00
Ka0rX
9acbe6473a Merge remote-tracking branch 'origin/master' 2023-01-25 14:19:09 +01:00
Taner
55eab768fe Update messages.yml 2023-01-24 08:42:29 +00:00
Ka0rX
c62d468991 New placeholders when casting skills. 2023-01-23 17:37:51 +01:00
Ka0rX
a827c27ec2 Fixed bug linked to PlayerClickEvent for GUI. 2023-01-23 14:39:30 +01:00
Jules
f59af50463 YAML backup if sql fails 2023-01-22 23:49:52 +01:00
Jules
47f7517d48 Data sync fix 2023-01-22 23:07:41 +01:00
Jules
30bf4b0e99 Combat commit 1 2023-01-22 21:59:06 +01:00
Jules
fa6809b483 SQL fix 2023-01-22 21:58:54 +01:00
Jules
c1a231e8e1 /mmocore savedata 2023-01-22 21:58:17 +01:00
Ka0rX
89da963a76 Compat MythicLib 2023-01-18 11:07:26 +01:00
Jules
d4a5011b41 Added method to PlayerResourceUpdateEvent 2023-01-11 16:38:49 +01:00
Indyuce
98cfda4cfe Rolled back not closing current quest 2023-01-06 22:50:59 +01:00
Indyuce
93ad4c8a0b Merge remote-tracking branch 'origin/master' 2023-01-06 16:18:13 +01:00
Indyuce
0505c77f7d Fixed version nb 2022-12-30 18:35:12 +01:00
Indyuce
09accfc0f0 Made combat log damage causes configurable 2022-12-30 18:05:51 +01:00
Indyuce
05264fe30a Moved lumine repo 2022-12-30 14:22:30 +01:00
Indyuce
481d9da579 Removed used of flatten plugin 2022-12-30 14:19:30 +01:00
Indyuce
35d90ae55b Cleaned up command api 2022-12-29 15:00:34 +01:00
444 changed files with 16556 additions and 7609 deletions

View File

@ -1,15 +0,0 @@
<settings>
<servers>
<server>
<id>nexus</id>
<username>${env.M2_REPO_USER}</username>
<password>${env.M2_REPO_PASS}</password>
<blocked>false</blocked>
</server>
<server>
<id>lumine</id>
<username>${env.M2_REPO_USER}</username>
<password>${env.M2_REPO_PASS}</password>
</server>
</servers>
</settings>

19
LICENSE
View File

@ -1,3 +1,18 @@
This project is owned and maintained by PhoenixDvpt and is distributed with "All Right's Reserved".
This project is owned and maintained by "Phoenix Development" and is distributed with "All Rights Reserved".
PhoenixDevt reserves the right to change these terms at any time, you have to comply with the most recent version.
We do NOT provide support to servers involved with piracy in any form, or owners who have downloaded ANY of our plugins from an unofficial/illegal source.
You can fork and modify the source code of this project as you wish to meet your server's needs, and merge requests are accepted under the terms that you grant full rights to us using any pushed code. However, you may not distribute the plugin for any purpose other than providing cross-compatibility with other Minecraft plugins, and may not bypass any anti-piracy protection.
Things can you CANNOT do:
- Issue a refund on PayPal without our explicit permission, as this is a digital good.
- Redistribute, sell or give an official/modified version of the plugin (with or without any type of counterpart) to anyone else.
- Modify and compile the project source code to bypass an anti-piracy protection.
- Download, compile, decompile or use the plugin on any server without purchasing a license.
Things can you CAN do when purchasing the plugin:
- Download and decompile the plugin file.
- Fork and modify the project source code to meet your production server's needs.
- Use it on ONE production server or network (= proxy-connected servers) and one private test server at a time.
You may propose a merge request, under the terms that you grant full rights to us using any pushed code.
If you are a developer and have not purchased a license, you have the permission to download, fork, edit and compile the project source code, and sell code modifications to your client ONLY IF they have already purchased a license. This only applies to one-time comission works and does NOT apply to public sales.

View File

@ -5,35 +5,18 @@
<parent>
<artifactId>MMOCore</artifactId>
<groupId>net.Indyuce</groupId>
<version>${revision}</version>
<version>1.12.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MMOCore-API</artifactId>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<build>
<finalName>${project.name}-${project.version}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<defaultGoal>clean package install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>16</source>
<target>16</target>
<encoding>UTF-8</encoding>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@ -97,8 +80,13 @@
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
@ -106,11 +94,6 @@
<url>https://maven.enginehub.org/repo/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
@ -121,16 +104,39 @@
<id>simonsators Repo</id>
<url>https://simonsator.de/repo</url>
</repository>
<!-- Heroes Repository
<repository>
<id>herocraft</id>
<url>https://nexus.hc.to/content/repositories/pub_releases</url>
</repository> -->
</repositories>
<dependencies>
<!-- Spigot API -->
<!-- Paper API -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-1.17.1</artifactId>
<version>dev</version>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.20.6-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Extra libs -->
@ -146,14 +152,32 @@
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Plugin dependencies -->
<dependency>
<groupId>io.lumine</groupId>
<artifactId>Mythic-Dist</artifactId>
<version>5.0.1</version>
<version>5.7.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.playavalon</groupId>
<artifactId>MythicDungeons</artifactId>
<version>1.4.1-SNAPSHOT-CUSTOM</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>fr.phoenixdevt</groupId>
<artifactId>Profile-API</artifactId>
<version>1.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -161,6 +185,7 @@
<artifactId>placeholderapi</artifactId>
<version>2.9.2</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -168,6 +193,7 @@
<artifactId>VaultAPI</artifactId>
<version>1.7.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -175,6 +201,18 @@
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.2-SNAPSHOT</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -182,6 +220,7 @@
<artifactId>ProtocolLib</artifactId>
<version>4.8.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -189,6 +228,7 @@
<artifactId>Citizens</artifactId>
<version>2.0.30</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Party plugins -->
@ -197,6 +237,7 @@
<artifactId>DevelopmentPAFSpigot</artifactId>
<version>1.0.65</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -204,6 +245,7 @@
<artifactId>Party-and-Friends-MySQL-Edition-Spigot-API</artifactId>
<version>1.5.4-RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -211,6 +253,15 @@
<artifactId>spigot-party-api-for-party-and-friends</artifactId>
<version>1.0.4-RELEASE</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.civious</groupId>
<artifactId>OBTeam</artifactId>
<version>1.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -218,6 +269,7 @@
<artifactId>Parties</artifactId>
<version>3.1.14</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -225,13 +277,31 @@
<artifactId>mcMMO</artifactId>
<version>2.1.209</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.erethon</groupId>
<artifactId>DungeonsXL</artifactId>
<version>0.18-PRE-02</version>
<version>0.18-SNAPSHOT-1149</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.herocraftonline</groupId>
<artifactId>Heroes</artifactId>
<version>1.9.22</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>de.erethon</groupId>
<artifactId>Bedrock</artifactId>
<version>1.2.5</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -239,6 +309,7 @@
<artifactId>Dungeons</artifactId>
<version>1.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Quest Plugins -->
@ -247,39 +318,45 @@
<artifactId>Quests</artifactId>
<version>4.4.1-b340</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>fr.skytasul.quests</groupId>
<artifactId>BeautyQuests</artifactId>
<version>0.19.5</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.guillaumevdn</groupId>
<artifactId>QuestCreator</artifactId>
<version>6.39.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.guillaumevdn</groupId>
<artifactId>GCore</artifactId>
<version>8.39.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Guild plugins -->
<dependency>
<groupId>com.massivecraft</groupId>
<artifactId>Factions</artifactId>
<version>1.6.9.5-2.9.8-RC</version>
<groupId>cc.javajobs</groupId>
<artifactId>FactionsBridge</artifactId>
<version>1.3.6</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>me.ulrich</groupId>
<artifactId>UltimateClans</artifactId>
<version>4.2.0</version>
<groupId>com.github.UlrichBR</groupId>
<artifactId>UClansV7-API</artifactId>
<version>7.1.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
@ -287,13 +364,15 @@
<artifactId>Guilds</artifactId>
<version>3.5.6.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.kingdoms.main</groupId>
<artifactId>Kingdoms</artifactId>
<version>1.11.15.0.0.0.1.1</version>
<version>1.15.5</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>

View File

@ -2,14 +2,15 @@ package net.Indyuce.mmocore;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.data.sql.SQLDataSource;
import io.lumine.mythic.lib.metrics.bukkit.Metrics;
import io.lumine.mythic.lib.util.MMOPlugin;
import io.lumine.mythic.lib.version.SpigotPlugin;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.social.PartyManager;
import net.Indyuce.mmocore.api.ConfigFile;
import net.Indyuce.mmocore.manager.ActionBarManager;
import net.Indyuce.mmocore.api.player.attribute.AttributeModifier;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.command.*;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener;
import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader;
import net.Indyuce.mmocore.comp.mythicmobs.MythicHook;
@ -21,45 +22,47 @@ import net.Indyuce.mmocore.comp.region.DefaultRegionHandler;
import net.Indyuce.mmocore.comp.region.RegionHandler;
import net.Indyuce.mmocore.comp.region.WorldGuardMMOLoader;
import net.Indyuce.mmocore.comp.region.WorldGuardRegionHandler;
import net.Indyuce.mmocore.comp.region.pvpmode.PvPModeListener;
import net.Indyuce.mmocore.comp.vault.VaultEconomy;
import net.Indyuce.mmocore.comp.vault.VaultMMOLoader;
import net.Indyuce.mmocore.guild.GuildModule;
import net.Indyuce.mmocore.guild.GuildModuleType;
import net.Indyuce.mmocore.guild.GuildRelationHandler;
import net.Indyuce.mmocore.guild.provided.Guild;
import net.Indyuce.mmocore.guild.provided.MMOCoreGuildModule;
import net.Indyuce.mmocore.guild.provided.YAMLGuildDataManager;
import net.Indyuce.mmocore.manager.*;
import net.Indyuce.mmocore.manager.data.DataProvider;
import net.Indyuce.mmocore.manager.data.mysql.MySQLDataProvider;
import net.Indyuce.mmocore.manager.data.yaml.YAMLDataProvider;
import net.Indyuce.mmocore.manager.data.GuildDataManager;
import net.Indyuce.mmocore.manager.data.LegacyDataProvider;
import net.Indyuce.mmocore.manager.data.PlayerDataManager;
import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler;
import net.Indyuce.mmocore.manager.profession.*;
import net.Indyuce.mmocore.manager.social.BoosterManager;
import net.Indyuce.mmocore.manager.social.PartyManager;
import net.Indyuce.mmocore.manager.social.RequestManager;
import net.Indyuce.mmocore.party.MMOCoreTargetRestriction;
import net.Indyuce.mmocore.party.PartyModule;
import net.Indyuce.mmocore.party.PartyModuleType;
import net.Indyuce.mmocore.party.PartyRelationHandler;
import net.Indyuce.mmocore.party.provided.MMOCorePartyModule;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import net.Indyuce.mmocore.script.mechanic.ExperienceMechanic;
import net.Indyuce.mmocore.script.mechanic.StaminaMechanic;
import net.Indyuce.mmocore.script.mechanic.ManaMechanic;
import net.Indyuce.mmocore.script.mechanic.StaminaMechanic;
import net.Indyuce.mmocore.script.mechanic.StelliumMechanic;
import net.Indyuce.mmocore.skill.cast.SkillCastingMode;
import net.Indyuce.mmocore.skill.trigger.MMOCoreTriggerType;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import io.lumine.mythic.lib.metrics.bukkit.Metrics;
import org.bukkit.command.CommandMap;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.EventPriority;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.lang.reflect.Field;
import java.util.logging.Level;
public class MMOCore extends JavaPlugin {
public class MMOCore extends MMOPlugin {
public static MMOCore plugin;
public final WaypointManager waypointManager = new WaypointManager();
public final SoundManager soundManager = new SoundManager();
public final RequestManager requestManager = new RequestManager();
@ -79,6 +82,10 @@ public class MMOCore extends JavaPlugin {
public final RestrictionManager restrictionManager = new RestrictionManager();
public final SkillTreeManager skillTreeManager = new SkillTreeManager();
public final StatManager statManager = new StatManager();
public final GuildDataManager nativeGuildManager = new YAMLGuildDataManager();
public final PlayerDataManager playerDataManager = new PlayerDataManager(this);
@Deprecated
public final DataProvider dataProvider = new LegacyDataProvider();
// Profession managers
public final CustomBlockManager mineManager = new CustomBlockManager();
@ -92,13 +99,11 @@ public class MMOCore extends JavaPlugin {
public VaultEconomy economy;
public RegionHandler regionHandler = new DefaultRegionHandler();
public PlaceholderParser placeholderParser = new DefaultParser();
public DataProvider dataProvider = new YAMLDataProvider();
// Modules
@NotNull
public PartyModule partyModule;
public GuildModule guildModule;
public boolean shouldDebugSQL = false;
public MMOCore() {
plugin = this;
@ -106,10 +111,13 @@ public class MMOCore extends JavaPlugin {
@Override
public void onLoad() {
getLogger().log(Level.INFO, "Plugin file is called '" + getFile().getName() + "'");
// Register MMOCore-specific objects
MythicLib.plugin.getEntities().registerRestriction(new MMOCoreTargetRestriction());
MythicLib.plugin.getEntities().registerRelationHandler(new PartyRelationHandler());
MythicLib.plugin.getEntities().registerRelationHandler(new GuildRelationHandler());
MythicLib.plugin.getModifiers().registerModifierType("attribute", configObject -> new AttributeModifier(configObject));
MMOCoreTriggerType.registerAll();
// Custom scripts
MythicLib.plugin.getSkills().registerMechanic("mana", config -> new ManaMechanic(config));
@ -143,12 +151,13 @@ public class MMOCore extends JavaPlugin {
getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')");
}
if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled"))
dataProvider = new MySQLDataProvider(getConfig());
shouldDebugSQL = getConfig().getBoolean("mysql.debug");
if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) {
final SQLDataSource dataSource = new SQLDataSource(this);
playerDataManager.setDataHandler(new SQLDataHandler(dataSource));
}
if (getConfig().isConfigurationSection("default-playerdata"))
dataProvider.getDataManager().loadDefaultData(getConfig().getConfigurationSection("default-playerdata"));
playerDataManager.loadDefaultData(getConfig().getConfigurationSection("default-playerdata"));
if (Bukkit.getPluginManager().getPlugin("Vault") != null) economy = new VaultEconomy();
@ -164,6 +173,8 @@ public class MMOCore extends JavaPlugin {
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
regionHandler = new WorldGuardRegionHandler();
if (getConfig().getBoolean("pvp_mode.enabled"))
Bukkit.getPluginManager().registerEvents(new PvPModeListener(), this);
getLogger().log(Level.INFO, "Hooked onto WorldGuard");
}
@ -173,8 +184,8 @@ public class MMOCore extends JavaPlugin {
}
/*
* Resource regeneration. Must check if entity is dead otherwise regen will make
* the 'respawn' button glitched plus HURT entity effect bug
* Resource regeneration. Must check if entity is dead otherwise regen
* will make the 'respawn' button glitched plus HURT entity effect bug
*/
new BukkitRunnable() {
public void run() {
@ -196,8 +207,6 @@ public class MMOCore extends JavaPlugin {
if (Bukkit.getPluginManager().getPlugin("MMOMana") != null) {
getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "MMOCore is not meant to be used with MMOItems ManaAndStamina");
getLogger().log(Level.SEVERE, ChatColor.DARK_RED + "Please read the installation guide!");
Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] MMOCore is not meant to be used with MMOItems ManaAndStamina");
Bukkit.broadcastMessage(ChatColor.DARK_RED + "[MMOCore] Please read the installation guide!");
return;
}
@ -207,9 +216,10 @@ public class MMOCore extends JavaPlugin {
try {
String partyPluginName = UtilityMethods.enumName(getConfig().getString("party-plugin"));
PartyModuleType moduleType = PartyModuleType.valueOf(partyPluginName);
Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed");
Validate.isTrue(moduleType.isValid(), "Plugin " + moduleType.getPluginName() + " is not installed");
partyModule = moduleType.provideModule();
} catch (RuntimeException exception) {
getLogger().log(Level.INFO, "Hooked parties onto " + moduleType.getPluginName());
} catch (Throwable exception) {
getLogger().log(Level.WARNING, "Could not initialize party module: " + exception.getMessage());
partyModule = new MMOCorePartyModule();
}
@ -220,6 +230,7 @@ public class MMOCore extends JavaPlugin {
GuildModuleType moduleType = GuildModuleType.valueOf(pluginName);
Validate.isTrue(moduleType.isValid(), "Plugin '" + moduleType.name() + "' is not installed");
guildModule = moduleType.provideModule();
getLogger().log(Level.INFO, "Hooked guilds onto " + moduleType.getPluginName());
} catch (RuntimeException exception) {
getLogger().log(Level.WARNING, "Could not initialize guild module: " + exception.getMessage());
guildModule = new MMOCoreGuildModule();
@ -227,8 +238,8 @@ public class MMOCore extends JavaPlugin {
// Skill casting
try {
SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode")));
Bukkit.getPluginManager().registerEvents(mode.loadFromConfig(getConfig().getConfigurationSection("skill-casting")), this);
final SkillCastingMode mode = SkillCastingMode.valueOf(UtilityMethods.enumName(getConfig().getString("skill-casting.mode")));
mode.setCurrent(getConfig().getConfigurationSection("skill-casting"));
} catch (RuntimeException exception) {
getLogger().log(Level.WARNING, "Could not load skill casting: " + exception.getMessage());
}
@ -237,6 +248,7 @@ public class MMOCore extends JavaPlugin {
try {
Class.forName("net.Indyuce.mmocore.MMOCoreBukkit").getConstructor(MMOCore.class).newInstance(this);
} catch (Throwable exception) {
exception.printStackTrace();
throw new RuntimeException("Cannot run an API build on Spigot!");
}
@ -245,95 +257,29 @@ public class MMOCore extends JavaPlugin {
* that after registering all the professses otherwise the player datas can't
* recognize what profess the player has and professes will be lost
*/
Bukkit.getOnlinePlayers().forEach(player -> dataProvider.getDataManager().setup(player.getUniqueId()));
playerDataManager.initialize(EventPriority.LOW, EventPriority.NORMAL);
// load guild data after loading player data
dataProvider.getGuildManager().load();
nativeGuildManager.load();
// Command
try {
final Field bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap");
bukkitCommandMap.setAccessible(true);
CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer());
FileConfiguration config = new ConfigFile("commands").getConfig();
if (config.contains("player"))
commandMap.register("mmocore", new PlayerStatsCommand(config.getConfigurationSection("player")));
if (config.contains("attributes"))
commandMap.register("mmocore", new AttributesCommand(config.getConfigurationSection("attributes")));
if (config.contains("class"))
commandMap.register("mmocore", new ClassCommand(config.getConfigurationSection("class")));
if (config.contains("waypoints"))
commandMap.register("mmocore", new WaypointsCommand(config.getConfigurationSection("waypoints")));
if (config.contains("quests"))
commandMap.register("mmocore", new QuestsCommand(config.getConfigurationSection("quests")));
if (config.contains("skills"))
commandMap.register("mmocore", new SkillsCommand(config.getConfigurationSection("skills")));
if (config.contains("friends"))
commandMap.register("mmocore", new FriendsCommand(config.getConfigurationSection("friends")));
if (config.contains("party"))
commandMap.register("mmocore", new PartyCommand(config.getConfigurationSection("party")));
if (config.contains("guild"))
commandMap.register("mmocore", new GuildCommand(config.getConfigurationSection("guild")));
if (config.contains("skill-trees"))
commandMap.register("mmocore", new SkillTreeCommand(config.getConfigurationSection("skill-trees")));
if (hasEconomy() && economy.isValid()) {
if (config.contains("withdraw"))
commandMap.register("mmocore", new WithdrawCommand(config.getConfigurationSection("withdraw")));
if (config.contains("deposit"))
commandMap.register("mmocore", new DepositCommand(config.getConfigurationSection("deposit")));
}
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
ex.printStackTrace();
}
// Toggleable Commands
ToggleableCommand.register();
// Register MMOCore command what soever
MMOCoreCommandTreeRoot mmoCoreCommand = new MMOCoreCommandTreeRoot();
getCommand("mmocore").setExecutor(mmoCoreCommand);
getCommand("mmocore").setTabCompleter(mmoCoreCommand);
if (getConfig().getBoolean("auto-save.enabled")) {
int autosave = getConfig().getInt("auto-save.interval") * 20;
new BukkitRunnable() {
public void run() {
// Save player data
for (PlayerData data : PlayerData.getAll())
if (data.isFullyLoaded())
dataProvider.getDataManager().saveData(data);
// Save guild info
for (Guild guild : dataProvider.getGuildManager().getAll())
dataProvider.getGuildManager().save(guild);
}
}.runTaskTimerAsynchronously(MMOCore.plugin, autosave, autosave);
}
}
@Override
public void onDisable() {
//Executes all the pending asynchronous task (like saving the playerData)
Bukkit.getScheduler().getPendingTasks().forEach(worker -> {
if (worker.getOwner().equals(this)) {
((Runnable) worker).run();
}
});
// Save player data
for (PlayerData data : PlayerData.getAll())
if (data.isFullyLoaded()) {
data.close();
dataProvider.getDataManager().saveData(data);
}
// Save guild info
for (Guild guild : dataProvider.getGuildManager().getAll())
dataProvider.getGuildManager().save(guild);
for (Guild guild : nativeGuildManager.getAll())
nativeGuildManager.save(guild);
// Close MySQL data provider (memory leaks)
if (dataProvider instanceof MySQLDataProvider)
((MySQLDataProvider) dataProvider).close();
// Close player data manager
playerDataManager.close();
// Reset active blocks
mineManager.resetRemainingBlocks();
@ -357,8 +303,6 @@ public class MMOCore extends JavaPlugin {
configManager = new ConfigManager();
if (clearBefore)
MythicLib.plugin.getSkills().initialize(true);
skillManager.initialize(clearBefore);
mineManager.initialize(clearBefore);
partyManager.initialize(clearBefore);
@ -372,7 +316,6 @@ public class MMOCore extends JavaPlugin {
statManager.initialize(clearBefore);
professionManager.initialize(clearBefore);
InventoryManager.load();
skillTreeManager.initialize(clearBefore);
classManager.initialize(clearBefore);
questManager.initialize(clearBefore);
@ -382,12 +325,14 @@ public class MMOCore extends JavaPlugin {
requestManager.initialize(clearBefore);
soundManager.initialize(clearBefore);
configItems.initialize(clearBefore);
//Needs to be loaded after the class manager.
InventoryManager.load();
if (getConfig().isConfigurationSection("action-bar"))
actionBarManager.reload(getConfig().getConfigurationSection("action-bar"));
if (clearBefore)
PlayerData.getAll().forEach(PlayerData::update);
PlayerData.getAll().forEach(PlayerData::reload);
}
public static void log(String message) {
@ -405,9 +350,4 @@ public class MMOCore extends JavaPlugin {
public boolean hasEconomy() {
return economy != null && economy.isValid();
}
public static void sqlDebug(String s) {
if (!MMOCore.plugin.shouldDebugSQL) return;
MMOCore.plugin.getLogger().warning("- [SQL Debug] " + s);
}
}

View File

@ -2,47 +2,143 @@ package net.Indyuce.mmocore.api;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.MMOCore;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ConfigMessage {
private final List<String> messages;
private final String key;
private final List<String> lines = new ArrayList<>();
private final boolean papiPlaceholders, actionbar, raw;
public ConfigMessage(String key) {
messages = MMOCore.plugin.configManager.getMessage(key);
private ConfigMessage(@NotNull String key) {
this.key = key;
// Initialize message list
final Object obj = MMOCore.plugin.configManager.getMessageObject(key);
if (obj == null) lines.add("<message_not_found:'" + key + "'>");
else if (obj instanceof List<?>) lines.addAll((List<String>) obj);
else {
final String tostr = obj.toString();
if (!tostr.isEmpty()) lines.add(tostr);
}
// Does message include placeholders
boolean hasPlaceholders = false;
for (String str : lines)
if (str.contains("%")) {
hasPlaceholders = true;
break;
}
this.papiPlaceholders = hasPlaceholders;
// Is message for action bar
actionbar = !lines.isEmpty() && lines.get(0).startsWith("%");
if (actionbar) lines.set(0, lines.get(0).substring(1));
// Are messages raw (JSON format)
raw = !lines.isEmpty() && (lines.get(0).startsWith("{") || lines.get(0).startsWith("["));
}
public ConfigMessage addPlaceholders(String... placeholders) {
for (int n = 0; n < messages.size(); n++) {
String line = messages.get(n);
/**
* Useful for things like indicators or specific lore lines
* which are string tags not requiring more than one string
* object. An empty return value is accepted as some features
* do require the ability to fully remove text.
*
* @return First line of message, if it exists.
*/
@NotNull
public String asLine() {
return lines.isEmpty() ? "" : lines.get(0);
}
@NotNull
public List<String> getLines() {
return lines;
}
@NotNull
public ConfigMessage addPlaceholders(@NotNull Object... placeholders) {
for (int n = 0; n < lines.size(); n++) {
String line = lines.get(n);
// Apply placeholders to string
for (int j = 0; j < placeholders.length - 1; j += 2) {
String placeholder = placeholders[j];
if (line.contains("{" + placeholder + "}"))
line = line.replace("{" + placeholder + "}", placeholders[j + 1]);
final String placeholder = String.valueOf(placeholders[j]);
line = line.replace("{" + placeholder + "}", String.valueOf(placeholders[j + 1]));
}
messages.set(n, line);
lines.set(n, line);
}
return this;
}
public void send(CommandSender sender) {
messages.forEach(line -> sender.sendMessage(format(sender, line)));
@Deprecated
public void sendAsJSon(Player player) {
send(player);
}
public void send(Player player) {
for (String line : lines) send(player, line);
}
public void send(Collection<? extends Player> players) {
players.forEach(player -> messages.forEach(line -> player.sendMessage(format(player, line))));
for (Player player : players) for (String line : lines) send(player, line);
}
public void sendAsJSon(Player player) {
messages.forEach(line -> MythicLib.plugin.getVersion().getWrapper().sendJson(player, format(player, line)));
/**
* Sends a line of text to a target player
*
* @param player Player to send message to. His player
* data is not necessarily fully loaded
* @param messageFormat Raw/normal message to send
*/
private void send(@NotNull Player player, String messageFormat) {
Validate.notNull(player, "Player cannot be null");
final String rawMessage = format(player, messageFormat);
final PlayerData playerData = PlayerData.has(player) ? PlayerData.get(player) : null;
// Handle special case with player data + action bar
if (playerData != null && playerData.isOnline() && actionbar) {
playerData.displayActionBar(rawMessage, raw);
return;
}
// Normal sender
if (this.raw) {
if (actionbar) MythicLib.plugin.getVersion().getWrapper().sendActionBarRaw(player, rawMessage);
else MythicLib.plugin.getVersion().getWrapper().sendJson(player, rawMessage);
} else {
if (actionbar)
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(rawMessage));
else player.sendMessage(rawMessage);
}
}
private String format(CommandSender sender, String input) {
String str = MythicLib.plugin.parseColors(input);
return sender instanceof Player ? MMOCore.plugin.placeholderParser.parse((OfflinePlayer) sender, str) : str;
@NotNull
private String format(@Nullable Player player, String input) {
input = MythicLib.plugin.parseColors(input);
if (!papiPlaceholders || player == null) return input; // Optimization
return MMOCore.plugin.placeholderParser.parse(player, input);
}
@NotNull
public static ConfigMessage fromKey(@NotNull String key, Object... placeholders) {
Validate.notNull(MMOCore.plugin.configManager, "MMOCore has not finished enabling");
final ConfigMessage message = new ConfigMessage(key);
if (placeholders.length != 0) message.addPlaceholders(placeholders);
return message;
}
}

View File

@ -25,7 +25,7 @@ public class MMOCoreAPI {
}
public PlayerData getPlayerData(OfflinePlayer player) {
return PlayerData.get(player.getUniqueId());
return PlayerData.get(player);
}
public boolean isInSameParty(Player player1, Player player2) {
@ -65,7 +65,7 @@ public class MMOCoreAPI {
public SkillResult cast(PlayerData playerData, ClassSkill skill) {
PlayerMetadata casterMeta = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
TriggerMetadata triggerMeta = new TriggerMetadata(casterMeta, null, null);
return new CastableSkill(skill, playerData.getSkillLevel(skill.getSkill())).cast(triggerMeta);
return new CastableSkill(skill, playerData).cast(triggerMeta);
}
/**

View File

@ -6,15 +6,14 @@ public enum SoundEvent {
WARP_CANCELLED,
WARP_CHARGE,
WARP_UNLOCK,
HOTBAR_SWAP,
SPELL_CAST_BEGIN,
SPELL_CAST_END,
CANT_SELECT_CLASS,
SELECT_CLASS,
LEVEL_ATTRIBUTE,
RESET_ATTRIBUTES,
RESET_SKILLS
,NOT_ENOUGH_POINTS,
RESET_SKILLS,
NOT_ENOUGH_POINTS,
CANCEL_QUEST,
START_QUEST,
CLOSE_LOOT_CHEST,

View File

@ -24,6 +24,7 @@ public class SoundObject {
private final float volume;
private final float pitch;
@Deprecated
public SoundObject(String input) {
String[] split = input.split(",");
@ -36,12 +37,14 @@ public class SoundObject {
}
this.sound = sound;
this.key = key;
this.key = key != null ? key.toLowerCase() : null;
volume = split.length > 1 ? Float.parseFloat(split[1]) : 1;
pitch = split.length > 2 ? Float.parseFloat(split[2]) : 1;
}
@Deprecated
public SoundObject(ConfigurationSection config) {
String input = config.getString("sound");
@ -54,7 +57,7 @@ public class SoundObject {
}
this.sound = sound;
this.key = key;
this.key = key != null ? key.toLowerCase() : null;
volume = (float) config.getDouble("volume", 1);
pitch = (float) config.getDouble("pitch", 1);
@ -62,34 +65,41 @@ public class SoundObject {
/**
* @return If this object is custom a custom sound, potentially
* from a resource pack
* from a resource pack
*/
@Deprecated
public boolean isCustom() {
return sound == null;
}
@Nullable
@Deprecated
public Sound getSound() {
return sound;
}
@Nullable
@Deprecated
public String getKey() {
return key;
}
@Deprecated
public float getVolume() {
return volume;
}
@Deprecated
public float getPitch() {
return pitch;
}
@Deprecated
public void playTo(Player player) {
playTo(player, volume, pitch);
}
@Deprecated
public void playTo(Player player, float volume, float pitch) {
if (isCustom())
player.playSound(player.getLocation(), key, volume, pitch);
@ -97,10 +107,12 @@ public class SoundObject {
player.playSound(player.getLocation(), sound, volume, pitch);
}
@Deprecated
public void playAt(Location loc) {
playAt(loc, volume, pitch);
}
@Deprecated
public void playAt(Location loc, float volume, float pitch) {
if (isCustom())
loc.getWorld().playSound(loc, key, volume, pitch);

View File

@ -43,7 +43,7 @@ public class BlockInfo {
options.put(option, config.getBoolean("options." + key));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load option '" + key + "' from block info '" + block.generateKey() + "': " + exception.getMessage());
"Could not load option '" + key + "' from block info '" + block.display() + "': " + exception.getMessage());
}
if (config.contains("triggers")) {
@ -55,7 +55,7 @@ public class BlockInfo {
triggers.add(MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(key)));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load trigger '" + key + "' from block info '" + block.generateKey() + "': " + exception.getMessage());
"Could not load trigger '" + key + "' from block info '" + block.display() + "': " + exception.getMessage());
}
}
@ -65,13 +65,13 @@ public class BlockInfo {
if (condition instanceof BlockCondition)
conditions.add((BlockCondition) condition);
}
}
public boolean getOption(BlockInfoOption option) {
return options.getOrDefault(option, option.getDefault());
}
@NotNull
public BlockType getBlock() {
return block;
}
@ -85,6 +85,7 @@ public class BlockInfo {
return table != null;
}
@Deprecated
public List<ItemStack> collectDrops(LootBuilder builder) {
return table != null ? table.collect(builder) : new ArrayList<>();
}

View File

@ -1,29 +1,31 @@
package net.Indyuce.mmocore.api.block;
import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface BlockType {
/**
* Called when placing temporary blocks
*/
void place(BlockInfo.RegeneratingBlock placed);
/**
* Called when placing temporary blocks
*/
void place(@NotNull BlockInfo.RegeneratingBlock placed);
/**
* Called when regenerating an older block with block regen
*/
void regenerate(BlockInfo.RegeneratingBlock regenerating);
/**
* Called when regenerating an older block with block regen
*/
void regenerate(@NotNull BlockInfo.RegeneratingBlock regenerating);
/**
* Generates a key used to store the BlockInfo instance in the manager map,
* the key depends on the block type to make sure there is no interference
*/
String generateKey();
@NotNull String display();
/**
* Applies some extra break restrictions; returns TRUE if the block can be
* broken. This method is used to prevent non mature crops from being broken
* for example
*/
boolean breakRestrictions(Block block);
/**
* Applies some extra break restrictions; returns TRUE if the block can be
* broken. This method is used to prevent non mature crops from being broken
* for example
*/
boolean breakRestrictions(@NotNull Block block);
int hashCode();
boolean equals(@Nullable Object obj);
}

View File

@ -1,59 +1,73 @@
package net.Indyuce.mmocore.api.block;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import org.bukkit.Location;
import org.bukkit.block.Block;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import java.util.Objects;
public class SkullBlockType implements BlockType {
private final String value;
private final String value;
public SkullBlockType(MMOLineConfig config) {
config.validate("value");
public SkullBlockType(MMOLineConfig config) {
config.validate("value");
value = config.getString("value");
}
value = config.getString("value");
}
public SkullBlockType(Block block) {
value = MythicLib.plugin.getVersion().getWrapper().getSkullValue(block);
}
public SkullBlockType(Block block) {
value = MythicLib.plugin.getVersion().getWrapper().getSkullValue(block);
}
public String getValue() {
return value;
}
public String getValue() {
return value;
}
@Override
public void place(RegeneratingBlock block) {
Location loc = block.getLocation();
loc.getBlock().setType(VersionMaterial.PLAYER_HEAD.toMaterial());
@Override
public void place(RegeneratingBlock block) {
Location loc = block.getLocation();
loc.getBlock().setType(Material.PLAYER_HEAD);
// save skull orientation if replaced block is a player head
if (MMOCoreUtils.isPlayerHead(block.getBlockData().getMaterial()))
loc.getBlock().setBlockData(block.getBlockData());
// save skull orientation if replaced block is a player head
if (MMOCoreUtils.isPlayerHead(block.getBlockData().getMaterial()))
loc.getBlock().setBlockData(block.getBlockData());
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
}
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
}
@Override
public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation();
// This makes sure that if a skull loses its original rotation
// it can revert back to it when the base block is regenerated
loc.getBlock().setBlockData(block.getBlockData());
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
}
@Override
public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation();
// This makes sure that if a skull loses its original rotation
// it can revert back to it when the base block is regenerated
loc.getBlock().setBlockData(block.getBlockData());
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
}
@Override
public String generateKey() {
return "vanilla-skull-" + value;
}
@Override
public String display() {
return "Skull{" + value + "}";
}
@Override
public boolean breakRestrictions(Block block) {
return true;
}
@Override
public boolean breakRestrictions(Block block) {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SkullBlockType that = (SkullBlockType) o;
return Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}

View File

@ -1,5 +1,7 @@
package net.Indyuce.mmocore.api.block;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Material;
@ -7,63 +9,75 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
import io.lumine.mythic.lib.api.MMOLineConfig;
import java.util.Objects;
public class VanillaBlockType implements BlockType {
private final Material type;
private final Material type;
/*
* allows to plant back crops with a custom age so that it does not always
* have to full grow again-
*/
private final int age;
/*
* allows to plant back crops with a custom age so that it does not always
* have to full grow again-
*/
private final int age;
public VanillaBlockType(MMOLineConfig config) {
config.validate("type");
public VanillaBlockType(MMOLineConfig config) {
config.validate("type");
type = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
age = config.getInt("age", 0);
type = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
age = config.getInt("age", 0);
Validate.isTrue(age >= 0 && age < 8, "Age must be between 0 and 7");
}
Validate.isTrue(age >= 0 && age < 8, "Age must be between 0 and 7");
}
public VanillaBlockType(Block block) {
type = block.getType();
age = 0;
}
public VanillaBlockType(Block block) {
type = block.getType();
age = 0;
}
public Material getType() {
return type;
}
public Material getType() {
return type;
}
@Override
public void place(RegeneratingBlock block) {
Location loc = block.getLocation();
block.getLocation().getBlock().setType(type);
@Override
public void place(RegeneratingBlock block) {
Location loc = block.getLocation();
block.getLocation().getBlock().setType(type);
BlockData state = block.getLocation().getBlock().getBlockData();
if (age > 0 && state instanceof Ageable) {
((Ageable) state).setAge(age);
loc.getBlock().setBlockData(state);
}
}
BlockData state = block.getLocation().getBlock().getBlockData();
if (age > 0 && state instanceof Ageable) {
((Ageable) state).setAge(age);
loc.getBlock().setBlockData(state);
}
}
@Override
public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation();
loc.getBlock().setType(type);
// Sets the original blocks old data (only when regenerating)
loc.getBlock().setBlockData(block.getBlockData());
}
@Override
public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation();
loc.getBlock().setType(type);
// Sets the original blocks old data (only when regenerating)
loc.getBlock().setBlockData(block.getBlockData());
}
@Override
public String generateKey() {
return "vanilla-block-" + type.name();
}
@Override
public String display() {
return "Vanilla{" + type.name() + "}";
}
@Override
public boolean breakRestrictions(Block block) {
return age == 0 || (block.getBlockData() instanceof Ageable && ((Ageable) block.getBlockData()).getAge() >= age);
}
@Override
public boolean breakRestrictions(Block block) {
return age == 0 || (block.getBlockData() instanceof Ageable && ((Ageable) block.getBlockData()).getAge() >= age);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VanillaBlockType that = (VanillaBlockType) o;
return type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(type);
}
}

View File

@ -5,6 +5,7 @@ import java.util.Set;
import java.util.UUID;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.util.item.CurrencyItemBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
@ -28,7 +29,7 @@ public class Withdraw implements Listener {
public Withdraw(Player player) {
this.player = player;
}
public Player getPlayer() {
return player;
}
@ -38,7 +39,7 @@ public class Withdraw implements Listener {
return;
withdrawing.add(player.getUniqueId());
MMOCore.plugin.configManager.getSimpleMessage("withdrawing").send(player);
ConfigMessage.fromKey("withdrawing").send(player);
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, this::close, 20 * 20);
}
@ -60,7 +61,7 @@ public class Withdraw implements Listener {
if (!event.getPlayer().equals(player))
return;
MMOCore.plugin.configManager.getSimpleMessage("withdraw-cancel").send(player);
ConfigMessage.fromKey("withdraw-cancel").send(player);
close();
}
@ -75,13 +76,13 @@ public class Withdraw implements Listener {
try {
worth = Integer.parseInt(event.getMessage());
} catch (Exception e) {
MMOCore.plugin.configManager.getSimpleMessage("wrong-number", "arg", event.getMessage()).send(player);
ConfigMessage.fromKey("wrong-number").addPlaceholders("arg", event.getMessage()).send(player);
return;
}
int left = (int) (MMOCore.plugin.economy.getEconomy().getBalance(player) - worth);
if (left < 0) {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-money", "left", "" + -left).send(player);
ConfigMessage.fromKey("not-enough-money").addPlaceholders("left", -left).send(player);
return;
}
@ -91,7 +92,7 @@ public class Withdraw implements Listener {
MMOCore.plugin.economy.getEconomy().withdrawPlayer(player, worth);
withdrawAlgorythm(worth);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
MMOCore.plugin.configManager.getSimpleMessage("withdrew", "worth", "" + worth).send(player);
ConfigMessage.fromKey("withdrew").addPlaceholders("worth", worth).send(player);
});
}

View File

@ -1,29 +0,0 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
/**
* In order to create bukkit async events we must call
* the right constructor:
* <p>
* {@link Event#Event(boolean)} and have the boolean set to true
*/
public abstract class AsyncPlayerDataEvent extends Event {
private final PlayerData playerData;
public AsyncPlayerDataEvent(PlayerData playerData) {
super(true);
this.playerData = playerData;
}
public PlayerData getData() {
return playerData;
}
public Player getPlayer() {
return playerData.getPlayer();
}
}

View File

@ -1,27 +0,0 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.HandlerList;
public class AsyncPlayerDataLoadEvent extends AsyncPlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
/**
* Called when a player data is being loaded into the game.
* This event is called async.
*
* @param playerData Player data being loaded
*/
public AsyncPlayerDataLoadEvent(PlayerData playerData) {
super(playerData);
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -4,7 +4,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.HandlerList;
/**
* @deprecated Use {@link AsyncPlayerDataLoadEvent} instead
* @deprecated Use {@link io.lumine.mythic.lib.api.event.SynchronizedDataLoadEvent} instead
*/
@Deprecated
public class PlayerDataLoadEvent extends PlayerDataEvent {

View File

@ -0,0 +1,42 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerEnterCastingModeEvent extends PlayerDataEvent implements Cancellable {
private boolean cancelled = false;
private static final HandlerList HANDLERS = new HandlerList();
@Deprecated
public PlayerEnterCastingModeEvent(@NotNull Player who) {
super(PlayerData.get(who));
}
public PlayerEnterCastingModeEvent(@NotNull PlayerData playerData) {
super(playerData);
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@ -0,0 +1,43 @@
package net.Indyuce.mmocore.api.event;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class PlayerExitCastingModeEvent extends PlayerDataEvent implements Cancellable {
private boolean cancelled = false;
private static final HandlerList HANDLERS = new HandlerList();
@Deprecated
public PlayerExitCastingModeEvent(@NotNull Player who) {
super(PlayerData.get(who));
}
public PlayerExitCastingModeEvent(@NotNull PlayerData who) {
super(who);
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@ -56,6 +56,10 @@ public class PlayerResourceUpdateEvent extends PlayerDataEvent implements Cancel
return amount;
}
public UpdateReason getReason() {
return reason;
}
/**
* Changes the amount of resource given/taken away
*

View File

@ -0,0 +1,36 @@
package net.Indyuce.mmocore.api.event.unlocking;
import net.Indyuce.mmocore.api.event.PlayerDataEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
public abstract class ItemChangeEvent extends PlayerDataEvent {
private final String itemKey;
public ItemChangeEvent(PlayerData playerData, String itemKey) {
super(playerData);
this.itemKey = itemKey;
}
/**
* @return The full item key in the format <plugin-id>:<item-type-id>:<item-id>.
*/
public String getItemKey() {
return itemKey;
}
/**
* @return The item-type-id which is the first parameter in the key format <item-type-id>:<item-id>.
*/
public String getItemTypeId() {
return itemKey.split(":")[0];
}
/**
* @return The item--id which is the last parameter in the key format <item-type-id>:<item-id>.
*/
public String getItemId() {
return itemKey.split(":")[1];
}
}

View File

@ -0,0 +1,24 @@
package net.Indyuce.mmocore.api.event.unlocking;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class ItemLockedEvent extends ItemChangeEvent {
private static final HandlerList handlers = new HandlerList();
public ItemLockedEvent(PlayerData playerData, String itemKey) {
super(playerData, itemKey);
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,22 @@
package net.Indyuce.mmocore.api.event.unlocking;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class ItemUnlockedEvent extends ItemChangeEvent {
private static final HandlerList handlers = new HandlerList();
public ItemUnlockedEvent(PlayerData playerData, String itemKey) {
super(playerData, itemKey);
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -19,10 +19,28 @@ public class DefaultMMOLoader extends MMOLoader {
public Trigger loadTrigger(MMOLineConfig config) {
if (config.getKey().equals("from"))
return new FromTrigger(config);
if (config.getKey().equals("stat"))
return new StatTrigger(config);
if(config.getKey().equals("unlock_slot"))
return new UnlockSlotTrigger(config);
if (config.getKey().equals("unlock_skill"))
return new UnlockSkillTrigger(config);
if (config.getKey().equals("bind_skill"))
return new BindSkillTrigger(config);
if (config.getKey().equals("levelup_skill"))
return new LevelUpSkillTrigger(config);
if (config.getKey().equals("skill_buff")||config.getKey().equals("skill_modifier"))
return new SkillModifierTrigger(config);
if (config.getKey().equals("message"))
return new MessageTrigger(config);
if (config.getKey().equals("sound") || config.getKey().equals("playsound"))
return new SoundTrigger(config);
@ -101,6 +119,12 @@ public class DefaultMMOLoader extends MMOLoader {
if (config.getKey().equals("permission"))
return new PermissionCondition(config);
if (config.getKey().equals("weather"))
return new WeatherCondition(config);
if (config.getKey().equals("time"))
return new TimeCondition(config);
return null;
}

View File

@ -1,49 +0,0 @@
package net.Indyuce.mmocore.api.player;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.event.PlayerCombatEvent;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitRunnable;
public class CombatRunnable extends BukkitRunnable {
private final PlayerData player;
private long lastHit = System.currentTimeMillis();
private boolean open = true;
public CombatRunnable(PlayerData player) {
this.player = player;
if (player.isOnline()) {
MMOCore.plugin.configManager.getSimpleMessage("now-in-combat").send(player.getPlayer());
Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, true));
runTaskTimer(MMOCore.plugin, 20, 20);
}
}
public void update() {
lastHit = System.currentTimeMillis();
}
@Override
public void run() {
if (!player.isOnline()) {
close();
return;
}
if (lastHit + MMOCore.plugin.configManager.combatLogTimer < System.currentTimeMillis()) {
Bukkit.getPluginManager().callEvent(new PlayerCombatEvent(player, false));
MMOCore.plugin.configManager.getSimpleMessage("leave-combat").send(player.getPlayer());
close();
}
}
private void close() {
Validate.isTrue(open, "Combat runnable has already been closed");
player.combat = null;
cancel();
open = false;
}
}

View File

@ -1,32 +0,0 @@
package net.Indyuce.mmocore.api.player;
import java.util.UUID;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
public abstract class OfflinePlayerData {
private final UUID uuid;
public OfflinePlayerData(UUID uuid) {
this.uuid = uuid;
}
public UUID getUniqueId() {
return uuid;
}
public abstract void removeFriend(UUID uuid);
public abstract boolean hasFriend(UUID uuid);
public abstract PlayerClass getProfess();
public abstract int getLevel();
public abstract long getLastLogin();
public static OfflinePlayerData get(UUID uuid) {
return MMOCore.plugin.dataProvider.getDataManager().getOffline(uuid);
}
}

View File

@ -6,11 +6,11 @@ import javax.inject.Provider;
import java.util.Objects;
/**
* Used by MMOCore when it has to store the last time
* a player did some action.
* <p>
* This also features a time out function which can
* be used for cooldowns
* Used by MMOCore when it has to store the last time a player
* did some action. This also features a time out function which
* can be used for cooldowns.
*
* @deprecated Merge with {@link io.lumine.mythic.lib.player.cooldown.CooldownMap}
*/
public enum PlayerActivity {
USE_WAYPOINT(() -> 5 * 1000L),
@ -21,7 +21,9 @@ public enum PlayerActivity {
LOOT_CHEST_SPAWN(() -> MMOCore.plugin.configManager.lootChestPlayerCooldown),
CAST_SKILL(() -> MMOCore.plugin.configManager.globalSkillCooldown);
CAST_SKILL(() -> MMOCore.plugin.configManager.globalSkillCooldown),
;
private final Provider<Long> timeout;

View File

@ -1,36 +1,30 @@
package net.Indyuce.mmocore.api.player.attribute;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
import io.lumine.mythic.lib.api.stat.api.InstanceModifier;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.player.modifier.PlayerModifier;
import io.lumine.mythic.lib.util.configobject.ConfigObject;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.apache.commons.lang.Validate;
import java.text.DecimalFormat;
import java.util.Objects;
import java.util.UUID;
public class AttributeModifier extends PlayerModifier {
public class AttributeModifier extends InstanceModifier {
private final String attribute;
private final double value;
private final ModifierType type;
private static final DecimalFormat oneDigit = MythicLib.plugin.getMMOConfig().newDecimalFormat("0.#");
/**
* Flat attribute modifier (simplest modifier you can think about)
*/
public AttributeModifier(String key, String attribute, double value) {
this(key, attribute, value, ModifierType.FLAT, EquipmentSlot.OTHER, ModifierSource.OTHER);
super(key, value);
this.attribute = attribute;
}
/**
* Attribute modifier given by an external mecanic, like a party buff, item set bonuses,
* skills or abilities... Anything apart from items and armor.
* Attribute modifier given by an external mechanic, like a party buff, item
* set bonuses, skills or abilities... Anything apart from items and armor.
*/
public AttributeModifier(String key, String attribute, double value, ModifierType type) {
this(key, attribute, value, type, EquipmentSlot.OTHER, ModifierSource.OTHER);
@ -47,11 +41,23 @@ public class AttributeModifier extends PlayerModifier {
* @param source Type of the item granting the stat modifier
*/
public AttributeModifier(String key, String attribute, double value, ModifierType type, EquipmentSlot slot, ModifierSource source) {
super(key, slot, source);
this(UUID.randomUUID(), key, attribute, value, type, slot, source);
}
/**
* Attribute modifier given by an item, either a weapon or an armor piece.
*
* @param key Player modifier key
* @param attribute Attribute being modified
* @param value Value of stat modifier
* @param type Is the modifier flat or multiplicative
* @param slot Slot of the item granting the stat modifier
* @param source Type of the item granting the stat modifier
*/
public AttributeModifier(UUID uniqueId, String key, String attribute, double value, ModifierType type, EquipmentSlot slot, ModifierSource source) {
super(uniqueId, key, slot, source, value, type);
this.attribute = attribute;
this.value = value;
this.type = type;
}
/**
@ -62,22 +68,14 @@ public class AttributeModifier extends PlayerModifier {
* @param str The string to be parsed
*/
public AttributeModifier(String key, String attribute, String str) {
super(key, EquipmentSlot.OTHER, ModifierSource.OTHER);
super(key, EquipmentSlot.OTHER, ModifierSource.OTHER, str);
Validate.notNull(str, "String cannot be null");
Validate.notEmpty(str, "String cannot be empty");
type = str.toCharArray()[str.length() - 1] == '%' ? ModifierType.RELATIVE : ModifierType.FLAT;
value = Double.parseDouble(type == ModifierType.RELATIVE ? str.substring(0, str.length() - 1) : str);
this.attribute = attribute;
}
public AttributeModifier(ConfigObject object) {
super(object.getString("key"), EquipmentSlot.OTHER, ModifierSource.OTHER);
super(object);
String str = Objects.requireNonNull(object.getString("value"));
type = str.toCharArray()[str.length() - 1] == '%' ? ModifierType.RELATIVE : ModifierType.FLAT;
value = Double.parseDouble(type == ModifierType.RELATIVE ? str.substring(0, str.length() - 1) : str);
this.attribute = object.getString("attribute");
}
@ -85,14 +83,6 @@ public class AttributeModifier extends PlayerModifier {
return attribute;
}
public ModifierType getType() {
return type;
}
public double getValue() {
return value;
}
/**
* Used to multiply some existing stat modifier by a constant, usually an
* integer, for instance when MMOCore party modifiers scale with the
@ -101,24 +91,19 @@ public class AttributeModifier extends PlayerModifier {
* @param coef The multiplicative constant
* @return A new instance of StatModifier with modified value
*/
public StatModifier multiply(double coef) {
return new StatModifier(getKey(), attribute, value * coef, type, getSlot(), getSource());
public AttributeModifier multiply(double coef) {
return new AttributeModifier(getUniqueId(), getKey(), attribute, value * coef, type, getSlot(), getSource());
}
@Override
public void register(MMOPlayerData mmoPlayerData) {
PlayerData playerData = PlayerData.get(mmoPlayerData.getUniqueId());
PlayerData playerData = PlayerData.get(mmoPlayerData);
playerData.getAttributes().getInstance(attribute).addModifier(this);
}
@Override
public void unregister(MMOPlayerData mmoPlayerData) {
PlayerData playerData = PlayerData.get(mmoPlayerData.getUniqueId());
PlayerData playerData = PlayerData.get(mmoPlayerData);
playerData.getAttributes().getInstance(attribute).removeModifier(getKey());
}
@Override
public String toString() {
return oneDigit.format(value) + (type == io.lumine.mythic.lib.player.modifier.ModifierType.RELATIVE ? "%" : "");
}
}

View File

@ -1,9 +1,10 @@
package net.Indyuce.mmocore.api.player.attribute;
import io.lumine.mythic.lib.api.stat.StatMap;
import io.lumine.mythic.lib.api.stat.StatInstance;
import io.lumine.mythic.lib.api.stat.handler.StatHandler;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.configuration.ConfigurationSection;
/**
* This fixes an issue where registering new stat modifiers in ML
@ -13,17 +14,13 @@ import net.Indyuce.mmocore.api.player.PlayerData;
* This stat handler MAY call subsequent stat handlers. There might
* be infinite recursion problems if another attr. grants extra attribute pts.
*/
public class MMOCoreAttributeStatHandler implements StatHandler {
public class MMOCoreAttributeStatHandler extends StatHandler {
private final PlayerAttribute attr;
private final String statName;
public MMOCoreAttributeStatHandler(PlayerAttribute attr) {
public MMOCoreAttributeStatHandler(ConfigurationSection config, PlayerAttribute attr) {
super(config, "ADDITIONAL_" + attr.getId().toUpperCase().replace("-", "_"));
this.attr = attr;
this.statName = "ADDITIONAL_" + attr.getId().toUpperCase().replace("-", "_");
}
public String getStat() {
return statName;
}
/**
@ -31,22 +28,12 @@ public class MMOCoreAttributeStatHandler implements StatHandler {
* is not loaded yet, hence the try/catch clause
*/
@Override
public void runUpdate(StatMap statMap) {
public void runUpdate(StatInstance instance) {
try {
final PlayerData playerData = MMOCore.plugin.dataProvider.getDataManager().get(statMap.getPlayerData().getUniqueId());
final PlayerData playerData = PlayerData.get(instance.getMap().getPlayerData());
playerData.getAttributes().getInstance(attr).updateStats();
} catch (NullPointerException exception) {
// Player data is not loaded yet so there's nothing to update.
}
}
@Override
public double getBaseValue(StatMap statMap) {
return 0;
}
@Override
public double getTotalValue(StatMap statMap) {
return statMap.getStat(statName);
}
}

View File

@ -85,7 +85,7 @@ public class PlayerAttribute implements ExperienceObject {
@NotNull
@Override
public ExperienceTable getExperienceTable() {
return Objects.requireNonNull(expTable);
return Objects.requireNonNull(expTable, "Attribute has no exp table");
}
@Override

View File

@ -1,13 +1,14 @@
package net.Indyuce.mmocore.api.player.attribute;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.player.modifier.Closeable;
import io.lumine.mythic.lib.api.stat.StatInstance;
import io.lumine.mythic.lib.gson.JsonElement;
import io.lumine.mythic.lib.gson.JsonObject;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.util.Closeable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.apache.commons.lang.Validate;
@ -32,11 +33,9 @@ public class PlayerAttributes {
public void load(ConfigurationSection config) {
for (String key : config.getKeys(false))
try {
String id = key.toLowerCase().replace("_", "-").replace(" ", "-");
Validate.isTrue(MMOCore.plugin.attributeManager.has(id), "Could not find attribute '" + id + "'");
PlayerAttribute attribute = MMOCore.plugin.attributeManager.get(id);
AttributeInstance ins = new AttributeInstance(attribute.getId());
final String id = key.toLowerCase().replace("_", "-").replace(" ", "-");
Validate.isTrue(MMOCore.plugin.attributeManager.has(id), "Could not find attribute called '" + id + "'");
final AttributeInstance ins = new AttributeInstance(id);
ins.setBase(config.getInt(key));
instances.put(id, ins);
} catch (IllegalArgumentException exception) {
@ -56,15 +55,12 @@ public class PlayerAttributes {
}
public void load(String json) {
Gson parser = new Gson();
JsonObject jo = parser.fromJson(json, JsonObject.class);
JsonObject jo = MythicLib.plugin.getGson().fromJson(json, JsonObject.class);
for (Entry<String, JsonElement> entry : jo.entrySet()) {
try {
String id = entry.getKey().toLowerCase().replace("_", "-").replace(" ", "-");
Validate.isTrue(MMOCore.plugin.attributeManager.has(id), "Could not find attribute '" + id + "'");
PlayerAttribute attribute = MMOCore.plugin.attributeManager.get(id);
AttributeInstance ins = new AttributeInstance(attribute.getId());
final String id = entry.getKey().toLowerCase().replace("_", "-").replace(" ", "-");
Validate.isTrue(MMOCore.plugin.attributeManager.has(id), "Could not find attribute called '" + id + "'");
final AttributeInstance ins = new AttributeInstance(id);
ins.setBase(entry.getValue().getAsInt());
instances.put(id, ins);
} catch (IllegalArgumentException exception) {
@ -113,13 +109,14 @@ public class PlayerAttributes {
return n;
}
// TODO have it extend ModifiedInstance
public class AttributeInstance {
private int spent;
private final String id, enumName;
private final Map<String, AttributeModifier> map = new HashMap<>();
public AttributeInstance(String id) {
public AttributeInstance(@NotNull String id) {
this.id = id;
this.enumName = UtilityMethods.enumName(this.id);
}
@ -128,6 +125,11 @@ public class PlayerAttributes {
return spent;
}
@Deprecated
public int getSpent() {
return getBase();
}
public void setBase(int value) {
spent = Math.max(0, value);
@ -136,7 +138,7 @@ public class PlayerAttributes {
}
public void addBase(int value) {
setBase(spent + value);
setBase(getBase() + value);
}
/*
@ -176,8 +178,7 @@ public class PlayerAttributes {
public AttributeModifier addModifier(AttributeModifier modifier) {
final AttributeModifier current = map.put(modifier.getKey(), modifier);
if (current != null && current instanceof Closeable)
((Closeable) current).close();
if (current instanceof Closeable) ((Closeable) current).close();
updateStats();
return current;
@ -210,6 +211,12 @@ public class PlayerAttributes {
public void updateStats() {
final PlayerAttribute attr = MMOCore.plugin.attributeManager.get(id);
final int total = getTotal();
// Remove ALL stat modifiers
for (StatInstance ins : data.getMMOPlayerData().getStatMap().getInstances())
ins.removeIf(str -> str.equals("attribute." + id));
// Register new stat modifiers
attr.getBuffs().forEach(buff -> buff.multiply(total).register(data.getMMOPlayerData()));
}
@ -218,10 +225,9 @@ public class PlayerAttributes {
}
}
@Deprecated
public void setBaseAttribute(String id, int value) {
getInstances().forEach(ins -> {
if (ins.getId().equals(id))
ins.setBase(value);
});
AttributeInstance ins = instances.get(id);
if (ins != null) ins.setBase(value);
}
}

View File

@ -1,12 +1,9 @@
package net.Indyuce.mmocore.api.player.profess;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.api.util.PostLoadObject;
import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
import io.lumine.mythic.lib.script.Script;
@ -14,7 +11,10 @@ import io.lumine.mythic.lib.skill.SimpleSkill;
import io.lumine.mythic.lib.skill.Skill;
import io.lumine.mythic.lib.skill.handler.MythicLibSkillHandler;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import io.lumine.mythic.lib.version.VersionMaterial;
import io.lumine.mythic.lib.util.FileUtils;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
import io.lumine.mythic.lib.version.VParticle;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.event.EventTrigger;
@ -25,30 +25,29 @@ import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.ExpCurve;
import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.experience.droptable.ExperienceTable;
import net.Indyuce.mmocore.loot.chest.particle.CastingParticle;
import net.Indyuce.mmocore.player.stats.StatInfo;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skill.binding.SkillSlot;
import net.Indyuce.mmocore.skill.cast.ComboMap;
import net.Indyuce.mmocore.experience.ExperienceObject;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.logging.Level;
public class PlayerClass extends PostLoadObject implements ExperienceObject {
public class PlayerClass implements ExperienceObject, PreloadedObject {
private final String name, id, actionBarFormat;
private final List<String> description = new ArrayList<>(), attrDescription = new ArrayList<>();
private final ItemStack icon;
@ -67,8 +66,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
@Nullable
private final CastingParticle castParticle;
private final int maxBoundActiveSkills, maxBoundPassiveSkills;
private final List<SkillSlot> skillSlots = new ArrayList<>();
private final List<SkillTree> skillTrees = new ArrayList<>();
private final List<PassiveSkill> classScripts = new LinkedList();
private final Map<String, LinearValue> stats = new HashMap<>();
@ -82,27 +80,33 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
@Deprecated
private final Map<String, EventTrigger> eventTriggers = new HashMap<>();
public PlayerClass(String id, FileConfiguration config) {
super(config);
private final PostLoadAction postLoadAction = new PostLoadAction(config -> {
if (config.contains("subclasses"))
for (String key : config.getConfigurationSection("subclasses").getKeys(false))
try {
subclasses.add(new Subclass(
MMOCore.plugin.classManager
.getOrThrow(key.toUpperCase().replace("-", "_").replace(" ", "_")),
config.getInt("subclasses." + key)));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load subclass '" + key + "' from class '"
+ getId() + "': " + exception.getMessage());
}
});
public PlayerClass(String id, ConfigurationSection config) {
postLoadAction.cacheConfig(config);
this.id = id.toUpperCase().replace("-", "_").replace(" ", "_");
name = MythicLib.plugin.parseColors(config.getString("display.name", "INVALID DISPLAY NAME"));
icon = MMOCoreUtils.readIcon(config.getString("display.item", "BARRIER"));
if (config.contains("display.texture") && icon.getType() == VersionMaterial.PLAYER_HEAD.toMaterial())
try {
ItemMeta meta = icon.getItemMeta();
Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
GameProfile gp = new GameProfile(UUID.randomUUID(), null);
gp.getProperties().put("textures", new Property("textures", config.getString("display.texture")));
profileField.set(meta, gp);
icon.setItemMeta(meta);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
| SecurityException exception) {
throw new IllegalArgumentException("Could not apply playerhead texture: " + exception.getMessage());
}
if (config.contains("display.texture") && icon.getType() == Material.PLAYER_HEAD) {
ItemMeta meta = icon.getItemMeta();
UtilityMethods.setTextureValue((SkullMeta) meta, config.getString("display.texture"));
icon.setItemMeta(meta);
}
for (String string : config.getStringList("display.lore"))
description.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string));
@ -114,12 +118,13 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
displayOrder = config.getInt("display.order");
actionBarFormat = config.contains("action-bar", true) ? config.getString("action-bar") : null;
// Exp curve
expCurve = config.contains("exp-curve")
? MMOCore.plugin.experience.getCurveOrThrow(
config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
: ExpCurve.DEFAULT;
maxBoundActiveSkills = config.getInt("max-bound-active-skills", MMOCore.plugin.configManager.maxBoundActiveSkills);
maxBoundPassiveSkills = config.getInt("max-bound-passive-skills", MMOCore.plugin.configManager.maxBoundPassiveSkills);
// Main exp table
ExperienceTable expTable = null;
if (config.contains("exp-table"))
try {
@ -128,6 +133,8 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp table from class '" + id + "': " + exception.getMessage());
}
this.expTable = expTable;
// Skill trees
if (config.contains("skill-trees"))
for (String str : config.getStringList("skill-trees"))
try {
@ -136,6 +143,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
MMOCore.log(Level.WARNING, "Could not find skill tree with ID: " + str);
}
// Class-specific scripts
if (config.contains("scripts"))
for (String key : config.getConfigurationSection("scripts").getKeys(false))
try {
@ -158,6 +166,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
}
this.comboMap = comboMap;
// Triggers (DEPRECATED)
if (config.contains("triggers"))
for (String key : config.getConfigurationSection("triggers").getKeys(false))
try {
@ -167,6 +176,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
MMOCore.log(Level.WARNING, "Could not load trigger '" + key + "' from class '" + id + "':" + exception.getMessage());
}
// Class STATS, not attributes (historic reasons)
if (config.contains("attributes"))
for (String key : config.getConfigurationSection("attributes").getKeys(false))
try {
@ -177,18 +187,28 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
+ id + "': " + exception.getMessage());
}
if (config.contains("skills"))
for (String key : config.getConfigurationSection("skills").getKeys(false))
try {
RegisteredSkill registered = MMOCore.plugin.skillManager.getSkillOrThrow(UtilityMethods.enumName(key));
skills.put(registered.getHandler().getId(), new ClassSkill(registered, config.getConfigurationSection("skills." + key)));
} catch (RuntimeException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill info '" + key + "' from class '"
+ id + "': " + exception.getMessage());
}
// Skill slots
if (config.isConfigurationSection("skill-slots"))
FileUtils.iterateConfigSectionList(
config.getConfigurationSection("skill-slots"),
skillSlots,
SkillSlot::new,
index -> new SkillSlot(index, 0, "true", "&eUnconfigured Skill Slot " + MMOCoreUtils.intToRoman(index), new ArrayList<>(), false, true, new ArrayList<>()),
(key, exception) -> MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill slot '" + key + "' from class '" + getId() + "': " + exception.getMessage()));
// Class skills
for (RegisteredSkill registered : MMOCore.plugin.skillManager.getAll()) {
final String key = registered.getHandler().getId();
if (config.contains("skills." + key))
skills.put(key, new ClassSkill(registered, config.getConfigurationSection("skills." + key)));
else
skills.put(key, new ClassSkill(registered, 1, 1, false));
}
// Casting particle
castParticle = config.contains("cast-particle") ? new CastingParticle(config.getConfigurationSection("cast-particle")) : null;
// Other class options
if (config.contains("options"))
for (String key : config.getConfigurationSection("options").getKeys(false))
try {
@ -199,11 +219,12 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
"Could not load option '" + key + "' from class '" + key + "': " + exception.getMessage());
}
// Experience sources
if (config.contains("main-exp-sources")) {
for (String key : config.getStringList("main-exp-sources"))
try {
MMOCore.plugin.experience.registerSource(MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), this));
} catch (IllegalArgumentException exception) {
} catch (RuntimeException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp source '" + key + "' from class '"
+ id + "': " + exception.getMessage());
}
@ -237,8 +258,6 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
* option was not provided.
*/
public PlayerClass(String id, String name, Material material) {
super(null);
this.id = id;
this.name = name;
manaDisplay = ManaDisplayOptions.DEFAULT;
@ -247,32 +266,15 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
expCurve = ExpCurve.DEFAULT;
expTable = null;
comboMap = null;
castParticle = new CastingParticle(Particle.SPELL_INSTANT);
castParticle = new CastingParticle(VParticle.INSTANT_EFFECT.get());
actionBarFormat = "";
this.icon = new ItemStack(material);
setOption(ClassOption.DISPLAY, false);
setOption(ClassOption.DEFAULT, false);
maxBoundActiveSkills = 6;
maxBoundPassiveSkills = 3;
for (PlayerResource resource : PlayerResource.values())
resourceHandlers.put(resource, new ResourceRegeneration(resource));
}
@Override
protected void whenPostLoaded(ConfigurationSection config) {
if (config.contains("subclasses"))
for (String key : config.getConfigurationSection("subclasses").getKeys(false))
try {
subclasses.add(new Subclass(
MMOCore.plugin.classManager
.getOrThrow(key.toUpperCase().replace("-", "_").replace(" ", "_")),
config.getInt("subclasses." + key)));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load subclass '" + key + "' from class '"
+ getId() + "': " + exception.getMessage());
}
}
public String getId() {
return id;
}
@ -283,7 +285,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
@Override
public String getKey() {
return "class." + getId();
return "class_" + getId();
}
@NotNull
@ -304,18 +306,17 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
return displayOrder;
}
@NotNull
@Override
public PostLoadAction getPostLoadAction() {
return postLoadAction;
}
@Override
public ExpCurve getExpCurve() {
return expCurve;
}
public int getMaxBoundActiveSkills() {
return maxBoundActiveSkills;
}
public int getMaxBoundPassiveSkills() {
return maxBoundPassiveSkills;
}
@NotNull
public ExperienceTable getExperienceTable() {
@ -354,8 +355,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
@Override
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, EXPSource source) {
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
: hologramLocation;
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null : hologramLocation;
playerData.giveExperience(experience, source, hologramLocation, true);
}
@ -416,18 +416,35 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
return false;
}
@Deprecated
public boolean hasSkill(RegisteredSkill skill) {
return hasSkill(skill.getHandler().getId());
}
@Deprecated
public boolean hasSkill(String id) {
return skills.containsKey(id);
}
public boolean hasSlot(int slot) {
return 1 <= slot && slot <= skillSlots.size();
}
public List<SkillTree> getSkillTrees() {
return skillTrees;
}
@Nullable
public SkillSlot getSkillSlot(int slot) {
return hasSlot(slot) ? skillSlots.get(slot - 1) : null;
}
@NotNull
public List<SkillSlot> getSlots() {
return skillSlots;
}
@NotNull
public ClassSkill getSkill(RegisteredSkill skill) {
return getSkill(skill.getHandler().getId());
}
@ -437,6 +454,7 @@ public class PlayerClass extends PostLoadObject implements ExperienceObject {
return skills.get(id);
}
@Deprecated
public Collection<ClassSkill> getSkills() {
return skills.values();
}

View File

@ -1,29 +1,35 @@
package net.Indyuce.mmocore.api.player.profess;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.gson.JsonElement;
import io.lumine.mythic.lib.gson.JsonObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.player.ClassDataContainer;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.skilltree.SkillTreeNode;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import org.bukkit.attribute.Attribute;
import org.bukkit.configuration.ConfigurationSection;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class SavedClassInformation {
public class SavedClassInformation implements ClassDataContainer {
private final int level, skillPoints, attributePoints, attributeReallocationPoints, skillTreeReallocationPoints, skillReallocationPoints;
private final double experience;
private final double experience, health, mana, stellium, stamina;
private final Map<String, Integer> attributeLevels = new HashMap<>();
private final Map<String, Integer> skillLevels = new HashMap<>();
private final Map<String, Integer> skillTreePoints = new HashMap<>();
private final Map<String, Integer> nodeLevels = new HashMap<>();
private final Map<String, Integer> nodeTimesClaimed = new HashMap<>();
private final List<String> boundSkills = new ArrayList<>();
private final Map<Integer, String> boundSkills = new HashMap<>();
private final Set<String> unlockedItems = new HashSet<>();
/**
* Used by YAML storage
@ -36,18 +42,34 @@ public class SavedClassInformation {
attributeReallocationPoints = config.getInt("attribute-realloc-points");
skillReallocationPoints = config.getInt("skill-reallocation-points");
skillTreeReallocationPoints = config.getInt("skill-tree-reallocation-points");
health = config.getDouble("health", 20);
mana = config.getDouble("mana", 0);
stamina = config.getDouble("stamina", 0);
stellium = config.getDouble("stellium", 0);
if (config.contains("attribute"))
config.getConfigurationSection("attribute").getKeys(false).forEach(key -> attributeLevels.put(key, config.getInt("attribute." + key)));
config.getConfigurationSection("attribute").getKeys(false)
.forEach(key -> attributeLevels.put(key, config.getInt("attribute." + key)));
if (config.contains("skill"))
config.getConfigurationSection("skill").getKeys(false).forEach(key -> skillLevels.put(key, config.getInt("skill." + key)));
config.getConfigurationSection("skill").getKeys(false)
.forEach(key -> skillLevels.put(key, config.getInt("skill." + key)));
if (config.contains("skill-tree-points"))
config.getConfigurationSection("skill-tree-points").getKeys(false).forEach(key -> skillTreePoints.put(key, config.getInt("skill-tree-points." + key)));
config.getConfigurationSection("skill-tree-points").getKeys(false)
.forEach(key -> skillTreePoints.put(key, config.getInt("skill-tree-points." + key)));
if (config.contains("node-levels"))
config.getConfigurationSection("node-levels").getKeys(false).forEach(key -> nodeLevels.put(key, config.getInt("node-levels." + key)));
config.getConfigurationSection("node-levels").getKeys(false)
.forEach(key -> nodeLevels.put(key, config.getInt("node-levels." + key)));
if (config.contains("node-times-claimed"))
config.getConfigurationSection("node-times-claimed").getKeys(false).forEach(key -> nodeTimesClaimed.put(key, config.getInt("node-times-claimed." + key)));
if (config.contains("bound-skills"))
config.getStringList("bound-skills").forEach(id -> boundSkills.add(id));
config.getConfigurationSection("node-times-claimed").getKeys(false)
.forEach(key -> nodeTimesClaimed.put(key, config.getInt("node-times-claimed." + key)));
/**
* 'bound-skills' used to be a list. This condition makes
* sure that the config is using the newest format.
*/
if (config.isConfigurationSection("bound-skills"))
config.getConfigurationSection("bound-skills").getKeys(false)
.forEach(key -> boundSkills.put(Integer.parseInt(key), config.getString("bound-skills." + key)));
unlockedItems.addAll(config.getStringList("unlocked-items"));
}
/**
@ -61,6 +83,11 @@ public class SavedClassInformation {
attributeReallocationPoints = json.get("attribute-realloc-points").getAsInt();
skillReallocationPoints = json.get("skill-reallocation-points").getAsInt();
skillTreeReallocationPoints = json.get("skill-tree-reallocation-points").getAsInt();
health = json.has("health") ? json.get("health").getAsDouble() : 20;
mana = json.has("mana") ? json.get("mana").getAsDouble() : 0;
stamina = json.has("stamina") ? json.get("stamina").getAsDouble() : 0;
stellium = json.has("stellium") ? json.get("stellium").getAsDouble() : 0;
if (json.has("attribute"))
for (Entry<String, JsonElement> entry : json.getAsJsonObject("attribute").entrySet())
attributeLevels.put(entry.getKey(), entry.getValue().getAsInt());
@ -76,8 +103,13 @@ public class SavedClassInformation {
if (json.has("node-times-claimed"))
for (Entry<String, JsonElement> entry : json.getAsJsonObject("node-times-claimed").entrySet())
nodeTimesClaimed.put(entry.getKey(), entry.getValue().getAsInt());
if (json.has("bound-skills"))
json.getAsJsonArray("bound-skills").forEach(id -> boundSkills.add(id.getAsString()));
//Old system was using a JsonArray. If it saved with the old system the if condition won't be respected.
if (json.has("bound-skills") && json.get("bound-skills").isJsonObject())
for (Entry<String, JsonElement> entry : json.getAsJsonObject("bound-skills").entrySet())
boundSkills.put(Integer.parseInt(entry.getKey()), entry.getValue().getAsString());
if (json.has("unlocked-items"))
for (JsonElement unlockedItem : json.get("unlocked-items").getAsJsonArray())
unlockedItems.add(unlockedItem.getAsString());
}
public SavedClassInformation(ClassDataContainer data) {
@ -88,37 +120,65 @@ public class SavedClassInformation {
this.skillTreeReallocationPoints = data.getSkillTreeReallocationPoints();
this.skillReallocationPoints = data.getSkillReallocationPoints();
this.experience = data.getExperience();
this.health = data.getHealth();
this.mana = data.getMana();
this.stellium = data.getStellium();
this.stamina = data.getStamina();
data.mapAttributeLevels().forEach((key, val) -> this.attributeLevels.put(key, val));
data.mapSkillLevels().forEach((key, val) -> skillLevels.put(key, val));
data.mapSkillTreePoints().forEach((key, val) -> skillTreePoints.put(key, val));
data.getNodeLevels().forEach((node, level) -> nodeLevels.put(node.getFullId(), level));
data.getNodeTimesClaimed().forEach((key, val) -> nodeTimesClaimed.put(key, val));
data.getBoundPassiveSkills().forEach(skill -> boundSkills.add(skill.getTriggeredSkill().getHandler().getId()));
data.getBoundSkills().forEach(skill -> boundSkills.add(skill.getSkill().getHandler().getId()));
attributeLevels.putAll(data.mapAttributeLevels());
skillLevels.putAll(data.mapSkillLevels());
skillTreePoints.putAll(data.mapSkillTreePoints());
nodeLevels.putAll(data.getNodeLevels());
nodeTimesClaimed.putAll(data.getNodeTimesClaimed());
boundSkills.putAll(data.mapBoundSkills());
unlockedItems.addAll(data.getUnlockedItems());
}
@Override
public int getLevel() {
return level;
}
@Override
public double getExperience() {
return experience;
}
@Override
public int getSkillPoints() {
return skillPoints;
}
@Override
public int getAttributePoints() {
return attributePoints;
}
@Override
public int getAttributeReallocationPoints() {
return attributeReallocationPoints;
}
@Override
public double getHealth() {
return health;
}
@Override
public double getMana() {
return mana;
}
@Override
public double getStellium() {
return stellium;
}
@Override
public double getStamina() {
return stamina;
}
public Set<String> getSkillKeys() {
return skillLevels.keySet();
}
@ -135,10 +195,27 @@ public class SavedClassInformation {
registerSkillLevel(skill.getHandler().getId(), level);
}
@Override
public Map<String, Integer> mapSkillLevels() {
return skillLevels;
}
@Override
public Map<String, Integer> mapSkillTreePoints() {
return skillTreePoints;
}
@Deprecated
public Map<Integer, String> getBoundSkills() {
return mapBoundSkills();
}
@Override
public int getSkillTreeReallocationPoints() {
return skillTreeReallocationPoints;
}
@Override
public int getSkillReallocationPoints() {
return skillReallocationPoints;
}
@ -155,6 +232,26 @@ public class SavedClassInformation {
return nodeLevels.get(node);
}
@Override
public Map<String, Integer> mapAttributeLevels() {
return attributeLevels;
}
@Override
public Map<Integer, String> mapBoundSkills() {
return boundSkills;
}
@Override
public Map<String, Integer> getNodeLevels() {
return nodeLevels;
}
@Override
public Map<String, Integer> getNodeTimesClaimed() {
return nodeTimesClaimed;
}
public Set<String> getSkillTreePointsKeys() {
return skillTreePoints.keySet();
}
@ -179,6 +276,11 @@ public class SavedClassInformation {
attributeLevels.put(attribute, level);
}
@Override
public Set<String> getUnlockedItems() {
return unlockedItems;
}
/**
* @param profess Target player class
* @param player Player changing class
@ -192,32 +294,22 @@ public class SavedClassInformation {
if (!player.getProfess().hasOption(ClassOption.DEFAULT) || MMOCore.plugin.configManager.saveDefaultClassInfo)
player.applyClassInfo(player.getProfess(), new SavedClassInformation(player));
// Remove class permanent buffs
player.getProfess().resetAdvancement(player, false);
/*
* Resets information which much be reset after everything is saved.
*/
player.mapSkillLevels().forEach((skill, level) -> player.resetSkillLevel(skill));
player.getAttributes().getInstances().forEach(ins -> ins.setBase(0));
player.clearSkillTreePoints();
player.clearNodeLevels();
player.clearNodeStates();
// We remove perm stats for nodes and class.
for (SkillTree skillTree : player.getProfess().getSkillTrees())
for (SkillTreeNode node : skillTree.getNodes())
node.getExperienceTable().removePermStats(player, node);
if (player.getProfess().hasExperienceTable())
player.getProfess().getExperienceTable().removePermStats(player, player.getProfess());
while (player.hasPassiveSkillBound(0))
player.unbindPassiveSkill(0);
while (player.hasSkillBound(0))
player.unbindSkill(0);
for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll()) {
attribute.resetAdvancement(player, false);
player.getAttributes().getInstance(attribute).setBase(0);
}
player.resetSkillTrees();
/*
* Reads this class info, applies it to the player. set class after
* changing level so the player stats can be calculated based on new
* level.
* changing level so the player stats can be calculated based on new level
*/
player.setLevel(level);
player.setExperience(experience);
@ -226,16 +318,13 @@ public class SavedClassInformation {
player.setAttributeReallocationPoints(attributeReallocationPoints);
player.setSkillTreeReallocationPoints(skillTreeReallocationPoints);
player.setSkillReallocationPoints(skillReallocationPoints);
for (String id : boundSkills) {
ClassSkill skill = profess.getSkill(id);
if (skill.getSkill().getTrigger().isPassive())
player.bindPassiveSkill(-1, skill.toPassive(player));
else
player.getBoundSkills().add(skill);
}
player.setUnlockedItems(unlockedItems);
player.setClass(profess);
for (int slot : boundSkills.keySet())
player.bindSkill(slot, profess.getSkill(boundSkills.get(slot)));
skillLevels.forEach(player::setSkillLevel);
attributeLevels.forEach((id, pts) -> player.getAttributes().setBaseAttribute(id, pts));
attributeLevels.forEach((id, pts) -> player.getAttributes().getInstance(id).setBase(pts));
// Careful, the global points must not be forgotten.
player.setSkillTreePoints("global", skillTreePoints.getOrDefault("global", 0));
@ -250,21 +339,17 @@ public class SavedClassInformation {
// Add the values to the times claimed table and claims the corresponding stat triggers.
nodeTimesClaimed.forEach((str, val) -> player.setClaims(str, val));
// We claim back the stats triggers for all the skill tree nodes of the new class.
for (SkillTree skillTree : profess.getSkillTrees())
for (SkillTreeNode node : skillTree.getNodes())
node.getExperienceTable().claimStatTriggers(player, node);
profess.getExperienceTable().claimStatTriggers(player, profess);
/*
* Unload current class information and set
* the new profess once everything is changed
*/
player.setClass(profess);
// Unload current class information
player.unloadClassInfo(profess);
// Updates level on exp bar
player.refreshVanillaExp();
// This needs to be done at the end to make sure the MAX_HEALTH/MAX_MANA/... stats are loaded.
player.getPlayer().setHealth(MMOCoreUtils.fixResource(health, player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()));
player.setHealth(health);
player.setMana(mana);
player.setStellium(stellium);
player.setStamina(stamina);
player.applyTemporaryTriggers();
player.getStats().updateStats();
}
}

View File

@ -21,7 +21,7 @@ public class AttackEventTrigger implements EventTriggerHandler {
// We don't want players dying by themselves when using an enderpearl.
if (event.getPlayer().equals(event.getEntity())) return;
PlayerData player = PlayerData.get(event.getData().getUniqueId());
PlayerData player = PlayerData.get(event.getData());
PlayerClass profess = player.getProfess();
for (DamageType type : event.getAttack().getDamage().collectTypes()) {

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.api.player.profess.event.trigger;
import io.lumine.mythic.lib.UtilityMethods;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
@ -17,6 +18,8 @@ public class BlockBrokenTrigger implements EventTriggerHandler {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if (UtilityMethods.isFake(event)) return;
PlayerData player = PlayerData.get(event.getPlayer());
if (player.getProfess().hasEventTriggers("break-block"))
player.getProfess().getEventTriggers("break-block").getTriggers().forEach(trigger -> trigger.apply(player));

View File

@ -1,6 +1,6 @@
package net.Indyuce.mmocore.api.player.social;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.player.PlayerActivity;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Sound;
@ -21,8 +21,8 @@ public class FriendRequest extends Request {
getCreator().addFriend(getTarget().getUniqueId());
getTarget().addFriend(getCreator().getUniqueId());
if (getCreator().isOnline()) {
MMOCore.plugin.configManager.getSimpleMessage("now-friends", "player", getTarget().getPlayer().getName()).send(getCreator().getPlayer());
MMOCore.plugin.configManager.getSimpleMessage("now-friends", "player", getCreator().getPlayer().getName()).send(getTarget().getPlayer());
ConfigMessage.fromKey("now-friends", "player", getTarget().getPlayer().getName()).send(getCreator().getPlayer());
ConfigMessage.fromKey("now-friends", "player", getCreator().getPlayer().getName()).send(getTarget().getPlayer());
}
}
}

View File

@ -8,6 +8,7 @@ import io.lumine.mythic.lib.player.modifier.ModifierSource;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.player.skill.PassiveSkill;
import io.lumine.mythic.lib.player.skill.PassiveSkillMap;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.Profession;
@ -45,7 +46,7 @@ public class PlayerStats {
}
public double getStat(String stat) {
return getMap().getInstance(stat).getTotal();
return getMap().getStat(stat);
}
/**
@ -66,14 +67,24 @@ public class PlayerStats {
return data.getProfess().calculateStat(stat, profession == null ? data.getLevel() : data.getCollectionSkills().getLevel(profession));
}
public void updateStats() {
updateStats(false);
}
/**
* Used to update MMOCore stat modifiers due to class and send them over to
* MythicLib. Must be ran everytime the player levels up or changes class.
* MythicLib. Must be ran everytime the player levels up, changes class or
* when the plugin reloads.
* <p>
* This is also called when reloading the plugin to make class setup easier,
* see {@link PlayerData#update()} for more info
* Login scripts are a pretty special case of scripts/skills since they are
* not loaded yet when MythicLib triggers them naturally. Therefore, they
* need to be cast as soon as they are loaded into the MMOCore player data.
*
* @param castLoginScripts Should login scripts be cast
*/
public synchronized void updateStats() {
public synchronized void updateStats(boolean castLoginScripts) {
// Update player stats
for (String stat : MMOCore.plugin.statManager.getRegistered()) {
final StatInstance instance = getMap().getInstance(stat);
final StatInstance.ModifierPacket packet = instance.newPacket();
@ -90,25 +101,32 @@ public class PlayerStats {
packet.runUpdate();
}
/*
* This is here because it requires updates for the same reasons
* as statistics (when the player level changes, when his class
* changes, when he logs on..)
*
* This updates the player's PASSIVE skills
*/
// Updates the player's unbindable CLASS passive skills
final PassiveSkillMap skillMap = data.getMMOPlayerData().getPassiveSkillMap();
skillMap.removeModifiers("MMOCorePermanentSkill");
for (ClassSkill skill : data.getProfess().getSkills())
if (skill.isPermanent()
&& skill.getSkill().getTrigger() != TriggerType.LOGIN
&& data.hasUnlocked(skill)
&& data.hasUnlockedLevel(skill))
skillMap.addModifier(skill.toPassive(data));
if (!MMOCore.plugin.configManager.passiveSkillNeedBound) {
skillMap.removeModifiers("MMOCorePassiveSkill");
for (ClassSkill skill : data.getProfess().getSkills())
if (skill.getSkill().getTrigger().isPassive())
skillMap.addModifier(skill.toPassive(data));
}
// This updates the player's class SCRIPTS
// Updates the player's CLASS scripts
skillMap.removeModifiers("MMOCoreClassScript");
for (PassiveSkill script : data.getProfess().getScripts())
skillMap.addModifier(script);
if (script.getType() != TriggerType.LOGIN) skillMap.addModifier(script);
// If data hasn't been synchronized yet, cast LOGIN scripts
if (castLoginScripts) {
// Call class login skills
for (ClassSkill skill : data.getProfess().getSkills())
if (skill.getSkill().getTrigger() == TriggerType.LOGIN)
skill.toCastable(data).cast(data.getMMOPlayerData());
// Call class login scripts
for (PassiveSkill skill : data.getProfess().getScripts())
if (skill.getType() == TriggerType.LOGIN) skill.getTriggeredSkill().cast(data.getMMOPlayerData());
}
}
}

View File

@ -1,15 +1,14 @@
package net.Indyuce.mmocore.api.quest;
import io.lumine.mythic.lib.util.Closeable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.Closable;
import net.Indyuce.mmocore.api.quest.objective.Objective;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import net.Indyuce.mmocore.api.quest.objective.Objective;
public abstract class ObjectiveProgress implements Closable {
public abstract class ObjectiveProgress implements Closeable {
private final Objective objective;
private final QuestProgress questProgress;

View File

@ -1,11 +1,11 @@
package net.Indyuce.mmocore.api.quest;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.gson.JsonElement;
import io.lumine.mythic.lib.gson.JsonObject;
import io.lumine.mythic.lib.util.Closeable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.Closable;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.boss.BarColor;
@ -21,7 +21,7 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
public class PlayerQuests implements Closable {
public class PlayerQuests implements Closeable {
private final PlayerData playerData;
private final Map<String, Long> finished = new HashMap<>();
@ -38,6 +38,7 @@ public class PlayerQuests implements Closable {
bossbarNamespacedKey = new NamespacedKey(MMOCore.plugin, "mmocore_quest_progress_" + playerData.getUniqueId().toString());
bossbar = Bukkit.createBossBar(bossbarNamespacedKey, "", BarColor.PURPLE, BarStyle.SEGMENTED_20);
bossbar.addPlayer(playerData.getPlayer());
bossbar.setVisible(false); // Safety
// Bossbar is disabled
} else {
@ -98,8 +99,7 @@ public class PlayerQuests implements Closable {
}
public void load(String json) {
Gson parser = new Gson();
JsonObject jo = parser.fromJson(json, JsonObject.class);
JsonObject jo = MythicLib.plugin.getGson().fromJson(json, JsonObject.class);
if (jo.has("current")) {
JsonObject cur = jo.getAsJsonObject("current");
try {
@ -173,6 +173,9 @@ public class PlayerQuests implements Closable {
bossbar.removeAll();
Bukkit.removeBossBar(bossbarNamespacedKey);
}
// Close current objective progress
closeCurrentQuest();
}
public boolean checkCooldownAvailability(Quest quest) {

View File

@ -1,12 +1,8 @@
package net.Indyuce.mmocore.api.quest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.PostLoadAction;
import io.lumine.mythic.lib.util.PreloadedObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.objective.Objective;
@ -14,26 +10,32 @@ import net.Indyuce.mmocore.experience.Profession;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.util.PostLoadObject;
import java.util.*;
import java.util.logging.Level;
public class Quest extends PostLoadObject {
private final String id;
private final String name;
public class Quest implements PreloadedObject {
private final String id, name;
private final List<Quest> parents = new ArrayList<>();
private final List<Objective> objectives = new ArrayList<>();
private final List<String> lore;
private final int mainLevelRestriction;
private final Map<Profession, Integer> levelRestrictions = new HashMap<>();
// cooldown in millis
// Cooldown in millis
private final long cooldown;
public Quest(String id, FileConfiguration config) {
super(config);
private final PostLoadAction postLoadAction = new PostLoadAction(config -> {
// Load parent quests
if (config.contains("parent"))
for (String parent : config.getStringList("parent"))
parents.add(MMOCore.plugin.questManager.getOrThrow(parent.toLowerCase().replace(" ", "-").replace("_", "-")));
});
public Quest(String id, ConfigurationSection config) {
postLoadAction.cacheConfig(config);
this.id = id.toLowerCase().replace("_", "-").replace(" ", "-");
cooldown = (long) (config.contains("delay") ? config.getDouble("delay") * 60 * 60 * 1000 : -1);
@ -69,11 +71,10 @@ public class Quest extends PostLoadObject {
}
}
@NotNull
@Override
protected void whenPostLoaded(ConfigurationSection config) {
if (config.contains("parent"))
for (String parent : config.getStringList("parent"))
parents.add(MMOCore.plugin.questManager.getOrThrow(parent.toLowerCase().replace(" ", "-").replace("_", "-")));
public PostLoadAction getPostLoadAction() {
return postLoadAction;
}
public String getId() {

View File

@ -5,61 +5,63 @@ import net.Indyuce.mmocore.api.quest.objective.Objective;
import io.lumine.mythic.lib.MythicLib;
public class QuestProgress {
private final Quest quest;
private final PlayerData player;
private final Quest quest;
private final PlayerData player;
private int objective;
private ObjectiveProgress objectiveProgress;
private int objective;
private ObjectiveProgress objectiveProgress;
public QuestProgress(Quest quest, PlayerData player) {
this(quest, player, 0);
}
public QuestProgress(Quest quest, PlayerData player) {
this(quest, player, 0);
}
public QuestProgress(Quest quest, PlayerData player, int objective) {
this.quest = quest;
this.player = player;
this.objective = objective;
objectiveProgress = nextObjective().newProgress(this);
}
public QuestProgress(Quest quest, PlayerData player, int objective) {
this.quest = quest;
this.player = player;
public Quest getQuest() {
return quest;
}
this.objective = objective;
objectiveProgress = nextObjective().newProgress(this);
}
public PlayerData getPlayer() {
return player;
}
public Quest getQuest() {
return quest;
}
public int getObjectiveNumber() {
return objective;
}
public PlayerData getPlayer() {
return player;
}
public ObjectiveProgress getProgress() {
return objectiveProgress;
}
public int getObjectiveNumber() {
return objective;
}
private Objective nextObjective() {
return quest.getObjectives().get(objective);
}
public ObjectiveProgress getProgress() {
return objectiveProgress;
}
public void completeObjective() {
objective++;
objectiveProgress.close();
private Objective nextObjective() {
return quest.getObjectives().get(objective);
}
// apply triggers
objectiveProgress.getObjective().getTriggers().forEach(trigger -> trigger.schedule(getPlayer()));
public void completeObjective() {
objective++;
objectiveProgress.close();
final ObjectiveProgress finishedObjectiveProgress = objectiveProgress;
// end quest
if (objective >= quest.getObjectives().size())
player.getQuestData().finishCurrent();
else
objectiveProgress = nextObjective().newProgress(this);
// Start next objective, or end quest.
if (objective >= quest.getObjectives().size()) player.getQuestData().finishCurrent();
else objectiveProgress = nextObjective().newProgress(this);
player.getQuestData().updateBossBar();
}
player.getQuestData().updateBossBar();
public String getFormattedLore() {
return MythicLib.plugin.parseColors(objectiveProgress.formatLore(objectiveProgress.getObjective().getDefaultLore()));
}
/*
* Apply triggers only at the end! It comes handy when starting another
* quest in some storyline using triggers from the previous quest.
*/
finishedObjectiveProgress.getObjective().getTriggers().forEach(trigger -> trigger.schedule(getPlayer()));
}
public String getFormattedLore() {
return MythicLib.plugin.parseColors(objectiveProgress.formatLore(objectiveProgress.getObjective().getDefaultLore()));
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.api.quest.objective;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.api.quest.ObjectiveProgress;
import net.Indyuce.mmocore.api.event.CustomBlockMineEvent;
import net.Indyuce.mmocore.api.quest.QuestProgress;
@ -42,6 +43,8 @@ public class MineBlockObjective extends Objective {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if(!getQuestProgress().getPlayer().isOnline()) return;
if (UtilityMethods.isFake(event)) return;
if ((!playerPlaced) && event.getBlock().hasMetadata("player_placed"))
return;
if (event.getPlayer().equals(getQuestProgress().getPlayer().getPlayer()) && event.getBlock().getType() == block) {

View File

@ -0,0 +1,34 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import javax.annotation.Nullable;
public class BindSkillTrigger extends Trigger implements Removable {
private final RegisteredSkill skill;
private final int slot;
public BindSkillTrigger(MMOLineConfig config) {
super(config);
config.validateKeys("skill", "slot");
slot = config.getInt("slot");
skill = MMOCore.plugin.skillManager.getSkillOrThrow(config.getString("skill"));
}
@Override
public void apply(PlayerData playerData) {
final @Nullable ClassSkill found = playerData.getProfess().getSkill(skill);
if (found != null) playerData.bindSkill(slot, found);
}
@Override
public void remove(PlayerData playerData) {
playerData.unbindSkill(slot);
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Bukkit;
@ -23,7 +24,9 @@ public class CommandTrigger extends Trigger {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), format(player.getPlayer()));
}
@BackwardsCompatibility(version = "1.12-SNAPSHOT")
private String format(Player player) {
// TODO remove use of confusing non-PAPI %player% placeholder
return MMOCore.plugin.placeholderParser.parse(player, command.replace("%player%", player.getName()));
}
}

View File

@ -36,6 +36,6 @@ public class ExperienceTrigger extends Trigger {
@Override
public void apply(PlayerData player) {
dispenser.giveExperience(player, amount.calculateInt(), null, source);
dispenser.giveExperience(player, amount.calculate(), null, source);
}
}

View File

@ -0,0 +1,30 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.skill.RegisteredSkill;
public class LevelUpSkillTrigger extends Trigger implements Removable {
private final RegisteredSkill skill;
private final int amount;
public LevelUpSkillTrigger(MMOLineConfig config) {
super(config);
config.validateKeys("skill", "amount");
amount = config.getInt("amount");
skill = MMOCore.plugin.skillManager.getSkillOrThrow(config.getString("skill"));
}
@Override
public void apply(PlayerData playerData) {
playerData.setSkillLevel(skill, playerData.getSkillLevel(skill) + amount);
}
@Override
public void remove(PlayerData playerData) {
playerData.setSkillLevel(skill, Math.max(0, playerData.getSkillLevel(skill) - amount));
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.entity.Player;
@ -22,7 +23,9 @@ public class MessageTrigger extends Trigger {
player.getPlayer().sendMessage(format(player.getPlayer()));
}
@BackwardsCompatibility(version = "1.12-SNAPSHOT")
private String format(Player player) {
// TODO remove use of confusing non-PAPI %player% placeholder
return MMOCore.plugin.placeholderParser.parse(player, message.replace("%player%", player.getName()));
}
}

View File

@ -0,0 +1,73 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import io.lumine.mythic.lib.player.skillmod.SkillModifier;
import io.lumine.mythic.lib.skill.handler.SkillHandler;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.quest.trigger.api.Temporary;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.stream.Collectors;
public class SkillModifierTrigger extends Trigger implements Removable, Temporary {
private SkillModifier mod;
private boolean mutable = true;
public SkillModifierTrigger(MMOLineConfig config) {
super(config);
config.validateKeys("modifier");
config.validateKeys("amount");
final double amount = config.getDouble("amount");
final String parameter = config.getString("modifier");
final String formula = config.getString("formula", "true");
final ModifierType type = config.contains("type") ? ModifierType.valueOf(UtilityMethods.enumName(config.getString("type"))) : ModifierType.FLAT;
final List<SkillHandler<?>> targetSkills = MMOCore.plugin.skillManager.getAll().stream().filter(skill -> skill.matchesFormula(formula)).map(RegisteredSkill::getHandler).collect(Collectors.toList());
mod = new SkillModifier(Trigger.STAT_MODIFIER_KEY, parameter, targetSkills, amount, type);
}
public void updateKey(@NotNull String key) {
Validate.isTrue(mutable, "No longer mutable");
this.mod = new SkillModifier(key, mod.getParameter(), mod.getSkills(), mod.getValue(), mod.getType());
}
public List<SkillHandler<?>> getTargetSkills() {
return mod.getSkills();
}
@Override
public void apply(PlayerData player) {
mod.register(player.getMMOPlayerData());
}
@Override
public void remove(PlayerData playerData) {
mod.unregister(playerData.getMMOPlayerData());
}
/**
* Used by skill slots to apply a skill modifier.
* to a dynamically chosen skill handler.
*/
public void apply(PlayerData playerData, SkillHandler<?> skill) {
mutable = false;
mod.register(playerData.getMMOPlayerData(), skill);
}
/**
* Used by skill slots to remove a skillBuff
* from a dynamically chosen skill handler.
*/
public void remove(PlayerData playerData, SkillHandler<?> skill) {
mod.unregister(playerData.getMMOPlayerData(), skill);
}
}

View File

@ -4,16 +4,14 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.stat.modifier.StatModifier;
import io.lumine.mythic.lib.player.modifier.ModifierType;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.api.quest.trigger.api.Temporary;
import org.apache.commons.lang.Validate;
import java.util.UUID;
public class StatTrigger extends Trigger {
public class StatTrigger extends Trigger implements Removable, Temporary {
private final StatModifier modifier;
private final String stat;
private final double amount;
private final ModifierType type;
private double totalAmount;
private final UUID uuid =UUID.randomUUID();
public StatTrigger(MMOLineConfig config) {
super(config);
@ -25,23 +23,18 @@ public class StatTrigger extends Trigger {
Validate.isTrue(type.equals("FLAT") || type.equals("RELATIVE"));
stat = config.getString("stat");
amount = config.getDouble("amount");
this.type = ModifierType.valueOf(type);
this.totalAmount = 0;
modifier = new StatModifier(Trigger.STAT_MODIFIER_KEY, stat, amount, ModifierType.valueOf(type));
}
@Override
public void apply(PlayerData player) {
totalAmount+=amount;
new StatModifier("trigger."+uuid.toString(),stat,totalAmount,type).register(player.getMMOPlayerData());
StatModifier prevModifier = player.getMMOPlayerData().getStatMap().getInstance(stat).getModifier(modifier.getUniqueId());
if (prevModifier == null) modifier.register(player.getMMOPlayerData());
else prevModifier.add(amount).register(player.getMMOPlayerData());
}
/**
* Removes the effect of the trigger to the player by registering the
* opposite amount. (Little corrective term for the relative to have the inverse.
* Not a problem to store twice the stat modifiers are there only remain in the RAM.
*/
@Override
public void remove(PlayerData playerData) {
totalAmount-=amount;
new StatModifier("trigger."+uuid.toString(), stat, totalAmount, type).register(playerData.getMMOPlayerData());
modifier.unregister(playerData.getMMOPlayerData());
}
}

View File

@ -6,6 +6,8 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Bukkit;
public abstract class Trigger {
public static String STAT_MODIFIER_KEY = "mmocore_trigger";
private final long delay;
public Trigger(MMOLineConfig config) {

View File

@ -0,0 +1,33 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import javax.annotation.Nullable;
public class UnlockSkillTrigger extends Trigger implements Removable {
private final RegisteredSkill skill;
public UnlockSkillTrigger(MMOLineConfig config) {
super(config);
config.validateKeys("skill");
skill = MMOCore.plugin.skillManager.getSkillOrThrow(config.getString("skill"));
}
@Override
public void apply(PlayerData playerData) {
final @Nullable ClassSkill found = playerData.getProfess().getSkill(skill);
if (found != null) playerData.unlock(found);
}
@Override
public void remove(PlayerData playerData) {
final @Nullable ClassSkill found = playerData.getProfess().getSkill(skill);
if (found != null) playerData.lock(found);
}
}

View File

@ -0,0 +1,35 @@
package net.Indyuce.mmocore.api.quest.trigger;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.binding.SkillSlot;
import net.Indyuce.mmocore.api.quest.trigger.api.Removable;
import org.apache.commons.lang.Validate;
public class UnlockSlotTrigger extends Trigger implements Removable {
private final int slot;
public UnlockSlotTrigger(MMOLineConfig config) {
super(config);
config.validateKeys("slot");
try {
slot = Integer.parseInt(config.getString("slot"));
} catch (NumberFormatException exception) {
throw new IllegalArgumentException("Slot should be a number");
}
Validate.isTrue(slot > 0, "Slot number must be positive");
}
@Override
public void apply(PlayerData player) {
player.unlock(player.getProfess().getSkillSlot(slot));
}
@Override
public void remove(PlayerData player) {
player.lock(player.getProfess().getSkillSlot(slot));
}
}

View File

@ -0,0 +1,13 @@
package net.Indyuce.mmocore.api.quest.trigger.api;
import net.Indyuce.mmocore.api.player.PlayerData;
/**
* Cancelable triggers cause problems when letting the player reset
* their advancement on things they can spend points in/level up.
* If you give access to some resource to the player via a trigger,
* you must take it away when resetting their progression.
*/
public interface Removable {
public void remove(PlayerData playerData);
}

View File

@ -0,0 +1,12 @@
package net.Indyuce.mmocore.api.quest.trigger.api;
/**
* Non-permanent triggers are triggers which are not saved
* by the player and taken off when the player logs off,
* for instance temporary player modifiers. They need to
* be re-applied everytime the player logs back.
*
* @author jules
*/
public interface Temporary extends Removable {
}

View File

@ -1,15 +0,0 @@
package net.Indyuce.mmocore.api.util;
/**
* Indicates that a class temporarily registers something
* such as a Bukkit event, which needs to be unregistered
* when the class is finally garbage collected.
*/
public interface Closable {
/**
* Method that must be called before the class
* is garbage collected
*/
void close();
}

View File

@ -1,15 +1,14 @@
package net.Indyuce.mmocore.api.util;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.common.collect.MultimapBuilder;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.gson.JsonArray;
import io.lumine.mythic.lib.gson.JsonObject;
import io.lumine.mythic.lib.hologram.Hologram;
import io.lumine.mythic.lib.version.VersionMaterial;
import io.lumine.mythic.lib.version.VEnchantment;
import net.Indyuce.mmocore.MMOCore;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@ -18,11 +17,13 @@ import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import org.jetbrains.annotations.NotNull;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import java.io.ByteArrayInputStream;
@ -34,11 +35,37 @@ public class MMOCoreUtils {
return item != null && item.hasItemMeta() && item.getItemMeta().hasDisplayName();
}
public static String displayName(ItemStack item) {
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName()
: caseOnWords(item.getType().name().replace("_", " "));
/**
* If a given player is not in the server cache, no information
* cannot be retrieved from that player (without using requests
* to MC servers obviously). In that case, the instance of
* OfflinePlayer is pretty much useless and it only wraps its
* UUID which was already known beforehand.
*
* @param player Offline player instance to test
* @return Is the instance valid
*/
public static boolean isInvalid(OfflinePlayer player) {
return player.getName() == null;
}
@Deprecated
public static String displayName(ItemStack item) {
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName()
: UtilityMethods.caseOnWords(item.getType().name().replace("_", " "));
}
/**
* @param current Current value of resource
* @param maxStat Maximum value of resource
* @return Clamped resource value. If the provided current value is 0,
* this function will return the maximum resource value.
*/
public static double fixResource(double current, double maxStat) {
return current == 0 ? maxStat : Math.max(0, Math.min(current, maxStat));
}
@Deprecated
public static String caseOnWords(String s) {
StringBuilder builder = new StringBuilder(s);
boolean isLastSpace = true;
@ -53,44 +80,26 @@ public class MMOCoreUtils {
return builder.toString();
}
/**
*
* @param value an integer you want to convert
* @return the string representing the integer but with roman letters
*/
public static String toRomanNumerals(int value) {
LinkedHashMap<String, Integer> roman_numerals = new LinkedHashMap<String, Integer>();
roman_numerals.put("M", 1000);
roman_numerals.put("CM", 900);
roman_numerals.put("D", 500);
roman_numerals.put("CD", 400);
roman_numerals.put("C", 100);
roman_numerals.put("XC", 90);
roman_numerals.put("L", 50);
roman_numerals.put("XL", 40);
roman_numerals.put("X", 10);
roman_numerals.put("IX", 9);
roman_numerals.put("V", 5);
roman_numerals.put("IV", 4);
roman_numerals.put("I", 1);
String res = "";
for(Map.Entry<String, Integer> entry : roman_numerals.entrySet()){
int matches = value/entry.getValue();
res += repeat(entry.getKey(), matches);
value = value % entry.getValue();
}
return res;
public static String ymlName(String str) {
return str.toLowerCase().replace("_", "-").replace(" ", "-");
}
@Deprecated
public static String toRomanNumerals(int value) {
return intToRoman(value);
}
private static String repeat(String s, int n) {
if(s == null) {
if (s == null) {
return null;
}
final StringBuilder sb = new StringBuilder();
for(int i = 0; i < n; i++) {
for (int i = 0; i < n; i++) {
sb.append(s);
}
return sb.toString();
}
/**
* Displays an in game indicator using a hologram. This uses
* LumineUtils hologramFactory to summon holograms
@ -101,18 +110,38 @@ public class MMOCoreUtils {
* @param message Message to display
*/
public static void displayIndicator(Location loc, String message) {
Hologram holo = Hologram.create(loc, Arrays.asList(message));
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> holo.despawn(), 20);
Hologram holo = Hologram.create(loc, MythicLib.plugin.parseColors(Collections.singletonList(message)));
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, holo::despawn, 20);
}
public static boolean isPlayerHead(Material material) {
return material == VersionMaterial.PLAYER_HEAD.toMaterial() || material == VersionMaterial.PLAYER_WALL_HEAD.toMaterial();
return material == Material.PLAYER_HEAD || material == Material.PLAYER_WALL_HEAD;
}
public static ItemStack readIcon(String string) throws IllegalArgumentException {
String[] split = string.split(":");
Material material = Material.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_"));
return split.length > 1 ? MythicLib.plugin.getVersion().getWrapper().textureItem(material, Integer.parseInt(split[1])) : new ItemStack(material);
public static void addAllItemFlags(@NotNull ItemMeta meta) {
meta.addItemFlags(ItemFlag.values());
// Fix 1.20.6+ Paper bug that sucks. HIDE_ATTRIBUTES no longer works when item attribute list is empty
// TODO refactor with GUI update.
try {
meta.setAttributeModifiers(MultimapBuilder.hashKeys(0).hashSetValues(0).build());
} catch (Exception exception) {
// Not needed
}
}
@NotNull
public static ItemStack readIcon(String string) {
final String[] split = string.split(":");
final ItemStack item = new ItemStack(Material.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_")));
if (split.length > 1) {
final ItemMeta meta = item.getItemMeta();
meta.setCustomModelData(Integer.parseInt(split[1]));
item.setItemMeta(meta);
}
return item;
}
public static int getWorth(ItemStack[] items) {
@ -228,6 +257,7 @@ public class MMOCoreUtils {
return entities;
}
@Deprecated
public static void heal(LivingEntity target, double value) {
double max = target.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
double gain = Math.min(max, target.getHealth() + value) - target.getHealth();
@ -238,6 +268,8 @@ public class MMOCoreUtils {
target.setHealth(target.getHealth() + gain);
}
private static final Random RANDOM = new Random();
/**
* Method used when mining a custom block or fishing, as the corresponding
* interaction event is cancelled durability is not handled. This method is
@ -252,21 +284,27 @@ public class MMOCoreUtils {
* @param damage Damage that needs to be applied
*/
public static void decreaseDurability(Player player, EquipmentSlot slot, int damage) {
ItemStack item = player.getInventory().getItem(slot);
if (item == null || item.getType().getMaxDurability() == 0 || !item.hasItemMeta() || !(item.getItemMeta() instanceof Damageable) || item.getItemMeta().isUnbreakable())
ItemStack item = UtilityMethods.getHandItem(player, slot);
if (item == null || item.getType().getMaxDurability() == 0 || item.getItemMeta().isUnbreakable())
return;
// Check unbreakable, ignore if necessary
final ItemMeta meta = item.getItemMeta();
final int unbreakingLevel = meta.getEnchantLevel(VEnchantment.UNBREAKING.get());
if (unbreakingLevel > 0 && RANDOM.nextInt(unbreakingLevel + 1) != 0) return;
PlayerItemDamageEvent event = new PlayerItemDamageEvent(player, item, damage);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return;
ItemMeta meta = item.getItemMeta();
if (event.getDamage() + ((Damageable) meta).getDamage() >= item.getType().getMaxDurability()) {
final int newDamage = event.getDamage() + ((Damageable) meta).getDamage();
if (newDamage >= item.getType().getMaxDurability()) {
player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1F, 1F);
player.getInventory().setItem(slot, null);
} else {
((Damageable) meta).setDamage(((Damageable) meta).getDamage() + event.getDamage());
((Damageable) meta).setDamage(newDamage);
item.setItemMeta(meta);
}
}
@ -277,4 +315,11 @@ public class MMOCoreUtils {
public static Location getCenterLocation(Entity entity) {
return entity.getBoundingBox().getCenter().toLocation(entity.getWorld());
}
public static void debug(String message) {
message = ChatColor.YELLOW + "Debug> " + ChatColor.WHITE + message;
for (Player player : Bukkit.getOnlinePlayers())
player.sendMessage(message);
Bukkit.getConsoleSender().sendMessage(message);
}
}

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmocore.api.util.input;
import net.Indyuce.mmocore.MMOCore;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmocore.api.ConfigMessage;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -12,8 +13,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Consumer;
import io.lumine.mythic.lib.MythicLib;
@Deprecated
public class AnvilGUI extends PlayerInput {
private final int containerId;
@ -24,7 +23,7 @@ public class AnvilGUI extends PlayerInput {
ItemStack paper = new ItemStack(Material.PAPER);
ItemMeta paperMeta = paper.getItemMeta();
paperMeta.setDisplayName(MMOCore.plugin.configManager.getSimpleMessage("player-input.anvil." + type.getLowerCaseName()).message());
paperMeta.setDisplayName(ConfigMessage.fromKey("player-input.anvil." + type.getLowerCaseName()).asLine());
paper.setItemMeta(paperMeta);
MythicLib.plugin.getVersion().getWrapper().handleInventoryCloseEvent(player);

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmocore.api.util.input;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.gui.api.PluginInventory;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -37,8 +38,7 @@ public class ChatInput extends PlayerInput {
this.lastOpened = lastOpened;
player.closeInventory();
MMOCore.plugin.configManager.getSimpleMessage("player-input.chat." + inputType.getLowerCaseName()).send(player);
MMOCore.plugin.configManager.getSimpleMessage("player-input.chat.cancel").send(player);
ConfigMessage.fromKey("player-input.chat." + inputType.getLowerCaseName()).send(player);
}
@Override
@ -56,7 +56,7 @@ public class ChatInput extends PlayerInput {
if (event.getMessage().equals("cancel")) {
if (lastOpened != null)
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> lastOpened.open());
MMOCore.plugin.configManager.getSimpleMessage("player-input.chat." + inputType.getLowerCaseName() + "-cancel").send(getPlayer());
ConfigMessage.fromKey("player-input.chat." + inputType.getLowerCaseName() + "-cancel").send(getPlayer());
} else
// Run sync
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> output(event.getMessage()));

View File

@ -29,7 +29,6 @@ public abstract class PlayerInput implements Listener {
public enum InputType {
FRIEND_REQUEST,
PARTY_INVITE,
GUILD_INVITE,
GUILD_CREATION_TAG,

View File

@ -2,7 +2,13 @@ package net.Indyuce.mmocore.api.util.math.formula;
import io.lumine.mythic.lib.MythicLib;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
/**
* Bounded linear formula.
*
* @author Jules
*/
public class LinearValue {
private final double base, perLevel, min, max;
private final boolean hasMin, hasMax;
@ -97,6 +103,7 @@ public class LinearValue {
return hasMin;
}
@NotNull
public String getDisplay(int level) {
return MythicLib.plugin.getMMOConfig().decimals.format(calculate(level));
}

View File

@ -1,25 +1,26 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class AttributesCommand extends BukkitCommand {
public class AttributesCommand extends RegisteredCommand {
public AttributesCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the attribute menu.");
super(config, ToggleableCommand.ATTRIBUTES);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.attributes"))
return false;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;

View File

@ -1,21 +1,19 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class ClassCommand extends BukkitCommand {
public class ClassCommand extends RegisteredCommand {
public ClassCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Select a new class.");
super(config, ToggleableCommand.CLASS);
}
@Override

View File

@ -1,19 +1,17 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.gui.eco.DepositMenu;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class DepositCommand extends BukkitCommand {
public class DepositCommand extends RegisteredCommand {
public DepositCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the currency deposit menu.");
super(config, ToggleableCommand.DEPOSIT);
}
@Override
@ -29,7 +27,7 @@ public class DepositCommand extends BukkitCommand {
// if (sender instanceof Player)
// if (!isNearEnderchest(((Player) sender).getLocation())) {
// sender.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("stand-near-enderchest"));
// sender.sendMessage(ConfigMessage.fromKey("stand-near-enderchest"));
// return true;
// }

View File

@ -3,6 +3,8 @@ package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.social.FriendRequest;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.social.Request;
@ -10,23 +12,21 @@ import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class FriendsCommand extends BukkitCommand {
public class FriendsCommand extends RegisteredCommand {
public FriendsCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the friends menu.");
super(config, ToggleableCommand.FRIENDS);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.friends"))
return false;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;

View File

@ -2,6 +2,8 @@ package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.social.Request;
@ -11,24 +13,21 @@ import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class GuildCommand extends BukkitCommand {
public class GuildCommand extends RegisteredCommand {
public GuildCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the guilds menu.");
super(config, ToggleableCommand.GUILD);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.guild"))
return false;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;
@ -50,7 +49,7 @@ public class GuildCommand extends BukkitCommand {
final Request req = MMOCore.plugin.requestManager.getRequest(uuid);
Validate.isTrue(!req.isTimedOut() && req instanceof GuildInvite);
invite = (GuildInvite) req;
Validate.isTrue(MMOCore.plugin.dataProvider.getGuildManager().isRegistered(invite.getGuild()));
Validate.isTrue(MMOCore.plugin.nativeGuildManager.isRegistered(invite.getGuild()));
} catch (Exception exception) {
return true;
}

View File

@ -2,6 +2,8 @@ package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.social.Request;
@ -12,28 +14,29 @@ import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class PartyCommand extends BukkitCommand {
public class PartyCommand extends RegisteredCommand {
public PartyCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the party menu.");
super(config, ToggleableCommand.PARTY);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.party"))
return false;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;
}
if(!(MMOCore.plugin.partyModule instanceof MMOCorePartyModule)){
sender.sendMessage(ChatColor.RED+"You can't use MMOCore party system as you delegated the party system to another plugin.");
return true;
}
PlayerData data = PlayerData.get((OfflinePlayer) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "party");

View File

@ -1,34 +1,34 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class PlayerStatsCommand extends BukkitCommand {
public PlayerStatsCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Show player stats.");
}
public class PlayerStatsCommand extends RegisteredCommand {
public PlayerStatsCommand(ConfigurationSection config) {
super(config, ToggleableCommand.PLAYER);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;
}
PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "profile");
Bukkit.getServer().getPluginManager().callEvent(event);
if(!event.isCancelled()) InventoryManager.PLAYER_STATS.newInventory(data).open();
return true;
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.profile"))
return false;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return true;
}
PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "profile");
Bukkit.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) InventoryManager.PLAYER_STATS.newInventory(data).open();
return true;
}
}

View File

@ -0,0 +1,57 @@
package net.Indyuce.mmocore.command;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class PvpModeCommand extends RegisteredCommand {
public PvpModeCommand(ConfigurationSection config) {
super(config, ToggleableCommand.PVP_MODE);
}
public static final String COOLDOWN_KEY = "PvpMode";
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command is for players only.");
return false;
}
if (!sender.hasPermission("mmocore.pvpmode")) {
ConfigMessage.fromKey("not-enough-perms").send((Player) sender);
return false;
}
final PlayerData playerData = PlayerData.get((Player) sender);
// Command cooldown
if (playerData.getCooldownMap().isOnCooldown(COOLDOWN_KEY)) {
ConfigMessage.fromKey("pvp-mode.cooldown", "remaining", MythicLib.plugin.getMMOConfig().decimal.format(playerData.getCooldownMap().getCooldown(COOLDOWN_KEY))).send((Player) sender);
return true;
}
playerData.getCombat().setPvpMode(!playerData.getCombat().isInPvpMode());
playerData.getCooldownMap().applyCooldown(COOLDOWN_KEY, playerData.getCombat().isInPvpMode() ? MMOCore.plugin.configManager.pvpModeToggleOnCooldown : MMOCore.plugin.configManager.pvpModeToggleOffCooldown);
// Toggling on when in PVP region
if (playerData.getCombat().isInPvpMode() &&
MythicLib.plugin.getFlags().isFlagAllowed(playerData.getPlayer(), CustomFlag.PVP_MODE)) {
playerData.getCombat().setInvulnerable(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand);
ConfigMessage.fromKey("pvp-mode.toggle.on-invulnerable", "time",
MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.configManager.pvpModeInvulnerabilityTimeCommand)).send(playerData.getPlayer());
// Just send message otherwise
} else
ConfigMessage.fromKey("pvp-mode.toggle." + (playerData.getCombat().isInPvpMode() ? "on" : "off") + "-safe").send((Player) sender);
return true;
}
}

View File

@ -1,24 +1,24 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class QuestsCommand extends BukkitCommand {
public class QuestsCommand extends RegisteredCommand {
public QuestsCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the quests menu.");
super(config, ToggleableCommand.QUESTS);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.quests"))
return false;
if (sender instanceof Player) {
PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "quests");

View File

@ -1,44 +0,0 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class SkillTreeCommand extends BukkitCommand {
public SkillTreeCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the skills menu.");
}
@Override
public boolean execute(@NotNull CommandSender sender, String s, String[] args) {
if (!(sender instanceof Player player))
return false;
PlayerData data = PlayerData.get(player);
MMOCommandEvent event = new MMOCommandEvent(data, "skilltrees");
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
return true;
if (data.getProfess().getSkillTrees().size() != 0) {
InventoryManager.TREE_VIEW.newInventory(data).open();
return false;
}
else {
MMOCore.plugin.configManager.getSimpleMessage("no-skill-tree").send(player);
return true;
}
}
}

View File

@ -0,0 +1,77 @@
package net.Indyuce.mmocore.command;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Collectors;
public class SkillTreesCommand extends RegisteredCommand {
public SkillTreesCommand(ConfigurationSection config) {
super(config, ToggleableCommand.SKILL_TREES);
}
@Override
public boolean execute(@NotNull CommandSender sender, String s, String[] args) {
if (!sender.hasPermission("mmocore.skilltrees"))
return false;
if (!(sender instanceof Player))
return false;
final Player player = (Player) sender;
PlayerData data = PlayerData.get(player);
MMOCommandEvent event = new MMOCommandEvent(data, "skilltrees");
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
return false;
// Default skilltree command
if (args.length == 0) {
if (!MMOCore.plugin.configManager.enableGlobalSkillTreeGUI) {
sender.sendMessage(ChatColor.RED + "Usage: /skilltrees <skilltree_id>");
return false;
}
if (data.getProfess().getSkillTrees().size() != 0) {
InventoryManager.TREE_VIEW.newInventory(data).open();
return true;
} else {
ConfigMessage.fromKey("no-skill-tree").send(player);
return false;
}
}
if (args.length == 1) {
if (!MMOCore.plugin.configManager.enableSpecificSkillTreeGUI) {
sender.sendMessage(ChatColor.RED + "Usage: /skilltrees <skilltree-id>");
return false;
}
if (data.getProfess().getSkillTrees()
.stream()
.filter(skillTree -> UtilityMethods.ymlName(skillTree.getId()).equals(UtilityMethods.ymlName(args[0])))
.collect(Collectors.toList())
.size() != 0) {
InventoryManager.SPECIFIC_TREE_VIEW.get(UtilityMethods.ymlName(args[0])).newInventory(data).open();
return true;
} else {
sender.sendMessage(ChatColor.RED + "Your class does not have a skill tree with id: " + args[0]);
return false;
}
} else {
if (MMOCore.plugin.configManager.enableSpecificSkillTreeGUI)
sender.sendMessage(ChatColor.RED + "Usage: /skilltrees <skilltree-id>");
else
sender.sendMessage(ChatColor.RED + "Usage: /skilltrees");
return false;
}
}
}

View File

@ -1,33 +1,33 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class SkillsCommand extends BukkitCommand {
public class SkillsCommand extends RegisteredCommand {
public SkillsCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Opens the skills menu.");
super(config, ToggleableCommand.SKILLS);
}
@Override
public boolean execute(CommandSender sender, String label, String[] args) {
if (!sender.hasPermission("mmocore.skills"))
return false;
if (sender instanceof Player) {
PlayerData data = PlayerData.get((Player) sender);
MMOCommandEvent event = new MMOCommandEvent(data, "skills");
Bukkit.getServer().getPluginManager().callEvent(event);
if(event.isCancelled()) return true;
if (data.getProfess().getSkills().size() < 1) {
MMOCore.plugin.configManager.getSimpleMessage("no-class-skill").send((Player) sender);
if (data.getUnlockedSkills().isEmpty()) {
ConfigMessage.fromKey("no-class-skill").send((Player) sender);
return true;
}

View File

@ -1,20 +1,18 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import net.Indyuce.mmocore.manager.InventoryManager;
import net.Indyuce.mmocore.api.event.MMOCommandEvent;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
public class WaypointsCommand extends BukkitCommand {
public class WaypointsCommand extends RegisteredCommand {
public WaypointsCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Open the waypoints menu.");
super(config, ToggleableCommand.WAYPOINTS);
}
@Override

View File

@ -1,23 +1,21 @@
package net.Indyuce.mmocore.command;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.eco.Withdraw;
import net.Indyuce.mmocore.command.api.RegisteredCommand;
import net.Indyuce.mmocore.command.api.ToggleableCommand;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import net.Indyuce.mmocore.api.eco.Withdraw;
public class WithdrawCommand extends BukkitCommand {
public class WithdrawCommand extends RegisteredCommand {
public WithdrawCommand(ConfigurationSection config) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription("Creates a withdraw request.");
super(config, ToggleableCommand.WITHDRAW);
}
@Override
@ -39,7 +37,7 @@ public class WithdrawCommand extends BukkitCommand {
amount = Integer.parseInt(amountArgument);
Validate.isTrue(amount >= 0);
} catch (IllegalArgumentException exception) {
sender.sendMessage(MMOCore.plugin.configManager.getSimpleMessage("wrong-number", "arg", "" + args[0]).message());
sender.sendMessage(ConfigMessage.fromKey("wrong-number", "arg", "" + args[0]).asLine());
return true;
}
@ -52,14 +50,14 @@ public class WithdrawCommand extends BukkitCommand {
int left = (int) MMOCore.plugin.economy.getEconomy().getBalance(player) - amount;
if (left < 0) {
MMOCore.plugin.configManager.getSimpleMessage("not-enough-money", "left", "" + -left).send(player);
ConfigMessage.fromKey("not-enough-money", "left", "" + -left).send(player);
return true;
}
MMOCore.plugin.economy.getEconomy().withdrawPlayer(player, amount);
request.withdrawAlgorythm(amount);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
MMOCore.plugin.configManager.getSimpleMessage("withdrew", "worth", "" + amount).send(player);
ConfigMessage.fromKey("withdrew", "worth", amount).send(player);
return true;
}
}

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmocore.command;
package net.Indyuce.mmocore.command.api;
import io.lumine.mythic.lib.UtilityMethods;
import net.Indyuce.mmocore.MMOCore;

View File

@ -0,0 +1,14 @@
package net.Indyuce.mmocore.command.api;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
public abstract class RegisteredCommand extends BukkitCommand {
public RegisteredCommand(@NotNull ConfigurationSection config, ToggleableCommand command) {
super(config.getString("main"));
setAliases(config.getStringList("aliases"));
setDescription(config.getString("description", command.getDescription()));
}
}

View File

@ -0,0 +1,112 @@
package net.Indyuce.mmocore.command.api;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigFile;
import net.Indyuce.mmocore.command.*;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.logging.Level;
/**
* Commands which can be disabled using commands.yml
*/
public enum ToggleableCommand {
PLAYER("player", "Displays player stats", config -> new PlayerStatsCommand(config), "p", "profile"),
ATTRIBUTES("attributes", "Display and manage attributes", config -> new AttributesCommand(config), "att", "stats"),
CLASS("class", "Select a new class", config -> new ClassCommand(config), "c"),
WAYPOINTS("waypoints", "Display discovered waypoints", config -> new WaypointsCommand(config), "wp"),
QUESTS("quests", "Display available quests", config -> new QuestsCommand(config), "q", "journal"),
SKILLS("skills", "Spend skill points to unlock new skills", config -> new SkillsCommand(config), "s"),
FRIENDS("friends", "Show online/offline friends", config -> new FriendsCommand(config), "f"),
PARTY("party", "Invite players in a party to split exp", config -> new PartyCommand(config)),
GUILD("guild", "Show players in current guild", config -> new GuildCommand(config)),
WITHDRAW("withdraw", "Withdraw money into coins and notes", config -> new WithdrawCommand(config), v -> MMOCore.plugin.hasEconomy() && MMOCore.plugin.economy.isValid(), "w"),
SKILL_TREES("skilltrees", "Open up the skill tree menu", config -> new SkillTreesCommand(config), "st", "trees", "tree"),
DEPOSIT("deposit", "Open the currency deposit menu", config -> new DepositCommand(config), "d"),
PVP_MODE("pvpmode", "Toggle on/off PVP mode.", config -> new PvpModeCommand(config), "pvp");
private final String mainLabel;
private final String description;
private final Function<ConfigurationSection, RegisteredCommand> generator;
private final List<String> aliases;
private final Predicate<Void> enabled;
ToggleableCommand(@NotNull String mainLabel, @NotNull String description, @NotNull Function<ConfigurationSection, RegisteredCommand> generator, @NotNull String... aliases) {
this(mainLabel, description, generator, null, aliases);
}
ToggleableCommand(@NotNull String mainLabel, @NotNull String description, @NotNull Function<ConfigurationSection, RegisteredCommand> generator, @Nullable Predicate<Void> enabled, @NotNull String... aliases) {
this.mainLabel = mainLabel;
this.description = description;
this.generator = generator;
this.aliases = Arrays.asList(aliases);
this.enabled = enabled == null ? v -> true : enabled;
}
public String getMainLabel() {
return mainLabel;
}
public String getDescription() {
return description;
}
public List<String> getAliases() {
return aliases;
}
public String getConfigPath() {
return name().toLowerCase().replace("_", "-");
}
public boolean isEnabled() {
return enabled.test(null);
}
public static void register() {
// Load default config file
if (!new File(MMOCore.plugin.getDataFolder(), "commands.yml").exists()) {
final ConfigFile config = new ConfigFile("commands");
for (ToggleableCommand cmd : values()) {
final String path = cmd.getConfigPath();
config.getConfig().set(path + ".main", cmd.mainLabel);
config.getConfig().set(path + ".aliases", cmd.aliases);
config.getConfig().set(path + ".description", cmd.description);
}
config.save();
}
try {
// Find command map
final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
commandMapField.setAccessible(true);
final CommandMap commandMap = (CommandMap) commandMapField.get(Bukkit.getServer());
// Enable commands individually
final FileConfiguration config = new ConfigFile("commands").getConfig();
for (ToggleableCommand cmd : values())
if (cmd.isEnabled() && config.contains(cmd.getConfigPath()))
commandMap.register("mmocore", cmd.generator.apply(config.getConfigurationSection(cmd.getConfigPath())));
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Unable to register custom commands:");
exception.printStackTrace();
}
}
}

View File

@ -21,14 +21,15 @@ public class AdminCommandTreeNode extends CommandTreeNode {
addChild(new LevelCommandTreeNode(this));
addChild(new AttributeCommandTreeNode(this));
addChild(new SkillCommandTreeNode(this));
addChild(new SaveDataTreeNode(this));
addChild(new SlotCommandTreeNode(this));
addChild(new PointsCommandTreeNode("skill", this, PlayerData::setSkillPoints, PlayerData::giveSkillPoints, PlayerData::getSkillPoints));
addChild(new PointsCommandTreeNode("class", this, PlayerData::setClassPoints, PlayerData::giveClassPoints, PlayerData::getClassPoints));
addChild(new PointsCommandTreeNode("attribute", this, PlayerData::setAttributePoints, PlayerData::giveAttributePoints, PlayerData::getAttributePoints));
addChild(new PointsCommandTreeNode("attr-realloc", this, PlayerData::setAttributeReallocationPoints, PlayerData::giveAttributeReallocationPoints, PlayerData::getAttributeReallocationPoints));
addChild(new PointsCommandTreeNode("skill-realloc", this, PlayerData::setSkillReallocationPoints, PlayerData::giveSkillReallocationPoints, PlayerData::getSkillReallocationPoints));
addChild(new PointsCommandTreeNode("skill-tree-realloc", this, PlayerData::setSkillTreeReallocationPoints, PlayerData::giveSkillTreeReallocationPoints, PlayerData::getSkillTreeReallocationPoints));
addChild(new SkillTreePointsCommandTreeNode(this,(playerData, integer, s) -> playerData.setSkillTreePoints(s,integer),(playerData, integer, s) -> playerData.giveSkillTreePoints(s,integer),((playerData, s) -> playerData.getSkillTreePoint(s))));
addChild(new SkillTreePointsCommandTreeNode(this, (playerData, integer, s) -> playerData.setSkillTreePoints(s, integer), (playerData, integer, s) -> playerData.giveSkillTreePoints(s, integer), PlayerData::getSkillTreePoints));
for (PlayerResource res : PlayerResource.values())
addChild(new ResourceCommandTreeNode(res.name().toLowerCase(), this, res));
}

View File

@ -4,7 +4,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -1,20 +1,20 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import net.Indyuce.mmocore.api.player.profess.SavedClassInformation;
import net.Indyuce.mmocore.command.CommandVerbose;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
public class ClassCommandTreeNode extends CommandTreeNode {
public ClassCommandTreeNode(CommandTreeNode parent) {
super(parent, "class");
@ -52,9 +52,9 @@ public class ClassCommandTreeNode extends CommandTreeNode {
return CommandResult.SUCCESS;
(data.hasSavedClass(profess) ? data.getClassInfo(profess)
: new SavedClassInformation(MMOCore.plugin.dataProvider.getDataManager().getDefaultData())).load(profess, data);
: new SavedClassInformation(MMOCore.plugin.playerDataManager.getDefaultData())).load(profess, data);
if (data.isOnline()) {
MMOCore.plugin.configManager.getSimpleMessage("class-select", "class", profess.getName()).send(data.getPlayer());
ConfigMessage.fromKey("class-select", "class", profess.getName()).send(data.getPlayer());
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1, 1);
}

View File

@ -8,7 +8,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
import net.Indyuce.mmocore.util.TriConsumer;
import org.apache.commons.lang.Validate;

View File

@ -1,21 +1,13 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.data.DataExport;
import io.lumine.mythic.lib.data.sql.SQLDataSource;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.data.mysql.MySQLDataProvider;
import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler;
import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
/**
* This command allows to transfer data from your actual storage type
@ -26,82 +18,15 @@ public class ExportDataTreeNode extends CommandTreeNode {
super(parent, "exportdata");
}
/**
* Amount of requests generated every batch
*/
private static final int BATCH_AMOUNT = 50;
/**
* Period in ticks
*/
private static final int BATCH_PERIOD = 20;
private static final DecimalFormat decFormat = new DecimalFormat("0.#");
@Override
@NotNull
public CommandResult execute(CommandSender sender, String[] strings) {
if (!MMOCore.plugin.dataProvider.getDataManager().getLoaded().isEmpty()) {
sender.sendMessage("Please make sure no players are logged in when using this command. " +
"If you are still seeing this message, restart your server and execute this command before any player logs in.");
return CommandResult.FAILURE;
}
// Export YAML to SQL
final boolean result = new DataExport<>(MMOCore.plugin.playerDataManager, sender).start(
() -> new YAMLPlayerDataHandler(MMOCore.plugin),
() -> new SQLDataHandler(new SQLDataSource(MMOCore.plugin)));
final List<UUID> playerIds = Arrays.stream(new File(MMOCore.plugin.getDataFolder() + "/userdata").listFiles())
.map(file -> UUID.fromString(file.getName().replace(".yml", ""))).collect(Collectors.toList());
// Initialize fake SQL data provider
final MySQLDataProvider sqlProvider;
try {
sqlProvider = new MySQLDataProvider(MMOCore.plugin.getConfig());
} catch (RuntimeException exception) {
sender.sendMessage("Could not initialize SQL provider (see console for stack trace): " + exception.getMessage());
return CommandResult.FAILURE;
}
final double timeEstimation = (double) playerIds.size() / BATCH_AMOUNT * BATCH_PERIOD / 20;
sender.sendMessage("Exporting " + playerIds.size() + " player data(s).. See console for details");
sender.sendMessage("Minimum expected time: " + decFormat.format(timeEstimation) + "s");
// Save player data
new BukkitRunnable() {
int errorCount = 0;
int batchCounter = 0;
@Override
public void run() {
for (int i = 0; i < BATCH_AMOUNT; i++) {
final int index = BATCH_AMOUNT * batchCounter + i;
/*
* Saving is done. Close connection to avoid memory
* leaks and ouput the results to the command executor
*/
if (index >= playerIds.size()) {
cancel();
sqlProvider.close();
MMOCore.plugin.getLogger().log(Level.WARNING, "Exported " + playerIds.size() + " player datas to SQL database. Total errors: " + errorCount);
return;
}
final UUID playerId = playerIds.get(index);
try {
final PlayerData offlinePlayerData = new PlayerData(new MMOPlayerData(playerId));
MMOCore.plugin.dataProvider.getDataManager().loadData(offlinePlayerData);
// Player data is loaded, now it gets saved through SQL
sqlProvider.getDataManager().saveData(offlinePlayerData);
} catch (RuntimeException exception) {
errorCount++;
exception.printStackTrace();
}
}
batchCounter++;
}
}.runTaskTimerAsynchronously(MMOCore.plugin, 0, BATCH_PERIOD);
return CommandResult.SUCCESS;
return result ? CommandResult.SUCCESS : CommandResult.FAILURE;
}
}

View File

@ -3,7 +3,7 @@ package net.Indyuce.mmocore.command.rpg.admin;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -36,7 +36,7 @@ public class HideActionBarCommandTreeNode extends CommandTreeNode {
return CommandResult.FAILURE;
}
long lastUsed = System.currentTimeMillis() - PlayerActivity.ACTION_BAR_MESSAGE.getTimeOut() + amount * 50;
final long lastUsed = System.currentTimeMillis() - PlayerActivity.ACTION_BAR_MESSAGE.getTimeOut() + amount * 50;
PlayerData.get(player).setLastActivity(PlayerActivity.ACTION_BAR_MESSAGE, lastUsed);
return CommandResult.SUCCESS;
}

View File

@ -7,7 +7,7 @@ import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.util.TriConsumer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;

View File

@ -1,7 +1,7 @@
package net.Indyuce.mmocore.command.rpg.admin;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -4,7 +4,7 @@ import java.util.function.BiConsumer;
import java.util.function.Function;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -1,29 +1,33 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.experience.Profession;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import net.Indyuce.mmocore.command.CommandVerbose;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import java.util.HashSet;
public class ResetCommandTreeNode extends CommandTreeNode {
public ResetCommandTreeNode(CommandTreeNode parent) {
super(parent, "reset");
addChild(new ResetClassesCommandTreeNode(this));
addChild(new ResetLevelsCommandTreeNode(this));
addChild(new ResetSkillsCommandTreeNode(this));
addChild(new ResetAllCommandTreeNode(this));
addChild(new ResetQuestsCommandTreeNode(this));
addChild(new ResetAttributesCommandTreeNode(this));
addChild(new ResetWaypointsCommandTreeNode(this));
addChild(new ResetSkillTreesCommandTreeNode(this));
addChild(new ResetAllCommandTreeNode(this));
}
@Override
@ -40,8 +44,7 @@ public class ResetCommandTreeNode extends CommandTreeNode {
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
@ -49,216 +52,245 @@ public class ResetCommandTreeNode extends CommandTreeNode {
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
MMOCore.plugin.dataProvider.getDataManager().getDefaultData().apply(data);
data.setExperience(0);
for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
data.getCollectionSkills().setExperience(profession, 0);
data.getCollectionSkills().setLevel(profession, 0);
}
MMOCore.plugin.classManager.getAll().forEach(data::unloadClassInfo);
data.getAttributes().getInstances().forEach(ins -> ins.setBase(0));
data.mapSkillLevels().forEach((skill, level) -> data.resetSkillLevel(skill));
data.setSkillTreePoints("global", 0);
for (SkillTree skillTree : data.getProfess().getSkillTrees()) {
data.resetSkillTree(skillTree);
data.setSkillTreePoints(skillTree.getId(), 0);
}
data.resetTimesClaimed();
while (data.hasSkillBound(0))
data.unbindSkill(0);
while (data.hasPassiveSkillBound(0))
data.unbindPassiveSkill(0);
data.getQuestData().resetFinishedQuests();
data.getQuestData().start(null);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s data was succesfully reset.");
return CommandResult.SUCCESS;
}
}
public static class ResetWaypointsCommandTreeNode extends CommandTreeNode {
public ResetWaypointsCommandTreeNode(CommandTreeNode parent) {
super(parent, "waypoints");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
PlayerData data = PlayerData.get(player);
data.getWaypoints().clear();
return CommandResult.SUCCESS;
}
}
public static class ResetQuestsCommandTreeNode extends CommandTreeNode {
public ResetQuestsCommandTreeNode(CommandTreeNode parent) {
super(parent, "quests");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
data.getQuestData().resetFinishedQuests();
data.getQuestData().start(null);
return CommandResult.SUCCESS;
}
}
public static class ResetSkillsCommandTreeNode extends CommandTreeNode {
public ResetSkillsCommandTreeNode(CommandTreeNode parent) {
super(parent, "skills");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
data.mapSkillLevels().forEach((skill, level) -> data.resetSkillLevel(skill));
while (data.hasSkillBound(0))
data.unbindSkill(0);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill data was succesfully reset.");
return CommandResult.SUCCESS;
}
}
public static class ResetSkillTreesCommandTreeNode extends CommandTreeNode {
public ResetSkillTreesCommandTreeNode(CommandTreeNode parent) {
super(parent, "skill-trees");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
for (SkillTree skillTree : data.getProfess().getSkillTrees())
data.resetSkillTree(skillTree);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill-tree data was succesfully reset.");
return CommandResult.SUCCESS;
}
}
public class ResetAttributesCommandTreeNode extends CommandTreeNode {
public ResetAttributesCommandTreeNode(CommandTreeNode parent) {
super(parent, "attributes");
addParameter(Parameter.PLAYER);
addParameter(new Parameter("(-reallocate)", (explore, list) -> list.add("-reallocate")));
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
/*
* force reallocating of player attribute points
*/
if (args.length > 4 && args[4].equalsIgnoreCase("-reallocate")) {
int points = 0;
for (PlayerAttributes.AttributeInstance ins : data.getAttributes().getInstances()) {
points += ins.getBase();
ins.setBase(0);
}
data.giveAttributePoints(points);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s attribute points spendings were successfully reset.");
return CommandResult.SUCCESS;
}
data.getAttributes().getInstances().forEach(ins -> ins.setBase(0));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s attributes were succesfully reset.");
return CommandResult.SUCCESS;
}
}
public static class ResetLevelsCommandTreeNode extends CommandTreeNode {
public ResetLevelsCommandTreeNode(CommandTreeNode parent) {
super(parent, "levels");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get(player);
data.setLevel(MMOCore.plugin.dataProvider.getDataManager().getDefaultData().getLevel());
data.setExperience(0);
for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
data.getCollectionSkills().setExperience(profession, 0);
data.getCollectionSkills().setLevel(profession, 0);
profession.getExperienceTable().reset(data, profession);
}
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET,
ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s levels were succesfully reset.");
ResetClassesCommandTreeNode.resetClasses(data);
ResetLevelsCommandTreeNode.resetLevels(data);
ResetSkillsCommandTreeNode.resetSkills(data);
ResetQuestsCommandTreeNode.resetQuests(data);
ResetAttributesCommandTreeNode.resetAttributes(data, givePoints);
ResetWaypointsCommandTreeNode.resetWaypoints(data);
ResetSkillTreesCommandTreeNode.resetSkillTrees(data);
// Reset times-claimed not being properly emptied otherwise
data.getItemClaims().clear();
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s data was successfully reset.");
return CommandResult.SUCCESS;
}
}
}
class ResetWaypointsCommandTreeNode extends CommandTreeNode {
public ResetWaypointsCommandTreeNode(CommandTreeNode parent) {
super(parent, "waypoints");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetWaypoints(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s waypoints were successfully reset.");
return CommandResult.SUCCESS;
}
static void resetWaypoints(@NotNull PlayerData playerData) {
playerData.getWaypoints().clear();
}
}
class ResetQuestsCommandTreeNode extends CommandTreeNode {
public ResetQuestsCommandTreeNode(CommandTreeNode parent) {
super(parent, "quests");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetQuests(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s quests were successfully reset.");
return CommandResult.SUCCESS;
}
static void resetQuests(@NotNull PlayerData data) {
data.getQuestData().resetFinishedQuests();
data.getQuestData().start(null);
}
}
class ResetSkillsCommandTreeNode extends CommandTreeNode {
public ResetSkillsCommandTreeNode(CommandTreeNode parent) {
super(parent, "skills");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetSkills(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill data was successfully reset.");
return CommandResult.SUCCESS;
}
static void resetSkills(@NotNull PlayerData data) {
data.mapSkillLevels().forEach((skill, ignored) -> data.resetSkillLevel(skill));
while (data.hasSkillBound(0)) data.unbindSkill(0);
data.setUnlockedItems(new HashSet<>()); // TODO class-specific unlockables etc.
}
}
class ResetSkillTreesCommandTreeNode extends CommandTreeNode {
public ResetSkillTreesCommandTreeNode(CommandTreeNode parent) {
super(parent, "skill-trees");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetSkillTrees(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s skill-tree data was successfully reset.");
return CommandResult.SUCCESS;
}
// TODO option to reallocate skill tree points instead of not giving any back
static void resetSkillTrees(@NotNull PlayerData data) {
data.resetSkillTrees();
}
}
class ResetAttributesCommandTreeNode extends CommandTreeNode {
public ResetAttributesCommandTreeNode(CommandTreeNode parent) {
super(parent, "attributes");
addParameter(Parameter.PLAYER);
addParameter(new Parameter("(-reallocate)", (explore, list) -> list.add("-reallocate")));
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
final boolean givePoints = args.length > 4 && args[4].equalsIgnoreCase("-reallocate");
resetAttributes(PlayerData.get(player), givePoints);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s attributes were successfully reset.");
return CommandResult.SUCCESS;
}
static void resetAttributes(@NotNull PlayerData data, boolean givePoints) {
// Give back attribute points
if (givePoints) {
int points = 0;
for (PlayerAttributes.AttributeInstance ins : data.getAttributes().getInstances()) {
points += ins.getBase();
ins.setBase(0);
}
data.giveAttributePoints(points);
return;
}
for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll()) {
attribute.resetAdvancement(data, true);
data.getAttributes().getInstance(attribute).setBase(0);
}
}
}
class ResetLevelsCommandTreeNode extends CommandTreeNode {
public ResetLevelsCommandTreeNode(CommandTreeNode parent) {
super(parent, "levels");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetLevels(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s levels were successfully reset.");
return CommandResult.SUCCESS;
}
static void resetLevels(@NotNull PlayerData data) {
// Class
data.setLevel(MMOCore.plugin.playerDataManager.getDefaultData().getLevel());
data.setExperience(0);
data.getProfess().resetAdvancement(data, true);
// Professions
for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
data.getCollectionSkills().setExperience(profession, 0);
data.getCollectionSkills().setLevel(profession, 0);
profession.resetAdvancement(data, true);
}
}
}
class ResetClassesCommandTreeNode extends CommandTreeNode {
public ResetClassesCommandTreeNode(CommandTreeNode parent) {
super(parent, "classes");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 4) return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
resetClasses(PlayerData.get(player));
CommandVerbose.verbose(sender, CommandVerbose.CommandType.RESET, ChatColor.GOLD + player.getName() + ChatColor.YELLOW + "'s classes were successfully reset.");
return CommandResult.SUCCESS;
}
static void resetClasses(@NotNull PlayerData data) {
MMOCore.plugin.classManager.getAll().forEach(data::unloadClassInfo);
MMOCore.plugin.playerDataManager.getDefaultData().apply(data);
data.setClass(MMOCore.plugin.classManager.getDefaultClass());
}
}

View File

@ -5,7 +5,7 @@ import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.trigger.ManaTrigger;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;

View File

@ -0,0 +1,37 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* Saves player data
*/
public class SaveDataTreeNode extends CommandTreeNode {
public SaveDataTreeNode(CommandTreeNode parent) {
super(parent, "savedata");
addParameter(Parameter.PLAYER);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[2]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[2] + ".");
return CommandResult.FAILURE;
}
MMOCore.plugin.playerDataManager.getDataHandler().saveData(PlayerData.get(player), false);
return CommandResult.SUCCESS;
}
}

View File

@ -5,7 +5,7 @@ import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.skill.ClassSkill;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -19,19 +19,21 @@ public class SkillCommandTreeNode extends CommandTreeNode {
public SkillCommandTreeNode(CommandTreeNode parent) {
super(parent, "skill");
addChild(new ActionCommandTreeNode(this, "give", (old, amount) -> old + amount));
addChild(new ActionCommandTreeNode(this, "set", (old, amount) -> amount));
addChild(new LockSkillCommandTreeNode(this, "lock", true));
addChild(new LockSkillCommandTreeNode(this, "unlock", false));
addChild(new LevelCommandTreeNode(this, "give", (old, amount) -> old + amount));
addChild(new LevelCommandTreeNode(this, "set", (old, amount) -> amount));
}
public class ActionCommandTreeNode extends CommandTreeNode {
public class LevelCommandTreeNode extends CommandTreeNode {
private final BiFunction<Integer, Integer, Integer> change;
public ActionCommandTreeNode(CommandTreeNode parent, String type, BiFunction<Integer, Integer, Integer> change) {
public LevelCommandTreeNode(CommandTreeNode parent, String type, BiFunction<Integer, Integer, Integer> change) {
super(parent, type);
this.change = change;
addParameter(Parameter.PLAYER);
addParameter(new Parameter("<attribute>",
addParameter(new Parameter("<skill>",
(explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
addParameter(Parameter.AMOUNT);
}
@ -55,19 +57,17 @@ public class SkillCommandTreeNode extends CommandTreeNode {
}
ClassSkill classSkill=null;
for(ClassSkill var:playerData.getProfess().getSkills()) {
if(var.getSkill().equals(skill))
classSkill=var;
ClassSkill classSkill = null;
for (ClassSkill var : playerData.getProfess().getSkills()) {
if (var.getSkill().equals(skill))
classSkill = var;
}
if(classSkill==null||classSkill.getUnlockLevel() > playerData.getLevel()) {
sender.sendMessage(ChatColor.RED+ skill.getName()+" is not unlockable for "+player.getName()+".");
if (classSkill == null || classSkill.getUnlockLevel() > playerData.getLevel()) {
sender.sendMessage(ChatColor.RED + skill.getName() + " is not unlockable for " + player.getName() + ".");
return CommandResult.FAILURE;
}
int amount;
try {
amount = Integer.parseInt(args[5]);
@ -77,12 +77,59 @@ public class SkillCommandTreeNode extends CommandTreeNode {
}
int value = change.apply(playerData.getSkillLevel(skill), amount);
playerData.setSkillLevel(skill, value);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.GOLD + player.getName() + ChatColor.YELLOW
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + player.getName() + ChatColor.YELLOW
+ " is now level " + ChatColor.GOLD + value + ChatColor.YELLOW + " for " + skill.getName() + ".");
return CommandResult.SUCCESS;
}
}
public class LockSkillCommandTreeNode extends CommandTreeNode {
private final boolean lock;
public LockSkillCommandTreeNode(CommandTreeNode parent, String id, boolean lock) {
super(parent, id);
this.lock = lock;
addParameter(Parameter.PLAYER);
addParameter(new Parameter("<skill>",
(explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 5)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData playerData = PlayerData.get(player);
ClassSkill skill = playerData.getProfess().getSkill(args[4]);
if (skill == null) {
sender.sendMessage(ChatColor.RED + "Class doesn't have a skill called " + args[4] + ".");
return CommandResult.FAILURE;
}
if (lock) {
if (!playerData.hasUnlocked(skill)) {
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already locked for " + player.getName());
return CommandResult.SUCCESS;
}
playerData.lock(skill);
} else {
if (playerData.hasUnlocked(skill)) {
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "Skill " + skill.getSkill().getName() + " already unlocked for " + player.getName());
return CommandResult.SUCCESS;
}
playerData.unlock(skill);
}
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getName() + ChatColor.YELLOW + " now " + (lock ? "locked" : "unlocked") + " for " + ChatColor.GOLD + player.getName());
return CommandResult.SUCCESS;
}
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
return CommandResult.THROW_USAGE;

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.util.TriConsumer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;

View File

@ -0,0 +1,159 @@
package net.Indyuce.mmocore.command.rpg.admin;
import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.skill.binding.BoundSkillInfo;
import net.Indyuce.mmocore.skill.binding.SkillSlot;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.skill.ClassSkill;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class SlotCommandTreeNode extends CommandTreeNode {
public SlotCommandTreeNode(CommandTreeNode parent) {
super(parent, "slot");
addChild(new LockSlotCommandTreeNode(this, "lock", true));
addChild(new LockSlotCommandTreeNode(this, "unlock", false));
addChild(new UnbindSlotCommandTreeNode(this, "unbind"));
addChild(new BindSlotCommandTreeNode(this, "bind"));
}
public class LockSlotCommandTreeNode extends CommandTreeNode {
private final boolean lock;
public LockSlotCommandTreeNode(CommandTreeNode parent, String id, boolean lock) {
super(parent, id);
this.lock = lock;
addParameter(Parameter.PLAYER);
addParameter(Parameter.AMOUNT);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 5)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData playerData = PlayerData.get(player);
int slot;
try {
slot = Integer.parseInt(args[4]);
} catch (NumberFormatException e) {
sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
return CommandResult.FAILURE;
}
if (slot <= 0) {
sender.sendMessage(ChatColor.RED + "The slot can't be negative.");
return CommandResult.FAILURE;
}
SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot);
if (skillSlot.isUnlockedByDefault()) {
sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default.");
return CommandResult.FAILURE;
}
if (lock) {
if (!playerData.hasUnlocked(skillSlot)) {
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill slot " + skillSlot.getName() + " is already locked" + " for " + player.getName());
return CommandResult.SUCCESS;
}
playerData.lock(skillSlot);
} else {
if (playerData.hasUnlocked(skillSlot)) {
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill slot " + skillSlot.getName() + " is already unlocked" + " for " + player.getName());
return CommandResult.SUCCESS;
}
playerData.unlock(skillSlot);
}
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "The skill slot " + skillSlot.getName() + " is now " + (lock ? "locked" : "unlocked" + " for " + player.getName()));
return CommandResult.SUCCESS;
}
}
public class BindSlotCommandTreeNode extends CommandTreeNode {
public BindSlotCommandTreeNode(CommandTreeNode parent, String id) {
super(parent, id);
addParameter(Parameter.PLAYER);
addParameter(Parameter.AMOUNT);
addParameter(new Parameter("<skill>",
(explorer, list) -> MMOCore.plugin.skillManager.getAll().forEach(skill -> list.add(skill.getHandler().getId().toUpperCase()))));
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 6)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData playerData = PlayerData.get(player);
int slot;
try {
slot = Integer.parseInt(args[4]);
} catch (NumberFormatException e) {
sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
return CommandResult.FAILURE;
}
ClassSkill skill = playerData.getProfess().getSkill(args[5]);
if (skill == null) {
sender.sendMessage(ChatColor.RED + "The player's class doesn't have a skill called " + args[5] + ".");
return CommandResult.FAILURE;
}
playerData.bindSkill(slot, skill);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + "Skill " + ChatColor.GOLD + skill.getSkill().getHandler().getId() + ChatColor.YELLOW + " now bound to slot " + ChatColor.GOLD + slot);
return CommandResult.SUCCESS;
}
}
public class UnbindSlotCommandTreeNode extends CommandTreeNode {
public UnbindSlotCommandTreeNode(CommandTreeNode parent, String id) {
super(parent, id);
addParameter(Parameter.PLAYER);
addParameter(Parameter.AMOUNT);
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 5)
return CommandResult.THROW_USAGE;
Player player = Bukkit.getPlayer(args[3]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find the player called " + args[3] + ".");
return CommandResult.FAILURE;
}
PlayerData playerData = PlayerData.get(player);
int slot;
try {
slot = Integer.parseInt(args[4]);
} catch (NumberFormatException e) {
sender.sendMessage(ChatColor.RED + args[4] + " is not a valid number.");
return CommandResult.FAILURE;
}
final BoundSkillInfo found = playerData.unbindSkill(slot);
CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.YELLOW + (found != null ?
"Skill " + ChatColor.GOLD + found.getClassSkill().getSkill().getName() + ChatColor.YELLOW + " was taken off the slot " + ChatColor.GOLD + slot :
"Could not find skill at slot " + ChatColor.GOLD + slot));
return CommandResult.SUCCESS;
}
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
return CommandResult.THROW_USAGE;
}
}

View File

@ -49,7 +49,7 @@ public class CreateCommandTreeNode extends CommandTreeNode {
if (args[2].equalsIgnoreCase("main")) {
MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, extra, length));
new ConfigMessage("booster-main").addPlaceholders("multiplier", "" + (1 + extra)).send(Bukkit.getOnlinePlayers());
ConfigMessage.fromKey("booster-main").addPlaceholders("multiplier", "" + (1 + extra)).send(Bukkit.getOnlinePlayers());
Bukkit.getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1));
return CommandResult.SUCCESS;
}
@ -62,7 +62,7 @@ public class CreateCommandTreeNode extends CommandTreeNode {
Profession profession = MMOCore.plugin.professionManager.get(format);
MMOCore.plugin.boosterManager.register(new Booster(args.length > 5 ? args[5] : null, profession, extra, length));
new ConfigMessage("booster-skill").addPlaceholders("multiplier", "" + (1 + extra), "profession", profession.getName())
ConfigMessage.fromKey("booster-skill").addPlaceholders("multiplier", "" + (1 + extra), "profession", profession.getName())
.send(Bukkit.getOnlinePlayers());
Bukkit.getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1));
return CommandResult.SUCCESS;

View File

@ -12,30 +12,30 @@ import org.bukkit.entity.Player;
public class StatModifiersCommandTreeNode extends CommandTreeNode {
public StatModifiersCommandTreeNode(CommandTreeNode parent) {
super(parent, "statmods");
public StatModifiersCommandTreeNode(CommandTreeNode parent) {
super(parent, "statmods");
addParameter(new Parameter("<stat>", (explorer, list) -> list.add("STAT_ID")));
}
}
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
@Override
public CommandResult execute(CommandSender sender, String[] args) {
if (args.length < 3)
return CommandResult.THROW_USAGE;
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by a player.");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get((Player) sender);
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "This command can only be used by a player.");
return CommandResult.FAILURE;
}
PlayerData data = PlayerData.get((Player) sender);
StatInstance instance = data.getMMOPlayerData().getStatMap().getInstance(UtilityMethods.enumName(args[2]));
sender.sendMessage("Stat Modifiers (" + instance.getKeys().size() + "):");
for (String key : instance.getKeys()) {
StatModifier mod = instance.getModifier(key);
sender.sendMessage("- " + key + ": " + mod.getValue() + " " + mod.getType().name());
}
StatInstance instance = data.getMMOPlayerData().getStatMap().getInstance(UtilityMethods.enumName(args[2]));
sender.sendMessage("Stat Modifiers (" + instance.getKeys().size() + "):");
for (String key : instance.getKeys()) {
StatModifier mod = instance.getModifier(key);
sender.sendMessage("-> '" + key + "' " + mod.getValue() + " " + mod.getType().name() + " " + mod.getSlot() + " " + mod.getSource());
}
return CommandResult.SUCCESS;
}
return CommandResult.SUCCESS;
}
}

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.lib.command.api.CommandTreeNode;
import io.lumine.mythic.lib.command.api.Parameter;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.api.CommandVerbose;
import net.Indyuce.mmocore.waypoint.Waypoint;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.api.adapters.AbstractItemStack;
import io.lumine.mythic.api.config.MythicLineConfig;
import io.lumine.mythic.api.drops.DropMetadata;
import io.lumine.mythic.api.drops.IItemDrop;
import io.lumine.mythic.bukkit.adapters.BukkitItemStack;
import io.lumine.mythic.bukkit.BukkitAdapter;
import io.lumine.mythic.core.drops.Drop;
import net.Indyuce.mmocore.util.item.CurrencyItemBuilder;
@ -27,7 +27,8 @@ public class CurrencyItemDrop extends Drop implements IItemDrop {
@Override
public AbstractItemStack getDrop(DropMetadata dropMetadata, double v) {
return new BukkitItemStack(new CurrencyItemBuilder(key, random(minw, maxw)).build());
// Not great wrt to performance. Should build the item like MM does
return BukkitAdapter.adapt(new CurrencyItemBuilder(key, random(minw, maxw)).build());
}
private int random(int a, int b) {

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.api.adapters.AbstractItemStack;
import io.lumine.mythic.api.config.MythicLineConfig;
import io.lumine.mythic.api.drops.DropMetadata;
import io.lumine.mythic.api.drops.IItemDrop;
import io.lumine.mythic.bukkit.adapters.BukkitItemStack;
import io.lumine.mythic.bukkit.BukkitAdapter;
import io.lumine.mythic.core.drops.Drop;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
@ -49,7 +49,8 @@ public class GoldPouchDrop extends Drop implements IItemDrop {
}
nbt.addTag(new ItemTag("RpgPouchSize", 18), new ItemTag("RpgPouchMob", true), new ItemTag("RpgPouchInventory", MMOCoreUtils.toBase64(content)));
return new BukkitItemStack(nbt.toItem());
// Not great wrt to performance. Should build the item like MM does
return BukkitAdapter.adapt(nbt.toItem());
}
private ItemStack setAmount(ItemStack item, int amount) {

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.comp.placeholder;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import org.bukkit.OfflinePlayer;
import io.lumine.mythic.lib.MythicLib;
@ -7,7 +8,9 @@ import io.lumine.mythic.lib.MythicLib;
public class DefaultParser implements PlaceholderParser {
@Override
@BackwardsCompatibility(version = "1.12-SNAPSHOT")
public String parse(OfflinePlayer player, String string) {
// TODO remove use of confusing non-PAPI %player% placeholder
return MythicLib.plugin.parseColors(string.replace("%player%", player.getName()));
}
}

View File

@ -1,234 +1,316 @@
package net.Indyuce.mmocore.comp.placeholder;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.util.AltChar;
import io.lumine.mythic.lib.manager.StatManager;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.api.quest.PlayerQuests;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.party.AbstractParty;
import net.Indyuce.mmocore.skill.CastableSkill;
import net.Indyuce.mmocore.skill.ClassSkill;
import net.Indyuce.mmocore.skill.RegisteredSkill;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.util.Objects;
import java.util.UUID;
public class RPGPlaceholders extends PlaceholderExpansion {
@Override
public boolean persist() {
return true;
}
@Override
public boolean persist() {
return true;
}
@Override
public boolean canRegister() {
return true;
}
@Override
public boolean canRegister() {
return true;
}
@Override
public String getAuthor() {
return "Indyuce";
}
@Override
public String getAuthor() {
return "Indyuce";
}
@Override
public String getIdentifier() {
return "mmocore";
}
@Override
public String getIdentifier() {
return "mmocore";
}
@Override
public String getVersion() {
return MMOCore.plugin.getDescription().getVersion();
}
@Override
public String getVersion() {
return MMOCore.plugin.getDescription().getVersion();
}
@SuppressWarnings("DuplicateExpressions")
@Override
public String onRequest(OfflinePlayer player, String identifier) {
if (!PlayerData.has(player.getUniqueId()))
return null;
private static final String ERROR_PLACEHOLDER = " ";
PlayerData playerData = PlayerData.get(player);
if (identifier.equals("mana_icon"))
return playerData.getProfess().getManaDisplay().getIcon();
if (identifier.equals("mana_name"))
return playerData.getProfess().getManaDisplay().getName();
@SuppressWarnings("DuplicateExpressions")
@Override
public String onRequest(OfflinePlayer player, String identifier) {
if (!PlayerData.has(player.getUniqueId()))
return null;
final PlayerData playerData = PlayerData.get(player);
if (identifier.equals("level"))
return "" + playerData.getLevel();
if (identifier.equals("mana_icon"))
return playerData.getProfess().getManaDisplay().getIcon();
else if (identifier.startsWith("skill_level_")) {
String id = identifier.substring(12);
RegisteredSkill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.getSkill(id), "Could not find skill with ID '" + id + "'");
return String.valueOf(playerData.getSkillLevel(skill));
}
if (identifier.equals("mana_name"))
return playerData.getProfess().getManaDisplay().getName();
else if (identifier.equals("level_percent")) {
double current = playerData.getExperience(), next = playerData.getLevelUpExperience();
return MythicLib.plugin.getMMOConfig().decimal.format(current / next * 100);
}
if (identifier.equals("level"))
return String.valueOf(playerData.getLevel());
else if (identifier.equals("health"))
return StatManager.format("MAX_HEALTH", player.getPlayer().getHealth());
else if (identifier.startsWith("skill_level_")) {
String id = identifier.substring(12);
RegisteredSkill skill = MMOCore.plugin.skillManager.getSkillOrThrow(id);
return String.valueOf(playerData.getSkillLevel(skill));
}
else if (identifier.equals("max_health"))
return StatManager.format("MAX_HEALTH", player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
/*
* Given a skill slot number (integer) and a parameter name,
* return the player's value of that skill parameter from that
* specific skill slot.
*/
else if (identifier.startsWith("bound_skill_parameter_")) {
final String[] ids = identifier.substring(22).split(":");
final String parameterId = ids[0];
final int skillSlot = Integer.parseInt(ids[1]);
final ClassSkill found = playerData.getBoundSkill(skillSlot);
if (found == null) return "";
final CastableSkill castable = found.toCastable(playerData);
final double value = playerData.getMMOPlayerData().getSkillModifierMap().calculateValue(castable, parameterId);
return MythicLib.plugin.getMMOConfig().decimal.format(value);
}
else if (identifier.equals("health_bar") && player.isOnline()) {
StringBuilder format = new StringBuilder();
double ratio = 20 * player.getPlayer().getHealth() / player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? ChatColor.RED : ratio >= j - .5 ? ChatColor.DARK_RED : ChatColor.DARK_GRAY).append(AltChar.listSquare);
return format.toString();
}
// Returns a player's value of a skill parameter.
else if (identifier.startsWith("skill_modifier_") || identifier.startsWith("skill_parameter_")) {
final String[] ids = identifier.substring(identifier.startsWith("skill_modifier_") ? 15 : 16).split(":");
final String parameterId = ids[0];
final String skillId = ids[1];
final RegisteredSkill skill = Objects.requireNonNull(MMOCore.plugin.skillManager.getSkill(skillId), "Could not find skill with ID '" + skillId + "'");
final CastableSkill castable = playerData.getProfess().getSkill(skill).toCastable(playerData);
final double value = playerData.getMMOPlayerData().getSkillModifierMap().calculateValue(castable, parameterId);
return MythicLib.plugin.getMMOConfig().decimal.format(value);
}
else if (identifier.equals("class"))
return playerData.getProfess().getName();
else if (identifier.startsWith("attribute_points_spent_")) {
final String attributeId = identifier.substring(23);
final PlayerAttributes.AttributeInstance attributeInstance = Objects.requireNonNull(playerData.getAttributes().getInstance(attributeId), "Could not find attribute with ID '" + attributeId + "'");
return String.valueOf(attributeInstance.getBase());
}
else if (identifier.startsWith("profession_percent_")) {
PlayerProfessions professions = playerData.getCollectionSkills();
String name = identifier.substring(19).replace(" ", "-").replace("_", "-").toLowerCase();
Profession profession = MMOCore.plugin.professionManager.get(name);
double current = professions.getExperience(profession), next = professions.getLevelUpExperience(profession);
return MythicLib.plugin.getMMOConfig().decimal.format(current / next * 100);
}
else if (identifier.equals("level_percent")) {
double current = playerData.getExperience(), next = playerData.getLevelUpExperience();
return MythicLib.plugin.getMMOConfig().decimal.format(current / next * 100);
}
else if (identifier.startsWith("is_casting")) {
return String.valueOf(playerData.isCasting());
} else if (identifier.startsWith("in_combat")) {
return String.valueOf(playerData.isInCombat());
}
else if (identifier.equals("health"))
return StatManager.format("MAX_HEALTH", player.getPlayer().getHealth());
else if (identifier.startsWith("bound_")) {
int slot = Math.max(0, Integer.parseInt(identifier.substring(6)) - 1);
return playerData.hasSkillBound(slot) ? playerData.getBoundSkill(slot).getSkill().getName()
: MMOCore.plugin.configManager.noSkillBoundPlaceholder;
}
else if (identifier.equals("max_health"))
return StatManager.format("MAX_HEALTH", player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
else if (identifier.startsWith("profession_experience_"))
return MythicLib.plugin.getMMOConfig().decimal.format(
playerData.getCollectionSkills().getExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
else if (identifier.equals("health_bar") && player.isOnline()) {
StringBuilder format = new StringBuilder();
double ratio = 20 * player.getPlayer().getHealth() / player.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? ChatColor.RED : ratio >= j - .5 ? ChatColor.DARK_RED : ChatColor.DARK_GRAY).append(AltChar.listSquare);
return format.toString();
} else if (identifier.equals("class"))
return playerData.getProfess().getName();
else if (identifier.startsWith("profession_next_level_"))
return "" + PlayerData.get(player).getCollectionSkills()
.getLevelUpExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase());
else if (identifier.startsWith("profession_percent_")) {
PlayerProfessions professions = playerData.getCollectionSkills();
String name = identifier.substring(19).replace(" ", "-").replace("_", "-").toLowerCase();
Profession profession = MMOCore.plugin.professionManager.get(name);
double current = professions.getExperience(profession), next = professions.getLevelUpExperience(profession);
return MythicLib.plugin.getMMOConfig().decimal.format(current / next * 100);
else if (identifier.startsWith("party_count")) {
AbstractParty party = playerData.getParty();
return party == null ? "0" : String.valueOf(party.countMembers());
}
} else if (identifier.equals("is_casting"))
return String.valueOf(playerData.isCasting());
else if (identifier.startsWith("profession_"))
return String
.valueOf(playerData.getCollectionSkills().getLevel(identifier.substring(11).replace(" ", "-").replace("_", "-").toLowerCase()));
else if (identifier.equals("in_combat"))
return String.valueOf(playerData.isInCombat());
else if (identifier.equals("experience"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getExperience());
else if (identifier.equals("pvp_mode"))
return String.valueOf(playerData.getCombat().isInPvpMode());
else if (identifier.equals("next_level"))
return String.valueOf(playerData.getLevelUpExperience());
else if (identifier.startsWith("since_enter_combat"))
return playerData.isInCombat() ? MythicLib.plugin.getMMOConfig().decimal.format((System.currentTimeMillis() - playerData.getCombat().getLastEntry()) / 1000.) : "-1";
else if (identifier.equals("class_points"))
return String.valueOf(playerData.getClassPoints());
else if (identifier.startsWith("invulnerability_left"))
return MythicLib.plugin.getMMOConfig().decimal.format(Math.max(0, (playerData.getCombat().getInvulnerableTill() - System.currentTimeMillis()) / 1000.));
else if (identifier.equals("skill_points"))
return String.valueOf(playerData.getSkillPoints());
else if (identifier.startsWith("since_last_hit"))
return playerData.isInCombat() ? MythicLib.plugin.getMMOConfig().decimal.format((System.currentTimeMillis() - playerData.getCombat().getLastHit()) / 1000.) : "-1";
else if (identifier.equals("attribute_points"))
return String.valueOf(playerData.getAttributePoints());
// Returns the bound skill ID
else if (identifier.startsWith("id_bound_")) {
final int slot = Math.max(1, Integer.parseInt(identifier.substring(9)));
final ClassSkill info = playerData.getBoundSkill(slot);
return info == null ? "" : info.getSkill().getHandler().getId();
}
else if (identifier.equals("attribute_reallocation_points"))
return String.valueOf(playerData.getAttributeReallocationPoints());
// Returns the casting slot taking into account the skill slot offset
else if (identifier.startsWith("cast_slot_offset_")) {
final Player online = player.getPlayer();
Validate.notNull(online, "Player is offline");
final int slot = Integer.parseInt(identifier.substring(17));
return String.valueOf(slot + (online.getInventory().getHeldItemSlot() < slot ? 1 : 0));
}
else if (identifier.startsWith("attribute_"))
return String.valueOf(playerData.getAttributes()
.getAttribute(MMOCore.plugin.attributeManager.get(identifier.substring(10).toLowerCase().replace("_", "-"))));
// Is there a passive skill bound to given slot
else if (identifier.startsWith("passive_bound_")) {
final int slot = Integer.parseInt(identifier.substring(14));
final ClassSkill skill = playerData.getBoundSkill(slot);
return String.valueOf(skill != null && skill.getSkill().getTrigger().isPassive());
}
else if (identifier.equals("mana"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getMana());
// Returns the bound skill name
else if (identifier.startsWith("bound_")) {
final int slot = Math.max(1, Integer.parseInt(identifier.substring(6)));
final ClassSkill skill = playerData.getBoundSkill(slot);
if (skill == null) return MMOCore.plugin.configManager.noSkillBoundPlaceholder;
return (playerData.getCooldownMap().isOnCooldown(skill) ? ChatColor.RED : ChatColor.GREEN) + skill.getSkill().getName();
}
else if (identifier.equals("mana_bar")) {
return playerData.getProfess().getManaDisplay().generateBar(playerData.getMana(), playerData.getStats().getStat("MAX_MANA"));
}
// Returns cooldown of skill bound at given slot
else if (identifier.startsWith("cooldown_bound_")) {
int slot = Math.max(0, Integer.parseInt(identifier.substring(15)));
if (playerData.hasSkillBound(slot))
return Double.toString(playerData.getCooldownMap().getCooldown(playerData.getBoundSkill(slot)));
else return MMOCore.plugin.configManager.noSkillBoundPlaceholder;
} else if (identifier.startsWith("profession_experience_"))
return MythicLib.plugin.getMMOConfig().decimal.format(
playerData.getCollectionSkills().getExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
else if (identifier.startsWith("exp_multiplier_")) {
String format = identifier.substring(15).toLowerCase().replace("_", "-").replace(" ", "-");
Profession profession = format.equals("main") ? null : MMOCore.plugin.professionManager.get(format);
return MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.boosterManager.getMultiplier(profession) * 100);
}
else if (identifier.startsWith("profession_next_level_"))
return String.valueOf(PlayerData.get(player).getCollectionSkills()
.getLevelUpExperience(identifier.substring(22).replace(" ", "-").replace("_", "-").toLowerCase()));
else if (identifier.startsWith("exp_boost_")) {
String format = identifier.substring(10).toLowerCase().replace("_", "-").replace(" ", "-");
Profession profession = format.equals("main") ? null : MMOCore.plugin.professionManager.get(format);
return MythicLib.plugin.getMMOConfig().decimal.format((MMOCore.plugin.boosterManager.getMultiplier(profession) - 1) * 100);
}
else if (identifier.startsWith("party_count")) {
final @Nullable AbstractParty party = playerData.getParty();
return party == null ? "0" : String.valueOf(party.countMembers());
} else if (identifier.startsWith("party_member_")) {
final int n = Integer.parseInt(identifier.substring(13)) - 1;
final @Nullable AbstractParty party = playerData.getParty();
if (party == null) return ERROR_PLACEHOLDER;
if (n >= party.countMembers()) return ERROR_PLACEHOLDER;
final @Nullable PlayerData member = party.getMember(n);
if (member == null) return ERROR_PLACEHOLDER;
return member.getPlayer().getName();
} else if (identifier.equals("online_friends")) {
int count = 0;
for (UUID friendId : playerData.getFriends())
if (Bukkit.getPlayer(friendId) != null) count++;
return String.valueOf(count);
} else if (identifier.startsWith("online_friend_")) {
final int n = Integer.parseInt(identifier.substring(14)) - 1;
if (n >= playerData.getFriends().size()) return ERROR_PLACEHOLDER;
final @Nullable Player friend = Bukkit.getPlayer(playerData.getFriends().get(n));
if (friend == null) return ERROR_PLACEHOLDER;
return friend.getName();
} else if (identifier.startsWith("profession_"))
return String
.valueOf(playerData.getCollectionSkills().getLevel(identifier.substring(11).replace(" ", "-").replace("_", "-").toLowerCase()));
else if (identifier.equals("stamina"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getStamina());
else if (identifier.equals("experience"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getExperience());
else if (identifier.equals("stamina_bar")) {
StringBuilder format = new StringBuilder();
double ratio = 20 * playerData.getStamina() / playerData.getStats().getStat("MAX_STAMINA");
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? MMOCore.plugin.configManager.staminaFull
: ratio >= j - .5 ? MMOCore.plugin.configManager.staminaHalf : MMOCore.plugin.configManager.staminaEmpty)
.append(AltChar.listSquare);
return format.toString();
}
else if (identifier.equals("next_level"))
return String.valueOf(playerData.getLevelUpExperience());
else if (identifier.startsWith("stat_")) {
final String stat = identifier.substring(5).toUpperCase();
return StatManager.format(identifier.substring(5), playerData.getStats().getStat(stat));
}
else if (identifier.equals("class_points"))
return String.valueOf(playerData.getClassPoints());
else if (identifier.equals("stellium"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getStellium());
else if (identifier.equals("skill_points"))
return String.valueOf(playerData.getSkillPoints());
else if (identifier.equals("stellium_bar")) {
StringBuilder format = new StringBuilder();
double ratio = 20 * playerData.getStellium() / playerData.getStats().getStat("MAX_STELLIUM");
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? ChatColor.BLUE : ratio >= j - .5 ? ChatColor.AQUA : ChatColor.WHITE).append(AltChar.listSquare);
return format.toString();
}
else if (identifier.equals("attribute_points"))
return String.valueOf(playerData.getAttributePoints());
else if (identifier.equals("quest")) {
PlayerQuests data = playerData.getQuestData();
return data.hasCurrent() ? data.getCurrent().getQuest().getName() : "None";
}
else if (identifier.equals("attribute_reallocation_points"))
return String.valueOf(playerData.getAttributeReallocationPoints());
else if (identifier.equals("quest_progress")) {
PlayerQuests data = playerData.getQuestData();
else if (identifier.startsWith("attribute_"))
return String.valueOf(playerData.getAttributes()
.getAttribute(MMOCore.plugin.attributeManager.get(identifier.substring(10).toLowerCase().replace("_", "-"))));
return data.hasCurrent() ? MythicLib.plugin.getMMOConfig().decimal
.format( (double) data.getCurrent().getObjectiveNumber() / data.getCurrent().getQuest().getObjectives().size() * 100L) : "0";
}
else if (identifier.equals("mana"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getMana());
else if (identifier.equals("quest_objective")) {
PlayerQuests data = playerData.getQuestData();
return data.hasCurrent() ? data.getCurrent().getFormattedLore() : "None";
}
else if (identifier.equals("mana_bar"))
return playerData.getProfess().getManaDisplay().generateBar(playerData.getMana(), playerData.getStats().getStat("MAX_MANA"));
else if (identifier.startsWith("guild_")) {
String placeholder = identifier.substring(6);
if (playerData.getGuild() == null)
return "";
else if (identifier.startsWith("exp_multiplier_")) {
String format = identifier.substring(15).toLowerCase().replace("_", "-").replace(" ", "-");
Profession profession = format.equals("main") ? null : MMOCore.plugin.professionManager.get(format);
return MythicLib.plugin.getMMOConfig().decimal.format(MMOCore.plugin.boosterManager.getMultiplier(profession) * 100);
} else if (identifier.startsWith("exp_boost_")) {
String format = identifier.substring(10).toLowerCase().replace("_", "-").replace(" ", "-");
Profession profession = format.equals("main") ? null : MMOCore.plugin.professionManager.get(format);
return MythicLib.plugin.getMMOConfig().decimal.format((MMOCore.plugin.boosterManager.getMultiplier(profession) - 1) * 100);
} else if (identifier.equals("stamina"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getStamina());
if (placeholder.equalsIgnoreCase("name"))
return playerData.getGuild().getName();
else if (placeholder.equalsIgnoreCase("tag"))
return playerData.getGuild().getTag();
else if (placeholder.equalsIgnoreCase("leader"))
return Bukkit.getOfflinePlayer(playerData.getGuild().getOwner()).getName();
else if (placeholder.equalsIgnoreCase("members"))
return String.valueOf(playerData.getGuild().countMembers());
else if (placeholder.equalsIgnoreCase("online_members"))
return String.valueOf(playerData.getGuild().countOnlineMembers());
}
else if (identifier.equals("stamina_bar")) {
StringBuilder format = new StringBuilder();
double ratio = 20 * playerData.getStamina() / playerData.getStats().getStat("MAX_STAMINA");
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? MMOCore.plugin.configManager.staminaFull
: ratio >= j - .5 ? MMOCore.plugin.configManager.staminaHalf : MMOCore.plugin.configManager.staminaEmpty)
.append(AltChar.listSquare);
return format.toString();
} else if (identifier.startsWith("stat_")) {
final String stat = UtilityMethods.enumName(identifier.substring(5));
return StatManager.format(stat, playerData.getMMOPlayerData());
} else if (identifier.equals("stellium"))
return MythicLib.plugin.getMMOConfig().decimal.format(playerData.getStellium());
return null;
}
else if (identifier.equals("stellium_bar")) {
StringBuilder format = new StringBuilder();
double ratio = 20 * playerData.getStellium() / playerData.getStats().getStat("MAX_STELLIUM");
for (double j = 1; j < 20; j++)
format.append(ratio >= j ? ChatColor.BLUE : ratio >= j - .5 ? ChatColor.AQUA : ChatColor.WHITE).append(AltChar.listSquare);
return format.toString();
} else if (identifier.equals("quest")) {
PlayerQuests data = playerData.getQuestData();
return data.hasCurrent() ? data.getCurrent().getQuest().getName() : "None";
} else if (identifier.equals("quest_progress")) {
PlayerQuests data = playerData.getQuestData();
return data.hasCurrent() ? MythicLib.plugin.getMMOConfig().decimal
.format((double) data.getCurrent().getObjectiveNumber() / data.getCurrent().getQuest().getObjectives().size() * 100L) : "0";
} else if (identifier.equals("quest_objective")) {
PlayerQuests data = playerData.getQuestData();
return data.hasCurrent() ? data.getCurrent().getFormattedLore() : "None";
} else if (identifier.startsWith("guild_")) {
String placeholder = identifier.substring(6);
if (playerData.getGuild() == null)
return "";
if (placeholder.equalsIgnoreCase("name"))
return playerData.getGuild().getName();
else if (placeholder.equalsIgnoreCase("tag"))
return playerData.getGuild().getTag();
else if (placeholder.equalsIgnoreCase("leader"))
return Bukkit.getOfflinePlayer(playerData.getGuild().getOwner()).getName();
else if (placeholder.equalsIgnoreCase("members"))
return String.valueOf(playerData.getGuild().countMembers());
else if (placeholder.equalsIgnoreCase("online_members"))
return String.valueOf(playerData.getGuild().countOnlineMembers());
}
return null;
}
}

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