2525
2626import com .lunarclient .apollo .example .ApolloExamplePlugin ;
2727import com .lunarclient .apollo .example .module .impl .CosmeticExample ;
28+ import com .lunarclient .apollo .example .nms .CommandCosmetic ;
2829import com .lunarclient .apollo .example .nms .PlayerNpc ;
30+ import com .lunarclient .apollo .example .util .CommandUtil ;
2931import java .util .ArrayList ;
32+ import java .util .Collections ;
33+ import java .util .HashMap ;
3034import java .util .List ;
35+ import java .util .Map ;
3136import java .util .Optional ;
3237import java .util .UUID ;
38+ import java .util .stream .Collectors ;
3339import org .bukkit .ChatColor ;
3440import org .bukkit .command .Command ;
3541import org .bukkit .command .CommandExecutor ;
@@ -82,21 +88,31 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
8288
8389 switch (args [0 ].toLowerCase ()) {
8490 case "equip" : {
91+ if (args .length >= 3 && this .isCosmeticType (args [2 ])) {
92+ this .handleTypedEquip (player , example , uuid , npcName , args );
93+ break ;
94+ }
95+
8596 List <Integer > cosmeticIds = this .parseCosmeticIds (args );
8697 example .equipNpcCosmeticsInternal (player , uuid , cosmeticIds );
98+ this .persistEquipped (uuid , cosmeticIds .stream ()
99+ .map (id -> CommandCosmetic .builder ().id (id ).build ())
100+ .collect (Collectors .toList ()));
87101 player .sendMessage (ChatColor .GREEN + "Equipped cosmetics " + cosmeticIds + " on NPC " + npcName );
88102 break ;
89103 }
90104
91105 case "unequip" : {
92106 List <Integer > cosmeticIds = this .parseCosmeticIds (args );
93107 example .unequipNpcCosmeticsInternal (player , uuid , cosmeticIds );
108+ this .persistUnequipped (uuid , cosmeticIds );
94109 player .sendMessage (ChatColor .GREEN + "Unequipped cosmetics " + cosmeticIds + " from NPC " + npcName );
95110 break ;
96111 }
97112
98113 case "reset" : {
99114 example .resetNpcCosmeticsExample (player , uuid );
115+ this .persistReset (uuid );
100116 player .sendMessage (ChatColor .GREEN + "Reset all cosmetics on NPC " + npcName );
101117 break ;
102118 }
@@ -170,6 +186,125 @@ private boolean handleSpray(Player player, CosmeticExample example, String[] arg
170186 return true ;
171187 }
172188
189+ private boolean isCosmeticType (String type ) {
190+ String lower = type .toLowerCase ();
191+ return "hat" .equals (lower ) || "cloak" .equals (lower ) || "pet" .equals (lower ) || "body" .equals (lower );
192+ }
193+
194+ private void handleTypedEquip (Player player , CosmeticExample example , UUID uuid , String npcName , String [] args ) {
195+ if (args .length < 4 ) {
196+ this .sendUsage (player );
197+ return ;
198+ }
199+
200+ int cosmeticId ;
201+ try {
202+ cosmeticId = Integer .parseInt (args [3 ]);
203+ } catch (NumberFormatException ex ) {
204+ player .sendMessage (ChatColor .RED + "Cosmetic id must be an integer." );
205+ return ;
206+ }
207+
208+ Map <String , String > options = this .parseOptions (args , 4 );
209+ String type = args [2 ].toLowerCase ();
210+
211+ CommandCosmetic .Options optionsSpec ;
212+ switch (type ) {
213+ case "hat" : {
214+ optionsSpec = CommandCosmetic .Hat .builder ()
215+ .showOverHelmet (CommandUtil .parseBoolean (options .get ("showoverhelmet" ), true ))
216+ .showOverSkinLayer (CommandUtil .parseBoolean (options .get ("showoverskinlayer" ), true ))
217+ .heightOffset (CommandUtil .parseFloat (options .get ("heightoffset" ), 0f ))
218+ .build ();
219+ break ;
220+ }
221+ case "cloak" : {
222+ optionsSpec = CommandCosmetic .Cloak .builder ()
223+ .useClothPhysics (CommandUtil .parseBoolean (options .get ("useclothphysics" ), false ))
224+ .build ();
225+ break ;
226+ }
227+ case "pet" : {
228+ optionsSpec = CommandCosmetic .Pet .builder ()
229+ .flipShoulder (CommandUtil .parseBoolean (options .get ("flipshoulder" ), false ))
230+ .build ();
231+ break ;
232+ }
233+ case "body" : {
234+ optionsSpec = CommandCosmetic .Body .builder ()
235+ .showOverChestplate (CommandUtil .parseBoolean (options .get ("showoverchestplate" ), true ))
236+ .showOverLeggings (CommandUtil .parseBoolean (options .get ("showoverleggings" ), true ))
237+ .showOverBoots (CommandUtil .parseBoolean (options .get ("showoverboots" ), true ))
238+ .build ();
239+ break ;
240+ }
241+ default : {
242+ this .sendUsage (player );
243+ return ;
244+ }
245+ }
246+
247+ CommandCosmetic spec = CommandCosmetic .builder ()
248+ .id (cosmeticId )
249+ .options (optionsSpec )
250+ .build ();
251+
252+ example .equipNpcCosmeticInternal (player , uuid , spec );
253+ this .persistEquipped (uuid , Collections .singletonList (spec ));
254+ player .sendMessage (ChatColor .GREEN + "Equipped " + type + " cosmetic " + cosmeticId + " on NPC " + npcName );
255+ }
256+
257+ private void persistEquipped (UUID npcUuid , List <CommandCosmetic > equipped ) {
258+ Optional <PlayerNpc > npcOpt = ApolloExamplePlugin .getInstance ().getNpcManager ().findByUuid (npcUuid );
259+ if (!npcOpt .isPresent ()) {
260+ return ;
261+ }
262+
263+ List <CommandCosmetic > cosmetics = npcOpt .get ().getCosmetics ();
264+ for (CommandCosmetic cosmetic : equipped ) {
265+ cosmetics .removeIf (existing -> existing .getId () == cosmetic .getId ());
266+ cosmetics .add (cosmetic );
267+ }
268+
269+ ApolloExamplePlugin .getInstance ().getNpcManager ().save ();
270+ }
271+
272+ private void persistUnequipped (UUID npcUuid , List <Integer > cosmeticIds ) {
273+ Optional <PlayerNpc > npcOpt = ApolloExamplePlugin .getInstance ().getNpcManager ().findByUuid (npcUuid );
274+ if (!npcOpt .isPresent ()) {
275+ return ;
276+ }
277+
278+ npcOpt .get ().getCosmetics ().removeIf (cosmetic -> cosmeticIds .contains (cosmetic .getId ()));
279+ ApolloExamplePlugin .getInstance ().getNpcManager ().save ();
280+ }
281+
282+ private void persistReset (UUID npcUuid ) {
283+ Optional <PlayerNpc > npcOpt = ApolloExamplePlugin .getInstance ().getNpcManager ().findByUuid (npcUuid );
284+ if (!npcOpt .isPresent ()) {
285+ return ;
286+ }
287+
288+ npcOpt .get ().getCosmetics ().clear ();
289+ ApolloExamplePlugin .getInstance ().getNpcManager ().save ();
290+ }
291+
292+ private Map <String , String > parseOptions (String [] args , int startIndex ) {
293+ Map <String , String > options = new HashMap <>();
294+ for (int i = startIndex ; i < args .length ; i ++) {
295+ String token = args [i ];
296+ int index = token .indexOf ('=' );
297+
298+ if (index <= 0 || index == token .length () - 1 ) {
299+ continue ;
300+ }
301+
302+ options .put (token .substring (0 , index ).toLowerCase (), token .substring (index + 1 ));
303+ }
304+
305+ return options ;
306+ }
307+
173308 private List <Integer > parseCosmeticIds (String [] args ) {
174309 List <Integer > ids = new ArrayList <>();
175310 for (int i = 2 ; i < args .length ; i ++) {
@@ -184,8 +319,26 @@ private List<Integer> parseCosmeticIds(String[] args) {
184319 private void sendUsage (Player player ) {
185320 player .sendMessage ("Usage:" );
186321 player .sendMessage (" - /cosmetic equip <npc_name> [cosmeticIds]" );
322+ player .sendMessage (ChatColor .ITALIC + " /cosmetic equip Apollo 434 3654 3977" );
323+ player .sendMessage ("" );
324+ player .sendMessage (" - /cosmetic equip <npc_name> hat <id>" );
325+ player .sendMessage (ChatColor .ITALIC + " /cosmetic equip Apollo hat 434 showOverHelmet=true showOverSkinLayer=true heightOffset=0.0" );
326+ player .sendMessage ("" );
327+ player .sendMessage (" - /cosmetic equip <npc_name> cloak <id>" );
328+ player .sendMessage (ChatColor .ITALIC + " /cosmetic equip Apollo cloak 3 useClothPhysics=true" );
329+ player .sendMessage ("" );
330+ player .sendMessage (" - /cosmetic equip <npc_name> pet <id>" );
331+ player .sendMessage (ChatColor .ITALIC + " /cosmetic equip Apollo pet 5095 flipShoulder=true" );
332+ player .sendMessage ("" );
333+ player .sendMessage (" - /cosmetic equip <npc_name> body <id>" );
334+ player .sendMessage (ChatColor .ITALIC + " /cosmetic equip Apollo body 3977 showOverChestplate=true showOverLeggings=true showOverBoots=true" );
335+ player .sendMessage ("" );
187336 player .sendMessage (" - /cosmetic unequip <npc_name> [cosmeticIds]" );
337+ player .sendMessage (ChatColor .ITALIC + " /cosmetic unequip Apollo 434 3654" );
338+ player .sendMessage ("" );
188339 player .sendMessage (" - /cosmetic reset <npc_name>" );
340+ player .sendMessage (ChatColor .ITALIC + " /cosmetic reset Apollo" );
341+ player .sendMessage ("" );
189342 this .sendSprayUsage (player );
190343 }
191344
0 commit comments