Merge remote-tracking branch 'upstream/development' into dev-mail

This commit is contained in:
Benjamin Elsdon 2022-04-27 07:37:05 +08:00
commit b9f7c657ac
87 changed files with 895 additions and 302 deletions

8
.gitignore vendored
View File

@ -30,6 +30,9 @@ hs_err_pid*
build/ build/
out/ out/
# Ignore Gradle properties
gradle.properties
# Eclipse # Eclipse
.project .project
.classpath .classpath
@ -53,9 +56,10 @@ resources/*
logs/* logs/*
data/AbilityEmbryos.json data/AbilityEmbryos.json
data/OpenConfig.json data/OpenConfig.json
proto/*
GM Handbook.txt GM Handbook.txt
config.json config.json
mitmdump.exe mitmdump.exe
grasscutter.jar *.jar
mongod.exe mongod.exe
/src/generated/
/*.sh

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "Grasscutter-Protos"]
path = Grasscutter-Protos
url = https://github.com/Melledy/Grasscutter-Protos

@ -1 +0,0 @@
Subproject commit ba0eab7d629b5adeb145bc430e14ffcb4bdf3d6a

View File

@ -75,7 +75,7 @@ Grasscutter uses Gradle to handle dependencies & building.
**Requirements:** **Requirements:**
- Java SE Development Kits - 16 - Java SE Development Kits - 17
- Git - Git
##### Windows ##### Windows

View File

@ -75,7 +75,7 @@ Grasscutter 使用 Gradle 来处理依赖及构建.
**依赖:** **依赖:**
- Java SE Development Kits - 16 - Java SE Development Kits - 17
- Git - Git
##### Windows ##### Windows

View File

@ -6,17 +6,45 @@
* User Manual available at https://docs.gradle.org/5.6.3/userguide/tutorial_java_projects.html * User Manual available at https://docs.gradle.org/5.6.3/userguide/tutorial_java_projects.html
*/ */
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18'
}
}
plugins { plugins {
// Apply the java plugin to add support for Java // Apply the java plugin to add support for Java
id 'java' id 'java'
// Apply the protobuf auto generator
id 'com.google.protobuf' version "0.8.18"
id 'idea'
// Apply the application plugin to add support for building a CLI application // Apply the application plugin to add support for building a CLI application
id 'application' id 'application'
id 'maven-publish'
id 'signing'
} }
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
group = 'tech.xigam'
version = '1.0.0-dev'
sourceCompatibility = 17 sourceCompatibility = 17
targetCompatibility = 17 targetCompatibility = 17
java {
withJavadocJar()
withSourcesJar()
}
repositories { repositories {
mavenCentral() mavenCentral()
} }
@ -38,6 +66,9 @@ dependencies {
implementation group: 'org.greenrobot', name: 'eventbus-java', version: '3.3.1' implementation group: 'org.greenrobot', name: 'eventbus-java', version: '3.3.1'
implementation group: 'org.danilopianini', name: 'java-quadtree', version: '0.1.9' implementation group: 'org.danilopianini', name: 'java-quadtree', version: '0.1.9'
protobuf files('proto/')
} }
application { application {
@ -65,3 +96,102 @@ jar {
destinationDir = file(".") destinationDir = file(".")
} }
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = 'grasscutter'
from components.java
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
pom {
name = 'Grasscutter'
description = 'A server software reimplementation for an anime game.'
url = 'https://github.com/Grasscutters/Grasscutter'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'melledy'
name = 'Melledy'
email = 'melledy@xigam.tech' // not a real email kek
}
developer {
id = 'magix'
name = 'Magix'
email = 'magix@xigam.tech'
}
}
scm {
connection = 'scm:git:git@github.com:Grasscutters/Grasscutter.git'
developerConnection = 'scm:git:ssh://github.com:Grasscutters/Grasscutter.git'
url = 'https://github.com/Grasscutters/Grasscutter'
}
}
}
}
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
def releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
def snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
name = 'sonatype'
credentials(PasswordCredentials)
}
}
}
clean {
delete protobuf.generatedFilesBaseDir
}
protobuf {
protoc {
// The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:3.18.1'
}
// generatedFilesBaseDir = "$projectDir/src/main/java/emu/grasscutter/net/proto/"
generatedFilesBaseDir = "$projectDir/src/generated/"
}
sourceSets {
main {
proto {
// In addition to the default 'src/main/proto'
srcDir 'src/generated'
}
java {
srcDir 'src/java'
}
}
}
idea {
module {
// proto files and generated Java files are automatically added as
// source dirs.
// If you have additional sources, add them here:
sourceDirs += file("/proto/");
}
}
signing {
sign publishing.publications.mavenJava
}
javadoc {
if(JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
}

View File

@ -36,7 +36,7 @@ public final class Grasscutter {
private static GameServer gameServer; private static GameServer gameServer;
private static PluginManager pluginManager; private static PluginManager pluginManager;
public static final Reflections reflector = new Reflections(); public static final Reflections reflector = new Reflections("emu.grasscutter");
static { static {
// Declare logback configuration. // Declare logback configuration.
@ -70,13 +70,13 @@ public final class Grasscutter {
// Database // Database
DatabaseManager.initialize(); DatabaseManager.initialize();
// Create plugin manager instance.
pluginManager = new PluginManager();
// Create server instances. // Create server instances.
dispatchServer = new DispatchServer(); dispatchServer = new DispatchServer();
gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port)); gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
// Create plugin manager instance.
pluginManager = new PluginManager();
// Start servers. // Start servers.
if(getConfig().RunMode.equalsIgnoreCase("HYBRID")) { if(getConfig().RunMode.equalsIgnoreCase("HYBRID")) {
dispatchServer.start(); dispatchServer.start();

View File

@ -14,4 +14,6 @@ public @interface Command {
String[] aliases() default {}; String[] aliases() default {};
String permission() default ""; String permission() default "";
boolean threading() default false;
} }

View File

@ -11,7 +11,6 @@ import java.util.*;
public final class CommandMap { public final class CommandMap {
private final Map<String, CommandHandler> commands = new HashMap<>(); private final Map<String, CommandHandler> commands = new HashMap<>();
private final Map<String, Command> annotations = new HashMap<>(); private final Map<String, Command> annotations = new HashMap<>();
public CommandMap() { public CommandMap() {
this(false); this(false);
} }
@ -106,8 +105,9 @@ 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."); return; CommandHandler.sendMessage(player, "No command specified.");
return;
} }
// Remove prefix if present. // Remove prefix if present.
@ -118,7 +118,6 @@ public final class CommandMap {
String[] split = rawMessage.split(" "); String[] split = rawMessage.split(" ");
List<String> args = new LinkedList<>(Arrays.asList(split)); List<String> args = new LinkedList<>(Arrays.asList(split));
String label = args.remove(0); String label = args.remove(0);
// Get command handler. // Get command handler.
CommandHandler handler = this.commands.get(label); CommandHandler handler = this.commands.get(label);
if (handler == null) { if (handler == null) {
@ -130,14 +129,22 @@ 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.isEmpty() && !account.hasPermission(permissionNode)) { if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) {
CommandHandler.sendMessage(player, "You do not have permission to run this command."); CommandHandler.sendMessage(player, "You do not have permission to run this command.");
return; return;
} }
} }
// Invoke execute method for handler. // Invoke execute method for handler.
handler.execute(player, args); boolean threading = this.annotations.get(label).threading();
Runnable runnable = () -> handler.execute(player, args);
if(threading) {
Thread command = new Thread(runnable);
command.start();
}
else {
runnable.run();
}
} }
/** /**

View File

@ -3,15 +3,10 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command; import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler; import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.inventory.ItemType;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List; import java.util.List;
@Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid] @Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid]
@ -33,62 +28,62 @@ public final class ClearCommand implements CommandHandler {
try { try {
target = Integer.parseInt(args.get(0)); target = Integer.parseInt(args.get(0));
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null && sender != null) { if (targetPlayer == null) {
target = sender.getUid(); target = sender.getUid();
} else { } else {
switch (cmdSwitch){ switch (cmdSwitch) {
case "wp": case "wp" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_WEAPON) .filter(item -> item.getItemType() == ItemType.ITEM_WEAPON)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared weapons for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared weapons for " + targetPlayer.getNickname() + " .");
break; }
case "art": case "art" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY) .filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY)
.filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> item.getLevel() == 1 && item.getExp() == 0)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " .");
break; }
case "mat": case "mat" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL) .filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL)
.filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> item.getLevel() == 1 && item.getExp() == 0)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " .");
break; }
case "all": case "all" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY) .filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY)
.filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0) .filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0)
.filter(item1 -> !item1.isLocked() && !item1.isEquipped()) .filter(item1 -> !item1.isLocked() && !item1.isEquipped())
.forEach(item1 -> playerInventory.removeItem(item1, item1.getCount())); .forEach(item1 -> playerInventory.removeItem(item1, item1.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL) .filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL)
.filter(item2 -> !item2.isLocked() && !item2.isEquipped()) .filter(item2 -> !item2.isLocked() && !item2.isEquipped())
.forEach(item2 -> playerInventory.removeItem(item2, item2.getCount())); .forEach(item2 -> playerInventory.removeItem(item2, item2.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON) .filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON)
.filter(item3 -> item3.getLevel() == 1 && item3.getExp() == 0) .filter(item3 -> item3.getLevel() == 1 && item3.getExp() == 0)
.filter(item3 -> !item3.isLocked() && !item3.isEquipped()) .filter(item3 -> !item3.isLocked() && !item3.isEquipped())
.forEach(item3 -> playerInventory.removeItem(item3, item3.getCount())); .forEach(item3 -> playerInventory.removeItem(item3, item3.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE) .filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE)
.filter(item4 -> !item4.isLocked() && !item4.isEquipped()) .filter(item4 -> !item4.isLocked() && !item4.isEquipped())
.forEach(item4 -> playerInventory.removeItem(item4, item4.getCount())); .forEach(item4 -> playerInventory.removeItem(item4, item4.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY) .filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY)
.filter(item5 -> !item5.isLocked() && !item5.isEquipped()) .filter(item5 -> !item5.isLocked() && !item5.isEquipped())
.forEach(item5 -> playerInventory.removeItem(item5, item5.getCount())); .forEach(item5 -> playerInventory.removeItem(item5, item5.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL) .filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL)
.filter(item6 -> !item6.isLocked() && !item6.isEquipped()) .filter(item6 -> !item6.isLocked() && !item6.isEquipped())
.forEach(item6 -> playerInventory.removeItem(item6, item6.getCount())); .forEach(item6 -> playerInventory.removeItem(item6, item6.getCount()));
sender.dropMessage("Cleared everything for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared everything for " + targetPlayer.getNickname() + " .");
break; }
} }
} }
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {

View File

@ -0,0 +1,189 @@
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.ItemType;
import java.util.*;
@Command(label = "giveall", usage = "giveall [player] <amount>",
description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true)
public class GiveAllCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
int target, amount = 99999;
switch (args.size()) {
case 0: // *no args*
if (sender == null) {
CommandHandler.sendMessage(null, "This usage can only be run in-game");
return;
}
target = sender.getUid();
break;
case 1: // [player]
try {
target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(sender, "Invalid player ID.");
return;
}
}catch (NumberFormatException ignored){
CommandHandler.sendMessage(sender, "Invalid player ID.");
return;
}
break;
case 2: // [player] [amount]
try {
target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = sender.getUid();
amount = Integer.parseInt(args.get(0));
} else {
amount = Integer.parseInt(args.get(1));
}
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid amount or player ID.");
return;
}
break;
default: // invalid
CommandHandler.sendMessage(null, "Usage: giveall [player] <amount>");
return;
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
}
this.giveAllItems(targetPlayer, amount);
CommandHandler.sendMessage(sender, "Giving all items done");
}
public void giveAllItems(GenshinPlayer player, int amount) {
CommandHandler.sendMessage(player, "Giving all items...");
for (AvatarData avatarData: GenshinData.getAvatarDataMap().values()) {
//Exclude test avatar
if (isTestAvatar(avatarData.getId())) continue;
GenshinAvatar avatar = new GenshinAvatar(avatarData);
avatar.setLevel(90);
avatar.setPromoteLevel(6);
for (int i = 1; i <= 6; ++i) {
avatar.getTalentIdList().add((avatar.getAvatarId() - 10000000) * 10 + i);
}
// This will handle stats and talents
avatar.recalcStats();
player.addAvatar(avatar);
}
//some test items
List<GenshinItem> genshinItemList = new ArrayList<>();
for (ItemData itemdata: GenshinData.getItemDataMap().values()) {
//Exclude test item
if (isTestItem(itemdata.getId())) continue;
if (itemdata.isEquip()) {
for (int i = 0; i < 10; ++i) {
GenshinItem genshinItem = new GenshinItem(itemdata);
if (itemdata.getItemType() == ItemType.ITEM_WEAPON) {
genshinItem.setLevel(90);
genshinItem.setPromoteLevel(6);
genshinItem.setRefinement(4);
}
genshinItemList.add(genshinItem);
}
}
else {
GenshinItem genshinItem = new GenshinItem(itemdata);
genshinItem.setCount(amount);
genshinItemList.add(genshinItem);
}
}
int packetNum = 20;
int itemLength = genshinItemList.size();
int number = itemLength / packetNum;
int remainder = itemLength % packetNum;
int offset = 0;
for (int i = 0; i < packetNum; ++i) {
if (remainder > 0) {
player.getInventory().addItems(genshinItemList.subList(i * number + offset, (i + 1) * number + offset + 1));
--remainder;
++offset;
}
else {
player.getInventory().addItems(genshinItemList.subList(i * number + offset, (i + 1) * number + offset));
}
}
}
public boolean isTestAvatar(int avatarId) {
return avatarId < 10000002 || avatarId >= 11000000;
}
public boolean isTestItem(int itemId) {
for (Range range: testItemRanges) {
if (range.check(itemId)) {
return true;
}
}
if (testItemsList.contains(itemId)) {
return true;
}
return false;
}
static class Range {
private int min;
private int max;
public Range(int min, int max) {
if(min > max){
min ^= max;
max ^= min;
min ^= max;
}
this.min = min;
this.max = max;
}
public boolean check(int value) {
return value >= this.min && value <= this.max;
}
}
private static final Range[] testItemRanges = new Range[] {
new Range(106, 139),
new Range(1000, 1099),
new Range(2001, 2008),
new Range(2017, 2029),
// new Range(108001, 108387) //food
};
private static final Integer[] testItemsIds = new Integer[] {
210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202, 2800,
100001, 100002, 100244, 100305, 100312, 100313, 101212, 11411, 11506, 11507, 11508, 12505,
12506, 12508, 12509, 13503, 13506, 14411, 14503, 14505, 14508, 15411, 15504, 15505,
15506, 15508, 20001, 10002, 10003, 10004, 10005, 10006, 10008 //9
};
private static final Collection<Integer> testItemsList = Arrays.asList(testItemsIds);
}

View File

@ -6,20 +6,19 @@ import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
import java.util.List; import java.util.List;
@Command(label = "heal", usage = "heal|h", @Command(label = "heal", usage = "heal|h", aliases = {"h"},
description = "Heal all characters in your current team.", aliases = {"h"}, permission = "player.heal") description = "Heal all characters in your current team.", permission = "player.heal")
public class HealCommand implements CommandHandler { public final class HealCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) { if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game."); CommandHandler.sendMessage(null, "Run this command in-game.");
return; return;
} }
sender.getTeamManager().getActiveTeam().forEach(entity -> { sender.getTeamManager().getActiveTeam().forEach(entity -> {
boolean isAlive = entity.isAlive(); boolean isAlive = entity.isAlive();
entity.setFightProperty( entity.setFightProperty(
@ -31,6 +30,6 @@ public class HealCommand implements CommandHandler {
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
} }
}); });
CommandHandler.sendMessage(sender, "All characters are healed."); CommandHandler.sendMessage(sender, "All characters have been healed.");
} }
} }

View File

@ -9,7 +9,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
@Command(label = "list", description = "List online players") @Command(label = "list", description = "List online players")
public class ListCommand implements CommandHandler { public final class ListCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
@ -19,14 +19,10 @@ public class ListCommand implements CommandHandler {
if (playersMap.size() != 0) { if (playersMap.size() != 0) {
StringBuilder playerSet = new StringBuilder(); StringBuilder playerSet = new StringBuilder();
playersMap.values().forEach(player ->
for (Map.Entry<Integer, GenshinPlayer> entry : playersMap.entrySet()) { playerSet.append(player.getNickname()).append(", "));
playerSet.append(entry.getValue().getNickname());
playerSet.append(", ");
}
String players = playerSet.toString(); String players = playerSet.toString();
CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2)); CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2));
} }
} }

View File

@ -43,7 +43,7 @@ public final class SetFetterLevelCommand implements CommandHandler {
sender.sendPacket(new PacketAvatarFetterDataNotify(avatar)); sender.sendPacket(new PacketAvatarFetterDataNotify(avatar));
CommandHandler.sendMessage(sender, "Fetter level set to " + fetterLevel); CommandHandler.sendMessage(sender, "Fetter level set to " + fetterLevel);
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, "Invalid fetter level."); CommandHandler.sendMessage(sender, "Invalid fetter level.");
} }
} }

View File

@ -13,7 +13,7 @@ import java.util.List;
@Command(label = "talent", usage = "talent <talentID> <value>", @Command(label = "talent", usage = "talent <talentID> <value>",
description = "Set talent level for your current active character", permission = "player.settalent") description = "Set talent level for your current active character", permission = "player.settalent")
public class TalentCommand implements CommandHandler { public final class TalentCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {

View File

@ -9,7 +9,7 @@ import java.util.List;
@Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"}, @Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"},
description = "Change the player's position.", permission = "player.teleport") description = "Change the player's position.", permission = "player.teleport")
public class TelePortCommand implements CommandHandler { public final class TeleportCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {

View File

@ -140,7 +140,7 @@ public class ResourceLoader {
} }
List<ScenePointEntry> scenePointList = new ArrayList<>(); List<ScenePointEntry> scenePointList = new ArrayList<>();
for (File file : folder.listFiles()) { for (File file : Objects.requireNonNull(folder.listFiles())) {
ScenePointConfig config = null; ScenePointConfig config = null;
Integer sceneId = null; Integer sceneId = null;

View File

@ -0,0 +1,10 @@
package emu.grasscutter.data.def;
import emu.grasscutter.data.ResourceType;
@ResourceType(name = "CombineExcelConfigData.json")
public class CombineData {
}

View File

@ -31,9 +31,10 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType; import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo; import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify; import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
@ -97,7 +98,7 @@ public class GenshinPlayer {
private TeamManager teamManager; private TeamManager teamManager;
private PlayerGachaInfo gachaInfo; private PlayerGachaInfo gachaInfo;
private PlayerProfile playerProfile; private PlayerProfile playerProfile;
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply; private MpSettingType mpSetting = MpSettingType.MP_SETTING_ENTER_AFTER_APPLY;
private boolean showAvatar; private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels; private Set<Integer> rewardedLevels;
@ -659,7 +660,7 @@ public class GenshinPlayer {
// Add to inventory // Add to inventory
boolean success = getInventory().addItem(item); boolean success = getInventory().addItem(item);
if (success) { if (success) {
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.InteractPickItem)); this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop)); this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop));
} }
} }
@ -689,7 +690,7 @@ public class GenshinPlayer {
.setMpSettingType(this.getMpSetting()) .setMpSettingType(this.getMpSetting())
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())); .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId());
if (this.getWorld() != null) { if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1); onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1);
@ -724,21 +725,19 @@ public class GenshinPlayer {
public SocialDetail.Builder getSocialDetail() { public SocialDetail.Builder getSocialDetail() {
SocialDetail.Builder social = SocialDetail.newBuilder() SocialDetail.Builder social = SocialDetail.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())) .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId())
.setNickname(this.getNickname()) .setNickname(this.getNickname())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setLevel(this.getLevel()) .setLevel(this.getLevel())
.setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty()) .setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty())
.setWorldLevel(this.getWorldLevel()) .setWorldLevel(this.getWorldLevel())
.setUnk1(1)
.setUnk3(1)
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setFinishAchievementNum(0); .setFinishAchievementNum(0);
return social; return social;
} }
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() { public PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder() return PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo.newBuilder()
.setSceneId(this.getSceneId()) .setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo()) .setPlayerLoc(this.getPlayerLocationInfo())
.build(); .build();
@ -763,7 +762,7 @@ public class GenshinPlayer {
while (it.hasNext()) { while (it.hasNext()) {
CoopRequest req = it.next(); CoopRequest req = it.next();
if (req.isExpired()) { if (req.isExpired()) {
req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpReason.SystemJudge)); req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.SYSTEM_JUDGE));
it.remove(); it.remove();
} }
} }

View File

@ -202,7 +202,7 @@ public class GenshinScene {
private void removePlayerAvatars(GenshinPlayer player) { private void removePlayerAvatars(GenshinPlayer player) {
Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator(); Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator();
while (it.hasNext()) { while (it.hasNext()) {
this.removeEntity(it.next(), VisionType.VisionRemove); this.removeEntity(it.next(), VisionType.VISION_REMOVE);
it.remove(); it.remove();
} }
} }
@ -233,7 +233,7 @@ public class GenshinScene {
this.addEntityDirectly(entity); this.addEntityDirectly(entity);
} }
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_BORN));
} }
private GenshinEntity removeEntityDirectly(GenshinEntity entity) { private GenshinEntity removeEntityDirectly(GenshinEntity entity) {
@ -241,7 +241,7 @@ public class GenshinScene {
} }
public void removeEntity(GenshinEntity entity) { public void removeEntity(GenshinEntity entity) {
this.removeEntity(entity, VisionType.VisionDie); this.removeEntity(entity, VisionType.VISION_DIE);
} }
public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) { public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) {
@ -254,8 +254,8 @@ public class GenshinScene {
public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) {
this.removeEntityDirectly(oldEntity); this.removeEntityDirectly(oldEntity);
this.addEntityDirectly(newEntity); this.addEntityDirectly(newEntity);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VisionReplace)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_REPLACE));
this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VisionReplace, oldEntity.getId())); this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_REPLACE, oldEntity.getId()));
} }
public void showOtherEntities(GenshinPlayer player) { public void showOtherEntities(GenshinPlayer player) {
@ -269,7 +269,7 @@ public class GenshinScene {
entities.add(entity); entities.add(entity);
} }
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionMeet)); player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
} }
public void handleAttack(AttackResult result) { public void handleAttack(AttackResult result) {
@ -381,11 +381,11 @@ public class GenshinScene {
if (toAdd.size() > 0) { if (toAdd.size() > 0) {
toAdd.stream().forEach(this::addEntityDirectly); toAdd.stream().forEach(this::addEntityDirectly);
this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
} }
if (toRemove.size() > 0) { if (toRemove.size() > 0) {
toRemove.stream().forEach(this::removeEntityDirectly); toRemove.stream().forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VisionRemove)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE));
} }
} }
@ -425,7 +425,7 @@ public class GenshinScene {
return; return;
} }
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VisionDie)); this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_DIE));
} }
// Broadcasting // Broadcasting

View File

@ -20,18 +20,11 @@ public class InvokeHandler<T> {
public synchronized void addEntry(ForwardType forward, T entry) { public synchronized void addEntry(ForwardType forward, T entry) {
switch (forward) { switch (forward) {
case ForwardToAll: case FORWARD_TO_ALL -> entryListForwardAll.add(entry);
entryListForwardAll.add(entry); case FORWARD_TO_ALL_EXCEPT_CUR, FORWARD_TO_ALL_EXIST_EXCEPT_CUR -> entryListForwardAllExceptCur.add(entry);
break; case FORWARD_TO_HOST -> entryListForwardHost.add(entry);
case ForwardToAllExceptCur: default -> {
case ForwardToAllExistExceptCur: }
entryListForwardAllExceptCur.add(entry);
break;
case ForwardToHost:
entryListForwardHost.add(entry);
break;
default:
break;
} }
} }

View File

@ -397,7 +397,7 @@ public class TeamManager {
this.setCurrentCharacterIndex(index); this.setCurrentCharacterIndex(index);
// Old entity motion state // Old entity motion state
oldEntity.setMotionState(MotionState.MotionStandby); oldEntity.setMotionState(MotionState.MOTION_STANDBY);
// Remove and Add // Remove and Add
getPlayer().getScene().replaceEntity(oldEntity, newEntity); getPlayer().getScene().replaceEntity(oldEntity, newEntity);
@ -476,7 +476,7 @@ public class TeamManager {
} }
// Teleport player // Teleport player
getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.EnterSelf, EnterReason.Revival, 3, GenshinConstants.START_POSITION)); getPlayer().sendPacket(new PacketPlayerEnterSceneNotify(getPlayer(), EnterType.ENTER_SELF, EnterReason.Revival, 3, GenshinConstants.START_POSITION));
// Set player position // Set player position
player.setSceneId(3); player.setSceneId(3);

View File

@ -197,7 +197,7 @@ public class World implements Iterable<GenshinPlayer> {
World world = new World(victim); World world = new World(victim);
world.addPlayer(victim); world.addPlayer(victim);
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.EnterSelf, EnterReason.TeamKick, victim.getSceneId(), victim.getPos())); victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPos()));
} }
} }
} }
@ -238,9 +238,9 @@ public class World implements Iterable<GenshinPlayer> {
// Teleport packet // Teleport packet
if (oldScene == newScene) { if (oldScene == newScene) {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterGoto, EnterReason.TransPoint, sceneId, pos)); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_GOTO, EnterReason.TransPoint, sceneId, pos));
} else { } else {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterJump, EnterReason.TransPoint, sceneId, pos)); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_JUMP, EnterReason.TransPoint, sceneId, pos));
} }
return true; return true;
} }

View File

@ -778,7 +778,7 @@ public class GenshinAvatar {
.setCoreProudSkillLevel(this.getCoreProudSkillLevel()) .setCoreProudSkillLevel(this.getCoreProudSkillLevel())
.putAllSkillLevelMap(this.getSkillLevelMap()) .putAllSkillLevelMap(this.getSkillLevelMap())
.addAllInherentProudSkillList(this.getProudSkillList()) .addAllInherentProudSkillList(this.getProudSkillList())
.putAllProudSkillExtraLevel(getProudSkillBonusMap()) .putAllProudSkillExtraLevelMap(getProudSkillBonusMap())
.setAvatarType(1) .setAvatarType(1)
.setBornTime(this.getBornTime()) .setBornTime(this.getBornTime())
.setFetterInfo(avatarFetter) .setFetterInfo(avatarFetter)

View File

@ -101,13 +101,13 @@ public class EntityAvatar extends GenshinEntity {
@Override @Override
public void onDeath(int killerId) { public void onDeath(int killerId) {
this.killedType = PlayerDieType.PlayerDieKillByMonster; this.killedType = PlayerDieType.PLAYER_DIE_KILL_BY_MONSTER;
this.killedBy = killerId; this.killedBy = killerId;
} }
public SceneAvatarInfo getSceneAvatarInfo() { public SceneAvatarInfo getSceneAvatarInfo() {
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder() SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
.setPlayerId(this.getPlayer().getUid()) .setUid(this.getPlayer().getUid())
.setAvatarId(this.getAvatar().getAvatarId()) .setAvatarId(this.getAvatar().getAvatarId())
.setGuid(this.getAvatar().getGuid()) .setGuid(this.getAvatar().getGuid())
.setPeerId(this.getPlayer().getPeerId()) .setPeerId(this.getPlayer().getPeerId())
@ -145,7 +145,7 @@ public class EntityAvatar extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityAvatar) .setEntityType(ProtEntityType.PROT_ENTITY_AVATAR)
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority) .setEntityAuthorityInfo(authority)
@ -161,7 +161,7 @@ public class EntityAvatar extends GenshinEntity {
if (entry.getIntKey() == 0) { if (entry.getIntKey() == 0) {
continue; continue;
} }
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build(); FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp); entityInfo.addFightPropList(fightProp);
} }

View File

@ -6,6 +6,7 @@ import emu.grasscutter.game.World;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair; import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo; import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData; import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo; import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
@ -112,7 +113,7 @@ public class EntityClientGadget extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget) .setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
@ -125,7 +126,7 @@ public class EntityClientGadget extends EntityGadget {
.build(); .build();
entityInfo.addPropList(pair); entityInfo.addPropList(pair);
GadgetClientParam clientGadget = GadgetClientParam.newBuilder() ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder()
.setCampId(this.getCampId()) .setCampId(this.getCampId())
.setCampType(this.getCampType()) .setCampType(this.getCampType())
.setOwnerEntityId(this.getOwnerEntityId()) .setOwnerEntityId(this.getOwnerEntityId())

View File

@ -92,7 +92,7 @@ public class EntityItem extends EntityGadget {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityGadget) .setEntityType(ProtEntityType.PROT_ENTITY_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
@ -108,7 +108,7 @@ public class EntityItem extends EntityGadget {
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
.setGadgetId(this.getItemData().getGadgetId()) .setGadgetId(this.getItemData().getGadgetId())
.setTrifleItem(this.getItem().toProto()) .setTrifleItem(this.getItem().toProto())
.setBornType(GadgetBornType.GadgetBornInAir) .setBornType(GadgetBornType.GADGET_BORN_IN_AIR)
.setAuthorityPeerId(this.getWorld().getHostPeerId()) .setAuthorityPeerId(this.getWorld().getHostPeerId())
.setIsEnableInteract(true); .setIsEnableInteract(true);

View File

@ -197,7 +197,7 @@ public class EntityMonster extends GenshinEntity {
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.ProtEntityMonster) .setEntityType(ProtEntityType.PROT_ENTITY_MONSTER)
.setMotionInfo(this.getMotionInfo()) .setMotionInfo(this.getMotionInfo())
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
@ -208,7 +208,7 @@ public class EntityMonster extends GenshinEntity {
if (entry.getIntKey() == 0) { if (entry.getIntKey() == 0) {
continue; continue;
} }
FightPropPair fightProp = FightPropPair.newBuilder().setType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build(); FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
entityInfo.addFightPropList(fightProp); entityInfo.addFightPropList(fightProp);
} }
@ -226,7 +226,7 @@ public class EntityMonster extends GenshinEntity {
.setAuthorityPeerId(getWorld().getHostPeerId()) .setAuthorityPeerId(getWorld().getHostPeerId())
.setPoseId(this.getPoseId()) .setPoseId(this.getPoseId())
.setBlockId(3001) .setBlockId(3001)
.setBornType(MonsterBornType.MonsterBornDefault) .setBornType(MonsterBornType.MONSTER_BORN_DEFAULT)
.setSpecialNameId(40); .setSpecialNameId(40);
if (getMonsterData().getDescribeData() != null) { if (getMonsterData().getDescribeData() != null) {
@ -240,7 +240,7 @@ public class EntityMonster extends GenshinEntity {
.setAbilityInfo(AbilitySyncStateInfo.newBuilder()) .setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.build(); .build();
monsterInfo.setWeaponList(weaponInfo); monsterInfo.addWeaponList(weaponInfo);
} }
entityInfo.setMonster(monsterInfo); entityInfo.setMonster(monsterInfo);

View File

@ -23,7 +23,7 @@ public abstract class GenshinEntity {
public GenshinEntity(GenshinScene scene) { public GenshinEntity(GenshinScene scene) {
this.scene = scene; this.scene = scene;
this.moveState = MotionState.MotionNone; this.moveState = MotionState.MOTION_NONE;
} }
public int getId() { public int getId() {

View File

@ -104,7 +104,7 @@ public class FriendsList {
} }
// Handle // Handle
if (result == DealAddFriendResultType.DealAddFriendAccept) { // Request accepted if (result == DealAddFriendResultType.DEAL_ADD_FRIEND_ACCEPT) { // Request accepted
myFriendship.setIsFriend(true); myFriendship.setIsFriend(true);
theirFriendship.setIsFriend(true); theirFriendship.setIsFriend(true);

View File

@ -1,5 +1,6 @@
package emu.grasscutter.game.friends; package emu.grasscutter.game.friends;
import emu.grasscutter.net.proto.PlatformTypeOuterClass;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import dev.morphia.annotations.*; import dev.morphia.annotations.*;
@ -91,16 +92,16 @@ public class Friendship {
.setUid(getFriendProfile().getUid()) .setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName()) .setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel()) .setLevel(getFriendProfile().getPlayerLevel())
.setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId())) .setAvatarId(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId()).getAvatarId())
.setWorldLevel(getFriendProfile().getWorldLevel()) .setWorldLevel(getFriendProfile().getWorldLevel())
.setSignature(getFriendProfile().getSignature()) .setSignature(getFriendProfile().getSignature())
.setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE : FriendOnlineState.FRIEND_DISCONNECT) .setOnlineState(getFriendProfile().isOnline() ? FriendOnlineState.FRIEND_ONLINE : FriendOnlineState.FREIEND_DISCONNECT)
.setIsMpModeAvailable(true) .setIsMpModeAvailable(true)
.setLastActiveTime(getFriendProfile().getLastActiveTime()) .setLastActiveTime(getFriendProfile().getLastActiveTime())
.setNameCardId(getFriendProfile().getNameCard()) .setNameCardId(getFriendProfile().getNameCard())
.setParam(getFriendProfile().getDaysSinceLogin()) .setParam(getFriendProfile().getDaysSinceLogin())
.setUnk1(1) .setIsGameSource(true)
.setUnk2(3) .setPlatformType(PlatformTypeOuterClass.PlatformType.PC)
.build(); .build();
return proto; return proto;

View File

@ -286,8 +286,6 @@ public class GachaManager {
this.watchService = FileSystems.getDefault().newWatchService(); this.watchService = FileSystems.getDefault().newWatchService();
Path path = new File(Grasscutter.getConfig().DATA_FOLDER).toPath(); Path path = new File(Grasscutter.getConfig().DATA_FOLDER).toPath();
path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH); path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH);
server.OnGameServerTick.register(this);
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"); Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload");
e.printStackTrace(); e.printStackTrace();

View File

@ -7,6 +7,7 @@ import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.game.World; import emu.grasscutter.game.World;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpNotify; import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpNotify;
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify; import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify;
@ -26,7 +27,7 @@ public class MultiplayerManager {
public void applyEnterMp(GenshinPlayer player, int targetUid) { public void applyEnterMp(GenshinPlayer player, int targetUid) {
GenshinPlayer target = getServer().getPlayerByUid(targetUid); GenshinPlayer target = getServer().getPlayerByUid(targetUid);
if (target == null) { if (target == null) {
player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpReason.PlayerCannotEnterMp)); player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP));
return; return;
} }
@ -71,12 +72,12 @@ public class MultiplayerManager {
// Sanity checks - Dont let the requesting player join if they are already in multiplayer // Sanity checks - Dont let the requesting player join if they are already in multiplayer
if (requester.getWorld().isMultiplayer()) { if (requester.getWorld().isMultiplayer()) {
request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpReason.PlayerCannotEnterMp)); request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_CANNOT_ENTER_MP));
return; return;
} }
// Response packet // Response packet
request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpReason.PlayerJudge)); request.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(hostPlayer, isAgreed, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.PLAYER_JUDGE));
// Declined // Declined
if (!isAgreed) { if (!isAgreed) {
@ -92,7 +93,7 @@ public class MultiplayerManager {
world.addPlayer(hostPlayer); world.addPlayer(hostPlayer);
// Rejoin packet // Rejoin packet
hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.EnterSelf, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos())); hostPlayer.sendPacket(new PacketPlayerEnterSceneNotify(hostPlayer, hostPlayer, EnterType.ENTER_SELF, EnterReason.HostFromSingleToMp, hostPlayer.getScene().getId(), hostPlayer.getPos()));
} }
// Set scene pos and id of requester to the host player's // Set scene pos and id of requester to the host player's
@ -104,7 +105,7 @@ public class MultiplayerManager {
hostPlayer.getWorld().addPlayer(requester); hostPlayer.getWorld().addPlayer(requester);
// Packet // Packet
requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.EnterOther, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos())); requester.sendPacket(new PacketPlayerEnterSceneNotify(requester, hostPlayer, EnterType.ENTER_OTHER, EnterReason.TeamJoin, hostPlayer.getScene().getId(), hostPlayer.getPos()));
} }
public boolean leaveCoop(GenshinPlayer player) { public boolean leaveCoop(GenshinPlayer player) {
@ -125,7 +126,7 @@ public class MultiplayerManager {
world.addPlayer(player); world.addPlayer(player);
// Packet // Packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TeamBack, player.getScene().getId(), player.getPos())); player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_SELF, EnterReason.TeamBack, player.getScene().getId(), player.getPos()));
return true; return true;
} }
@ -152,7 +153,7 @@ public class MultiplayerManager {
World world = new World(victim); World world = new World(victim);
world.addPlayer(victim); world.addPlayer(victim);
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.EnterSelf, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos())); victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getScene().getId(), victim.getPos()));
return true; return true;
} }
} }

View File

@ -1009,6 +1009,7 @@ public class PacketOpcodes {
public static final int SetNameCardRsp = 4009; public static final int SetNameCardRsp = 4009;
public static final int SetOpenStateReq = 162; public static final int SetOpenStateReq = 162;
public static final int SetOpenStateRsp = 189; public static final int SetOpenStateRsp = 189;
public static final int SetPlayerBirthdayReq = 4097; public static final int SetPlayerBirthdayReq = 4097;
public static final int SetPlayerBirthdayRsp = 4088; public static final int SetPlayerBirthdayRsp = 4088;
public static final int SetPlayerBornDataReq = 155; public static final int SetPlayerBornDataReq = 155;
@ -1034,8 +1035,6 @@ public class PacketOpcodes {
public static final int ShowTemplateReminderNotify = 3164; public static final int ShowTemplateReminderNotify = 3164;
public static final int SignInInfoReq = 2510; public static final int SignInInfoReq = 2510;
public static final int SignInInfoRsp = 2515; public static final int SignInInfoRsp = 2515;
public static final int SitReq = 354;
public static final int SitRsp = 335;
public static final int SocialDataNotify = 4063; public static final int SocialDataNotify = 4063;
public static final int SpringUseReq = 1720; public static final int SpringUseReq = 1720;
public static final int SpringUseRsp = 1727; public static final int SpringUseRsp = 1727;

View File

@ -1,6 +0,0 @@
package emu.grasscutter.net.packet;
public class Retcode {
public static final int SUCCESS = 0;
public static final int FAIL = 1;
}

View File

@ -13,9 +13,11 @@ import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.*; import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/** /**
* Manages the server's plugins & the event system. * Manages the server's plugins and the event system.
*/ */
public final class PluginManager { public final class PluginManager {
private final Map<String, Plugin> plugins = new HashMap<>(); private final Map<String, Plugin> plugins = new HashMap<>();
@ -60,6 +62,15 @@ public final class PluginManager {
return; return;
} }
JarFile jarFile = new JarFile(plugin);
Enumeration<JarEntry> entries = jarFile.entries();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue;
String className = entry.getName().replace(".class", "").replace("/", ".");
Class<?> clazz = loader.loadClass(className);
}
Class<?> pluginClass = loader.loadClass(pluginConfig.mainClass); Class<?> pluginClass = loader.loadClass(pluginConfig.mainClass);
Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance();
this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig)); this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig));

View File

@ -0,0 +1,5 @@
package emu.grasscutter.plugin.api;
public enum Item {
/* TODO: Use handbook to generate an Item enum. */
}

View File

@ -0,0 +1,113 @@
package emu.grasscutter.plugin.api;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.utils.Position;
/**
* Hooks into the {@link GenshinPlayer} class, adding convenient ways to do certain things.
*/
public final class PlayerHook {
private final GenshinPlayer player;
/**
* Hooks into the player.
* @param player The player to hook into.
*/
public PlayerHook(GenshinPlayer player) {
this.player = player;
}
/**
* Kicks a player from the server.
*/
public void kick() {
this.player.getSession().close();
}
/**
* Sends a player to another scene.
* @param sceneId The scene to send the player to.
*/
public void changeScenes(int sceneId) {
this.player.getWorld().transferPlayerToScene(this.player, sceneId, this.player.getPos());
}
/**
* Broadcasts an avatar property notify to all world players.
* @param property The property that was updated.
*/
public void updateFightProperty(FightProperty property) {
this.broadcastPacketToWorld(new PacketAvatarFightPropUpdateNotify(this.getCurrentAvatar(), property));
}
/**
* Broadcasts the packet sent to all world players.
* @param packet The packet to send.
*/
public void broadcastPacketToWorld(GenshinPacket packet) {
this.player.getWorld().broadcastPacket(packet);
}
/**
* Set the currently equipped avatar's health.
* @param health The health to set the avatar to.
*/
public void setHealth(float health) {
this.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health);
this.updateFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
}
/**
* Revives the specified avatar.
* @param avatar The avatar to revive.
*/
public void reviveAvatar(GenshinAvatar avatar) {
this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar));
}
/**
* Teleports a player to a position.
* This will **not** transfer the player to another scene.
* @param position The position to teleport the player to.
*/
public void teleport(Position position) {
this.player.getPos().set(position);
this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player,
EnterType.ENTER_JUMP, EnterReason.TransPoint,
this.player.getSceneId(), position
));
}
/**
* Gets the currently selected avatar's max health.
* @return The max health as a float.
*/
public float getMaxHealth() {
return this.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
}
/**
* Gets the currently selected avatar in entity form.
* @return The avatar as an {@link EntityAvatar}.
*/
public EntityAvatar getCurrentAvatarEntity() {
return this.player.getTeamManager().getCurrentAvatarEntity();
}
/**
* Gets the currently selected avatar.
* @return The avatar as an {@link GenshinAvatar}.
*/
public GenshinAvatar getCurrentAvatar() {
return this.getCurrentAvatarEntity().getAvatar();
}
}

View File

@ -0,0 +1,2 @@
# Grasscutter Plugin API
**Warning!** As of now, this is a work in progress and isn't completely documented.

View File

@ -0,0 +1,41 @@
package emu.grasscutter.plugin.api;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.server.game.GameServer;
import java.util.LinkedList;
import java.util.List;
/**
* Hooks into the {@link GameServer} class, adding convenient ways to do certain things.
*/
public final class ServerHook {
private static ServerHook instance;
private final GameServer server;
/**
* Gets the server hook instance.
* @return A {@link ServerHook} singleton.
*/
public static ServerHook getInstance() {
return instance;
}
/**
* Hooks into a server.
* @param server The server to hook into.
*/
public ServerHook(GameServer server) {
this.server = server;
instance = this;
}
/**
* Gets all online players.
* @return Players connected to the server.
*/
public List<GenshinPlayer> getOnlinePlayers() {
return new LinkedList<>(this.server.getPlayers().values());
}
}

View File

@ -103,8 +103,8 @@ public final class DispatchServer {
byte[] decoded2 = Base64.getDecoder().decode(query_cur_region); byte[] decoded2 = Base64.getDecoder().decode(query_cur_region);
QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2); QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2);
List<RegionSimpleInfo> servers = new ArrayList<RegionSimpleInfo>(); List<RegionSimpleInfo> servers = new ArrayList<>();
List<String> usedNames = new ArrayList<String>(); // List to check for potential naming conflicts List<String> usedNames = new ArrayList<>(); // List to check for potential naming conflicts
if (Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) { // Automatically add the game server if in if (Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) { // Automatically add the game server if in
// hybrid mode // hybrid mode
RegionSimpleInfo server = RegionSimpleInfo.newBuilder() RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
@ -126,10 +126,10 @@ public final class DispatchServer {
servers.add(server); servers.add(server);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() .setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty()
? Grasscutter.getConfig().getGameServerOptions().Ip ? Grasscutter.getConfig().getGameServerOptions().Ip
: Grasscutter.getConfig().getGameServerOptions().PublicIp)) : Grasscutter.getConfig().getGameServerOptions().PublicIp))
.setPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 .setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0
? Grasscutter.getConfig().getGameServerOptions().PublicPort ? Grasscutter.getConfig().getGameServerOptions().PublicPort
: Grasscutter.getConfig().getGameServerOptions().Port) : Grasscutter.getConfig().getGameServerOptions().Port)
.setSecretKey(ByteString .setSecretKey(ByteString
@ -169,8 +169,8 @@ public final class DispatchServer {
servers.add(server); servers.add(server);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setIp(regionInfo.Ip) .setGateserverIp(regionInfo.Ip)
.setPort(regionInfo.Port) .setGateserverPort(regionInfo.Port)
.setSecretKey(ByteString .setSecretKey(ByteString
.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) .copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build(); .build();
@ -181,7 +181,7 @@ public final class DispatchServer {
} }
QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder() QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder()
.addAllServers(servers) .addAllRegionList(servers)
.setClientSecretKey(rl.getClientSecretKey()) .setClientSecretKey(rl.getClientSecretKey())
.setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted()) .setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted())
.setEnableLoginPc(true) .setEnableLoginPc(true)
@ -268,7 +268,10 @@ public final class DispatchServer {
Grasscutter.getLogger() Grasscutter.getLogger()
.info(String.format("[Dispatch] Client %s request: query_region_list", t.getRemoteAddress())); .info(String.format("[Dispatch] Client %s request: query_region_list", t.getRemoteAddress()));
responseHTML(t, regionListBase64); // Invoke event.
QueryAllRegionsEvent event = new QueryAllRegionsEvent(regionListBase64); event.call();
// Respond with event result.
responseHTML(t, event.getRegionList());
}); });
for (String regionName : regions.keySet()) { for (String regionName : regions.keySet()) {

View File

@ -10,6 +10,10 @@ public abstract class ServerEvent extends Event {
this.type = type; this.type = type;
} }
public Type getServerType() {
return this.type;
}
public enum Type { public enum Type {
DISPATCH, DISPATCH,
GAME GAME

View File

@ -0,0 +1,9 @@
package emu.grasscutter.server.event.game;
import emu.grasscutter.server.event.ServerEvent;
public final class ServerTickEvent extends ServerEvent {
public ServerTickEvent() {
super(Type.GAME);
}
}

View File

@ -0,0 +1,19 @@
package emu.grasscutter.server.event.internal;
import emu.grasscutter.server.event.ServerEvent;
import java.time.OffsetDateTime;
public final class ServerStartEvent extends ServerEvent {
private final OffsetDateTime startTime;
public ServerStartEvent(Type type, OffsetDateTime startTime) {
super(type);
this.startTime = startTime;
}
public OffsetDateTime getStartTime() {
return this.startTime;
}
}

View File

@ -0,0 +1,19 @@
package emu.grasscutter.server.event.internal;
import emu.grasscutter.server.event.ServerEvent;
import java.time.OffsetDateTime;
public final class ServerStopEvent extends ServerEvent {
private final OffsetDateTime stopTime;
public ServerStopEvent(Type type, OffsetDateTime stopTime) {
super(type);
this.stopTime = stopTime;
}
public OffsetDateTime getStopTime() {
return this.stopTime;
}
}

View File

@ -1,6 +1,7 @@
package emu.grasscutter.server.game; package emu.grasscutter.server.game;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.time.OffsetDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -20,7 +21,10 @@ import emu.grasscutter.game.shop.ShopManager;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.netty.MihoyoKcpServer; import emu.grasscutter.netty.MihoyoKcpServer;
import org.greenrobot.eventbus.EventBus; import emu.grasscutter.server.event.ServerEvent;
import emu.grasscutter.server.event.game.ServerTickEvent;
import emu.grasscutter.server.event.internal.ServerStartEvent;
import emu.grasscutter.server.event.internal.ServerStopEvent;
public final class GameServer extends MihoyoKcpServer { public final class GameServer extends MihoyoKcpServer {
private final InetSocketAddress address; private final InetSocketAddress address;
@ -37,17 +41,9 @@ public final class GameServer extends MihoyoKcpServer {
private final DungeonManager dungeonManager; private final DungeonManager dungeonManager;
private final CommandMap commandMap; private final CommandMap commandMap;
public EventBus OnGameServerStartFinish;
public EventBus OnGameServerTick;
public EventBus OnGameServerStop;
public GameServer(InetSocketAddress address) { public GameServer(InetSocketAddress address) {
super(address); super(address);
OnGameServerStartFinish = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
OnGameServerTick = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
OnGameServerStop = EventBus.builder().throwSubscriberException(true).logNoSubscriberMessages(false).build();
this.setServerInitializer(new GameServerInitializer(this)); this.setServerInitializer(new GameServerInitializer(this));
this.address = address; this.address = address;
this.packetHandler = new GameServerPacketHandler(PacketHandler.class); this.packetHandler = new GameServerPacketHandler(PacketHandler.class);
@ -179,11 +175,7 @@ public final class GameServer extends MihoyoKcpServer {
world.onTick(); world.onTick();
} }
for (GenshinPlayer player : this.getPlayers().values()) { ServerTickEvent event = new ServerTickEvent(); event.call();
player.onTick();
}
OnGameServerTick.post(new GameServerTickEvent());
} }
public void registerWorld(World world) { public void registerWorld(World world) {
@ -198,12 +190,11 @@ public final class GameServer extends MihoyoKcpServer {
@Override @Override
public void onStartFinish() { public void onStartFinish() {
Grasscutter.getLogger().info("Game Server started on port " + address.getPort()); Grasscutter.getLogger().info("Game Server started on port " + address.getPort());
ServerStartEvent event = new ServerStartEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); event.call();
OnGameServerStartFinish.post(new GameServerStartFinishEvent());
} }
public void onServerShutdown() { public void onServerShutdown() {
OnGameServerStop.post(new GameServerStopEvent()); ServerStopEvent event = new ServerStopEvent(ServerEvent.Type.GAME, OffsetDateTime.now()); event.call();
// Kick and save all players // Kick and save all players
List<GenshinPlayer> list = new ArrayList<>(this.getPlayers().size()); List<GenshinPlayer> list = new ArrayList<>(this.getPlayers().size());

View File

@ -89,7 +89,7 @@ public class GameServerPacketHandler {
// Log unhandled packets // Log unhandled packets
if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) { if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
//Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode)); Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode));
} }
} }
} }

View File

@ -3,11 +3,14 @@ package emu.grasscutter.server.game;
import java.io.File; import java.io.File;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.Account; import emu.grasscutter.game.Account;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.packet.PacketOpcodesUtil; import emu.grasscutter.net.packet.PacketOpcodesUtil;
import emu.grasscutter.netty.MihoyoKcpChannel; import emu.grasscutter.netty.MihoyoKcpChannel;
import emu.grasscutter.server.event.game.SendPacketEvent; import emu.grasscutter.server.event.game.SendPacketEvent;
@ -178,9 +181,19 @@ public class GameSession extends MihoyoKcpChannel {
//System.out.println(Utils.bytesToHex(genshinPacket.getData())); //System.out.println(Utils.bytesToHex(genshinPacket.getData()));
} }
private static final Set<Integer> loopPacket = Set.of(
PacketOpcodes.PingReq,
PacketOpcodes.PingRsp,
PacketOpcodes.WorldPlayerRTTNotify,
PacketOpcodes.UnionCmdNotify,
PacketOpcodes.QueryPathReq
);
private void logPacket(GenshinPacket genshinPacket) { private void logPacket(GenshinPacket genshinPacket) {
Grasscutter.getLogger().info("SEND: " + PacketOpcodesUtil.getOpcodeName(genshinPacket.getOpcode()) + " (" + genshinPacket.getOpcode() + ")"); if (!loopPacket.contains(genshinPacket.getOpcode())) {
System.out.println(Utils.bytesToHex(genshinPacket.getData())); Grasscutter.getLogger().info("SEND: " + PacketOpcodesUtil.getOpcodeName(genshinPacket.getOpcode()) + " (" + genshinPacket.getOpcode() + ")");
System.out.println(Utils.bytesToHex(genshinPacket.getData()));
}
} }
@Override @Override
@ -226,8 +239,10 @@ public class GameSession extends MihoyoKcpChannel {
// Log packet // Log packet
if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) { if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")"); if (!loopPacket.contains(opcode)) {
System.out.println(Utils.bytesToHex(payload)); Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")");
System.out.println(Utils.bytesToHex(payload));
}
} }
// Handle // Handle

View File

@ -1,24 +0,0 @@
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SitReqOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketSitRsp;
import emu.grasscutter.utils.Position;
@Opcodes(PacketOpcodes.SitReq)
public class HandleSitReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
SitReqOuterClass.SitReq req = SitReqOuterClass.SitReq.parseFrom(payload);
float x = req.getPosition().getX();
float y = req.getPosition().getY();
float z = req.getPosition().getZ();
session.send(new PacketSitRsp(req.getChairId(), new Position(x, y, z), session.getPlayer().getTeamManager().getCurrentAvatarEntity().getId()));
}
}

View File

@ -19,12 +19,12 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
for (CombatInvokeEntry entry : notif.getInvokeListList()) { for (CombatInvokeEntry entry : notif.getInvokeListList()) {
switch (entry.getArgumentType()) { switch (entry.getArgumentType()) {
case CombatEvtBeingHit: case COMBAT_EVT_BEING_HIT:
// Handle damage // Handle damage
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
session.getPlayer().getScene().handleAttack(hitInfo.getAttackResult()); session.getPlayer().getScene().handleAttack(hitInfo.getAttackResult());
break; break;
case EntityMove: case ENTITY_MOVE:
// Handle movement // Handle movement
EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData());
GenshinEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); GenshinEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId());

View File

@ -0,0 +1,20 @@
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.CombineReqOuterClass;
import emu.grasscutter.server.game.GameSession;
@Opcodes(PacketOpcodes.CombineReq)
public class HandlerCombineReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
CombineReqOuterClass.CombineReq req = CombineReqOuterClass.CombineReq.parseFrom(payload);
}
}

View File

@ -32,7 +32,7 @@ public class HandlerMarkMapReq extends PacketHandler {
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
MarkMapReq req = MarkMapReq.parseFrom(payload); MarkMapReq req = MarkMapReq.parseFrom(payload);
if (req.getOp() != Operation.Add) { if (req.getOp() != MarkMapReq.Operation.ADD) {
return; return;
} }

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketPlayerGetForceQuitBanInfoRsp; import emu.grasscutter.server.packet.send.PacketPlayerGetForceQuitBanInfoRsp;
@ -14,10 +15,10 @@ public class HandlerPlayerGetForceQuitBanInfoReq extends PacketHandler {
if (session.getServer().getMultiplayerManager().leaveCoop(session.getPlayer())) { if (session.getServer().getMultiplayerManager().leaveCoop(session.getPlayer())) {
// Success // Success
session.send(new PacketPlayerGetForceQuitBanInfoRsp(0)); session.send(new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SUCC_VALUE));
} else { } else {
// Fail // Fail
session.send(new PacketPlayerGetForceQuitBanInfoRsp(1)); session.send(new PacketPlayerGetForceQuitBanInfoRsp(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE));
} }
} }

View File

@ -11,7 +11,7 @@ public class PacketAvatarChangeCostumeNotify extends GenshinPacket {
super(PacketOpcodes.AvatarChangeCostumeNotify); super(PacketOpcodes.AvatarChangeCostumeNotify);
AvatarChangeCostumeNotify proto = AvatarChangeCostumeNotify.newBuilder() AvatarChangeCostumeNotify proto = AvatarChangeCostumeNotify.newBuilder()
.setEntity(entity.toProto()) .setEntityInfo(entity.toProto())
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AvatarChangeCostumeRspOuterClass.AvatarChangeCostumeRsp; import emu.grasscutter.net.proto.AvatarChangeCostumeRspOuterClass.AvatarChangeCostumeRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketAvatarChangeCostumeRsp extends GenshinPacket { public class PacketAvatarChangeCostumeRsp extends GenshinPacket {
@ -21,7 +22,7 @@ public class PacketAvatarChangeCostumeRsp extends GenshinPacket {
super(PacketOpcodes.AvatarChangeCostumeRsp); super(PacketOpcodes.AvatarChangeCostumeRsp);
AvatarChangeCostumeRsp proto = AvatarChangeCostumeRsp.newBuilder() AvatarChangeCostumeRsp proto = AvatarChangeCostumeRsp.newBuilder()
.setRetcode(1) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AvatarWearFlycloakRspOuterClass.AvatarWearFlycloakRsp; import emu.grasscutter.net.proto.AvatarWearFlycloakRspOuterClass.AvatarWearFlycloakRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketAvatarWearFlycloakRsp extends GenshinPacket { public class PacketAvatarWearFlycloakRsp extends GenshinPacket {
public PacketAvatarWearFlycloakRsp(long avatarGuid, int costumeId) { public PacketAvatarWearFlycloakRsp(long avatarGuid, int costumeId) {
@ -20,7 +21,7 @@ public class PacketAvatarWearFlycloakRsp extends GenshinPacket {
super(PacketOpcodes.AvatarWearFlycloakRsp); super(PacketOpcodes.AvatarWearFlycloakRsp);
AvatarWearFlycloakRsp proto = AvatarWearFlycloakRsp.newBuilder() AvatarWearFlycloakRsp proto = AvatarWearFlycloakRsp.newBuilder()
.setRetcode(1) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -4,9 +4,9 @@ import java.util.List;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.packet.Retcode;
import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsRspOuterClass.CalcWeaponUpgradeReturnItemsRsp; import emu.grasscutter.net.proto.CalcWeaponUpgradeReturnItemsRspOuterClass.CalcWeaponUpgradeReturnItemsRsp;
import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam; import emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketCalcWeaponUpgradeReturnItemsRsp extends GenshinPacket { public class PacketCalcWeaponUpgradeReturnItemsRsp extends GenshinPacket {
@ -25,7 +25,7 @@ public class PacketCalcWeaponUpgradeReturnItemsRsp extends GenshinPacket {
super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp); super(PacketOpcodes.CalcWeaponUpgradeReturnItemsRsp);
CalcWeaponUpgradeReturnItemsRsp proto = CalcWeaponUpgradeReturnItemsRsp.newBuilder() CalcWeaponUpgradeReturnItemsRsp proto = CalcWeaponUpgradeReturnItemsRsp.newBuilder()
.setRetcode(Retcode.FAIL) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ChangeAvatarRspOuterClass.ChangeAvatarRsp; import emu.grasscutter.net.proto.ChangeAvatarRspOuterClass.ChangeAvatarRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketChangeAvatarRsp extends GenshinPacket { public class PacketChangeAvatarRsp extends GenshinPacket {
@ -10,8 +11,8 @@ public class PacketChangeAvatarRsp extends GenshinPacket {
super(PacketOpcodes.ChangeAvatarRsp); super(PacketOpcodes.ChangeAvatarRsp);
ChangeAvatarRsp p = ChangeAvatarRsp.newBuilder() ChangeAvatarRsp p = ChangeAvatarRsp.newBuilder()
.setRetcode(0) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.setCurrGuid(guid) .setCurGuid(guid)
.build(); .build();
this.setData(p); this.setData(p);

View File

@ -0,0 +1,58 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.CombineReqOuterClass;
import emu.grasscutter.net.proto.CombineRspOuterClass;
import emu.grasscutter.net.proto.ItemParamOuterClass;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketCombineRsp extends GenshinPacket {
public PacketCombineRsp() {
super(PacketOpcodes.CombineRsp);
CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder()
.setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build();
this.setData(proto);
}
public PacketCombineRsp(int retcode) {
super(PacketOpcodes.CombineRsp);
CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder()
.setRetcode(retcode).build();
this.setData(proto);
}
public PacketCombineRsp(CombineReqOuterClass.CombineReq combineReq,
Iterable<ItemParamOuterClass.ItemParam> costItemList,
Iterable<ItemParamOuterClass.ItemParam> resultItemList,
Iterable<ItemParamOuterClass.ItemParam> totalRandomItemList,
Iterable<ItemParamOuterClass.ItemParam> totalReturnItemList,
Iterable<ItemParamOuterClass.ItemParam> totalExtraItemList) {
super(PacketOpcodes.CombineRsp);
CombineRspOuterClass.CombineRsp proto = CombineRspOuterClass.CombineRsp.newBuilder()
.setRetcode(RetcodeOuterClass.Retcode.RET_SUCC_VALUE)
.setCombineId(combineReq.getCombineId())
.setCombineCount(combineReq.getCombineCount())
.setAvatarGuid(combineReq.getAvatarGuid())
.addAllCostItemList(costItemList)
.addAllResultItemList(resultItemList)
.addAllTotalRandomItemList(totalRandomItemList)
.addAllTotalReturnItemList(totalReturnItemList)
.addAllTotalExtraItemList(totalExtraItemList)
.build();
this.setData(proto);
}
}

View File

@ -7,6 +7,7 @@ import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.DoGachaRspOuterClass.DoGachaRsp; import emu.grasscutter.net.proto.DoGachaRspOuterClass.DoGachaRsp;
import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem; import emu.grasscutter.net.proto.GachaItemOuterClass.GachaItem;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketDoGachaRsp extends GenshinPacket { public class PacketDoGachaRsp extends GenshinPacket {
@ -33,7 +34,7 @@ public class PacketDoGachaRsp extends GenshinPacket {
super(PacketOpcodes.DoGachaRsp); super(PacketOpcodes.DoGachaRsp);
DoGachaRsp p = DoGachaRsp.newBuilder() DoGachaRsp p = DoGachaRsp.newBuilder()
.setRetcode(1) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(p); this.setData(p);

View File

@ -5,6 +5,7 @@ import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp; import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp;
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketGadgetInteractRsp extends GenshinPacket { public class PacketGadgetInteractRsp extends GenshinPacket {
public PacketGadgetInteractRsp(EntityGadget gadget, InteractType interact) { public PacketGadgetInteractRsp(EntityGadget gadget, InteractType interact) {
@ -23,7 +24,7 @@ public class PacketGadgetInteractRsp extends GenshinPacket {
super(PacketOpcodes.GadgetInteractRsp); super(PacketOpcodes.GadgetInteractRsp);
GadgetInteractRsp proto = GadgetInteractRsp.newBuilder() GadgetInteractRsp proto = GadgetInteractRsp.newBuilder()
.setRetcode(1) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -3,13 +3,14 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetAuthkeyRspOuterClass.GetAuthkeyRsp; import emu.grasscutter.net.proto.GetAuthkeyRspOuterClass.GetAuthkeyRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass;
public class PacketGetAuthkeyRsp extends GenshinPacket { public class PacketGetAuthkeyRsp extends GenshinPacket {
public PacketGetAuthkeyRsp() { public PacketGetAuthkeyRsp() {
super(PacketOpcodes.GetAuthkeyRsp); super(PacketOpcodes.GetAuthkeyRsp);
GetAuthkeyRsp proto = GetAuthkeyRsp.newBuilder().setRetcode(1).build(); GetAuthkeyRsp proto = GetAuthkeyRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build();
this.setData(proto); this.setData(proto);
} }

View File

@ -9,6 +9,7 @@ import emu.grasscutter.net.proto.FriendBriefOuterClass.FriendBrief;
import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState; import emu.grasscutter.net.proto.FriendOnlineStateOuterClass.FriendOnlineState;
import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFriendListRsp; import emu.grasscutter.net.proto.GetPlayerFriendListRspOuterClass.GetPlayerFriendListRsp;
import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage; import emu.grasscutter.net.proto.HeadImageOuterClass.HeadImage;
import emu.grasscutter.net.proto.PlatformTypeOuterClass;
public class PacketGetPlayerFriendListRsp extends GenshinPacket { public class PacketGetPlayerFriendListRsp extends GenshinPacket {
@ -19,15 +20,15 @@ public class PacketGetPlayerFriendListRsp extends GenshinPacket {
.setUid(GenshinConstants.SERVER_CONSOLE_UID) .setUid(GenshinConstants.SERVER_CONSOLE_UID)
.setNickname("Server") .setNickname("Server")
.setLevel(1) .setLevel(1)
.setAvatar(HeadImage.newBuilder().setAvatarId(GenshinConstants.MAIN_CHARACTER_FEMALE)) .setAvatarId(HeadImage.newBuilder().setAvatarId(GenshinConstants.MAIN_CHARACTER_FEMALE).getAvatarId())
.setWorldLevel(0) .setWorldLevel(0)
.setSignature("") .setSignature("")
.setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) .setLastActiveTime((int) (System.currentTimeMillis() / 1000f))
.setNameCardId(210001) .setNameCardId(210001)
.setOnlineState(FriendOnlineState.FRIEND_ONLINE) .setOnlineState(FriendOnlineState.FRIEND_ONLINE)
.setParam(1) .setParam(1)
.setUnk1(1) .setIsGameSource(true)
.setUnk2(3) .setPlatformType(PlatformTypeOuterClass.PlatformType.PC)
.build(); .build();
GetPlayerFriendListRsp.Builder proto = GetPlayerFriendListRsp.newBuilder().addFriendList(serverFriend); GetPlayerFriendListRsp.Builder proto = GetPlayerFriendListRsp.newBuilder().addFriendList(serverFriend);

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetPlayerSocialDetailRspOuterClass.GetPlayerSocialDetailRsp; import emu.grasscutter.net.proto.GetPlayerSocialDetailRspOuterClass.GetPlayerSocialDetailRsp;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
public class PacketGetPlayerSocialDetailRsp extends GenshinPacket { public class PacketGetPlayerSocialDetailRsp extends GenshinPacket {
@ -15,7 +16,7 @@ public class PacketGetPlayerSocialDetailRsp extends GenshinPacket {
if (detail != null) { if (detail != null) {
proto.setDetailData(detail); proto.setDetailData(detail);
} else { } else {
proto.setRetcode(1); proto.setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE);
} }
this.setData(proto); this.setData(proto);

View File

@ -16,18 +16,18 @@ public class PacketGetPlayerTokenRsp extends GenshinPacket {
this.setUseDispatchKey(true); this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder() GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
.setPlayerUid(session.getAccount().getPlayerUid()) .setUid(session.getAccount().getPlayerUid())
.setAccountToken(session.getAccount().getToken()) .setToken(session.getAccount().getToken())
.setAccountType(1) .setAccountType(1)
.setIsProficientPlayer(doesPlayerExist) // Not sure where this goes .setIsProficientPlayer(doesPlayerExist) // Not sure where this goes
.setSecretKey(Crypto.ENCRYPT_SEED) .setSecretKeySeed(Crypto.ENCRYPT_SEED)
.setSecretKeyBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER)) .setSecurityCmdBuffer(ByteString.copyFrom(Crypto.ENCRYPT_SEED_BUFFER))
.setPlatformType(3) .setPlatformType(3)
.setChannelId(1) .setChannelId(1)
.setCountryCode("US") .setCountryCode("US")
.setUnk1("c25-314dd05b0b5f") .setClientVersionRandomKey("c25-314dd05b0b5f")
.setUnk3(3) .setRegPlatform(3)
.setClientIp(session.getAddress().getAddress().getHostAddress()) .setClientIpStr(session.getAddress().getAddress().getHostAddress())
.build(); .build();
this.setData(p.toByteArray()); this.setData(p.toByteArray());

View File

@ -8,7 +8,7 @@ import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass.Player
public class PacketPlayerApplyEnterMpResultNotify extends GenshinPacket { public class PacketPlayerApplyEnterMpResultNotify extends GenshinPacket {
public PacketPlayerApplyEnterMpResultNotify(GenshinPlayer target, boolean isAgreed, PlayerApplyEnterMpReason reason) { public PacketPlayerApplyEnterMpResultNotify(GenshinPlayer target, boolean isAgreed, PlayerApplyEnterMpResultNotify.Reason reason) {
super(PacketOpcodes.PlayerApplyEnterMpResultNotify); super(PacketOpcodes.PlayerApplyEnterMpResultNotify);
PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder() PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder()
@ -21,7 +21,7 @@ public class PacketPlayerApplyEnterMpResultNotify extends GenshinPacket {
this.setData(proto); this.setData(proto);
} }
public PacketPlayerApplyEnterMpResultNotify(int targetId, String targetName, boolean isAgreed, PlayerApplyEnterMpReason reason) { public PacketPlayerApplyEnterMpResultNotify(int targetId, String targetName, boolean isAgreed, PlayerApplyEnterMpResultNotify.Reason reason) {
super(PacketOpcodes.PlayerApplyEnterMpResultNotify); super(PacketOpcodes.PlayerApplyEnterMpResultNotify);
PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder() PlayerApplyEnterMpResultNotify proto = PlayerApplyEnterMpResultNotify.newBuilder()

View File

@ -43,7 +43,7 @@ public class PacketPlayerChatNotify extends GenshinPacket {
this.setData(proto); this.setData(proto);
} }
public PacketPlayerChatNotify(GenshinPlayer sender, int channelId, SystemHint systemHint) { public PacketPlayerChatNotify(GenshinPlayer sender, int channelId, ChatInfo.SystemHint systemHint) {
super(PacketOpcodes.PlayerChatNotify); super(PacketOpcodes.PlayerChatNotify);
ChatInfo info = ChatInfo.newBuilder() ChatInfo info = ChatInfo.newBuilder()

View File

@ -13,7 +13,7 @@ public class PacketPlayerDataNotify extends GenshinPacket {
PlayerDataNotify.Builder p = PlayerDataNotify.newBuilder() PlayerDataNotify.Builder p = PlayerDataNotify.newBuilder()
.setNickName(player.getNickname()) .setNickName(player.getNickname())
.setClientTime(System.currentTimeMillis()) .setServerTime(System.currentTimeMillis())
.setIsFirstLoginToday(true) .setIsFirstLoginToday(true)
.setRegionId(player.getRegionId()); .setRegionId(player.getRegionId());

View File

@ -5,6 +5,7 @@ import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.inventory.GenshinItem; import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AbilityControlBlockOuterClass;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo; import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AvatarEnterSceneInfoOuterClass.AvatarEnterSceneInfo; import emu.grasscutter.net.proto.AvatarEnterSceneInfoOuterClass.AvatarEnterSceneInfo;
import emu.grasscutter.net.proto.MPLevelEntityInfoOuterClass.MPLevelEntityInfo; import emu.grasscutter.net.proto.MPLevelEntityInfoOuterClass.MPLevelEntityInfo;
@ -26,7 +27,7 @@ public class PacketPlayerEnterSceneInfoNotify extends GenshinPacket {
TeamEnterSceneInfo.newBuilder() TeamEnterSceneInfo.newBuilder()
.setTeamEntityId(player.getTeamManager().getEntityId()) // 150995833 .setTeamEntityId(player.getTeamManager().getEntityId()) // 150995833
.setTeamAbilityInfo(empty) .setTeamAbilityInfo(empty)
.setUnk(empty) .setAbilityControlBlock(AbilityControlBlockOuterClass.AbilityControlBlock.newBuilder().build())
); );
proto.setMpLevelEntityInfo( proto.setMpLevelEntityInfo(
MPLevelEntityInfo.newBuilder() MPLevelEntityInfo.newBuilder()

View File

@ -23,14 +23,14 @@ public class PacketPlayerEnterSceneNotify extends GenshinPacket {
.setSceneId(player.getSceneId()) .setSceneId(player.getSceneId())
.setPos(player.getPos().toProto()) .setPos(player.getPos().toProto())
.setSceneBeginTime(System.currentTimeMillis()) .setSceneBeginTime(System.currentTimeMillis())
.setType(EnterType.EnterSelf) .setType(EnterType.ENTER_SELF)
.setTargetUid(player.getUid()) .setTargetUid(player.getUid())
.setEnterSceneToken(player.getEnterSceneToken()) .setEnterSceneToken(player.getEnterSceneToken())
.setWorldLevel(player.getWorldLevel()) .setWorldLevel(player.getWorldLevel())
.setEnterReason(EnterReason.Login.getValue()) .setEnterReason(EnterReason.Login.getValue())
.setIsFirstLoginEnterScene(player.isFirstLoginEnterScene()) .setIsFirstLoginEnterScene(player.isFirstLoginEnterScene())
.setUnk1(1) .setWorldType(1)
.setUnk2("3-" + player.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402) .setSceneTransaction("3-" + player.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402)
.build(); .build();
this.setData(proto); this.setData(proto);
@ -62,8 +62,8 @@ public class PacketPlayerEnterSceneNotify extends GenshinPacket {
.addSceneTagIdList(109) .addSceneTagIdList(109)
.addSceneTagIdList(113) .addSceneTagIdList(113)
.addSceneTagIdList(117) .addSceneTagIdList(117)
.setUnk1(1) .setWorldType(1)
.setUnk2(newScene + "-" + target.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402) .setSceneTransaction(newScene + "-" + target.getUid() + "-" + (int) (System.currentTimeMillis() / 1000) + "-" + 18402)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -40,8 +40,8 @@ public class PacketPlayerLoginRsp extends GenshinPacket {
QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion); QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion);
RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder() RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
.setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp)) .setGateserverIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp))
.setPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 ? Grasscutter.getConfig().getGameServerOptions().PublicPort : Grasscutter.getConfig().getGameServerOptions().Port) .setGateserverPort(Grasscutter.getConfig().getGameServerOptions().PublicPort != 0 ? Grasscutter.getConfig().getGameServerOptions().PublicPort : Grasscutter.getConfig().getGameServerOptions().Port)
.setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin"))) .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build(); .build();
@ -64,7 +64,7 @@ public class PacketPlayerLoginRsp extends GenshinPacket {
.setClientSilenceDataVersion(info.getClientSilenceDataVersion()) .setClientSilenceDataVersion(info.getClientSilenceDataVersion())
.setClientMd5(info.getClientDataMd5()) .setClientMd5(info.getClientDataMd5())
.setClientSilenceMd5(info.getClientSilenceDataMd5()) .setClientSilenceMd5(info.getClientSilenceDataMd5())
.setResVersionConfig(info.getConfig()) .setResVersionConfig(info.getResVersionConfig())
.setClientVersionSuffix(info.getClientVersionSuffix()) .setClientVersionSuffix(info.getClientVersionSuffix())
.setClientSilenceVersionSuffix(info.getClientSilenceVersionSuffix()) .setClientSilenceVersionSuffix(info.getClientSilenceVersionSuffix())
.setIsScOpen(false) .setIsScOpen(false)

View File

@ -18,7 +18,7 @@ public class PacketPlayerStoreNotify extends GenshinPacket {
this.buildHeader(2); this.buildHeader(2);
PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder() PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder()
.setStoreType(StoreType.StorePack) .setStoreType(StoreType.STORE_PACK)
.setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll); .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll);
for (GenshinItem item : player.getInventory()) { for (GenshinItem item : player.getInventory()) {

View File

@ -15,7 +15,7 @@ public class PacketSceneEntityAppearNotify extends GenshinPacket {
super(PacketOpcodes.SceneEntityAppearNotify, true); super(PacketOpcodes.SceneEntityAppearNotify, true);
SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder() SceneEntityAppearNotify.Builder proto = SceneEntityAppearNotify.newBuilder()
.setAppearType(VisionType.VisionBorn) .setAppearType(VisionType.VISION_BORN)
.addEntityList(entity.toProto()); .addEntityList(entity.toProto());
this.setData(proto.build()); this.setData(proto.build());

View File

@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.net.proto.SceneKickPlayerRspOuterClass.SceneKickPlayerRsp; import emu.grasscutter.net.proto.SceneKickPlayerRspOuterClass.SceneKickPlayerRsp;
public class PacketSceneKickPlayerRsp extends GenshinPacket { public class PacketSceneKickPlayerRsp extends GenshinPacket {
@ -20,7 +21,7 @@ public class PacketSceneKickPlayerRsp extends GenshinPacket {
super(PacketOpcodes.SceneKickPlayerRsp); super(PacketOpcodes.SceneKickPlayerRsp);
SceneKickPlayerRsp proto = SceneKickPlayerRsp.newBuilder() SceneKickPlayerRsp proto = SceneKickPlayerRsp.newBuilder()
.setRetcode(1) .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE)
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -19,7 +19,7 @@ public class PacketSceneTeamUpdateNotify extends GenshinPacket {
for (GenshinPlayer p : player.getWorld().getPlayers()) { for (GenshinPlayer p : player.getWorld().getPlayers()) {
for (EntityAvatar entityAvatar : p.getTeamManager().getActiveTeam()) { for (EntityAvatar entityAvatar : p.getTeamManager().getActiveTeam()) {
SceneTeamAvatar.Builder avatarProto = SceneTeamAvatar.newBuilder() SceneTeamAvatar.Builder avatarProto = SceneTeamAvatar.newBuilder()
.setPlayerId(p.getUid()) .setPlayerUid(p.getUid())
.setAvatarGuid(entityAvatar.getAvatar().getGuid()) .setAvatarGuid(entityAvatar.getAvatar().getGuid())
.setSceneId(p.getSceneId()) .setSceneId(p.getSceneId())
.setEntityId(entityAvatar.getId()) .setEntityId(entityAvatar.getId())

View File

@ -5,6 +5,7 @@ import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp; import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
@ -26,7 +27,7 @@ public class PacketSceneTransToPointRsp extends GenshinPacket {
super(PacketOpcodes.SceneTransToPointRsp); super(PacketOpcodes.SceneTransToPointRsp);
SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder() SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder()
.setRetcode(1) // Internal server error .setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE) // Internal server error
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -4,6 +4,7 @@ import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp; import emu.grasscutter.net.proto.SetPlayerBirthdayRspOuterClass.SetPlayerBirthdayRsp;
import emu.grasscutter.net.proto.SetPlayerBornDataReqOuterClass;
public class PacketSetPlayerBirthdayRsp extends GenshinPacket { public class PacketSetPlayerBirthdayRsp extends GenshinPacket {

View File

@ -12,7 +12,7 @@ public class PacketSetPlayerHeadImageRsp extends GenshinPacket {
super(PacketOpcodes.SetPlayerHeadImageRsp); super(PacketOpcodes.SetPlayerHeadImageRsp);
SetPlayerHeadImageRsp proto = SetPlayerHeadImageRsp.newBuilder() SetPlayerHeadImageRsp proto = SetPlayerHeadImageRsp.newBuilder()
.setAvatar(HeadImage.newBuilder().setAvatarId(player.getHeadImage())) .setAvatarId(HeadImage.newBuilder().setAvatarId(player.getHeadImage()).getAvatarId())
.build(); .build();
this.setData(proto); this.setData(proto);

View File

@ -1,21 +0,0 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SitRspOuterClass.SitRsp;
import emu.grasscutter.utils.Position;
public class PacketSitRsp extends GenshinPacket {
public PacketSitRsp(long chairId, Position pos, int EntityId) {
super(PacketOpcodes.SitRsp);
SitRsp proto = SitRsp.newBuilder()
.setEntityId(EntityId)
.setPosition(pos.toProto())
.setChairId(chairId)
.build();
this.setData(proto);
}
}

View File

@ -18,7 +18,7 @@ public class PacketStoreItemChangeNotify extends GenshinPacket {
this(); this();
StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder()
.setStoreType(StoreType.StorePack) .setStoreType(StoreType.STORE_PACK)
.addItemList(item.toProto()); .addItemList(item.toProto());
this.setData(proto); this.setData(proto);
@ -28,9 +28,9 @@ public class PacketStoreItemChangeNotify extends GenshinPacket {
this(); this();
StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder() StoreItemChangeNotify.Builder proto = StoreItemChangeNotify.newBuilder()
.setStoreType(StoreType.StorePack); .setStoreType(StoreType.STORE_PACK);
items.stream().forEach(item -> proto.addItemList(item.toProto())); items.forEach(item -> proto.addItemList(item.toProto()));
this.setData(proto); this.setData(proto);
} }

View File

@ -18,7 +18,7 @@ public class PacketStoreItemDelNotify extends GenshinPacket {
this(); this();
StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder()
.setStoreType(StoreType.StorePack) .setStoreType(StoreType.STORE_PACK)
.addGuidList(item.getGuid()); .addGuidList(item.getGuid());
this.setData(proto); this.setData(proto);
@ -28,7 +28,7 @@ public class PacketStoreItemDelNotify extends GenshinPacket {
this(); this();
StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder() StoreItemDelNotify.Builder proto = StoreItemDelNotify.newBuilder()
.setStoreType(StoreType.StorePack); .setStoreType(StoreType.STORE_PACK);
items.stream().forEach(item -> proto.addGuidList(item.getGuid())); items.stream().forEach(item -> proto.addGuidList(item.getGuid()));

View File

@ -12,7 +12,7 @@ public class PacketStoreWeightLimitNotify extends GenshinPacket {
super(PacketOpcodes.StoreWeightLimitNotify); super(PacketOpcodes.StoreWeightLimitNotify);
StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder() StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder()
.setStoreType(StoreType.StorePack) .setStoreType(StoreType.STORE_PACK)
.setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll) .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll)
.setWeaponCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon) .setWeaponCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon)
.setReliquaryCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic) .setReliquaryCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic)

View File

@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.inventory.GenshinItem; import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.RetcodeOuterClass;
import emu.grasscutter.net.proto.UseItemRspOuterClass.UseItemRsp; import emu.grasscutter.net.proto.UseItemRspOuterClass.UseItemRsp;
public class PacketUseItemRsp extends GenshinPacket { public class PacketUseItemRsp extends GenshinPacket {
@ -22,7 +23,7 @@ public class PacketUseItemRsp extends GenshinPacket {
public PacketUseItemRsp() { public PacketUseItemRsp() {
super(PacketOpcodes.UseItemRsp); super(PacketOpcodes.UseItemRsp);
UseItemRsp proto = UseItemRsp.newBuilder().setRetcode(1).build(); UseItemRsp proto = UseItemRsp.newBuilder().setRetcode(RetcodeOuterClass.Retcode.RET_SVR_ERROR_VALUE).build();
this.setData(proto); this.setData(proto);
} }

View File

@ -14,7 +14,7 @@ public class PacketWorldPlayerLocationNotify extends GenshinPacket {
WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder(); WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder();
for (GenshinPlayer p : world.getPlayers()) { for (GenshinPlayer p : world.getPlayers()) {
proto.addPlayerLocList(p.getWorldPlayerLocationInfo()); proto.addPlayerWorldLocList(p.getWorldPlayerLocationInfo());
} }
this.setData(proto); this.setData(proto);

View File

@ -34,7 +34,7 @@ public final class Crypto {
public static void extractSecretKeyBuffer(byte[] data) { public static void extractSecretKeyBuffer(byte[] data) {
try { try {
GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data); GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data);
FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin", p.getSecretKeyBuffer().toByteArray()); FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin", p.getSecretKeyBytes().toByteArray());
Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey()); Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey());
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("Crypto error.", e); Grasscutter.getLogger().error("Crypto error.", e);