PlayerCommands.java 24.1 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
package emu.grasscutter.commands;

KingRainbow44's avatar
KingRainbow44 committed
3
import emu.grasscutter.Grasscutter;
Melledy's avatar
Melledy committed
4
5
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.ItemData;
6
import emu.grasscutter.data.def.AvatarData;
7
import emu.grasscutter.data.def.AvatarSkillDepotData;
Melledy's avatar
Melledy committed
8
9
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.GenshinPlayer;
Melledy's avatar
Melledy committed
10
import emu.grasscutter.game.GenshinScene;
KingRainbow44's avatar
KingRainbow44 committed
11
import emu.grasscutter.game.World;
Melledy's avatar
Melledy committed
12
13
14
15
16
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.inventory.GenshinItem;
KingRainbow44's avatar
KingRainbow44 committed
17
import emu.grasscutter.game.inventory.Inventory;
Melledy's avatar
Melledy committed
18
19
20
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.FightProperty;
SpikeHD's avatar
SpikeHD committed
21
import emu.grasscutter.game.props.PlayerProperty;
Melledy's avatar
Melledy committed
22
23
24
25
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.utils.Position;

KingRainbow44's avatar
KingRainbow44 committed
26
27
28
29
30
31
32
33
import java.util.LinkedList;
import java.util.List;

/**
 * A container for player-related commands.
 */
public final class PlayerCommands {
    @Command(label = "give", aliases = {"g", "item", "giveitem"}, 
34
            usage = "give [player] <itemId|itemName> [amount]", description = "Gives an item to you or the specified player", permission = "player.give")
KingRainbow44's avatar
KingRainbow44 committed
35
36
37
38
39
40
41
42
43
44
45
46
47
    public static class GiveCommand implements CommandHandler {

        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            int target, item, amount = 1;

            switch(args.size()) {
                default:
                    CommandHandler.sendMessage(player, "Usage: give <player> <itemId|itemName> [amount]");
                    return;
                case 1:
                    try {
                        item = Integer.parseInt(args.get(0));
KingRainbow44's avatar
KingRainbow44 committed
48
                        target = player.getAccount().getPlayerId();
KingRainbow44's avatar
KingRainbow44 committed
49
50
51
52
53
54
55
56
57
                    } catch (NumberFormatException ignored) {
                        // TODO: Parse from item name using GM Handbook.
                        CommandHandler.sendMessage(player, "Invalid item id.");
                        return;
                    }
                    break;
                case 2:
                    try {
                        target = Integer.parseInt(args.get(0));
Melledy's avatar
Melledy committed
58

59
60
                        if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
                            target = player.getUid(); amount = Integer.parseInt(args.get(1));
KingRainbow44's avatar
KingRainbow44 committed
61
62
63
64
65
66
67
68
69
70
71
72
73
                            item = Integer.parseInt(args.get(0));
                        } else {
                            item = Integer.parseInt(args.get(1));
                        }
                    } catch (NumberFormatException ignored) {
                        // TODO: Parse from item name using GM Handbook.
                        CommandHandler.sendMessage(player, "Invalid item or player ID.");
                        return;
                    }
                    break;
                case 3:
                    try {
                        target = Integer.parseInt(args.get(0));
Melledy's avatar
Melledy committed
74
                        
75
                        if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
KingRainbow44's avatar
KingRainbow44 committed
76
77
78
79
80
81
82
83
84
85
86
87
88
                            CommandHandler.sendMessage(player, "Invalid player ID."); return;
                        }

                        item = Integer.parseInt(args.get(1));
                        amount = Integer.parseInt(args.get(2));
                    } catch (NumberFormatException ignored) {
                        // TODO: Parse from item name using GM Handbook.
                        CommandHandler.sendMessage(player, "Invalid item or player ID.");
                        return;
                    }
                    break;
            }

89
            GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Melledy's avatar
Melledy committed
90

KingRainbow44's avatar
KingRainbow44 committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
            if(targetPlayer == null) {
                CommandHandler.sendMessage(player, "Player not found."); return;
            }

            ItemData itemData = GenshinData.getItemDataMap().get(item);
            if(itemData == null) {
                CommandHandler.sendMessage(player, "Invalid item id."); return;
            }
            
            this.item(targetPlayer, itemData, amount);
        }

        /**
         * give [player] [itemId|itemName] [amount]
         */
        @Override public void execute(List<String> args) {
            if(args.size() < 2) {
                CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount]");
                return;
            }
111

KingRainbow44's avatar
KingRainbow44 committed
112
113
114
115
116
            try {
                int target = Integer.parseInt(args.get(0));
                int item = Integer.parseInt(args.get(1));
                int amount = 1; if(args.size() > 2) amount = Integer.parseInt(args.get(2));
                
117
                GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Melledy's avatar
Melledy committed
118

KingRainbow44's avatar
KingRainbow44 committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
                if(targetPlayer == null) {
                    CommandHandler.sendMessage(null, "Player not found."); return;
                }
                
                ItemData itemData = GenshinData.getItemDataMap().get(item);
                if(itemData == null) {
                    CommandHandler.sendMessage(null, "Invalid item id."); return;
                }
                
                this.item(targetPlayer, itemData, amount);
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid item or player ID.");
            }
        }
        
        private void item(GenshinPlayer player, ItemData itemData, int amount) {
            GenshinItem genshinItem = new GenshinItem(itemData);
            if(itemData.isEquip()) {
                List<GenshinItem> items = new LinkedList<>();
                for(int i = 0; i < amount; i++) {
                    items.add(genshinItem);
                } player.getInventory().addItems(items);
                player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
            } else {
                genshinItem.setCount(amount);
                player.getInventory().addItem(genshinItem);
                player.sendPacket(new PacketItemAddHintNotify(genshinItem, ActionReason.SubfieldDrop));
            }
        }
    }
    
    @Command(label = "drop", aliases = {"d", "dropitem"}, 
151
152
            usage = "drop <itemId|itemName> [amount]",
            execution = Command.Execution.PLAYER, description = "Drops an item near you", permission = "server.drop")
KingRainbow44's avatar
KingRainbow44 committed
153
    public static class DropCommand implements CommandHandler {
154

KingRainbow44's avatar
KingRainbow44 committed
155
156
157
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 1) {
KingRainbow44's avatar
KingRainbow44 committed
158
                CommandHandler.sendMessage(player, "Usage: drop <itemId|itemName> [amount]");
KingRainbow44's avatar
KingRainbow44 committed
159
160
                return;
            }
161

KingRainbow44's avatar
KingRainbow44 committed
162
163
164
            try {
                int item = Integer.parseInt(args.get(0));
                int amount = 1; if(args.size() > 1) amount = Integer.parseInt(args.get(1));
Melledy's avatar
Melledy committed
165

KingRainbow44's avatar
KingRainbow44 committed
166
167
                ItemData itemData = GenshinData.getItemDataMap().get(item);
                if(itemData == null) {
KingRainbow44's avatar
KingRainbow44 committed
168
                    CommandHandler.sendMessage(player, "Invalid item id."); return;
KingRainbow44's avatar
KingRainbow44 committed
169
                }
170

KingRainbow44's avatar
KingRainbow44 committed
171
172
173
174
                if (itemData.isEquip()) {
                    float range = (5f + (.1f * amount));
                    for (int i = 0; i < amount; i++) {
                        Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
Melledy's avatar
Melledy committed
175
176
                        EntityItem entity = new EntityItem(player.getScene(), player, itemData, pos, 1);
                        player.getScene().addEntity(entity);
KingRainbow44's avatar
KingRainbow44 committed
177
178
                    }
                } else {
Melledy's avatar
Melledy committed
179
180
                    EntityItem entity = new EntityItem(player.getScene(), player, itemData, player.getPos().clone().addY(3f), amount);
                    player.getScene().addEntity(entity);
KingRainbow44's avatar
KingRainbow44 committed
181
182
                }
            } catch (NumberFormatException ignored) {
KingRainbow44's avatar
KingRainbow44 committed
183
                CommandHandler.sendMessage(player, "Invalid item or player ID.");
KingRainbow44's avatar
KingRainbow44 committed
184
185
186
            }
        }
    }
SpikeHD's avatar
SpikeHD committed
187

188
189
    @Command(label = "givechar", aliases = { "givec" }, usage = "givechar <playerId> <avatarId> [level]",
            description = "Gives the player a specified character", permission = "player.givechar")
SpikeHD's avatar
SpikeHD committed
190
    public static class GiveCharCommand implements CommandHandler {
191
        @Override public void execute(GenshinPlayer player, List<String> args) {
KingRainbow44's avatar
KingRainbow44 committed
192
            int target, avatarId, level = 1, ascension = 1;
SpikeHD's avatar
SpikeHD committed
193

KingRainbow44's avatar
KingRainbow44 committed
194
            if(args.size() < 1) {
KingRainbow44's avatar
KingRainbow44 committed
195
                CommandHandler.sendMessage(player, "Usage: givechar <player> <avatarId> [level]");
196
197
198
199
200
                return;
            }
            
            switch(args.size()) {
                default:
KingRainbow44's avatar
KingRainbow44 committed
201
                CommandHandler.sendMessage(player, "Usage: givechar <player> <avatarId> [level]");
202
203
204
205
                    return;
                case 2:
                    try {
                        target = Integer.parseInt(args.get(0));
Melledy's avatar
Melledy committed
206
                        if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
KingRainbow44's avatar
KingRainbow44 committed
207
208
                            target = player.getUid(); 
                            level = Integer.parseInt(args.get(1));
KingRainbow44's avatar
KingRainbow44 committed
209
                            avatarId = Integer.parseInt(args.get(0));
210
                        } else {
KingRainbow44's avatar
KingRainbow44 committed
211
                            avatarId = Integer.parseInt(args.get(1));
212
213
214
215
216
217
218
219
220
221
                        }
                    } catch (NumberFormatException ignored) {
                        // TODO: Parse from avatar name using GM Handbook.
                        CommandHandler.sendMessage(player, "Invalid avatar or player ID.");
                        return;
                    }
                    break;
                case 3:
                    try {
                        target = Integer.parseInt(args.get(0));
Melledy's avatar
Melledy committed
222
                        if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
223
224
225
                            CommandHandler.sendMessage(player, "Invalid player ID."); return;
                        }

KingRainbow44's avatar
KingRainbow44 committed
226
                        avatarId = Integer.parseInt(args.get(1));
227
228
229
230
231
232
233
234
                        level = Integer.parseInt(args.get(2));
                    } catch (NumberFormatException ignored) {
                        // TODO: Parse from avatar name using GM Handbook.
                        CommandHandler.sendMessage(player, "Invalid avatar or player ID.");
                        return;
                    }
                    break;
            }
SpikeHD's avatar
SpikeHD committed
235

Melledy's avatar
Melledy committed
236
            GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
237
            if(targetPlayer == null) {
KingRainbow44's avatar
KingRainbow44 committed
238
                CommandHandler.sendMessage(player, "Player not found."); return;
SpikeHD's avatar
SpikeHD committed
239
            }
240
                
KingRainbow44's avatar
KingRainbow44 committed
241
            AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId);
SpikeHD's avatar
SpikeHD committed
242
            if(avatarData == null) {
KingRainbow44's avatar
KingRainbow44 committed
243
                CommandHandler.sendMessage(player, "Invalid avatar id."); return;
SpikeHD's avatar
SpikeHD committed
244
245
            }

246
247
            // Calculate ascension level.
            if (level <= 40) {
KingRainbow44's avatar
KingRainbow44 committed
248
249
250
                ascension = (int) Math.ceil(level / 20f);
            } else {
                ascension = (int) Math.ceil(level / 10f) - 3;
251
252
            }

KingRainbow44's avatar
KingRainbow44 committed
253
            GenshinAvatar avatar = new GenshinAvatar(avatarId);
SpikeHD's avatar
SpikeHD committed
254
            avatar.setLevel(level);
255
            avatar.setPromoteLevel(ascension);
256
257
258
            
            // This will handle stats and talents
            avatar.recalcStats();
259
260
261
    
            targetPlayer.addAvatar(avatar);
        }
SpikeHD's avatar
SpikeHD committed
262

263
264
265
        @Override
        public void execute(List<String> args) {
            if(args.size() < 2) {
SpikeHD's avatar
SpikeHD committed
266
                CommandHandler.sendMessage(null, "Usage: givechar <player> <itemId|itemName> [amount]");
267
268
269
270
271
272
273
                return;
            }

            try {
                int target = Integer.parseInt(args.get(0));
                int avatarID = Integer.parseInt(args.get(1));
                int level = 1; if(args.size() > 2) level = Integer.parseInt(args.get(2));
KingRainbow44's avatar
KingRainbow44 committed
274
                int ascension;
275
                
Melledy's avatar
Melledy committed
276
                GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
277
278
279
280
281
282
283
284
285
                if(targetPlayer == null) {
                    CommandHandler.sendMessage(null, "Player not found."); return;
                }
                    
                AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarID);
                if(avatarData == null) {
                    CommandHandler.sendMessage(null, "Invalid avatar id."); return;
                }
                
286
287
                // Calculate ascension level.
                if (level <= 40) {
KingRainbow44's avatar
KingRainbow44 committed
288
289
290
                    ascension = (int) Math.ceil(level / 20f);
                } else {
                    ascension = (int) Math.ceil(level / 10f) - 3;
291
292
                }
                
293
294
                GenshinAvatar avatar = new GenshinAvatar(avatarID);
                avatar.setLevel(level);
295
                avatar.setPromoteLevel(ascension);
296
297
298

                // This will handle stats and talents
                avatar.recalcStats();
299
300
301
302
303
        
                targetPlayer.addAvatar(avatar);
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid item or player ID.");
            }
SpikeHD's avatar
SpikeHD committed
304
305
        }
    }
Melledy's avatar
Melledy committed
306

KingRainbow44's avatar
KingRainbow44 committed
307
    @Command(label = "spawn", execution = Command.Execution.PLAYER, 
308
            usage = "spawn <entityId|entityName> [level] [amount]", description = "Spawns an entity near you", permission = "server.spawn")
KingRainbow44's avatar
KingRainbow44 committed
309
310
311
312
313
314
315
316
    public static class SpawnCommand implements CommandHandler {
        
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 1) {
                CommandHandler.sendMessage(null, "Usage: spawn <entityId|entityName> [amount]");
                return;
            }
317

KingRainbow44's avatar
KingRainbow44 committed
318
319
320
321
            try {
                int entity = Integer.parseInt(args.get(0));
                int level = 1; if(args.size() > 1) level = Integer.parseInt(args.get(1));
                int amount = 1; if(args.size() > 2) amount = Integer.parseInt(args.get(2));
322

KingRainbow44's avatar
KingRainbow44 committed
323
324
325
326
                MonsterData entityData = GenshinData.getMonsterDataMap().get(entity);
                if(entityData == null) {
                    CommandHandler.sendMessage(null, "Invalid entity id."); return;
                }
327

KingRainbow44's avatar
KingRainbow44 committed
328
329
330
                float range = (5f + (.1f * amount));
                for (int i = 0; i < amount; i++) {
                    Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
Melledy's avatar
Melledy committed
331
332
                    EntityMonster monster = new EntityMonster(player.getScene(), entityData, pos, level);
                    player.getScene().addEntity(monster);
KingRainbow44's avatar
KingRainbow44 committed
333
334
335
336
337
338
339
340
                }
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid item or player ID.");
            }
        }
    }
    
    @Command(label = "killall", 
341
            usage = "killall [playerUid] [sceneId]", description = "Kill all entities", permission = "server.killall")
KingRainbow44's avatar
KingRainbow44 committed
342
    public static class KillAllCommand implements CommandHandler {
343

KingRainbow44's avatar
KingRainbow44 committed
344
345
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
Melledy's avatar
Melledy committed
346
347
            GenshinScene scene = player.getScene();
            scene.getEntities().values().stream()
KingRainbow44's avatar
KingRainbow44 committed
348
                    .filter(entity -> entity instanceof EntityMonster)
Melledy's avatar
Melledy committed
349
350
                    .forEach(entity -> scene.killEntity(entity, 0));
            CommandHandler.sendMessage(null, "Killing all monsters in scene " + scene.getId());
KingRainbow44's avatar
KingRainbow44 committed
351
352
353
354
        }
        
        @Override
        public void execute(List<String> args) {
Melledy's avatar
Melledy committed
355
356
            if(args.size() < 2) {
                CommandHandler.sendMessage(null, "Usage: killall [playerUid] [sceneId]"); return;
KingRainbow44's avatar
KingRainbow44 committed
357
            }
358

KingRainbow44's avatar
KingRainbow44 committed
359
            try {
Melledy's avatar
Melledy committed
360
361
362
            	int playerUid = Integer.parseInt(args.get(0));
                int sceneId = Integer.parseInt(args.get(1));
                
363
                GenshinPlayer player = Grasscutter.getGameServer().getPlayerByUid(playerUid);
Melledy's avatar
Melledy committed
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
                if (player == null) {
                	CommandHandler.sendMessage(null, "Player not found or offline.");
                	return;
                }
                
                GenshinScene scene = player.getWorld().getSceneById(sceneId);
                if (scene == null) {
                	CommandHandler.sendMessage(null, "Scene not found in player world");
                	return;
                }
                
                scene.getEntities().values().stream()
                        .filter(entity -> entity instanceof EntityMonster)
                        .forEach(entity -> scene.killEntity(entity, 0));
                CommandHandler.sendMessage(null, "Killing all monsters in scene " + scene.getId());
KingRainbow44's avatar
KingRainbow44 committed
379
            } catch (NumberFormatException ignored) {
Melledy's avatar
Melledy committed
380
                CommandHandler.sendMessage(null, "Invalid arguments.");
KingRainbow44's avatar
KingRainbow44 committed
381
382
383
384
385
            }
        }
    }
    
    @Command(label = "resetconst", aliases = {"resetconstellation"}, 
386
387
            usage = "resetconst [all]", execution = Command.Execution.PLAYER, permission = "player.resetconstellation",
            description = "Resets the constellation level on your current active character, will need to relog after using the command to see any changes.")
KingRainbow44's avatar
KingRainbow44 committed
388
389
390
391
392
393
394
395
396
397
398
399
400
401
    public static class ResetConstellationCommand implements CommandHandler {
        
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() > 0 && args.get(0).equalsIgnoreCase("all")) {
                player.getAvatars().forEach(this::resetConstellation);
                player.dropMessage("Reset all avatars' constellations.");
            } else {
                EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity(); 
                if(entity == null)
                    return;
                
                GenshinAvatar avatar = entity.getAvatar();
                this.resetConstellation(avatar);
402

KingRainbow44's avatar
KingRainbow44 committed
403
404
405
406
407
408
409
410
411
412
413
414
415
                player.dropMessage("Constellations for " + avatar.getAvatarData().getName() + " have been reset. Please relog to see changes.");
            }
        }
        
        private void resetConstellation(GenshinAvatar avatar) {
            avatar.getTalentIdList().clear();
            avatar.setCoreProudSkillLevel(0);
            avatar.recalcStats();
            avatar.save();
        }
    }
    
    @Command(label = "godmode",
416
            usage = "godmode", execution = Command.Execution.PLAYER, description = "Prevents you from taking damage", permission = "player.godmode")
KingRainbow44's avatar
KingRainbow44 committed
417
418
419
420
421
422
423
424
425
426
    public static class GodModeCommand implements CommandHandler {
        
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            player.setGodmode(!player.inGodmode());
            player.dropMessage("Godmode is now " + (player.inGodmode() ? "enabled" : "disabled") + ".");
        }
    }
    
    @Command(label = "sethealth", aliases = {"sethp"}, 
427
428
            usage = "sethealth <hp>", execution = Command.Execution.PLAYER, description = "Sets your health to the specified value",
            permission = "player.sethealth")
KingRainbow44's avatar
KingRainbow44 committed
429
    public static class SetHealthCommand implements CommandHandler {
430

KingRainbow44's avatar
KingRainbow44 committed
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 1) {
                CommandHandler.sendMessage(null, "Usage: sethealth <hp>"); return;
            }
            
            try {
                int health = Integer.parseInt(args.get(0));
                EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity();
                if(entity == null)
                    return;
                
                entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health);
                entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
                player.dropMessage("Health set to " + health + ".");
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid health value.");
            }
        }
    }
SpikeHD's avatar
SpikeHD committed
451

452
453
454
    @Command(label = "setworldlevel", aliases = {"setworldlvl"}, usage = "setworldlevel <level>",
            description = "Sets your world level (Relog to see proper effects)", permission = "player.setworldlevel",
            execution = Command.Execution.PLAYER)
SpikeHD's avatar
SpikeHD committed
455
456
457
458
    public static class SetWorldLevelCommand implements CommandHandler {
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 1) {
KingRainbow44's avatar
KingRainbow44 committed
459
                CommandHandler.sendMessage(player, "Usage: setworldlevel <level>"); return;
SpikeHD's avatar
SpikeHD committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
            }
            
            try {
                int level = Integer.parseInt(args.get(0));

                // Set in both world and player props
                player.getWorld().setWorldLevel(level);
                player.setProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL, level);

                player.dropMessage("World level set to " + level + ".");
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid world level.");
            }
        }
    }
KingRainbow44's avatar
KingRainbow44 committed
475
476
    
    @Command(label = "clearartifacts", aliases = {"clearart"}, 
477
478
            usage = "clearartifacts", execution = Command.Execution.PLAYER, permission = "player.clearartifacts",
            description = "Deletes all unequipped and unlocked level 0 artifacts, including yellow rarity ones from your inventory")
KingRainbow44's avatar
KingRainbow44 committed
479
480
481
482
483
484
485
486
487
488
489
    public static class ClearArtifactsCommand implements CommandHandler {
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            Inventory playerInventory = player.getInventory();
            playerInventory.getItems().values().stream()
                    .filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY)
                    .filter(item -> item.getLevel() == 1 && item.getExp() == 0)
                    .filter(item -> !item.isLocked() && !item.isEquipped())
                    .forEach(item -> playerInventory.removeItem(item, item.getCount()));
        }
    }
490

Melledy's avatar
Melledy committed
491
    @Command(label = "changescene", aliases = {"scene"}, 
492
            usage = "changescene <scene id>", description = "Changes your scene", permission = "player.changescene", execution = Command.Execution.PLAYER)
Melledy's avatar
Melledy committed
493
494
495
496
    public static class ChangeSceneCommand implements CommandHandler {
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 1) {
KingRainbow44's avatar
KingRainbow44 committed
497
                CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return;
Melledy's avatar
Melledy committed
498
499
500
            }
        
            try {
KingRainbow44's avatar
KingRainbow44 committed
501
502
503
504
505
506
                int sceneId = Integer.parseInt(args.get(0));
                boolean result = player.getWorld().transferPlayerToScene(player, sceneId, player.getPos());

                if (!result) {
                    CommandHandler.sendMessage(null, "Scene does not exist or you are already in it");
                }
Melledy's avatar
Melledy committed
507
            } catch (Exception e) {
KingRainbow44's avatar
KingRainbow44 committed
508
                CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return;
Melledy's avatar
Melledy committed
509
510
511
            }
        }
    }
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
    @Command(label = "sendservermessage", aliases = {"sendservmsg"},
            usage = "sendservermessage <player> <message>", description = "Sends a message to a player as the server",
            execution = Command.Execution.PLAYER, permission = "server.sendmessage")
    public static class SendServerMessageCommand implements CommandHandler {
        @Override
        public void execute(GenshinPlayer player, List<String> args) {
            if(args.size() < 2) {
                CommandHandler.sendMessage(null, "Usage: sendmessage <player> <message>"); return;
            }

            try {
                int target = Integer.parseInt(args.get(0));
                String message = String.join(" ", args.subList(1, args.size()));

527
                GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
528
529
530
531
532
533
534
535
536
537
538
                if(targetPlayer == null) {
                    CommandHandler.sendMessage(null, "Player not found."); return;
                }

                targetPlayer.dropMessage(message);
                CommandHandler.sendMessage(null, "Message sent.");
            } catch (NumberFormatException ignored) {
                CommandHandler.sendMessage(null, "Invalid player ID.");
            }
        }
    }
Melledy's avatar
Melledy committed
539
}