@@ -92,7 +92,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
9292 }
9393 // /toolstats edit stat value
9494 case "edit" : {
95- if (!sender .hasPermission ("toolstats.reset " )) {
95+ if (!sender .hasPermission ("toolstats.edit " )) {
9696 sender .sendMessage (Component .text ("You do not have permission for this command." , NamedTextColor .RED ));
9797 return true ;
9898 }
@@ -106,6 +106,23 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
106106 }
107107 handleEdit (args [1 ], args [2 ], (Player ) sender );
108108 return true ;
109+ }
110+ // /toolstats remove stat
111+ case "remove" : {
112+ if (!sender .hasPermission ("toolstats.remove" )) {
113+ sender .sendMessage (Component .text ("You do not have permission for this command." , NamedTextColor .RED ));
114+ return true ;
115+ }
116+ if (sender instanceof ConsoleCommandSender ) {
117+ sender .sendMessage (Component .text ("You must be a player for this command." , NamedTextColor .RED ));
118+ return true ;
119+ }
120+ if (args .length < 2 ) {
121+ sender .sendMessage (Component .text ("Invalid syntax. Usage: /toolstats remove <stat>" , NamedTextColor .RED ));
122+ return true ;
123+ }
124+ handleRemove (args [1 ], (Player ) sender );
125+ return true ;
109126
110127 }
111128 case "reset" : {
@@ -491,6 +508,13 @@ private void giveToken(Player target, String tokenType, int amount) {
491508 }
492509 }
493510
511+ /**
512+ * Handle edit subcommand.
513+ *
514+ * @param stat The stat to edit.
515+ * @param userValue The value the user entered.
516+ * @param player The player using the command.
517+ */
494518 private void handleEdit (String stat , Object userValue , Player player ) {
495519 ItemStack editedItem = player .getInventory ().getItemInMainHand ().clone ();
496520 if (!toolStats .itemChecker .isValidItem (editedItem .getType ())) {
@@ -500,7 +524,7 @@ private void handleEdit(String stat, Object userValue, Player player) {
500524 ItemMeta editedItemMeta = editedItem .getItemMeta ();
501525 PersistentDataContainer container = editedItemMeta .getPersistentDataContainer ();
502526 switch (stat ) {
503- case "crops-mined " : {
527+ case "crops-harvested " : {
504528 if (!toolStats .config .getBoolean ("enabled.crops-harvested" )) {
505529 player .sendMessage (Component .text ("This stat is disabled." , NamedTextColor .RED ));
506530 return ;
@@ -749,7 +773,7 @@ private void handleEdit(String stat, Object userValue, Player player) {
749773 player .sendMessage (Component .text ("Number must be positive." , NamedTextColor .RED ));
750774 return ;
751775 }
752- Long statValue = container .get (toolStats .arrowsShot , PersistentDataType .LONG );
776+ Long statValue = container .get (toolStats .flightTime , PersistentDataType .LONG );
753777 if (statValue == null ) {
754778 player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
755779 return ;
@@ -792,6 +816,284 @@ private void handleEdit(String stat, Object userValue, Player player) {
792816 }
793817 default : {
794818 player .sendMessage (Component .text ("That is not a valid stat to update." , NamedTextColor .RED ));
819+ return ;
820+ }
821+ }
822+ editedItem .setItemMeta (editedItemMeta );
823+ player .getInventory ().setItemInMainHand (editedItem );
824+ }
825+
826+ /**
827+ * Handle remove subcommand.
828+ *
829+ * @param stat The stat to remove.
830+ * @param player The player using the command.
831+ */
832+ private void handleRemove (String stat , Player player ) {
833+ ItemStack editedItem = player .getInventory ().getItemInMainHand ().clone ();
834+ if (!toolStats .itemChecker .isValidItem (editedItem .getType ())) {
835+ player .sendMessage (Component .text ("This is not a valid item." , NamedTextColor .RED ));
836+ return ;
837+ }
838+ ItemMeta editedItemMeta = editedItem .getItemMeta ();
839+ PersistentDataContainer container = editedItemMeta .getPersistentDataContainer ();
840+ switch (stat ) {
841+ case "crops-harvested" : {
842+ if (container .has (toolStats .cropsHarvested )) {
843+ Integer statValue = container .get (toolStats .cropsHarvested , PersistentDataType .INTEGER );
844+ if (statValue == null ) {
845+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
846+ return ;
847+ }
848+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
849+ if (tokens == null ) {
850+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
851+ return ;
852+ }
853+ container .remove (toolStats .cropsHarvested );
854+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "crops-mined" );
855+ if (newTokens .isEmpty ()) {
856+ container .remove (toolStats .tokenApplied );
857+ } else {
858+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
859+ }
860+
861+ Component oldLine = toolStats .configTools .formatLore ("crops-harvested" , "{crops}" , toolStats .numberFormat .formatInt (statValue ));
862+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
863+ editedItemMeta .lore (newLore );
864+ } else {
865+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
866+ }
867+ break ;
868+ }
869+ case "blocks-mined" : {
870+ if (container .has (toolStats .blocksMined )) {
871+ Integer statValue = container .get (toolStats .blocksMined , PersistentDataType .INTEGER );
872+ if (statValue == null ) {
873+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
874+ return ;
875+ }
876+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
877+ if (tokens == null ) {
878+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
879+ return ;
880+ }
881+ container .remove (toolStats .blocksMined );
882+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "blocks-mined" );
883+ if (newTokens .isEmpty ()) {
884+ container .remove (toolStats .tokenApplied );
885+ } else {
886+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
887+ }
888+
889+ Component oldLine = toolStats .configTools .formatLore ("blocks-mined" , "{blocks}" , toolStats .numberFormat .formatInt (statValue ));
890+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
891+ editedItemMeta .lore (newLore );
892+ } else {
893+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
894+ }
895+ break ;
896+ }
897+ case "damage-taken" : {
898+ if (container .has (toolStats .armorDamage )) {
899+ Double statValue = container .get (toolStats .armorDamage , PersistentDataType .DOUBLE );
900+ if (statValue == null ) {
901+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
902+ return ;
903+ }
904+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
905+ if (tokens == null ) {
906+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
907+ return ;
908+ }
909+ container .remove (toolStats .armorDamage );
910+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "damage-taken" );
911+ if (newTokens .isEmpty ()) {
912+ container .remove (toolStats .tokenApplied );
913+ } else {
914+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
915+ }
916+
917+ Component oldLine = toolStats .configTools .formatLore ("damage-taken" , "{damage}" , toolStats .numberFormat .formatDouble (statValue ));
918+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
919+ editedItemMeta .lore (newLore );
920+ } else {
921+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
922+ }
923+ break ;
924+ }
925+ case "damage-done" : {
926+ if (container .has (toolStats .damageDone )) {
927+ Double statValue = container .get (toolStats .damageDone , PersistentDataType .DOUBLE );
928+ if (statValue == null ) {
929+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
930+ return ;
931+ }
932+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
933+ if (tokens == null ) {
934+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
935+ return ;
936+ }
937+ container .remove (toolStats .damageDone );
938+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "damage-done" );
939+ if (newTokens .isEmpty ()) {
940+ container .remove (toolStats .tokenApplied );
941+ } else {
942+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
943+ }
944+
945+ Component oldLine = toolStats .configTools .formatLore ("damage-done" , "{damage}" , toolStats .numberFormat .formatDouble (statValue ));
946+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
947+ editedItemMeta .lore (newLore );
948+ } else {
949+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
950+ }
951+ break ;
952+ }
953+ case "mob-kills" : {
954+ if (container .has (toolStats .mobKills )) {
955+ Integer statValue = container .get (toolStats .mobKills , PersistentDataType .INTEGER );
956+ if (statValue == null ) {
957+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
958+ return ;
959+ }
960+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
961+ if (tokens == null ) {
962+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
963+ return ;
964+ }
965+ container .remove (toolStats .mobKills );
966+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "mob-kills" );
967+ if (newTokens .isEmpty ()) {
968+ container .remove (toolStats .tokenApplied );
969+ } else {
970+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
971+ }
972+
973+ Component oldLine = toolStats .configTools .formatLore ("kills.mob" , "{kills}" , toolStats .numberFormat .formatInt (statValue ));
974+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
975+ editedItemMeta .lore (newLore );
976+ } else {
977+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
978+ }
979+ break ;
980+ }
981+ case "player-kills" : {
982+ if (container .has (toolStats .playerKills )) {
983+ Integer statValue = container .get (toolStats .playerKills , PersistentDataType .INTEGER );
984+ if (statValue == null ) {
985+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
986+ return ;
987+ }
988+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
989+ if (tokens == null ) {
990+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
991+ return ;
992+ }
993+ container .remove (toolStats .playerKills );
994+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "player-kills" );
995+ if (newTokens .isEmpty ()) {
996+ container .remove (toolStats .tokenApplied );
997+ } else {
998+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
999+ }
1000+
1001+ Component oldLine = toolStats .configTools .formatLore ("kills.player" , "{kills}" , toolStats .numberFormat .formatInt (statValue ));
1002+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
1003+ editedItemMeta .lore (newLore );
1004+ } else {
1005+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1006+ }
1007+ break ;
1008+ }
1009+ case "sheep-sheared" : {
1010+ if (container .has (toolStats .sheepSheared )) {
1011+ Integer statValue = container .get (toolStats .sheepSheared , PersistentDataType .INTEGER );
1012+ if (statValue == null ) {
1013+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
1014+ return ;
1015+ }
1016+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
1017+ if (tokens == null ) {
1018+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
1019+ return ;
1020+ }
1021+ container .remove (toolStats .sheepSheared );
1022+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "sheep-sheared" );
1023+ if (newTokens .isEmpty ()) {
1024+ container .remove (toolStats .tokenApplied );
1025+ } else {
1026+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
1027+ }
1028+
1029+ Component oldLine = toolStats .configTools .formatLore ("sheep-sheared" , "{sheep}" , toolStats .numberFormat .formatInt (statValue ));
1030+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
1031+ editedItemMeta .lore (newLore );
1032+ } else {
1033+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1034+ }
1035+ break ;
1036+ }
1037+ case "flight-time" : {
1038+ if (container .has (toolStats .flightTime )) {
1039+ Long statValue = container .get (toolStats .flightTime , PersistentDataType .LONG );
1040+ if (statValue == null ) {
1041+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
1042+ return ;
1043+ }
1044+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
1045+ if (tokens == null ) {
1046+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
1047+ return ;
1048+ }
1049+ container .remove (toolStats .flightTime );
1050+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "flight-time" );
1051+ if (newTokens .isEmpty ()) {
1052+ container .remove (toolStats .tokenApplied );
1053+ } else {
1054+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
1055+ }
1056+
1057+ Map <String , String > timeFormatted = toolStats .numberFormat .formatTime (statValue );
1058+ Component oldLine = toolStats .configTools .formatLoreMultiplePlaceholders ("flight-time" , timeFormatted );
1059+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
1060+ editedItemMeta .lore (newLore );
1061+ } else {
1062+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1063+ }
1064+ break ;
1065+ }
1066+ case "fight-caught" : {
1067+ if (container .has (toolStats .fishCaught )) {
1068+ Integer statValue = container .get (toolStats .fishCaught , PersistentDataType .INTEGER );
1069+ if (statValue == null ) {
1070+ player .sendMessage (Component .text ("Unable to get stat from item." , NamedTextColor .RED ));
1071+ return ;
1072+ }
1073+ String tokens = container .get (toolStats .tokenApplied , PersistentDataType .STRING );
1074+ if (tokens == null ) {
1075+ player .sendMessage (Component .text ("Unable to get tokens from item." , NamedTextColor .RED ));
1076+ return ;
1077+ }
1078+ container .remove (toolStats .fishCaught );
1079+ List <String > newTokens = toolStats .itemChecker .removeToken (tokens , "fight-caught" );
1080+ if (newTokens .isEmpty ()) {
1081+ container .remove (toolStats .tokenApplied );
1082+ } else {
1083+ container .set (toolStats .tokenApplied , PersistentDataType .STRING , String .join ("," , newTokens ));
1084+ }
1085+
1086+ Component oldLine = toolStats .configTools .formatLore ("fished.fish-caught" , "{fish}" , toolStats .numberFormat .formatInt (statValue ));
1087+ List <Component > newLore = toolStats .itemLore .removeLore (editedItemMeta .lore (), oldLine );
1088+ editedItemMeta .lore (newLore );
1089+ } else {
1090+ player .sendMessage (Component .text ("This item does not have that stat." , NamedTextColor .RED ));
1091+ }
1092+ break ;
1093+ }
1094+ default : {
1095+ player .sendMessage (Component .text ("That is not a valid stat to update." , NamedTextColor .RED ));
1096+ return ;
7951097 }
7961098 }
7971099 editedItem .setItemMeta (editedItemMeta );
0 commit comments