Merge branch 'development' into main

This commit is contained in:
Yazawazi 2022-04-20 19:09:48 +08:00 committed by GitHub
commit 31d89369c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 182 additions and 109 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 `!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 # Quick Troubleshooting
* If compiling wasnt successful, please check your JDK installation (must be JDK 8 and validated JDK's bin PATH variable) * 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 * 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

@ -53,5 +53,6 @@ public final class Config {
public int MaxEntityLimit = 1000; // Max entity limit per world. // TODO: Enforce later. public int MaxEntityLimit = 1000; // Max entity limit per world. // TODO: Enforce later.
public int[] WelcomeEmotes = {2007, 1002, 4010}; public int[] WelcomeEmotes = {2007, 1002, 4010};
public String WelcomeMotd = "Welcome to Grasscutter emu"; 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) { public void invoke(GenshinPlayer player, String rawMessage) {
rawMessage = rawMessage.trim(); rawMessage = rawMessage.trim();
if(rawMessage.length() == 0) { if(rawMessage.length() == 0) {
CommandHandler.sendMessage(player, "No command specified."); CommandHandler.sendMessage(player, "No command specified."); return;
} }
// Remove prefix if present. // Remove prefix if present.
@ -113,7 +113,7 @@ public final class CommandMap {
if(player != null) { if(player != null) {
String permissionNode = this.annotations.get(label).permission(); String permissionNode = this.annotations.get(label).permission();
Account account = player.getAccount(); 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; CommandHandler.sendMessage(player, "You do not have permission to run this command."); return;
} }
} }

View File

@ -22,7 +22,9 @@ import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify; import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify;
import emu.grasscutter.server.packet.send.PacketGetPlayerTokenRsp;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
import emu.grasscutter.server.packet.send.PacketPlayerLoginRsp;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import java.util.LinkedList; import java.util.LinkedList;
@ -59,7 +61,8 @@ public final class PlayerCommands {
target = Integer.parseInt(args.get(0)); target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) { if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = player.getUid(); amount = Integer.parseInt(args.get(1)); target = player.getUid();
amount = Integer.parseInt(args.get(1));
item = Integer.parseInt(args.get(0)); item = Integer.parseInt(args.get(0));
} else { } else {
item = Integer.parseInt(args.get(1)); item = Integer.parseInt(args.get(1));
@ -75,7 +78,8 @@ public final class PlayerCommands {
target = Integer.parseInt(args.get(0)); target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) { if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID."); return; CommandHandler.sendMessage(player, "Invalid player ID.");
return;
} }
item = Integer.parseInt(args.get(1)); item = Integer.parseInt(args.get(1));
@ -91,12 +95,14 @@ public final class PlayerCommands {
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) { if (targetPlayer == null) {
CommandHandler.sendMessage(player, "Player not found."); return; CommandHandler.sendMessage(player, "Player not found.");
return;
} }
ItemData itemData = GenshinData.getItemDataMap().get(item); ItemData itemData = GenshinData.getItemDataMap().get(item);
if (itemData == null) { if (itemData == null) {
CommandHandler.sendMessage(player, "Invalid item id."); return; CommandHandler.sendMessage(player, "Invalid item id.");
return;
} }
this.item(targetPlayer, itemData, amount); this.item(targetPlayer, itemData, amount);
@ -105,7 +111,8 @@ public final class PlayerCommands {
/** /**
* give [player] [itemId|itemName] [amount] * give [player] [itemId|itemName] [amount]
*/ */
@Override public void execute(List<String> args) { @Override
public void execute(List<String> args) {
if (args.size() < 2) { if (args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount]"); CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount]");
return; return;
@ -114,17 +121,21 @@ public final class PlayerCommands {
try { try {
int target = Integer.parseInt(args.get(0)); int target = Integer.parseInt(args.get(0));
int item = Integer.parseInt(args.get(1)); 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); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) { if (targetPlayer == null) {
CommandHandler.sendMessage(null, "Player not found."); return; CommandHandler.sendMessage(null, "Player not found.");
return;
} }
ItemData itemData = GenshinData.getItemDataMap().get(item); ItemData itemData = GenshinData.getItemDataMap().get(item);
if (itemData == null) { if (itemData == null) {
CommandHandler.sendMessage(null, "Invalid item id."); return; CommandHandler.sendMessage(null, "Invalid item id.");
return;
} }
this.item(targetPlayer, itemData, amount); this.item(targetPlayer, itemData, amount);
@ -139,7 +150,8 @@ public final class PlayerCommands {
List<GenshinItem> items = new LinkedList<>(); List<GenshinItem> items = new LinkedList<>();
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
items.add(genshinItem); items.add(genshinItem);
} player.getInventory().addItems(items); }
player.getInventory().addItems(items);
player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop)); player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
} else { } else {
genshinItem.setCount(amount); genshinItem.setCount(amount);
@ -148,7 +160,6 @@ public final class PlayerCommands {
} }
} }
} }
@Command(label = "drop", aliases = {"d", "dropitem"}, @Command(label = "drop", aliases = {"d", "dropitem"},
usage = "drop <itemId|itemName> [amount]", usage = "drop <itemId|itemName> [amount]",
execution = Command.Execution.PLAYER, description = "Drops an item near you", permission = "server.drop") execution = Command.Execution.PLAYER, description = "Drops an item near you", permission = "server.drop")
@ -163,22 +174,27 @@ public final class PlayerCommands {
try { try {
int item = Integer.parseInt(args.get(0)); 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); ItemData itemData = GenshinData.getItemDataMap().get(item);
if (itemData == null) { if (itemData == null) {
CommandHandler.sendMessage(player, "Invalid item id."); return; CommandHandler.sendMessage(player, "Invalid item id.");
return;
} }
if (itemData.isEquip()) { if (itemData.isEquip()) {
float range = (5f + (.1f * amount)); float range = (5f + (.1f * amount));
for (int i = 0; i < amount; i++) { 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); EntityItem entity = new EntityItem(player.getScene(), player, itemData, pos, 1);
player.getScene().addEntity(entity); player.getScene().addEntity(entity);
} }
} else { } 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); player.getScene().addEntity(entity);
} }
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
@ -190,7 +206,8 @@ public final class PlayerCommands {
@Command(label = "givechar", aliases = { "givec" }, usage = "givechar <playerId> <avatarId> [level]", @Command(label = "givechar", aliases = { "givec" }, usage = "givechar <playerId> <avatarId> [level]",
description = "Gives the player a specified character", permission = "player.givechar") description = "Gives the player a specified character", permission = "player.givechar")
public static class GiveCharCommand implements CommandHandler { 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; int target, avatarId, level = 1, ascension = 1;
if (args.size() < 1) { if (args.size() < 1) {
@ -222,7 +239,8 @@ public final class PlayerCommands {
try { try {
target = Integer.parseInt(args.get(0)); target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) { if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(player, "Invalid player ID."); return; CommandHandler.sendMessage(player, "Invalid player ID.");
return;
} }
avatarId = Integer.parseInt(args.get(1)); avatarId = Integer.parseInt(args.get(1));
@ -237,12 +255,14 @@ public final class PlayerCommands {
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) { if (targetPlayer == null) {
CommandHandler.sendMessage(player, "Player not found."); return; CommandHandler.sendMessage(player, "Player not found.");
return;
} }
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId); AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId);
if (avatarData == null) { if (avatarData == null) {
CommandHandler.sendMessage(player, "Invalid avatar id."); return; CommandHandler.sendMessage(player, "Invalid avatar id.");
return;
} }
// Calculate ascension level. // Calculate ascension level.
@ -272,17 +292,21 @@ public final class PlayerCommands {
try { try {
int target = Integer.parseInt(args.get(0)); int target = Integer.parseInt(args.get(0));
int avatarID = Integer.parseInt(args.get(1)); 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; int ascension;
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) { if (targetPlayer == null) {
CommandHandler.sendMessage(null, "Player not found."); return; CommandHandler.sendMessage(null, "Player not found.");
return;
} }
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarID); AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarID);
if (avatarData == null) { if (avatarData == null) {
CommandHandler.sendMessage(null, "Invalid avatar id."); return; CommandHandler.sendMessage(null, "Invalid avatar id.");
return;
} }
// Calculate ascension level. // Calculate ascension level.
@ -319,17 +343,23 @@ public final class PlayerCommands {
try { try {
int entity = Integer.parseInt(args.get(0)); int entity = Integer.parseInt(args.get(0));
int level = 1; if(args.size() > 1) level = Integer.parseInt(args.get(1)); int level = 1;
int amount = 1; if(args.size() > 2) amount = Integer.parseInt(args.get(2)); 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); MonsterData entityData = GenshinData.getMonsterDataMap().get(entity);
if (entityData == null) { if (entityData == null) {
CommandHandler.sendMessage(null, "Invalid entity id."); return; CommandHandler.sendMessage(null, "Invalid entity id.");
return;
} }
float range = (5f + (.1f * amount)); float range = (5f + (.1f * amount));
for (int i = 0; i < amount; i++) { 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); EntityMonster monster = new EntityMonster(player.getScene(), entityData, pos, level);
player.getScene().addEntity(monster); player.getScene().addEntity(monster);
} }
@ -355,7 +385,8 @@ public final class PlayerCommands {
@Override @Override
public void execute(List<String> args) { public void execute(List<String> args) {
if (args.size() < 2) { if (args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: killall [playerUid] [sceneId]"); return; CommandHandler.sendMessage(null, "Usage: killall [playerUid] [sceneId]");
return;
} }
try { try {
@ -402,7 +433,8 @@ public final class PlayerCommands {
GenshinAvatar avatar = entity.getAvatar(); GenshinAvatar avatar = entity.getAvatar();
this.resetConstellation(avatar); 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.");
} }
} }
@ -433,7 +465,8 @@ public final class PlayerCommands {
@Override @Override
public void execute(GenshinPlayer player, List<String> args) { public void execute(GenshinPlayer player, List<String> args) {
if (args.size() < 1) { if (args.size() < 1) {
CommandHandler.sendMessage(null, "Usage: sethealth <hp>"); return; CommandHandler.sendMessage(null, "Usage: sethealth <hp>");
return;
} }
try { try {
@ -443,7 +476,8 @@ public final class PlayerCommands {
return; return;
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health); 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 + "."); player.dropMessage("Health set to " + health + ".");
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, "Invalid health value."); CommandHandler.sendMessage(null, "Invalid health value.");
@ -458,7 +492,8 @@ public final class PlayerCommands {
@Override @Override
public void execute(GenshinPlayer player, List<String> args) { public void execute(GenshinPlayer player, List<String> args) {
if (args.size() < 1) { if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: setworldlevel <level>"); return; CommandHandler.sendMessage(player, "Usage: setworldlevel <level>");
return;
} }
try { try {
@ -496,7 +531,8 @@ public final class PlayerCommands {
@Override @Override
public void execute(GenshinPlayer player, List<String> args) { public void execute(GenshinPlayer player, List<String> args) {
if (args.size() < 1) { if (args.size() < 1) {
CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return; CommandHandler.sendMessage(player, "Usage: changescene <scene id>");
return;
} }
try { try {
@ -507,7 +543,8 @@ public final class PlayerCommands {
CommandHandler.sendMessage(null, "Scene does not exist or you are already in it"); CommandHandler.sendMessage(null, "Scene does not exist or you are already in it");
} }
} catch (Exception e) { } catch (Exception e) {
CommandHandler.sendMessage(player, "Usage: changescene <scene id>"); return; CommandHandler.sendMessage(player, "Usage: changescene <scene id>");
return;
} }
} }
} }
@ -539,6 +576,17 @@ public final class PlayerCommands {
} }
} }
@Command(label = "pos",
usage = "Usage: pos", description = "Get coordinates.",
execution = Command.Execution.PLAYER)
public static class CordCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer player, List<String> args) {
player.dropMessage(String.format("Coord: %.3f, %.3f, %.3f", player.getPos().getX(), player.getPos().getY(), player.getPos().getZ()));
}
}
@Command(label = "weather", aliases = {"weather", "w"}, @Command(label = "weather", aliases = {"weather", "w"},
usage = "weather <weather id>", description = "Changes the weather.", usage = "weather <weather id>", description = "Changes the weather.",
execution = Command.Execution.PLAYER, permission = "player.weather" execution = Command.Execution.PLAYER, permission = "player.weather"
@ -563,4 +611,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

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

View File

@ -225,11 +225,23 @@ public final class DispatchServer {
// Login // Login
Account account = DatabaseHelper.getAccountByName(requestData.account); Account account = DatabaseHelper.getAccountByName(requestData.account);
// Test // Check if account exists, else create a new one.
if (account == null) { if (account == null) {
// Account doesnt exist, so we can either auto create it if the config value is set
if (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 {
responseData.retcode = -201; responseData.retcode = -201;
responseData.message = "Username not found."; responseData.message = "Username not found.";
}
} else { } else {
// Account was found, log the player in
responseData.message = "OK"; responseData.message = "OK";
responseData.data.account.uid = account.getId(); responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey(); responseData.data.account.token = account.generateSessionKey();