This commit is contained in:
Benjamin Elsdon 2022-04-20 17:18:51 +08:00
commit 22781ac6e7
7 changed files with 165 additions and 107 deletions

View File

@ -66,6 +66,9 @@ There is a dummy user named "Server" in every player's friends list that you can
`!clearartifacts` - Deletes all unequipped and unlocked level 0 artifacts, **including yellow rarity ones** from your inventory
### Bonus
When you want to teleport to somewhere, use the ingame marking function on Map, click Confirm. You will see your character falling from a very high destination, exact location that you marked.
# Quick Troubleshooting
* If compiling wasnt successful, please check your JDK installation (must be JDK 8 and validated JDK's bin PATH variable)
* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is the issue, if using Fiddler make sure it running on another port except 8888

File diff suppressed because one or more lines are too long

View File

@ -54,5 +54,6 @@ public final class Config {
public boolean WatchGacha = false;
public int[] WelcomeEmotes = {2007, 1002, 4010};
public String WelcomeMotd = "Welcome to Grasscutter emu";
public boolean AutomaticallyCreateAccounts = false;
}
}

View File

@ -91,7 +91,7 @@ public final class CommandMap {
public void invoke(GenshinPlayer player, String rawMessage) {
rawMessage = rawMessage.trim();
if(rawMessage.length() == 0) {
CommandHandler.sendMessage(player, "No command specified.");
CommandHandler.sendMessage(player, "No command specified."); return;
}
// Remove prefix if present.
@ -113,7 +113,7 @@ public final class CommandMap {
if(player != null) {
String permissionNode = this.annotations.get(label).permission();
Account account = player.getAccount();
if(permissionNode != "" && !account.hasPermission(permissionNode)) {
if(!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) {
CommandHandler.sendMessage(player, "You do not have permission to run this command."); return;
}
}

View File

@ -20,7 +20,9 @@ import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp;
import emu.grasscutter.utils.Position;
import java.util.LinkedList;
@ -38,7 +40,7 @@ public final class PlayerCommands {
public void execute(GenshinPlayer player, List<String> args) {
int target, item, amount = 1;
switch(args.size()) {
switch (args.size()) {
default:
CommandHandler.sendMessage(player, "Usage: give <player> <itemId|itemName> [amount]");
return;
@ -56,8 +58,9 @@ public final class PlayerCommands {
try {
target = Integer.parseInt(args.get(0));
if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = player.getUid(); amount = Integer.parseInt(args.get(1));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = player.getUid();
amount = Integer.parseInt(args.get(1));
item = Integer.parseInt(args.get(0));
} else {
item = Integer.parseInt(args.get(1));
@ -71,9 +74,10 @@ public final class PlayerCommands {
case 3:
try {
target = Integer.parseInt(args.get(0));
if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID."); return;
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID.");
return;
}
item = Integer.parseInt(args.get(1));
@ -88,23 +92,26 @@ public final class PlayerCommands {
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if(targetPlayer == null) {
CommandHandler.sendMessage(player, "Player not found."); return;
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;
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) {
@Override
public void execute(List<String> args) {
if (args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount]");
return;
}
@ -112,32 +119,37 @@ public final class PlayerCommands {
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));
int amount = 1;
if (args.size() > 2)
amount = Integer.parseInt(args.get(2));
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if(targetPlayer == null) {
CommandHandler.sendMessage(null, "Player not found."); return;
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;
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()) {
if (itemData.isEquip()) {
List<GenshinItem> items = new LinkedList<>();
for(int i = 0; i < amount; i++) {
for (int i = 0; i < amount; i++) {
items.add(genshinItem);
} player.getInventory().addItems(items);
}
player.getInventory().addItems(items);
player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
} else {
genshinItem.setCount(amount);
@ -146,7 +158,6 @@ public final class PlayerCommands {
}
}
}
@Command(label = "drop", aliases = {"d", "dropitem"},
usage = "drop <itemId|itemName> [amount]",
execution = Command.Execution.PLAYER, description = "Drops an item near you", permission = "server.drop")
@ -154,29 +165,34 @@ public final class PlayerCommands {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() < 1) {
if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: drop <itemId|itemName> [amount]");
return;
}
try {
int item = Integer.parseInt(args.get(0));
int amount = 1; if(args.size() > 1) amount = Integer.parseInt(args.get(1));
int amount = 1;
if (args.size() > 1)
amount = Integer.parseInt(args.get(1));
ItemData itemData = GenshinData.getItemDataMap().get(item);
if(itemData == null) {
CommandHandler.sendMessage(player, "Invalid item id."); return;
if (itemData == null) {
CommandHandler.sendMessage(player, "Invalid item id.");
return;
}
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));
Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2))
.addY(3f).addZ((float) (Math.random() * range) - (range / 2));
EntityItem entity = new EntityItem(player.getScene(), player, itemData, pos, 1);
player.getScene().addEntity(entity);
}
} else {
EntityItem entity = new EntityItem(player.getScene(), player, itemData, player.getPos().clone().addY(3f), amount);
EntityItem entity = new EntityItem(player.getScene(), player, itemData,
player.getPos().clone().addY(3f), amount);
player.getScene().addEntity(entity);
}
} catch (NumberFormatException ignored) {
@ -188,23 +204,24 @@ public final class PlayerCommands {
@Command(label = "givechar", aliases = { "givec" }, usage = "givechar <playerId> <avatarId> [level]",
description = "Gives the player a specified character", permission = "player.givechar")
public static class GiveCharCommand implements CommandHandler {
@Override public void execute(GenshinPlayer player, List<String> args) {
@Override
public void execute(GenshinPlayer player, List<String> args) {
int target, avatarId, level = 1, ascension = 1;
if(args.size() < 1) {
if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: givechar <player> <avatarId> [level]");
return;
}
switch(args.size()) {
switch (args.size()) {
default:
CommandHandler.sendMessage(player, "Usage: givechar <player> <avatarId> [level]");
CommandHandler.sendMessage(player, "Usage: givechar <player> <avatarId> [level]");
return;
case 2:
try {
target = Integer.parseInt(args.get(0));
if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = player.getUid();
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = player.getUid();
level = Integer.parseInt(args.get(1));
avatarId = Integer.parseInt(args.get(0));
} else {
@ -219,8 +236,9 @@ public final class PlayerCommands {
case 3:
try {
target = Integer.parseInt(args.get(0));
if(Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID."); return;
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID.");
return;
}
avatarId = Integer.parseInt(args.get(1));
@ -234,13 +252,15 @@ public final class PlayerCommands {
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if(targetPlayer == null) {
CommandHandler.sendMessage(player, "Player not found."); return;
if (targetPlayer == null) {
CommandHandler.sendMessage(player, "Player not found.");
return;
}
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId);
if(avatarData == null) {
CommandHandler.sendMessage(player, "Invalid avatar id."); return;
if (avatarData == null) {
CommandHandler.sendMessage(player, "Invalid avatar id.");
return;
}
// Calculate ascension level.
@ -253,16 +273,16 @@ public final class PlayerCommands {
GenshinAvatar avatar = new GenshinAvatar(avatarId);
avatar.setLevel(level);
avatar.setPromoteLevel(ascension);
// This will handle stats and talents
avatar.recalcStats();
targetPlayer.addAvatar(avatar);
}
@Override
public void execute(List<String> args) {
if(args.size() < 2) {
if (args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: givechar <player> <itemId|itemName> [amount]");
return;
}
@ -270,33 +290,37 @@ public final class PlayerCommands {
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));
int level = 1;
if (args.size() > 2)
level = Integer.parseInt(args.get(2));
int ascension;
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if(targetPlayer == null) {
CommandHandler.sendMessage(null, "Player not found."); return;
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;
if (avatarData == null) {
CommandHandler.sendMessage(null, "Invalid avatar id.");
return;
}
// Calculate ascension level.
if (level <= 40) {
ascension = (int) Math.ceil(level / 20f);
} else {
ascension = (int) Math.ceil(level / 10f) - 3;
}
GenshinAvatar avatar = new GenshinAvatar(avatarID);
avatar.setLevel(level);
avatar.setPromoteLevel(ascension);
// This will handle stats and talents
avatar.recalcStats();
targetPlayer.addAvatar(avatar);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, "Invalid item or player ID.");
@ -307,27 +331,33 @@ public final class PlayerCommands {
@Command(label = "spawn", execution = Command.Execution.PLAYER,
usage = "spawn <entityId|entityName> [level] [amount]", description = "Spawns an entity near you", permission = "server.spawn")
public static class SpawnCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() < 1) {
if (args.size() < 1) {
CommandHandler.sendMessage(null, "Usage: spawn <entityId|entityName> [amount]");
return;
}
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));
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));
MonsterData entityData = GenshinData.getMonsterDataMap().get(entity);
if(entityData == null) {
CommandHandler.sendMessage(null, "Invalid entity id."); return;
if (entityData == null) {
CommandHandler.sendMessage(null, "Invalid entity id.");
return;
}
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));
Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f)
.addZ((float) (Math.random() * range) - (range / 2));
EntityMonster monster = new EntityMonster(player.getScene(), entityData, pos, level);
player.getScene().addEntity(monster);
}
@ -349,29 +379,30 @@ public final class PlayerCommands {
.forEach(entity -> scene.killEntity(entity, 0));
CommandHandler.sendMessage(null, "Killing all monsters in scene " + scene.getId());
}
@Override
public void execute(List<String> args) {
if(args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: killall [playerUid] [sceneId]"); return;
if (args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: killall [playerUid] [sceneId]");
return;
}
try {
int playerUid = Integer.parseInt(args.get(0));
int playerUid = Integer.parseInt(args.get(0));
int sceneId = Integer.parseInt(args.get(1));
GenshinPlayer player = Grasscutter.getGameServer().getPlayerByUid(playerUid);
if (player == null) {
CommandHandler.sendMessage(null, "Player not found or offline.");
return;
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;
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));
@ -381,29 +412,30 @@ public final class PlayerCommands {
}
}
}
@Command(label = "resetconst", aliases = {"resetconstellation"},
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.")
public static class ResetConstellationCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() > 0 && args.get(0).equalsIgnoreCase("all")) {
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)
EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity();
if (entity == null)
return;
GenshinAvatar avatar = entity.getAvatar();
this.resetConstellation(avatar);
player.dropMessage("Constellations for " + avatar.getAvatarData().getName() + " have been reset. Please relog to see changes.");
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);
@ -411,18 +443,18 @@ public final class PlayerCommands {
avatar.save();
}
}
@Command(label = "godmode",
usage = "godmode", execution = Command.Execution.PLAYER, description = "Prevents you from taking damage", permission = "player.godmode")
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"},
usage = "sethealth <hp>", execution = Command.Execution.PLAYER, description = "Sets your health to the specified value",
permission = "player.sethealth")
@ -430,18 +462,20 @@ public final class PlayerCommands {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() < 1) {
CommandHandler.sendMessage(null, "Usage: sethealth <hp>"); return;
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)
if (entity == null)
return;
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
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.");
@ -455,10 +489,11 @@ public final class PlayerCommands {
public static class SetWorldLevelCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: setworldlevel <level>"); return;
if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: setworldlevel <level>");
return;
}
try {
int level = Integer.parseInt(args.get(0));
@ -472,7 +507,7 @@ public final class PlayerCommands {
}
}
}
@Command(label = "clearartifacts", aliases = {"clearart"},
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")
@ -493,10 +528,11 @@ public final class PlayerCommands {
public static class ChangeSceneCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
if(args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return;
if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: changescene <scene id>");
return;
}
try {
int sceneId = Integer.parseInt(args.get(0));
boolean result = player.getWorld().transferPlayerToScene(player, sceneId, player.getPos());
@ -505,7 +541,8 @@ public final class PlayerCommands {
CommandHandler.sendMessage(null, "Scene does not exist or you are already in it");
}
} catch (Exception e) {
CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return;
CommandHandler.sendMessage(player, "Usage: changescene <scene id>");
return;
}
}
}
@ -536,4 +573,12 @@ public final class PlayerCommands {
}
}
}
@Command(label = "restart", usage = "Usage: restart", description = "Restarts the current session", execution = Command.Execution.PLAYER, permission = "player.restart")
public static class RestartCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
player.getSession().close();
}
}
}

View File

@ -189,6 +189,7 @@ public final class ServerCommands {
} else {
CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerId() + ".");
account.addPermission("*"); // Grant the player superuser permissions.
account.save(); // Save account to database.
}
return;
case "delete":

View File

@ -225,8 +225,16 @@ public final class DispatchServer {
// Login
Account account = DatabaseHelper.getAccountByName(requestData.account);
// Test
if (account == null) {
// Check if account exists, else create a new one.
if (account == null && Grasscutter.getConfig().ServerOptions.AutomaticallyCreateAccounts) {
// This account has been created AUTOMATICALLY. There will be no permissions added.
account = DatabaseHelper.createAccountWithId(requestData.account, 0);
responseData.message = "OK";
responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
} else if (!Grasscutter.getConfig().ServerOptions.AutomaticallyCreateAccounts) {
responseData.retcode = -201;
responseData.message = "Username not found.";
} else {