2929import org .bukkit .command .ConsoleCommandSender ;
3030import org .bukkit .entity .Player ;
3131import org .bukkit .inventory .ItemStack ;
32+ import org .bukkit .inventory .PlayerInventory ;
3233import org .bukkit .inventory .ShapedRecipe ;
3334import org .bukkit .inventory .meta .ItemMeta ;
3435import org .bukkit .persistence .PersistentDataContainer ;
@@ -227,6 +228,29 @@ public void execute(@NonNull CommandSourceStack source, String @NonNull [] args)
227228 }
228229 return ;
229230 }
231+ case "add" : {
232+ if (!sender .hasPermission ("toolstats.add" )) {
233+ sender .sendMessage (Component .text ("You do not have permission for this command." , NamedTextColor .RED ));
234+ return ;
235+ }
236+ if (sender instanceof ConsoleCommandSender ) {
237+ sender .sendMessage (Component .text ("You must be a player for this command." , NamedTextColor .RED ));
238+ return ;
239+ }
240+ // Make sure /toolstats add <stat> is present
241+ if (args .length < 2 ) {
242+ sender .sendMessage (Component .text ("Invalid syntax. Usage: /toolstats add <stat>" , NamedTextColor .RED ));
243+ return ;
244+ }
245+ //Make sure they typed in a valid stat
246+ String stat = args [1 ];
247+ if (!toolStats .tokenData .getTokenTypes ().contains (stat )) {
248+ sender .sendMessage (Component .text ("That is not a valid stat." , NamedTextColor .RED ));
249+ return ;
250+ }
251+ addStat (stat , (Player ) sender );
252+ return ;
253+ }
230254 default : {
231255 sender .sendMessage (Component .text ("Invalid sub-command." , NamedTextColor .RED ));
232256 }
@@ -449,6 +473,169 @@ private void giveToken(Player target, String tokenType, int amount) {
449473 target .getInventory ().addItem (token );
450474 }
451475
476+ /**
477+ * Add a stat to an item, setting it to zero.
478+ * @param stat The stat to add.
479+ * @param player The player running the command.
480+ */
481+ private void addStat (String stat , Player player ) {
482+ PlayerInventory playerInventory = player .getInventory ();
483+ ItemStack heldItem = playerInventory .getItemInMainHand ();
484+ ItemMeta heldItemMeta = heldItem .getItemMeta ();
485+ if (heldItemMeta == null ) {
486+ return ;
487+ }
488+ if (toolStats .itemChecker .checkTokens (heldItemMeta .getPersistentDataContainer (), stat )) {
489+ player .sendMessage (Component .text ("This item already has this stat." , NamedTextColor .RED ));
490+ return ;
491+ }
492+
493+ if (stat .equalsIgnoreCase ("remove" ) || stat .equalsIgnoreCase ("reset" )) {
494+ player .sendMessage (Component .text ("That is not a valid stat." , NamedTextColor .RED ));
495+ return ;
496+ }
497+
498+ ItemStack newItem = toolStats .itemChecker .addToken (heldItem , stat );
499+ switch (stat ) {
500+ case "crops-mined" : {
501+ if (toolStats .config .getBoolean ("enabled.crops-harvested" )) {
502+ newItem .setItemMeta (toolStats .itemLore .updateCropsMined (newItem , 0 ));
503+ } else {
504+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
505+ return ;
506+ }
507+ break ;
508+ }
509+ case "blocks-mined" : {
510+ if (toolStats .configTools .checkConfig (newItem .getType (), "blocks-mined" )) {
511+ newItem .setItemMeta (toolStats .itemLore .updateBlocksMined (newItem , 0 ));
512+ } else {
513+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
514+ return ;
515+ }
516+ break ;
517+ }
518+ case "damage-taken" : {
519+ if (toolStats .config .getBoolean ("enabled.armor-damage" )) {
520+ newItem .setItemMeta (toolStats .itemLore .updateArmorDamage (newItem , 0.0 , false ));
521+ } else {
522+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
523+ return ;
524+ }
525+ break ;
526+ }
527+ case "damage-done" : {
528+ if (toolStats .configTools .checkConfig (newItem .getType (), "damage-done" )) {
529+ newItem .setItemMeta (toolStats .itemLore .updateWeaponDamage (newItem , 0.0 , false ));
530+ } else {
531+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
532+ return ;
533+ }
534+ break ;
535+ }
536+ case "mob-kills" : {
537+ if (toolStats .configTools .checkConfig (newItem .getType (), "mob-kills" )) {
538+ newItem .setItemMeta (toolStats .itemLore .updateMobKills (newItem , 0 ));
539+ } else {
540+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
541+ return ;
542+ }
543+ break ;
544+ }
545+ case "player-kills" : {
546+ if (toolStats .configTools .checkConfig (newItem .getType (), "player-kills" )) {
547+ newItem .setItemMeta (toolStats .itemLore .updatePlayerKills (newItem , 0 ));
548+ } else {
549+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
550+ return ;
551+ }
552+ break ;
553+ }
554+ case "arrows-shot" : {
555+ if (toolStats .config .getBoolean ("enabled.arrows-shot" )) {
556+ newItem .setItemMeta (toolStats .itemLore .updateArrowsShot (newItem , 0 ));
557+ } else {
558+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
559+ return ;
560+ }
561+ break ;
562+ }
563+ case "sheep-sheared" : {
564+ if (toolStats .config .getBoolean ("enabled.sheep-sheared" )) {
565+ newItem .setItemMeta (toolStats .itemLore .updateSheepSheared (newItem , 0 ));
566+ } else {
567+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
568+ return ;
569+ }
570+ break ;
571+ }
572+ case "flight-time" : {
573+ if (toolStats .config .getBoolean ("enabled.flight-time" )) {
574+ newItem .setItemMeta (toolStats .itemLore .updateFlightTime (newItem , 0 ));
575+ } else {
576+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
577+ return ;
578+ }
579+ break ;
580+ }
581+ case "fish-caught" : {
582+ if (toolStats .config .getBoolean ("enabled.fish-caught" )) {
583+ newItem .setItemMeta (toolStats .itemLore .updateFishCaught (newItem , 0 ));
584+ } else {
585+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
586+ return ;
587+ }
588+ break ;
589+ }
590+ case "wither-kills" : {
591+ if (toolStats .config .getBoolean ("enabled.bosses-killed.wither" )) {
592+ newItem .setItemMeta (toolStats .itemLore .updateBossesKilled (newItem , 0 , "wither" ));
593+ } else {
594+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
595+ return ;
596+ }
597+ break ;
598+ }
599+ case "enderdragon-kills" : {
600+ if (toolStats .config .getBoolean ("enabled.bosses-killed.enderdragon" )) {
601+ newItem .setItemMeta (toolStats .itemLore .updateBossesKilled (newItem , 0 , "enderdragon" ));
602+ } else {
603+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
604+ return ;
605+ }
606+ break ;
607+ }
608+ case "critical-strikes" : {
609+ if (toolStats .config .getBoolean ("enabled.critical-strikes" )) {
610+ newItem .setItemMeta (toolStats .itemLore .updateCriticalStrikes (newItem , 0 ));
611+ } else {
612+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
613+ return ;
614+ }
615+ break ;
616+ }
617+ case "trident-throws" : {
618+ if (toolStats .config .getBoolean ("enabled.trident-throws" )) {
619+ newItem .setItemMeta (toolStats .itemLore .updateTridentThrows (newItem , 0 ));
620+ } else {
621+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
622+ return ;
623+ }
624+ break ;
625+ }
626+ case "logs-stripped" : {
627+ if (toolStats .config .getBoolean ("enabled.logs-stripped" )) {
628+ newItem .setItemMeta (toolStats .itemLore .updateLogsStripped (newItem , 0 ));
629+ } else {
630+ player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
631+ return ;
632+ }
633+ break ;
634+ }
635+ }
636+ player .sendMessage (Component .text (stat + " has been added!" , NamedTextColor .GREEN ));
637+ }
638+
452639 /**
453640 * Handle edit subcommand.
454641 *
@@ -969,6 +1156,7 @@ private void handleRemove(String stat, Player player) {
9691156 editedItemMeta .lore (newLore );
9701157 } else {
9711158 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1159+ return ;
9721160 }
9731161 break ;
9741162 }
@@ -997,6 +1185,7 @@ private void handleRemove(String stat, Player player) {
9971185 editedItemMeta .lore (newLore );
9981186 } else {
9991187 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1188+ return ;
10001189 }
10011190 break ;
10021191 }
@@ -1025,6 +1214,7 @@ private void handleRemove(String stat, Player player) {
10251214 editedItemMeta .lore (newLore );
10261215 } else {
10271216 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1217+ return ;
10281218 }
10291219 break ;
10301220 }
@@ -1053,6 +1243,7 @@ private void handleRemove(String stat, Player player) {
10531243 editedItemMeta .lore (newLore );
10541244 } else {
10551245 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1246+ return ;
10561247 }
10571248 break ;
10581249 }
@@ -1081,6 +1272,7 @@ private void handleRemove(String stat, Player player) {
10811272 editedItemMeta .lore (newLore );
10821273 } else {
10831274 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1275+ return ;
10841276 }
10851277 break ;
10861278 }
@@ -1109,6 +1301,7 @@ private void handleRemove(String stat, Player player) {
11091301 editedItemMeta .lore (newLore );
11101302 } else {
11111303 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1304+ return ;
11121305 }
11131306 break ;
11141307 }
@@ -1137,6 +1330,7 @@ private void handleRemove(String stat, Player player) {
11371330 editedItemMeta .lore (newLore );
11381331 } else {
11391332 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1333+ return ;
11401334 }
11411335 break ;
11421336 }
@@ -1166,6 +1360,7 @@ private void handleRemove(String stat, Player player) {
11661360 editedItemMeta .lore (newLore );
11671361 } else {
11681362 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1363+ return ;
11691364 }
11701365 break ;
11711366 }
@@ -1194,6 +1389,7 @@ private void handleRemove(String stat, Player player) {
11941389 editedItemMeta .lore (newLore );
11951390 } else {
11961391 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1392+ return ;
11971393 }
11981394 break ;
11991395 }
@@ -1222,6 +1418,7 @@ private void handleRemove(String stat, Player player) {
12221418 editedItemMeta .lore (newLore );
12231419 } else {
12241420 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1421+ return ;
12251422 }
12261423 break ;
12271424 }
@@ -1250,6 +1447,7 @@ private void handleRemove(String stat, Player player) {
12501447 editedItemMeta .lore (newLore );
12511448 } else {
12521449 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1450+ return ;
12531451 }
12541452 break ;
12551453 }
@@ -1278,6 +1476,7 @@ private void handleRemove(String stat, Player player) {
12781476 editedItemMeta .lore (newLore );
12791477 } else {
12801478 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1479+ return ;
12811480 }
12821481 break ;
12831482 }
@@ -1306,6 +1505,7 @@ private void handleRemove(String stat, Player player) {
13061505 editedItemMeta .lore (newLore );
13071506 } else {
13081507 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1508+ return ;
13091509 }
13101510 break ;
13111511 }
@@ -1334,6 +1534,7 @@ private void handleRemove(String stat, Player player) {
13341534 editedItemMeta .lore (newLore );
13351535 } else {
13361536 player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1537+ return ;
13371538 }
13381539 break ;
13391540 }
@@ -1347,6 +1548,8 @@ private void handleRemove(String stat, Player player) {
13471548 player .sendMessage (Component .text ("Removed stat " + stat + " for held item!" , NamedTextColor .GREEN ));
13481549 }
13491550
1551+
1552+
13501553 @ Override
13511554 public @ NonNull Collection <String > suggest (@ NonNull CommandSourceStack source , String [] args ) {
13521555 CommandSender sender = source .getSender ();
@@ -1371,6 +1574,9 @@ private void handleRemove(String stat, Player player) {
13711574 if (sender .hasPermission ("toolstats.purge" )) {
13721575 suggestions .add ("purge" );
13731576 }
1577+ if (sender .hasPermission ("toolstats.add" )) {
1578+ suggestions .add ("add" );
1579+ }
13741580 return suggestions ;
13751581 }
13761582
@@ -1392,6 +1598,15 @@ private void handleRemove(String stat, Player player) {
13921598 .collect (Collectors .toList ());
13931599 }
13941600
1601+ // suggest keys for add
1602+ if (args .length == 2 && args [0 ].equalsIgnoreCase ("add" ) && sender .hasPermission ("toolstats.add" )) {
1603+ // yes I am lazy
1604+ return toolStats .tokenData .getTokenTypes ().stream ()
1605+ .filter (s -> !s .equals ("remove" ) && !s .equals ("reset" ))
1606+ .map (s -> s .equals ("crops-mined" ) ? "crops-harvested" : s )
1607+ .collect (Collectors .toList ());
1608+ }
1609+
13951610 // suggest keys for remove
13961611 if (args .length == 2 && args [0 ].equalsIgnoreCase ("remove" ) && sender .hasPermission ("toolstats.remove" )) {
13971612 // yes I am lazy
0 commit comments