From 7e4e1c086c66c1407be7bbbcf9005d7a6556f463 Mon Sep 17 00:00:00 2001
From: junu128 <93566768+junu128@users.noreply.github.com>
Date: Wed, 20 Apr 2022 10:50:05 +0800
Subject: [PATCH 01/78] Add files via upload
---
add-to-wiki/resources-fun.md | 77 ++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 add-to-wiki/resources-fun.md
diff --git a/add-to-wiki/resources-fun.md b/add-to-wiki/resources-fun.md
new file mode 100644
index 000000000..7fc3653f6
--- /dev/null
+++ b/add-to-wiki/resources-fun.md
@@ -0,0 +1,77 @@
+# Fun
+## Prerequisites
+- [MongoDBCompass](https://www.mongodb.com/try/download/compass)
+
+***
+
+### Colored nickname and signature :peacock: ([written by](https://github.com/actuallyeunha))
+Unity supports colored text by default (See [Unity Manual](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html) for more info)
+
+By replacing them with `text` or `text` you can change most, if not all, strings' colors.
+
+
+1. Open MongoDBCompass and connect to your db
+2. Go to `grasscutter/players`
+3. Make your changes. *Change it inside `playerProfile` too!*
+ e.g `nickname: "na.na"`;
+ `signature: "Running on Grasscutter!"`
+4. Update the document
+5. Relog to see changes
+
+Enjoy your colorful name :sparkles:
+
+
+***
+## Avatar/Character
+### Changing Level/Ascension/Talents
+> Make sure you have created an account with the avatars/characters.
+1. Open **MongoDBCompass**
+2. Connect to the host (default URI is `mongodb://localhost:27017`)
+3. Navigate to Databases > `grasscutter` > `avatars`
+4. (Optional) Set **View** to `JSON View`
+5. In the **Filter** field, type `{ avatarId: X }` where `X` is the Avatar ID that you are trying to modify. **Avatar IDs are 8-digits.**
+6. Click the **Find** next to the field.
+7. After the documents have been filtered, edit the document
+ 1. To change character **level**, change the value next to `"level"`
+ 2. To change character **ascension**, change the value next to `"promoteLevel"`
+ Check [Wiki](https://genshin-impact.fandom.com/wiki/Characters#:~:text=one%20Acquaint%20Fate.-,Ascension%20Phase,-Max%20Char.%20Level) for ascension values
+ 3. To change **talents**, expand `"proudSkillList"`
+ 1. To unlock the avatar's **1st Ascension Passive**, add XX2101 inside `"proudSkillList"`, where **XX is the last 2 digits of the Avatar ID**. **Make sure to add a `,` for each line.**
+ 2. To unlock the avatar's **4th Ascension Passive**, do the same as before, but replace `2101` with `2201`.
+8. After editing, you can now **Replace**.
+
+### Example
+A document in JSON view that has the Avatar ID 10000058, level 90, ascension phase 6, all talents unlocked.
+
+
+
+
+### Notes
+- On the last line of `"proudSkillList"`, a `,` is no longer needed.
+- After replacing the document, make sure to restart the server for changes to take effect.
+
+
+## Weapons
+> Make sure you have created an account with the weapons.
+1. Open **MongoDBCompass**
+2. Connect to the host (default URI is `mongodb://localhost:27017`)
+3. Navigate to Databases > `grasscutter` > `items`
+4. (Optional) Set **View** to `JSON View`
+5. In the **Filter** field, type `{ itemId: Y }` where `Y` is the Item/Weapon ID that you are trying to modify. **Weapon IDs are 5 digits.**
+6. Click the **Find** next to the field.
+7. After the documents have been filtered, edit the document
+ 1. To change weapon **level**, change the value next to `"level"`
+ 2. To change weapon **ascension**, change the value next to `"promoteLevel"`
+ Check [Wiki](https://genshin-impact.fandom.com/wiki/Weapons#:~:text=reaching%202nd%20Ascension.-,Ascension%20Phase,-Max%20Weapon%20Level) for ascension values
+ 3. To change **refinement**, change the value next to `"refinement"`
+ * Refinement Rank 1 = 0
+ * Refinement Rank 2 = 1
+ * Refinement Rank 3 = 2
+ * Refinement Rank 4 = 3
+ * Refinement Rank 5 = 4
+8. After editing, you can now **Replace**.
+
+### Example
+A document in JSON view that has the Weapon ID 12503, level 90, ascension phase 6, refinement rank 5.
+
+
\ No newline at end of file
From 1a92ce80c67ab5a617af6436572a90bfeeddbef5 Mon Sep 17 00:00:00 2001
From: junu128 <93566768+junu128@users.noreply.github.com>
Date: Wed, 20 Apr 2022 11:12:16 +0800
Subject: [PATCH 02/78] Update resources-fun.md
---
add-to-wiki/resources-fun.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/add-to-wiki/resources-fun.md b/add-to-wiki/resources-fun.md
index 7fc3653f6..57808f841 100644
--- a/add-to-wiki/resources-fun.md
+++ b/add-to-wiki/resources-fun.md
@@ -22,6 +22,7 @@ Enjoy your colorful name :sparkles:
***
+This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [level]
## Avatar/Character
### Changing Level/Ascension/Talents
> Make sure you have created an account with the avatars/characters.
@@ -74,4 +75,4 @@ A document in JSON view that has the Avatar ID 10000058, level 90, ascension pha
### Example
A document in JSON view that has the Weapon ID 12503, level 90, ascension phase 6, refinement rank 5.
-
\ No newline at end of file
+
From b7f98972fa5a3c3f0ae3db8d975ffc7ca4a2cea1 Mon Sep 17 00:00:00 2001
From: junu128 <93566768+junu128@users.noreply.github.com>
Date: Wed, 20 Apr 2022 11:12:56 +0800
Subject: [PATCH 03/78] Update resources-fun.md
---
add-to-wiki/resources-fun.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/add-to-wiki/resources-fun.md b/add-to-wiki/resources-fun.md
index 57808f841..86c0e898c 100644
--- a/add-to-wiki/resources-fun.md
+++ b/add-to-wiki/resources-fun.md
@@ -22,8 +22,8 @@ Enjoy your colorful name :sparkles:
***
-This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [level]
## Avatar/Character
+This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [level]
### Changing Level/Ascension/Talents
> Make sure you have created an account with the avatars/characters.
1. Open **MongoDBCompass**
From a3bb1b1b54344c1860d1749e8a22aaffc15d0eb3 Mon Sep 17 00:00:00 2001
From: junu128 <93566768+junu128@users.noreply.github.com>
Date: Wed, 20 Apr 2022 11:50:56 +0800
Subject: [PATCH 04/78] Update resources-fun.md
---
add-to-wiki/resources-fun.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/add-to-wiki/resources-fun.md b/add-to-wiki/resources-fun.md
index 86c0e898c..6b1afea25 100644
--- a/add-to-wiki/resources-fun.md
+++ b/add-to-wiki/resources-fun.md
@@ -23,7 +23,7 @@ Enjoy your colorful name :sparkles:
***
## Avatar/Character
-This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [level]
+This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [avatarID] [level]
### Changing Level/Ascension/Talents
> Make sure you have created an account with the avatars/characters.
1. Open **MongoDBCompass**
From 56d693331955bfebaee2e4001e40dca40382fc96 Mon Sep 17 00:00:00 2001
From: JuliusP <93566768+JuliusPtolemy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 08:56:15 +0800
Subject: [PATCH 05/78] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index aedab22f2..299093c4c 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ There is a dummy user named "Server" in every player's friends list that you can
`!resetconst` - Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
-`!sethp [hp]`
+`!setstats [stat] [value]`
`!clearartifacts` - Deletes all unequipped and unlocked level 0 artifacts, **including yellow rarity ones** from your inventory
From baf392e476c4a7b7612f977ec3d37c7f60f7218d Mon Sep 17 00:00:00 2001
From: JuliusP <93566768+JuliusPtolemy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 08:57:32 +0800
Subject: [PATCH 06/78] Delete add-to-wiki directory
---
add-to-wiki/resources-fun.md | 78 ------------------------------------
1 file changed, 78 deletions(-)
delete mode 100644 add-to-wiki/resources-fun.md
diff --git a/add-to-wiki/resources-fun.md b/add-to-wiki/resources-fun.md
deleted file mode 100644
index 6b1afea25..000000000
--- a/add-to-wiki/resources-fun.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# Fun
-## Prerequisites
-- [MongoDBCompass](https://www.mongodb.com/try/download/compass)
-
-***
-
-### Colored nickname and signature :peacock: ([written by](https://github.com/actuallyeunha))
-Unity supports colored text by default (See [Unity Manual](https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html) for more info)
-
-By replacing them with `text` or `text` you can change most, if not all, strings' colors.
-
-
-1. Open MongoDBCompass and connect to your db
-2. Go to `grasscutter/players`
-3. Make your changes. *Change it inside `playerProfile` too!*
- e.g `nickname: "na.na"`;
- `signature: "Running on Grasscutter!"`
-4. Update the document
-5. Relog to see changes
-
-Enjoy your colorful name :sparkles:
-
-
-***
-## Avatar/Character
-This guide is recommended if you have the character/weapon. If you want to get a character at Level Z, then use !givechar [avatarID] [level]
-### Changing Level/Ascension/Talents
-> Make sure you have created an account with the avatars/characters.
-1. Open **MongoDBCompass**
-2. Connect to the host (default URI is `mongodb://localhost:27017`)
-3. Navigate to Databases > `grasscutter` > `avatars`
-4. (Optional) Set **View** to `JSON View`
-5. In the **Filter** field, type `{ avatarId: X }` where `X` is the Avatar ID that you are trying to modify. **Avatar IDs are 8-digits.**
-6. Click the **Find** next to the field.
-7. After the documents have been filtered, edit the document
- 1. To change character **level**, change the value next to `"level"`
- 2. To change character **ascension**, change the value next to `"promoteLevel"`
- Check [Wiki](https://genshin-impact.fandom.com/wiki/Characters#:~:text=one%20Acquaint%20Fate.-,Ascension%20Phase,-Max%20Char.%20Level) for ascension values
- 3. To change **talents**, expand `"proudSkillList"`
- 1. To unlock the avatar's **1st Ascension Passive**, add XX2101 inside `"proudSkillList"`, where **XX is the last 2 digits of the Avatar ID**. **Make sure to add a `,` for each line.**
- 2. To unlock the avatar's **4th Ascension Passive**, do the same as before, but replace `2101` with `2201`.
-8. After editing, you can now **Replace**.
-
-### Example
-A document in JSON view that has the Avatar ID 10000058, level 90, ascension phase 6, all talents unlocked.
-
-
-
-
-### Notes
-- On the last line of `"proudSkillList"`, a `,` is no longer needed.
-- After replacing the document, make sure to restart the server for changes to take effect.
-
-
-## Weapons
-> Make sure you have created an account with the weapons.
-1. Open **MongoDBCompass**
-2. Connect to the host (default URI is `mongodb://localhost:27017`)
-3. Navigate to Databases > `grasscutter` > `items`
-4. (Optional) Set **View** to `JSON View`
-5. In the **Filter** field, type `{ itemId: Y }` where `Y` is the Item/Weapon ID that you are trying to modify. **Weapon IDs are 5 digits.**
-6. Click the **Find** next to the field.
-7. After the documents have been filtered, edit the document
- 1. To change weapon **level**, change the value next to `"level"`
- 2. To change weapon **ascension**, change the value next to `"promoteLevel"`
- Check [Wiki](https://genshin-impact.fandom.com/wiki/Weapons#:~:text=reaching%202nd%20Ascension.-,Ascension%20Phase,-Max%20Weapon%20Level) for ascension values
- 3. To change **refinement**, change the value next to `"refinement"`
- * Refinement Rank 1 = 0
- * Refinement Rank 2 = 1
- * Refinement Rank 3 = 2
- * Refinement Rank 4 = 3
- * Refinement Rank 5 = 4
-8. After editing, you can now **Replace**.
-
-### Example
-A document in JSON view that has the Weapon ID 12503, level 90, ascension phase 6, refinement rank 5.
-
-
From eb466ffec041e5d0b39ef14e26fb43a4a0446418 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 18:37:07 -0700
Subject: [PATCH 07/78] Fix water and the visual map in archipelago
---
.../server/packet/send/PacketSceneUnlockInfoNotify.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
index 857f9879c..fb45bb361 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
@@ -13,7 +13,7 @@ public class PacketSceneUnlockInfoNotify extends GenshinPacket {
SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder()
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3))
- .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4))
+ .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4).addSceneTagIdList(106).addSceneTagIdList(109))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(5))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(6))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(7))
From 268a0f94ce8c8884319ec90f4c229c6111f5c41b Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 18:44:02 -0700
Subject: [PATCH 08/78] Fix player location updates in co-op
---
.../emu/grasscutter/game/GenshinPlayer.java | 26 +-
.../WorldPlayerLocationInfoOuterClass.java | 743 ++++++++++++++++++
.../WorldPlayerLocationNotifyOuterClass.java | 144 ++--
.../packet/recv/HandlerEnterSceneDoneReq.java | 5 +-
.../send/PacketScenePlayerLocationNotify.java | 7 +-
.../send/PacketWorldPlayerLocationNotify.java | 2 +-
6 files changed, 849 insertions(+), 78 deletions(-)
create mode 100644 src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationInfoOuterClass.java
diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
index 1d8650e54..b60a5e7ac 100644
--- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java
+++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
@@ -31,6 +31,7 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
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.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
@@ -49,9 +50,11 @@ import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.server.packet.send.PacketPlayerPropNotify;
import emu.grasscutter.server.packet.send.PacketPlayerStoreNotify;
import emu.grasscutter.server.packet.send.PacketPrivateChatNotify;
+import emu.grasscutter.server.packet.send.PacketScenePlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketSetNameCardRsp;
import emu.grasscutter.server.packet.send.PacketStoreWeightLimitNotify;
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
+import emu.grasscutter.server.packet.send.PacketWorldPlayerLocationNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.utils.Position;
@@ -101,6 +104,7 @@ public class GenshinPlayer {
@Transient private int enterSceneToken;
@Transient private SceneLoadState sceneState;
@Transient private boolean hasSentAvatarDataNotify;
+ @Transient private long nextSendPlayerLocTime = 0;
@Transient private final Int2ObjectMap coopRequests;
@Transient private final InvokeHandler combatInvokeHandler;
@@ -654,6 +658,13 @@ public class GenshinPlayer {
return social;
}
+ public WorldPlayerLocationInfo getWorldPlayerLocationInfo() {
+ return WorldPlayerLocationInfo.newBuilder()
+ .setSceneId(this.getSceneId())
+ .setPlayerLoc(this.getPlayerLocationInfo())
+ .build();
+ }
+
public PlayerLocationInfo getPlayerLocationInfo() {
return PlayerLocationInfo.newBuilder()
.setUid(this.getUid())
@@ -679,9 +690,22 @@ public class GenshinPlayer {
}
// Ping
if (this.getWorld() != null) {
- this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld())); // Player ping
+ // RTT notify - very important to send this often
+ this.sendPacket(new PacketWorldPlayerRTTNotify(this.getWorld()));
+
+ // Update player locations if in multiplayer every 5 seconds
+ long time = System.currentTimeMillis();
+ if (this.getWorld().isMultiplayer() && this.getScene() != null && time > nextSendPlayerLocTime) {
+ this.sendPacket(new PacketWorldPlayerLocationNotify(this.getWorld()));
+ this.sendPacket(new PacketScenePlayerLocationNotify(this.getScene()));
+ this.resetSendPlayerLocTime();
+ }
}
}
+
+ public void resetSendPlayerLocTime() {
+ this.nextSendPlayerLocTime = System.currentTimeMillis() + 5000;
+ }
@PostLoad
private void onLoad() {
diff --git a/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationInfoOuterClass.java b/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationInfoOuterClass.java
new file mode 100644
index 000000000..b8c634fd1
--- /dev/null
+++ b/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationInfoOuterClass.java
@@ -0,0 +1,743 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: WorldPlayerLocationInfo.proto
+
+package emu.grasscutter.net.proto;
+
+public final class WorldPlayerLocationInfoOuterClass {
+ private WorldPlayerLocationInfoOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface WorldPlayerLocationInfoOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:WorldPlayerLocationInfo)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * uint32 sceneId = 1;
+ * @return The sceneId.
+ */
+ int getSceneId();
+
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return Whether the playerLoc field is set.
+ */
+ boolean hasPlayerLoc();
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return The playerLoc.
+ */
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLoc();
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocOrBuilder();
+ }
+ /**
+ * Protobuf type {@code WorldPlayerLocationInfo}
+ */
+ public static final class WorldPlayerLocationInfo extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:WorldPlayerLocationInfo)
+ WorldPlayerLocationInfoOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use WorldPlayerLocationInfo.newBuilder() to construct.
+ private WorldPlayerLocationInfo(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private WorldPlayerLocationInfo() {
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new WorldPlayerLocationInfo();
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private WorldPlayerLocationInfo(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 8: {
+
+ sceneId_ = input.readUInt32();
+ break;
+ }
+ case 18: {
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder subBuilder = null;
+ if (playerLoc_ != null) {
+ subBuilder = playerLoc_.toBuilder();
+ }
+ playerLoc_ = input.readMessage(emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.parser(), extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(playerLoc_);
+ playerLoc_ = subBuilder.buildPartial();
+ }
+
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.internal_static_WorldPlayerLocationInfo_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.internal_static_WorldPlayerLocationInfo_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.class, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder.class);
+ }
+
+ public static final int SCENEID_FIELD_NUMBER = 1;
+ private int sceneId_;
+ /**
+ * uint32 sceneId = 1;
+ * @return The sceneId.
+ */
+ @java.lang.Override
+ public int getSceneId() {
+ return sceneId_;
+ }
+
+ public static final int PLAYERLOC_FIELD_NUMBER = 2;
+ private emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo playerLoc_;
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return Whether the playerLoc field is set.
+ */
+ @java.lang.Override
+ public boolean hasPlayerLoc() {
+ return playerLoc_ != null;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return The playerLoc.
+ */
+ @java.lang.Override
+ public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLoc() {
+ return playerLoc_ == null ? emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.getDefaultInstance() : playerLoc_;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ @java.lang.Override
+ public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocOrBuilder() {
+ return getPlayerLoc();
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (sceneId_ != 0) {
+ output.writeUInt32(1, sceneId_);
+ }
+ if (playerLoc_ != null) {
+ output.writeMessage(2, getPlayerLoc());
+ }
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (sceneId_ != 0) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(1, sceneId_);
+ }
+ if (playerLoc_ != null) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, getPlayerLoc());
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo)) {
+ return super.equals(obj);
+ }
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo other = (emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo) obj;
+
+ if (getSceneId()
+ != other.getSceneId()) return false;
+ if (hasPlayerLoc() != other.hasPlayerLoc()) return false;
+ if (hasPlayerLoc()) {
+ if (!getPlayerLoc()
+ .equals(other.getPlayerLoc())) return false;
+ }
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (37 * hash) + SCENEID_FIELD_NUMBER;
+ hash = (53 * hash) + getSceneId();
+ if (hasPlayerLoc()) {
+ hash = (37 * hash) + PLAYERLOC_FIELD_NUMBER;
+ hash = (53 * hash) + getPlayerLoc().hashCode();
+ }
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code WorldPlayerLocationInfo}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:WorldPlayerLocationInfo)
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.internal_static_WorldPlayerLocationInfo_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.internal_static_WorldPlayerLocationInfo_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.class, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder.class);
+ }
+
+ // Construct using emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ sceneId_ = 0;
+
+ if (playerLocBuilder_ == null) {
+ playerLoc_ = null;
+ } else {
+ playerLoc_ = null;
+ playerLocBuilder_ = null;
+ }
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.internal_static_WorldPlayerLocationInfo_descriptor;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getDefaultInstanceForType() {
+ return emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo build() {
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo buildPartial() {
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo result = new emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo(this);
+ result.sceneId_ = sceneId_;
+ if (playerLocBuilder_ == null) {
+ result.playerLoc_ = playerLoc_;
+ } else {
+ result.playerLoc_ = playerLocBuilder_.build();
+ }
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo) {
+ return mergeFrom((emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo other) {
+ if (other == emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.getDefaultInstance()) return this;
+ if (other.getSceneId() != 0) {
+ setSceneId(other.getSceneId());
+ }
+ if (other.hasPlayerLoc()) {
+ mergePlayerLoc(other.getPlayerLoc());
+ }
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+
+ private int sceneId_ ;
+ /**
+ * uint32 sceneId = 1;
+ * @return The sceneId.
+ */
+ @java.lang.Override
+ public int getSceneId() {
+ return sceneId_;
+ }
+ /**
+ * uint32 sceneId = 1;
+ * @param value The sceneId to set.
+ * @return This builder for chaining.
+ */
+ public Builder setSceneId(int value) {
+
+ sceneId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint32 sceneId = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearSceneId() {
+
+ sceneId_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo playerLoc_;
+ private com.google.protobuf.SingleFieldBuilderV3<
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder> playerLocBuilder_;
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return Whether the playerLoc field is set.
+ */
+ public boolean hasPlayerLoc() {
+ return playerLocBuilder_ != null || playerLoc_ != null;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ * @return The playerLoc.
+ */
+ public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLoc() {
+ if (playerLocBuilder_ == null) {
+ return playerLoc_ == null ? emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.getDefaultInstance() : playerLoc_;
+ } else {
+ return playerLocBuilder_.getMessage();
+ }
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public Builder setPlayerLoc(emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo value) {
+ if (playerLocBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ playerLoc_ = value;
+ onChanged();
+ } else {
+ playerLocBuilder_.setMessage(value);
+ }
+
+ return this;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public Builder setPlayerLoc(
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder builderForValue) {
+ if (playerLocBuilder_ == null) {
+ playerLoc_ = builderForValue.build();
+ onChanged();
+ } else {
+ playerLocBuilder_.setMessage(builderForValue.build());
+ }
+
+ return this;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public Builder mergePlayerLoc(emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo value) {
+ if (playerLocBuilder_ == null) {
+ if (playerLoc_ != null) {
+ playerLoc_ =
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.newBuilder(playerLoc_).mergeFrom(value).buildPartial();
+ } else {
+ playerLoc_ = value;
+ }
+ onChanged();
+ } else {
+ playerLocBuilder_.mergeFrom(value);
+ }
+
+ return this;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public Builder clearPlayerLoc() {
+ if (playerLocBuilder_ == null) {
+ playerLoc_ = null;
+ onChanged();
+ } else {
+ playerLoc_ = null;
+ playerLocBuilder_ = null;
+ }
+
+ return this;
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder getPlayerLocBuilder() {
+
+ onChanged();
+ return getPlayerLocFieldBuilder().getBuilder();
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocOrBuilder() {
+ if (playerLocBuilder_ != null) {
+ return playerLocBuilder_.getMessageOrBuilder();
+ } else {
+ return playerLoc_ == null ?
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.getDefaultInstance() : playerLoc_;
+ }
+ }
+ /**
+ * .PlayerLocationInfo playerLoc = 2;
+ */
+ private com.google.protobuf.SingleFieldBuilderV3<
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>
+ getPlayerLocFieldBuilder() {
+ if (playerLocBuilder_ == null) {
+ playerLocBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>(
+ getPlayerLoc(),
+ getParentForChildren(),
+ isClean());
+ playerLoc_ = null;
+ }
+ return playerLocBuilder_;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:WorldPlayerLocationInfo)
+ }
+
+ // @@protoc_insertion_point(class_scope:WorldPlayerLocationInfo)
+ private static final emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo();
+ }
+
+ public static emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public WorldPlayerLocationInfo parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new WorldPlayerLocationInfo(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_WorldPlayerLocationInfo_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_WorldPlayerLocationInfo_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\035WorldPlayerLocationInfo.proto\032\030PlayerL" +
+ "ocationInfo.proto\"R\n\027WorldPlayerLocation" +
+ "Info\022\017\n\007sceneId\030\001 \001(\r\022&\n\tplayerLoc\030\002 \001(\013" +
+ "2\023.PlayerLocationInfoB\033\n\031emu.grasscutter" +
+ ".net.protob\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.getDescriptor(),
+ });
+ internal_static_WorldPlayerLocationInfo_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_WorldPlayerLocationInfo_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_WorldPlayerLocationInfo_descriptor,
+ new java.lang.String[] { "SceneId", "PlayerLoc", });
+ emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.getDescriptor();
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationNotifyOuterClass.java b/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationNotifyOuterClass.java
index fb3321673..89859a9d1 100644
--- a/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationNotifyOuterClass.java
+++ b/src/main/java/emu/grasscutter/net/proto/WorldPlayerLocationNotifyOuterClass.java
@@ -19,27 +19,27 @@ public final class WorldPlayerLocationNotifyOuterClass {
com.google.protobuf.MessageOrBuilder {
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- java.util.List
+ java.util.List
getPlayerLocListList();
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLocList(int index);
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getPlayerLocList(int index);
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
int getPlayerLocListCount();
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- java.util.List extends emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>
+ java.util.List extends emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder>
getPlayerLocListOrBuilderList();
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
int index);
}
/**
@@ -89,13 +89,13 @@ public final class WorldPlayerLocationNotifyOuterClass {
case 0:
done = true;
break;
- case 10: {
+ case 18: {
if (!((mutable_bitField0_ & 0x00000001) != 0)) {
- playerLocList_ = new java.util.ArrayList();
+ playerLocList_ = new java.util.ArrayList();
mutable_bitField0_ |= 0x00000001;
}
playerLocList_.add(
- input.readMessage(emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.parser(), extensionRegistry));
+ input.readMessage(emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.parser(), extensionRegistry));
break;
}
default: {
@@ -133,42 +133,42 @@ public final class WorldPlayerLocationNotifyOuterClass {
emu.grasscutter.net.proto.WorldPlayerLocationNotifyOuterClass.WorldPlayerLocationNotify.class, emu.grasscutter.net.proto.WorldPlayerLocationNotifyOuterClass.WorldPlayerLocationNotify.Builder.class);
}
- public static final int PLAYERLOCLIST_FIELD_NUMBER = 1;
- private java.util.List playerLocList_;
+ public static final int PLAYERLOCLIST_FIELD_NUMBER = 2;
+ private java.util.List playerLocList_;
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
@java.lang.Override
- public java.util.List getPlayerLocListList() {
+ public java.util.List getPlayerLocListList() {
return playerLocList_;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
@java.lang.Override
- public java.util.List extends emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>
+ public java.util.List extends emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder>
getPlayerLocListOrBuilderList() {
return playerLocList_;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
@java.lang.Override
public int getPlayerLocListCount() {
return playerLocList_.size();
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
@java.lang.Override
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLocList(int index) {
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getPlayerLocList(int index) {
return playerLocList_.get(index);
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
@java.lang.Override
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
int index) {
return playerLocList_.get(index);
}
@@ -188,7 +188,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
for (int i = 0; i < playerLocList_.size(); i++) {
- output.writeMessage(1, playerLocList_.get(i));
+ output.writeMessage(2, playerLocList_.get(i));
}
unknownFields.writeTo(output);
}
@@ -201,7 +201,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
size = 0;
for (int i = 0; i < playerLocList_.size(); i++) {
size += com.google.protobuf.CodedOutputStream
- .computeMessageSize(1, playerLocList_.get(i));
+ .computeMessageSize(2, playerLocList_.get(i));
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
@@ -515,22 +515,22 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
private int bitField0_;
- private java.util.List playerLocList_ =
+ private java.util.List playerLocList_ =
java.util.Collections.emptyList();
private void ensurePlayerLocListIsMutable() {
if (!((bitField0_ & 0x00000001) != 0)) {
- playerLocList_ = new java.util.ArrayList(playerLocList_);
+ playerLocList_ = new java.util.ArrayList(playerLocList_);
bitField0_ |= 0x00000001;
}
}
private com.google.protobuf.RepeatedFieldBuilderV3<
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder> playerLocListBuilder_;
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder> playerLocListBuilder_;
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public java.util.List getPlayerLocListList() {
+ public java.util.List getPlayerLocListList() {
if (playerLocListBuilder_ == null) {
return java.util.Collections.unmodifiableList(playerLocList_);
} else {
@@ -538,7 +538,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public int getPlayerLocListCount() {
if (playerLocListBuilder_ == null) {
@@ -548,9 +548,9 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo getPlayerLocList(int index) {
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo getPlayerLocList(int index) {
if (playerLocListBuilder_ == null) {
return playerLocList_.get(index);
} else {
@@ -558,10 +558,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder setPlayerLocList(
- int index, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo value) {
+ int index, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo value) {
if (playerLocListBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
@@ -575,10 +575,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder setPlayerLocList(
- int index, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder builderForValue) {
+ int index, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder builderForValue) {
if (playerLocListBuilder_ == null) {
ensurePlayerLocListIsMutable();
playerLocList_.set(index, builderForValue.build());
@@ -589,9 +589,9 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public Builder addPlayerLocList(emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo value) {
+ public Builder addPlayerLocList(emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo value) {
if (playerLocListBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
@@ -605,10 +605,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder addPlayerLocList(
- int index, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo value) {
+ int index, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo value) {
if (playerLocListBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
@@ -622,10 +622,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder addPlayerLocList(
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder builderForValue) {
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder builderForValue) {
if (playerLocListBuilder_ == null) {
ensurePlayerLocListIsMutable();
playerLocList_.add(builderForValue.build());
@@ -636,10 +636,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder addPlayerLocList(
- int index, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder builderForValue) {
+ int index, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder builderForValue) {
if (playerLocListBuilder_ == null) {
ensurePlayerLocListIsMutable();
playerLocList_.add(index, builderForValue.build());
@@ -650,10 +650,10 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder addAllPlayerLocList(
- java.lang.Iterable extends emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo> values) {
+ java.lang.Iterable extends emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo> values) {
if (playerLocListBuilder_ == null) {
ensurePlayerLocListIsMutable();
com.google.protobuf.AbstractMessageLite.Builder.addAll(
@@ -665,7 +665,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder clearPlayerLocList() {
if (playerLocListBuilder_ == null) {
@@ -678,7 +678,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
public Builder removePlayerLocList(int index) {
if (playerLocListBuilder_ == null) {
@@ -691,16 +691,16 @@ public final class WorldPlayerLocationNotifyOuterClass {
return this;
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder getPlayerLocListBuilder(
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder getPlayerLocListBuilder(
int index) {
return getPlayerLocListFieldBuilder().getBuilder(index);
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder getPlayerLocListOrBuilder(
int index) {
if (playerLocListBuilder_ == null) {
return playerLocList_.get(index); } else {
@@ -708,9 +708,9 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public java.util.List extends emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>
+ public java.util.List extends emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder>
getPlayerLocListOrBuilderList() {
if (playerLocListBuilder_ != null) {
return playerLocListBuilder_.getMessageOrBuilderList();
@@ -719,33 +719,33 @@ public final class WorldPlayerLocationNotifyOuterClass {
}
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder addPlayerLocListBuilder() {
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder addPlayerLocListBuilder() {
return getPlayerLocListFieldBuilder().addBuilder(
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.getDefaultInstance());
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.getDefaultInstance());
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder addPlayerLocListBuilder(
+ public emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder addPlayerLocListBuilder(
int index) {
return getPlayerLocListFieldBuilder().addBuilder(
- index, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.getDefaultInstance());
+ index, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.getDefaultInstance());
}
/**
- * repeated .PlayerLocationInfo playerLocList = 1;
+ * repeated .WorldPlayerLocationInfo playerLocList = 2;
*/
- public java.util.List
+ public java.util.List
getPlayerLocListBuilderList() {
return getPlayerLocListFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilderV3<
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder>
getPlayerLocListFieldBuilder() {
if (playerLocListBuilder_ == null) {
playerLocListBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo.Builder, emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfoOrBuilder>(
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo.Builder, emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfoOrBuilder>(
playerLocList_,
((bitField0_ & 0x00000001) != 0),
getParentForChildren(),
@@ -821,16 +821,16 @@ public final class WorldPlayerLocationNotifyOuterClass {
descriptor;
static {
java.lang.String[] descriptorData = {
- "\n\037WorldPlayerLocationNotify.proto\032\030Playe" +
- "rLocationInfo.proto\"G\n\031WorldPlayerLocati" +
- "onNotify\022*\n\rplayerLocList\030\001 \003(\0132\023.Player" +
- "LocationInfoB\033\n\031emu.grasscutter.net.prot" +
- "ob\006proto3"
+ "\n\037WorldPlayerLocationNotify.proto\032\035World" +
+ "PlayerLocationInfo.proto\"L\n\031WorldPlayerL" +
+ "ocationNotify\022/\n\rplayerLocList\030\002 \003(\0132\030.W" +
+ "orldPlayerLocationInfoB\033\n\031emu.grasscutte" +
+ "r.net.protob\006proto3"
};
descriptor = com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.getDescriptor(),
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.getDescriptor(),
});
internal_static_WorldPlayerLocationNotify_descriptor =
getDescriptor().getMessageTypes().get(0);
@@ -838,7 +838,7 @@ public final class WorldPlayerLocationNotifyOuterClass {
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_WorldPlayerLocationNotify_descriptor,
new java.lang.String[] { "PlayerLocList", });
- emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.getDescriptor();
+ emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.getDescriptor();
}
// @@protoc_insertion_point(outer_class_scope)
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java
index 5b56a39f4..2f7da6884 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java
@@ -31,8 +31,11 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
// Locations
session.send(new PacketWorldPlayerLocationNotify(session.getPlayer().getWorld()));
- session.send(new PacketScenePlayerLocationNotify(session.getPlayer()));
+ session.send(new PacketScenePlayerLocationNotify(session.getPlayer().getScene()));
session.send(new PacketWorldPlayerRTTNotify(session.getPlayer().getWorld()));
+
+ // Reset timer for sending player locations
+ session.getPlayer().resetSendPlayerLocTime();
}
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java
index f6fa9b8f0..2e9fb479d 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketScenePlayerLocationNotify.java
@@ -1,19 +1,20 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.GenshinPlayer;
+import emu.grasscutter.game.GenshinScene;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.ScenePlayerLocationNotifyOuterClass.ScenePlayerLocationNotify;
public class PacketScenePlayerLocationNotify extends GenshinPacket {
- public PacketScenePlayerLocationNotify(GenshinPlayer player) {
+ public PacketScenePlayerLocationNotify(GenshinScene scene) {
super(PacketOpcodes.ScenePlayerLocationNotify);
ScenePlayerLocationNotify.Builder proto = ScenePlayerLocationNotify.newBuilder()
- .setSceneId(player.getSceneId());
+ .setSceneId(scene.getId());
- for (GenshinPlayer p : player.getWorld().getPlayers()) {
+ for (GenshinPlayer p : scene.getPlayers()) {
proto.addPlayerLocList(p.getPlayerLocationInfo());
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java
index cb546f0e7..1bb09f8db 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketWorldPlayerLocationNotify.java
@@ -14,7 +14,7 @@ public class PacketWorldPlayerLocationNotify extends GenshinPacket {
WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder();
for (GenshinPlayer p : world.getPlayers()) {
- proto.addPlayerLocList(p.getPlayerLocationInfo());
+ proto.addPlayerLocList(p.getWorldPlayerLocationInfo());
}
this.setData(proto);
From 434573115c2913e4bc376afae4d9b3decde09e7f Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 18:48:26 -0700
Subject: [PATCH 09/78] Fix not being able to join friend's world
---
.../emu/grasscutter/game/GenshinPlayer.java | 20 +++++++++----------
.../game/friends/PlayerProfile.java | 1 +
.../send/PacketGetPlayerFriendListRsp.java | 1 -
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
index b60a5e7ac..c7ac82bc6 100644
--- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java
+++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
@@ -125,6 +125,12 @@ public class GenshinPlayer {
}
this.properties.put(prop.getId(), 0);
}
+
+ this.gachaInfo = new PlayerGachaInfo();
+ this.nameCardList = new HashSet<>();
+ this.flyCloakList = new HashSet<>();
+ this.costumeList = new HashSet<>();
+
this.setSceneId(3);
this.setRegionId(1);
this.sceneState = SceneLoadState.NONE;
@@ -144,11 +150,6 @@ public class GenshinPlayer {
this.nickname = "Traveler";
this.signature = "";
this.teamManager = new TeamManager(this);
- this.gachaInfo = new PlayerGachaInfo();
- this.playerProfile = new PlayerProfile(this);
- this.nameCardList = new HashSet<>();
- this.flyCloakList = new HashSet<>();
- this.costumeList = new HashSet<>();
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1);
this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1);
this.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50);
@@ -169,6 +170,7 @@ public class GenshinPlayer {
public void setUid(int id) {
this.id = id;
+ this.getProfile().syncWithCharacter(this);
}
public long getNextGenshinGuid() {
@@ -720,12 +722,8 @@ public class GenshinPlayer {
// Make sure these exist
if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this);
- } if (this.getGachaInfo() == null) {
- this.gachaInfo = new PlayerGachaInfo();
- } if (this.nameCardList == null) {
- this.nameCardList = new HashSet<>();
- } if (this.costumeList == null) {
- this.costumeList = new HashSet<>();
+ } if (this.getProfile().getId() == 0) {
+ this.getProfile().syncWithCharacter(this);
}
// Check if player object exists in server
diff --git a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
index cc7408aa6..067cca28d 100644
--- a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
+++ b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
@@ -87,6 +87,7 @@ public class PlayerProfile {
return;
}
+ this.id = player.getUid();
this.name = player.getNickname();
this.avatarId = player.getHeadImage();
this.signature = player.getSignature();
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java
index 9df89af5f..4d22f9603 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerFriendListRsp.java
@@ -23,7 +23,6 @@ public class PacketGetPlayerFriendListRsp extends GenshinPacket {
.setWorldLevel(0)
.setSignature("")
.setLastActiveTime((int) (System.currentTimeMillis() / 1000f))
- .setIsMpModeAvailable(true)
.setNameCardId(210001)
.setOnlineState(FriendOnlineState.FRIEND_ONLINE)
.setParam(1)
From 639eba528fa48060379e1e4a583be4986bf3d8b9 Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Thu, 21 Apr 2022 10:37:24 +0800
Subject: [PATCH 10/78] folder check
---
src/main/java/emu/grasscutter/data/ResourceLoader.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java
index e597257ce..8a29f5a72 100644
--- a/src/main/java/emu/grasscutter/data/ResourceLoader.java
+++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java
@@ -129,6 +129,12 @@ public class ResourceLoader {
private static void loadScenePoints() {
Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)");
File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutPut/Scene/Point");
+
+ if (!folder.isDirectory() || !folder.exists() || folder.listFiles() == null) {
+ Grasscutter.getLogger().error("Scene point files cannot be found, you cannot use teleport waypoints!");
+ return;
+ }
+
List scenePointList = new ArrayList<>();
for (File file : folder.listFiles()) {
ScenePointConfig config = null;
From 636d9ff206526f8b6792d34ef72c0430095feacf Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Thu, 21 Apr 2022 11:43:31 +0800
Subject: [PATCH 11/78] add description and permission to setstats command
---
.../java/emu/grasscutter/command/commands/SetStatsCommand.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
index afc1a3e14..e9c4254b6 100644
--- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
@@ -10,7 +10,7 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import java.util.List;
@Command(label = "setstats", usage = "setstats|stats ",
- aliases = {"stats"})
+ description = "Set fight property for the specific player", aliases = {"stats"}, permission = "player.setstats")
public final class SetStatsCommand implements CommandHandler {
@Override
From 56ee7b719a01cf52e758ae0ec17cc2c0b7921eab Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Thu, 21 Apr 2022 11:52:53 +0800
Subject: [PATCH 12/78] change description
---
.../java/emu/grasscutter/command/commands/SetStatsCommand.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
index e9c4254b6..78f15de2d 100644
--- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
@@ -10,7 +10,7 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import java.util.List;
@Command(label = "setstats", usage = "setstats|stats ",
- description = "Set fight property for the specific player", aliases = {"stats"}, permission = "player.setstats")
+ description = "Set fight property for your current active character", aliases = {"stats"}, permission = "player.setstats")
public final class SetStatsCommand implements CommandHandler {
@Override
From 252fa6b958f6c7101f42d3482fc08792f77f8d06 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 21:03:18 -0700
Subject: [PATCH 13/78] Fix weapon skills (and artifact sets) not working when
you equip them
---
.../game/avatar/GenshinAvatar.java | 47 ++++++++++++-------
.../grasscutter/game/entity/EntityAvatar.java | 4 +-
.../game/managers/InventoryManager.java | 28 +++--------
.../send/PacketAbilityChangeNotify.java | 4 +-
4 files changed, 42 insertions(+), 41 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
index a5dcb3ee8..9723c23d7 100644
--- a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
@@ -13,6 +13,7 @@ import dev.morphia.annotations.Indexed;
import dev.morphia.annotations.PostLoad;
import dev.morphia.annotations.PrePersist;
import dev.morphia.annotations.Transient;
+import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.common.FightPropData;
import emu.grasscutter.data.custom.OpenConfigEntry;
@@ -42,6 +43,7 @@ import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo;
+import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify;
import emu.grasscutter.utils.ProtoHelper;
@@ -69,7 +71,7 @@ public class GenshinAvatar {
@Transient private final Int2ObjectMap equips;
@Transient private final Int2FloatOpenHashMap fightProp;
- @Transient private final Set bonusAbilityList;
+ @Transient private Set extraAbilityEmbryos;
private Map skillLevelMap; // Talent levels
private Map proudSkillBonusMap; // Talent bonus levels (from const)
@@ -86,7 +88,7 @@ public class GenshinAvatar {
// Morhpia only!
this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap();
- this.bonusAbilityList = new HashSet<>();
+ this.extraAbilityEmbryos = new HashSet<>();
this.proudSkillBonusMap = new HashMap<>(); // TODO Move to genshin avatar
}
@@ -260,8 +262,8 @@ public class GenshinAvatar {
return proudSkillBonusMap;
}
- public Set getBonusAbilityList() {
- return bonusAbilityList;
+ public Set getExtraAbilityEmbryos() {
+ return extraAbilityEmbryos;
}
public float getCurrentHp() {
@@ -347,14 +349,14 @@ public class GenshinAvatar {
item.setEquipCharacter(this.getAvatarId());
item.save();
+ if (this.getPlayer().hasSentAvatarDataNotify()) {
+ this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
+ }
+
if (shouldRecalc) {
this.recalcStats();
}
- if (this.getPlayer().hasSentAvatarDataNotify()) {
- this.getPlayer().sendPacket(new PacketAvatarEquipChangeNotify(this, item));
- }
-
return true;
}
@@ -371,11 +373,18 @@ public class GenshinAvatar {
}
public void recalcStats() {
+ recalcStats(false);
+ }
+
+ public void recalcStats(boolean forceSendAbilityChange) {
// Setup
AvatarData data = this.getAvatarData();
AvatarPromoteData promoteData = GenshinData.getAvatarPromoteData(data.getAvatarPromoteId(), this.getPromoteLevel());
Int2IntOpenHashMap setMap = new Int2IntOpenHashMap();
- this.getBonusAbilityList().clear();
+
+ // Extra ability embryos
+ Set prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos();
+ this.extraAbilityEmbryos = new HashSet<>();
// Get hp percent, set to 100% if none
float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
@@ -458,7 +467,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this affix
- this.addToAbilityList(affix.getOpenConfig(), true);
+ this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
} else {
break;
}
@@ -505,7 +514,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this affix
- this.addToAbilityList(affix.getOpenConfig(), true);
+ this.addToExtraAbilityEmbryos(affix.getOpenConfig(), true);
}
}
}
@@ -538,7 +547,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this proud skill
- this.addToAbilityList(proudSkillData.getOpenConfig(), true);
+ this.addToExtraAbilityEmbryos(proudSkillData.getOpenConfig(), true);
}
// Constellations
@@ -550,7 +559,7 @@ public class GenshinAvatar {
}
// Add any skill strings from this constellation
- this.addToAbilityList(avatarTalentData.getOpenConfig(), false);
+ this.addToExtraAbilityEmbryos(avatarTalentData.getOpenConfig(), false);
}
}
@@ -573,11 +582,17 @@ public class GenshinAvatar {
// Packet
if (getPlayer() != null && getPlayer().hasSentAvatarDataNotify()) {
+ // Update stats for client
getPlayer().sendPacket(new PacketAvatarFightPropNotify(this));
+ // Update client abilities
+ EntityAvatar entity = this.getAsEntity();
+ if (entity != null && (!this.getExtraAbilityEmbryos().equals(prevExtraAbilityEmbryos) || forceSendAbilityChange)) {
+ getPlayer().sendPacket(new PacketAbilityChangeNotify(entity));
+ }
}
}
- public void addToAbilityList(String openConfig, boolean forceAdd) {
+ public void addToExtraAbilityEmbryos(String openConfig, boolean forceAdd) {
if (openConfig == null || openConfig.length() == 0) {
return;
}
@@ -586,14 +601,14 @@ public class GenshinAvatar {
if (entry == null) {
if (forceAdd) {
// Add config string to ability skill list anyways
- this.getBonusAbilityList().add(openConfig);
+ this.getExtraAbilityEmbryos().add(openConfig);
}
return;
}
if (entry.getAddAbilities() != null) {
for (String ability : entry.getAddAbilities()) {
- this.getBonusAbilityList().add(ability);
+ this.getExtraAbilityEmbryos().add(ability);
}
}
}
diff --git a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
index 86e8ea458..233da5288 100644
--- a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
+++ b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
@@ -223,8 +223,8 @@ public class EntityAvatar extends GenshinEntity {
}
}
// Add equip abilities
- if (this.getAvatar().getBonusAbilityList().size() > 0) {
- for (String skill : this.getAvatar().getBonusAbilityList()) {
+ if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) {
+ for (String skill : this.getAvatar().getExtraAbilityEmbryos()) {
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
.setAbilityId(++embryoId)
.setAbilityNameHash(Utils.abilityHash(skill))
diff --git a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java
index 935652d77..532155db1 100644
--- a/src/main/java/emu/grasscutter/game/managers/InventoryManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/InventoryManager.java
@@ -589,7 +589,6 @@ public class InventoryManager {
// Update proud skills
AvatarSkillDepotData skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(avatar.getSkillDepotId());
- boolean hasAddedProudSkill = false;
if (skillDepot != null && skillDepot.getInherentProudSkillOpens() != null) {
for (InherentProudSkillOpens openData : skillDepot.getInherentProudSkillOpens()) {
@@ -599,7 +598,6 @@ public class InventoryManager {
if (openData.getNeedAvatarPromoteLevel() == avatar.getPromoteLevel()) {
int proudSkillId = (openData.getProudSkillGroupId() * 100) + 1;
if (GenshinData.getProudSkillDataMap().containsKey(proudSkillId)) {
- hasAddedProudSkill = true;
avatar.getProudSkillList().add(proudSkillId);
player.sendPacket(new PacketProudSkillChangeNotify(avatar));
}
@@ -607,20 +605,13 @@ public class InventoryManager {
}
}
- // Racalc stats and save avatar
- avatar.recalcStats();
- avatar.save();
-
- // Resend ability embryos if proud skill has been added
- if (hasAddedProudSkill && avatar.getAsEntity() != null) {
- player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
- }
-
- // TODO Send entity prop update packet to world
-
// Packets
player.sendPacket(new PacketAvatarPropNotify(avatar));
player.sendPacket(new PacketAvatarPromoteRsp(avatar));
+
+ // TODO Send entity prop update packet to world
+ avatar.recalcStats(true);
+ avatar.save();
}
public void upgradeAvatar(GenshinPlayer player, long guid, int itemId, int count) {
@@ -827,25 +818,20 @@ public class InventoryManager {
// Apply + recalc
avatar.getTalentIdList().add(talentData.getId());
avatar.setCoreProudSkillLevel(currentTalentLevel + 1);
- avatar.recalcStats();
// Packet
player.sendPacket(new PacketAvatarUnlockTalentNotify(avatar, nextTalentId));
player.sendPacket(new PacketUnlockAvatarTalentRsp(avatar, nextTalentId));
- // Proud skill bonus map
+ // Proud skill bonus map (Extra skills)
OpenConfigEntry entry = GenshinData.getOpenConfigEntries().get(talentData.getOpenConfig());
if (entry != null && entry.getExtraTalentIndex() > 0) {
avatar.recalcProudSkillBonusMap();
player.sendPacket(new PacketProudSkillExtraLevelNotify(avatar, entry.getExtraTalentIndex()));
}
- // Resend ability embryos
- if (avatar.getAsEntity() != null) {
- player.sendPacket(new PacketAbilityChangeNotify(avatar.getAsEntity()));
- }
-
- // Save avatar
+ // Recalc + save avatar
+ avatar.recalcStats(true);
avatar.save();
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java
index a6e1fb452..d8cdfdef8 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAbilityChangeNotify.java
@@ -8,8 +8,8 @@ import emu.grasscutter.net.proto.AbilityChangeNotifyOuterClass.AbilityChangeNoti
public class PacketAbilityChangeNotify extends GenshinPacket {
public PacketAbilityChangeNotify(EntityAvatar entity) {
- super(PacketOpcodes.AbilityChangeNotify);
-
+ super(PacketOpcodes.AbilityChangeNotify, true);
+
AbilityChangeNotify proto = AbilityChangeNotify.newBuilder()
.setEntityId(entity.getId())
.setAbilityControlBlock(entity.getAbilityControlBlock())
From 35925903a14a110d964bf6043f4e382518dde44e Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 21:33:58 -0700
Subject: [PATCH 14/78] Refactor PacketSceneTransToPointRsp and add a null
check when getting ScenePointEntries
---
.../command/commands/ChangeSceneCommand.java | 10 +++++--
src/main/java/emu/grasscutter/game/World.java | 21 +-------------
.../recv/HandlerSceneTransToPointReq.java | 19 +++++++++++-
.../send/PacketSceneTransToPointRsp.java | 29 +++++++++----------
4 files changed, 41 insertions(+), 38 deletions(-)
diff --git a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java
index a5afe7bf7..eb2e998f2 100644
--- a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java
@@ -23,11 +23,17 @@ public final class ChangeSceneCommand implements CommandHandler {
try {
int sceneId = Integer.parseInt(args.get(0));
+
+ if (sceneId == sender.getSceneId()) {
+ CommandHandler.sendMessage(sender, "You are already in that scene");
+ return;
+ }
+
boolean result = sender.getWorld().transferPlayerToScene(sender, sceneId, sender.getPos());
-
CommandHandler.sendMessage(sender, "Changed to scene " + sceneId);
+
if (!result) {
- CommandHandler.sendMessage(sender, "Scene does not exist or you are already in it");
+ CommandHandler.sendMessage(sender, "Scene does not exist");
}
} catch (Exception e) {
CommandHandler.sendMessage(sender, "Usage: changescene ");
diff --git a/src/main/java/emu/grasscutter/game/World.java b/src/main/java/emu/grasscutter/game/World.java
index 4375d8e4f..f88d3bee4 100644
--- a/src/main/java/emu/grasscutter/game/World.java
+++ b/src/main/java/emu/grasscutter/game/World.java
@@ -206,28 +206,9 @@ public class World implements Iterable {
public void deregisterScene(GenshinScene scene) {
this.getScenes().remove(scene.getId());
}
-
- public boolean forceTransferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
- // Forces the client to reload the scene map to prevent the player from falling off the map.
- if (GenshinData.getSceneDataMap().get(sceneId) == null) {
- return false;
- }
-
- if (player.getScene() != null) {
- player.getScene().removePlayer(player);
- }
-
- GenshinScene scene = this.getSceneById(sceneId);
- scene.addPlayer(player);
- player.getPos().set(pos);
-
- // Teleport packet
- player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TransPoint, sceneId, pos));
- return true;
- }
public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
- if (player.getScene().getId() == sceneId || GenshinData.getSceneDataMap().get(sceneId) == null) {
+ if (GenshinData.getSceneDataMap().get(sceneId) == null) {
return false;
}
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java
index 619a37b1e..f01f5980d 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneTransToPointReq.java
@@ -1,11 +1,15 @@
package emu.grasscutter.server.packet.recv;
+import emu.grasscutter.data.GenshinData;
+import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SceneTransToPointReqOuterClass.SceneTransToPointReq;
+import emu.grasscutter.net.proto.SceneTransToPointRspOuterClass.SceneTransToPointRsp;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketSceneTransToPointRsp;
+import emu.grasscutter.utils.Position;
@Opcodes(PacketOpcodes.SceneTransToPointReq)
public class HandlerSceneTransToPointReq extends PacketHandler {
@@ -13,7 +17,20 @@ public class HandlerSceneTransToPointReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
SceneTransToPointReq req = SceneTransToPointReq.parseFrom(payload);
- session.send(new PacketSceneTransToPointRsp(session.getPlayer(), req.getPointId(), req.getSceneId()));
+
+ String code = req.getSceneId() + "_" + req.getPointId();
+ ScenePointEntry scenePointEntry = GenshinData.getScenePointEntries().get(code);
+
+ if (scenePointEntry != null) {
+ float x = scenePointEntry.getPointData().getTranPos().getX();
+ float y = scenePointEntry.getPointData().getTranPos().getY();
+ float z = scenePointEntry.getPointData().getTranPos().getZ();
+
+ session.getPlayer().getWorld().transferPlayerToScene(session.getPlayer(), req.getSceneId(), new Position(x, y, z));
+ session.send(new PacketSceneTransToPointRsp(session.getPlayer(), req.getPointId(), req.getSceneId()));
+ } else {
+ session.send(new PacketSceneTransToPointRsp());
+ }
}
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java
index 965c6aa6b..4795c5e9f 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneTransToPointRsp.java
@@ -13,23 +13,22 @@ public class PacketSceneTransToPointRsp extends GenshinPacket {
public PacketSceneTransToPointRsp(GenshinPlayer player, int pointId, int sceneId) {
super(PacketOpcodes.SceneTransToPointRsp);
- String code = sceneId + "_" + pointId;
- ScenePointEntry scenePointEntry = GenshinData.getScenePointEntries().get(code);
-
- float x = scenePointEntry.getPointData().getTranPos().getX();
- float y = scenePointEntry.getPointData().getTranPos().getY();
- float z = scenePointEntry.getPointData().getTranPos().getZ();
-
- player.getPos().set(new Position(x, y, z));
-
- player.getWorld().forceTransferPlayerToScene(player, sceneId, player.getPos());
-
SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder()
- .setRetcode(0)
- .setPointId(pointId)
- .setSceneId(sceneId)
- .build();
+ .setRetcode(0)
+ .setPointId(pointId)
+ .setSceneId(sceneId)
+ .build();
+
+ this.setData(proto);
+ }
+
+ public PacketSceneTransToPointRsp() {
+ super(PacketOpcodes.SceneTransToPointRsp);
+ SceneTransToPointRsp proto = SceneTransToPointRsp.newBuilder()
+ .setRetcode(1) // Internal server error
+ .build();
+
this.setData(proto);
}
}
From 7b43e9a6d8962cbf053247bd51c74a1dacd4ab95 Mon Sep 17 00:00:00 2001
From: labalityowo <56186498+labalityowo@users.noreply.github.com>
Date: Thu, 21 Apr 2022 11:42:21 +0700
Subject: [PATCH 15/78] Remove the stella appearance
---
src/main/java/emu/grasscutter/game/gacha/GachaManager.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
index eb1cba379..a38b91812 100644
--- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
+++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
@@ -218,7 +218,6 @@ public class GachaManager {
addStarglitter = 2;
// Add 1 const
gachaItem.addTransferItems(GachaTransferItem.newBuilder().setItem(ItemParam.newBuilder().setItemId(constItemId).setCount(1)).setIsTransferItemNew(constItem == null));
- gachaItem.addTokenItemList(ItemParam.newBuilder().setItemId(constItemId).setCount(1));
player.getInventory().addItem(constItemId, 1);
} else {
// Is max const
From 9c136859eb9ed842e43905868d81414e8848928f Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Thu, 21 Apr 2022 12:49:23 +0800
Subject: [PATCH 16/78] add args check
---
.../emu/grasscutter/command/commands/SetStatsCommand.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
index 78f15de2d..e3efdb0d5 100644
--- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java
@@ -20,6 +20,11 @@ public final class SetStatsCommand implements CommandHandler {
return;
}
+ if (args.size() < 2){
+ CommandHandler.sendMessage(sender, "Usage: setstats|stats ");
+ return;
+ }
+
String stat = args.get(0);
switch (stat) {
default:
From 75cea5bc4872b79b2eb8964cab113824f2a8be51 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Wed, 20 Apr 2022 21:50:33 -0700
Subject: [PATCH 17/78] More refactoring (player id -> player uid)
---
.../grasscutter/command/commands/AccountCommand.java | 2 +-
.../emu/grasscutter/command/commands/KickCommand.java | 2 +-
src/main/java/emu/grasscutter/game/Account.java | 5 +++--
src/main/java/emu/grasscutter/game/GenshinPlayer.java | 2 +-
.../java/emu/grasscutter/game/friends/FriendsList.java | 2 +-
.../java/emu/grasscutter/game/friends/Friendship.java | 2 +-
.../emu/grasscutter/game/friends/PlayerProfile.java | 10 +++++-----
.../server/packet/recv/HandlerGetPlayerTokenReq.java | 8 ++++----
.../server/packet/recv/HandlerPlayerLoginReq.java | 2 +-
.../packet/recv/HandlerSetPlayerBornDataReq.java | 2 +-
.../server/packet/send/PacketGetPlayerTokenRsp.java | 2 +-
11 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java
index 2c21cba79..26570e0e8 100644
--- a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java
@@ -46,7 +46,7 @@ public final class AccountCommand implements CommandHandler {
CommandHandler.sendMessage(null, "Account already exists.");
return;
} else {
- CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerId() + ".");
+ CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerUid() + ".");
account.addPermission("*"); // Grant the player superuser permissions.
account.save(); // Save account to database.
}
diff --git a/src/main/java/emu/grasscutter/command/commands/KickCommand.java b/src/main/java/emu/grasscutter/command/commands/KickCommand.java
index 188ce1877..61e9d759b 100644
--- a/src/main/java/emu/grasscutter/command/commands/KickCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/KickCommand.java
@@ -22,7 +22,7 @@ public final class KickCommand implements CommandHandler {
}
if (sender != null) {
- CommandHandler.sendMessage(sender, String.format("Player [%s:%s] has kicked player [%s:%s]", sender.getAccount().getPlayerId(), sender.getAccount().getUsername(), target, targetPlayer.getAccount().getUsername()));
+ CommandHandler.sendMessage(sender, String.format("Player [%s:%s] has kicked player [%s:%s]", sender.getAccount().getPlayerUid(), sender.getAccount().getUsername(), target, targetPlayer.getAccount().getUsername()));
}
CommandHandler.sendMessage(sender, String.format("Kicking player [%s:%s]", target, targetPlayer.getAccount().getUsername()));
diff --git a/src/main/java/emu/grasscutter/game/Account.java b/src/main/java/emu/grasscutter/game/Account.java
index 2eeeed3b1..dfb1e2829 100644
--- a/src/main/java/emu/grasscutter/game/Account.java
+++ b/src/main/java/emu/grasscutter/game/Account.java
@@ -1,5 +1,6 @@
package emu.grasscutter.game;
+import dev.morphia.annotations.AlsoLoad;
import dev.morphia.annotations.Collation;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
@@ -24,7 +25,7 @@ public class Account {
private String username;
private String password; // Unused for now
- private int playerId;
+ @AlsoLoad("playerUid") private int playerId;
private String email;
private String token;
@@ -68,7 +69,7 @@ public class Account {
this.token = token;
}
- public int getPlayerId() {
+ public int getPlayerUid() {
return this.playerId;
}
diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
index c7ac82bc6..1bc989183 100644
--- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java
+++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
@@ -722,7 +722,7 @@ public class GenshinPlayer {
// Make sure these exist
if (this.getTeamManager() == null) {
this.teamManager = new TeamManager(this);
- } if (this.getProfile().getId() == 0) {
+ } if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this);
}
diff --git a/src/main/java/emu/grasscutter/game/friends/FriendsList.java b/src/main/java/emu/grasscutter/game/friends/FriendsList.java
index 582a10efd..45a11fb1c 100644
--- a/src/main/java/emu/grasscutter/game/friends/FriendsList.java
+++ b/src/main/java/emu/grasscutter/game/friends/FriendsList.java
@@ -220,7 +220,7 @@ public class FriendsList {
friendship.setOwner(getPlayer());
// Check if friend is online
- GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getId());
+ GenshinPlayer friend = getPlayer().getSession().getServer().getPlayerByUid(friendship.getFriendProfile().getUid());
if (friend != null) {
// Set friend to online mode
friendship.setFriendProfile(friend);
diff --git a/src/main/java/emu/grasscutter/game/friends/Friendship.java b/src/main/java/emu/grasscutter/game/friends/Friendship.java
index 2be7d1fce..172d1bd43 100644
--- a/src/main/java/emu/grasscutter/game/friends/Friendship.java
+++ b/src/main/java/emu/grasscutter/game/friends/Friendship.java
@@ -88,7 +88,7 @@ public class Friendship {
public FriendBrief toProto() {
FriendBrief proto = FriendBrief.newBuilder()
- .setUid(getFriendProfile().getId())
+ .setUid(getFriendProfile().getUid())
.setNickname(getFriendProfile().getName())
.setLevel(getFriendProfile().getPlayerLevel())
.setAvatar(HeadImage.newBuilder().setAvatarId(getFriendProfile().getAvatarId()))
diff --git a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
index 067cca28d..b9381c901 100644
--- a/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
+++ b/src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
@@ -7,7 +7,7 @@ import emu.grasscutter.utils.Utils;
public class PlayerProfile {
@Transient private GenshinPlayer player;
- private int id;
+ @AlsoLoad("id") private int uid;
private int nameCard;
private int avatarId;
private String name;
@@ -22,12 +22,12 @@ public class PlayerProfile {
public PlayerProfile() { }
public PlayerProfile(GenshinPlayer player) {
- this.id = player.getUid();
+ this.uid = player.getUid();
this.syncWithCharacter(player);
}
- public int getId() {
- return id;
+ public int getUid() {
+ return uid;
}
public GenshinPlayer getPlayer() {
@@ -87,7 +87,7 @@ public class PlayerProfile {
return;
}
- this.id = player.getUid();
+ this.uid = player.getUid();
this.name = player.getNickname();
this.avatarId = player.getHeadImage();
this.signature = player.getSignature();
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java
index dc686f5c1..5034fb01a 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java
@@ -35,15 +35,15 @@ public class HandlerGetPlayerTokenReq extends PacketHandler {
// Has character
boolean doesPlayerExist = false;
- if (account.getPlayerId() > 0) {
+ if (account.getPlayerUid() > 0) {
// Set flag for player existing
- doesPlayerExist = DatabaseHelper.checkPlayerExists(account.getPlayerId());
+ doesPlayerExist = DatabaseHelper.checkPlayerExists(account.getPlayerUid());
}
// Set reserve player id if account doesnt exist
if (!doesPlayerExist) {
- int id = DatabaseHelper.getNextPlayerId(session.getAccount().getPlayerId());
- if (id != session.getAccount().getPlayerId()) {
+ int id = DatabaseHelper.getNextPlayerId(session.getAccount().getPlayerUid());
+ if (id != session.getAccount().getPlayerUid()) {
session.getAccount().setPlayerId(id);
session.getAccount().save();
}
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java
index 183ef7461..05753aec0 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerLoginReq.java
@@ -30,7 +30,7 @@ public class HandlerPlayerLoginReq extends PacketHandler {
}
// Load character from db
- GenshinPlayer player = DatabaseHelper.getPlayerById(session.getAccount().getPlayerId());
+ GenshinPlayer player = DatabaseHelper.getPlayerById(session.getAccount().getPlayerUid());
if (player == null) {
// Send packets
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java
index 5cbbd8d04..72fc709d9 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetPlayerBornDataReq.java
@@ -43,7 +43,7 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
try {
// Save to db
- DatabaseHelper.createPlayer(player, session.getAccount().getPlayerId());
+ DatabaseHelper.createPlayer(player, session.getAccount().getPlayerUid());
// Create avatar
if (player.getAvatars().getAvatarCount() == 0) {
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java
index 2306aa0ae..00f512ea7 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetPlayerTokenRsp.java
@@ -16,7 +16,7 @@ public class PacketGetPlayerTokenRsp extends GenshinPacket {
this.setUseDispatchKey(true);
GetPlayerTokenRsp p = GetPlayerTokenRsp.newBuilder()
- .setPlayerUid(session.getAccount().getPlayerId())
+ .setPlayerUid(session.getAccount().getPlayerUid())
.setAccountToken(session.getAccount().getToken())
.setAccountType(1)
.setIsProficientPlayer(doesPlayerExist) // Not sure where this goes
From 75719c5b3be720d87405f83034291021e3d98090 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 13:53:50 +0800
Subject: [PATCH 18/78] Restructured the config file in preperation for server
run modes
---
src/main/java/emu/grasscutter/Config.java | 70 ++++++++++---------
.../java/emu/grasscutter/Grasscutter.java | 2 +-
.../emu/grasscutter/game/GenshinPlayer.java | 2 +-
.../java/emu/grasscutter/game/TeamInfo.java | 6 +-
.../emu/grasscutter/game/TeamManager.java | 4 +-
.../grasscutter/game/gacha/GachaBanner.java | 2 +-
.../grasscutter/game/gacha/GachaManager.java | 2 +-
.../grasscutter/game/inventory/Inventory.java | 8 +--
.../server/dispatch/DispatchServer.java | 28 ++++----
.../server/game/GameServerPacketHandler.java | 2 +-
.../grasscutter/server/game/GameSession.java | 4 +-
.../packet/send/PacketPlayerStoreNotify.java | 2 +-
.../packet/send/PacketPullRecentChatRsp.java | 6 +-
.../send/PacketStoreWeightLimitNotify.java | 10 +--
14 files changed, 77 insertions(+), 71 deletions(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index dddbbfa9e..c6748fb41 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -1,20 +1,7 @@
package emu.grasscutter;
public final class Config {
- public String DispatchServerIp = "127.0.0.1";
- public String DispatchServerPublicIp = "";
- public int DispatchServerPort = 443;
- public String DispatchServerKeystorePath = "./keystore.p12";
- public String DispatchServerKeystorePassword = "";
- public Boolean UseSSL = true;
-
- public String GameServerName = "Test";
- public String GameServerIp = "127.0.0.1";
- public String GameServerPublicIp = "";
- public int GameServerPort = 22102;
-
- public int UploadLogPort = 80;
-
+
public String DatabaseUrl = "mongodb://localhost:27017";
public String DatabaseCollection = "grasscutter";
@@ -23,26 +10,36 @@ public final class Config {
public String PACKETS_FOLDER = "./packets/";
public String DUMPS_FOLDER = "./dumps/";
public String KEY_FOLDER = "./keys/";
- public boolean LOG_PACKETS = false;
- public GameRates Game = new GameRates();
- public ServerOptions ServerOptions = new ServerOptions();
-
- public GameRates getGameRates() {
- return Game;
+ public GameServerOptions GameServer = new GameServerOptions();
+ public DispatchServerOptions DispatchServer = new DispatchServerOptions();
+
+ public GameServerOptions getGameServerOptions() {
+ return GameServer;
+ }
+
+ public DispatchServerOptions getDispatchOptions() { return DispatchServer; }
+
+ public static class DispatchServerOptions {
+ public String Ip = "127.0.0.1";
+ public String PublicIp = "";
+ public int Port = 443;
+ public int UploadLogPort = 80;
+ public String KeystorePath = "./keystore.p12";
+ public String KeystorePassword = "";
+ public Boolean UseSSL = true;
+
+ public boolean AutomaticallyCreateAccounts = false;
}
- public ServerOptions getServerOptions() {
- return ServerOptions;
- }
-
- public static class GameRates {
- public float ADVENTURE_EXP_RATE = 1.0f;
- public float MORA_RATE = 1.0f;
- public float DOMAIN_DROP_RATE = 1.0f;
- }
-
- public static class ServerOptions {
+ public static class GameServerOptions {
+ public String Name = "Test";
+ public String Ip = "127.0.0.1";
+ public String PublicIp = "";
+ public int Port = 22102;
+
+ public boolean LOG_PACKETS = false;
+
public int InventoryLimitWeapon = 2000;
public int InventoryLimitRelic = 2000;
public int InventoryLimitMaterial = 2000;
@@ -54,6 +51,15 @@ public final class Config {
public boolean WatchGacha = false;
public int[] WelcomeEmotes = {2007, 1002, 4010};
public String WelcomeMotd = "Welcome to Grasscutter emu";
- public boolean AutomaticallyCreateAccounts = false;
+
+ public GameRates Game = new GameRates();
+
+ public GameRates getGameRates() { return Game; }
+
+ public static class GameRates {
+ public float ADVENTURE_EXP_RATE = 1.0f;
+ public float MORA_RATE = 1.0f;
+ public float DOMAIN_DROP_RATE = 1.0f;
+ }
}
}
diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java
index 0e34c120d..0b8f1efd8 100644
--- a/src/main/java/emu/grasscutter/Grasscutter.java
+++ b/src/main/java/emu/grasscutter/Grasscutter.java
@@ -76,7 +76,7 @@ public final class Grasscutter {
dispatchServer = new DispatchServer();
dispatchServer.start();
- gameServer = new GameServer(new InetSocketAddress(getConfig().GameServerIp, getConfig().GameServerPort));
+ gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
gameServer.start();
// Open console.
diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
index 1d8650e54..bf841090e 100644
--- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java
+++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
@@ -288,7 +288,7 @@ public class GenshinPlayer {
}
private float getExpModifier() {
- return Grasscutter.getConfig().getGameRates().ADVENTURE_EXP_RATE;
+ return Grasscutter.getConfig().getGameServerOptions().getGameRates().ADVENTURE_EXP_RATE;
}
// Affected by exp rate
diff --git a/src/main/java/emu/grasscutter/game/TeamInfo.java b/src/main/java/emu/grasscutter/game/TeamInfo.java
index 0a12b1d2c..c60ce8cc0 100644
--- a/src/main/java/emu/grasscutter/game/TeamInfo.java
+++ b/src/main/java/emu/grasscutter/game/TeamInfo.java
@@ -13,7 +13,7 @@ public class TeamInfo {
public TeamInfo() {
this.name = "";
- this.avatars = new ArrayList<>(Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam);
+ this.avatars = new ArrayList<>(Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam);
}
public String getName() {
@@ -37,7 +37,7 @@ public class TeamInfo {
}
public boolean addAvatar(GenshinAvatar avatar) {
- if (size() >= Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam || contains(avatar)) {
+ if (size() >= Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam || contains(avatar)) {
return false;
}
@@ -57,7 +57,7 @@ public class TeamInfo {
}
public void copyFrom(TeamInfo team) {
- copyFrom(team, Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam);
+ copyFrom(team, Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam);
}
public void copyFrom(TeamInfo team, int maxTeamSize) {
diff --git a/src/main/java/emu/grasscutter/game/TeamManager.java b/src/main/java/emu/grasscutter/game/TeamManager.java
index 4cd7bfcdf..065c3bd28 100644
--- a/src/main/java/emu/grasscutter/game/TeamManager.java
+++ b/src/main/java/emu/grasscutter/game/TeamManager.java
@@ -164,13 +164,13 @@ public class TeamManager {
public int getMaxTeamSize() {
if (getPlayer().isInMultiplayer()) {
- int max = Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeamMultiplayer;
+ int max = Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeamMultiplayer;
if (getPlayer().getWorld().getHost() == this.getPlayer()) {
return Math.max(1, (int) Math.ceil(max / (double) getWorld().getPlayerCount()));
}
return Math.max(1, (int) Math.floor(max / (double) getWorld().getPlayerCount()));
}
- return Grasscutter.getConfig().getServerOptions().MaxAvatarsInTeam;
+ return Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam;
}
// Methods
diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java
index 3e6bcdf7e..ed5492b62 100644
--- a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java
+++ b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java
@@ -92,7 +92,7 @@ public class GachaBanner {
}
public GachaInfo toProto() {
- String record = "http://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + "/gacha";
+ String record = "http://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + "/gacha";
GachaInfo.Builder info = GachaInfo.newBuilder()
.setGachaType(this.getGachaType())
diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
index a38b91812..079f0dda3 100644
--- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
+++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java
@@ -299,7 +299,7 @@ public class GachaManager {
@Subscribe
public synchronized void watchBannerJson(GameServerTickEvent tickEvent) {
- if(Grasscutter.getConfig().getServerOptions().WatchGacha) {
+ if(Grasscutter.getConfig().getGameServerOptions().WatchGacha) {
try {
WatchKey watchKey = watchService.take();
diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java
index 19bdcc525..8954b1031 100644
--- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java
+++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java
@@ -37,10 +37,10 @@ public class Inventory implements Iterable {
this.store = new Long2ObjectOpenHashMap<>();
this.inventoryTypes = new Int2ObjectOpenHashMap<>();
- this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitWeapon));
- this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitRelic));
- this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitMaterial));
- this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getServerOptions().InventoryLimitFurniture));
+ this.createInventoryTab(ItemType.ITEM_WEAPON, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon));
+ this.createInventoryTab(ItemType.ITEM_RELIQUARY, new EquipInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic));
+ this.createInventoryTab(ItemType.ITEM_MATERIAL, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial));
+ this.createInventoryTab(ItemType.ITEM_FURNITURE, new MaterialInventoryTab(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture));
}
public GenshinPlayer getPlayer() {
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index f13b9dc2f..cda908480 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -55,7 +55,7 @@ public final class DispatchServer {
public static String query_cur_region = "";
public DispatchServer() {
- this.address = new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().DispatchServerPort);
+ this.address = new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, Grasscutter.getConfig().getDispatchOptions().Port);
this.gson = new GsonBuilder().create();
this.loadQueries();
@@ -99,19 +99,19 @@ public final class DispatchServer {
byte[] decoded2 = Base64.getDecoder().decode(query_cur_region);
QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2);
-
+
RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
.setName("os_usa")
- .setTitle(Grasscutter.getConfig().GameServerName)
+ .setTitle(Grasscutter.getConfig().getGameServerOptions().Name)
.setType("DEV_PUBLIC")
- .setDispatchUrl("https://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
+ .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
.build();
RegionSimpleInfo serverTest2 = RegionSimpleInfo.newBuilder()
.setName("os_euro")
.setTitle("Grasscutter")
.setType("DEV_PUBLIC")
- .setDispatchUrl("https://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
+ .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
.build();
QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder()
@@ -123,8 +123,8 @@ public final class DispatchServer {
.build();
RegionInfo currentRegion = regionQuery.getRegionInfo().toBuilder()
- .setIp((Grasscutter.getConfig().GameServerPublicIp.isEmpty() ? Grasscutter.getConfig().GameServerIp : Grasscutter.getConfig().GameServerPublicIp))
- .setPort(Grasscutter.getConfig().GameServerPort)
+ .setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp))
+ .setPort(Grasscutter.getConfig().getGameServerOptions().Port)
.setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build();
@@ -140,12 +140,12 @@ public final class DispatchServer {
public void start() throws Exception {
HttpServer server;
- if(Grasscutter.getConfig().UseSSL) {
+ if(Grasscutter.getConfig().getDispatchOptions().UseSSL) {
HttpsServer httpsServer;
httpsServer = HttpsServer.create(getAddress(), 0);
SSLContext sslContext = SSLContext.getInstance("TLS");
- try (FileInputStream fis = new FileInputStream(Grasscutter.getConfig().DispatchServerKeystorePath)) {
- char[] keystorePassword = Grasscutter.getConfig().DispatchServerKeystorePassword.toCharArray();
+ try (FileInputStream fis = new FileInputStream(Grasscutter.getConfig().getDispatchOptions().KeystorePath)) {
+ char[] keystorePassword = Grasscutter.getConfig().getDispatchOptions().KeystorePassword.toCharArray();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(fis, keystorePassword);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
@@ -228,7 +228,7 @@ public final class DispatchServer {
// Check if account exists, else create a new one.
if (account == null) {
// Account doesnt exist, so we can either auto create it if the config value is set
- if (Grasscutter.getConfig().ServerOptions.AutomaticallyCreateAccounts) {
+ if (Grasscutter.getConfig().getDispatchOptions().AutomaticallyCreateAccounts) {
// This account has been created AUTOMATICALLY. There will be no permissions added.
account = DatabaseHelper.createAccountWithId(requestData.account, 0);
@@ -410,7 +410,7 @@ public final class DispatchServer {
Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
// Logging servers
- HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, 8888), 0);
+ HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, 8888), 0);
overseaLogServer.createContext( // overseauspider.yuanshen.com
"/log",
new DispatchHttpJsonHandler("{\"code\":0}")
@@ -418,7 +418,7 @@ public final class DispatchServer {
overseaLogServer.start();
Grasscutter.getLogger().info("Log server (overseauspider) started on port " + 8888);
- HttpServer uploadLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().UploadLogPort), 0);
+ HttpServer uploadLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, Grasscutter.getConfig().getDispatchOptions().UploadLogPort), 0);
uploadLogServer.createContext( // log-upload-os.mihoyo.com
"/crash/dataUpload",
new DispatchHttpJsonHandler("{\"code\":0}")
@@ -435,7 +435,7 @@ public final class DispatchServer {
os.close();
});
uploadLogServer.start();
- Grasscutter.getLogger().info("Log server (log-upload-os) started on port " + Grasscutter.getConfig().UploadLogPort);
+ Grasscutter.getLogger().info("Log server (log-upload-os) started on port " + Grasscutter.getConfig().getDispatchOptions().UploadLogPort);
}
private Map parseQueryString(String qs) {
diff --git a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
index 118637668..62a57df91 100644
--- a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
+++ b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
@@ -87,7 +87,7 @@ public class GameServerPacketHandler {
}
// Log unhandled packets
- if (Grasscutter.getConfig().LOG_PACKETS) {
+ if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
//Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode));
}
}
diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java
index 1a54f31ba..ebd66dc20 100644
--- a/src/main/java/emu/grasscutter/server/game/GameSession.java
+++ b/src/main/java/emu/grasscutter/server/game/GameSession.java
@@ -165,7 +165,7 @@ public class GameSession extends MihoyoKcpChannel {
byte[] data = genshinPacket.build();
// Log
- if (Grasscutter.getConfig().LOG_PACKETS) {
+ if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
logPacket(genshinPacket);
}
@@ -225,7 +225,7 @@ public class GameSession extends MihoyoKcpChannel {
}
// Log packet
- if (Grasscutter.getConfig().LOG_PACKETS) {
+ if (Grasscutter.getConfig().getGameServerOptions().LOG_PACKETS) {
Grasscutter.getLogger().info("RECV: " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")");
System.out.println(Utils.bytesToHex(payload));
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java
index c21a15351..a3309a5c1 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerStoreNotify.java
@@ -19,7 +19,7 @@ public class PacketPlayerStoreNotify extends GenshinPacket {
PlayerStoreNotify.Builder p = PlayerStoreNotify.newBuilder()
.setStoreType(StoreType.StorePack)
- .setWeightLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitAll);
+ .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll);
for (GenshinItem item : player.getInventory()) {
Item itemProto = item.toProto();
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java
index 8048e4b0d..5af6999d5 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPullRecentChatRsp.java
@@ -1,6 +1,6 @@
package emu.grasscutter.server.packet.send;
-import emu.grasscutter.Config.ServerOptions;
+import emu.grasscutter.Config.GameServerOptions;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.GenshinPlayer;
@@ -14,7 +14,7 @@ public class PacketPullRecentChatRsp extends GenshinPacket {
public PacketPullRecentChatRsp(GenshinPlayer player) {
super(PacketOpcodes.PullRecentChatRsp);
- ServerOptions serverOptions = Grasscutter.getConfig().getServerOptions();
+ GameServerOptions serverOptions = Grasscutter.getConfig().getGameServerOptions();
PullRecentChatRsp.Builder proto = PullRecentChatRsp.newBuilder();
if (serverOptions.WelcomeEmotes != null && serverOptions.WelcomeEmotes.length > 0) {
@@ -33,7 +33,7 @@ public class PacketPullRecentChatRsp extends GenshinPacket {
.setTime((int) (System.currentTimeMillis() / 1000))
.setUid(GenshinConstants.SERVER_CONSOLE_UID)
.setToUid(player.getUid())
- .setText(Grasscutter.getConfig().getServerOptions().WelcomeMotd)
+ .setText(Grasscutter.getConfig().getGameServerOptions().WelcomeMotd)
.build();
proto.addChatInfo(welcomeMotd);
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java
index b93130388..04668b00e 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketStoreWeightLimitNotify.java
@@ -13,11 +13,11 @@ public class PacketStoreWeightLimitNotify extends GenshinPacket {
StoreWeightLimitNotify p = StoreWeightLimitNotify.newBuilder()
.setStoreType(StoreType.StorePack)
- .setWeightLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitAll)
- .setWeaponCountLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitWeapon)
- .setReliquaryCountLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitRelic)
- .setMaterialCountLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitMaterial)
- .setFurnitureCountLimit(Grasscutter.getConfig().getServerOptions().InventoryLimitFurniture)
+ .setWeightLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitAll)
+ .setWeaponCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitWeapon)
+ .setReliquaryCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitRelic)
+ .setMaterialCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitMaterial)
+ .setFurnitureCountLimit(Grasscutter.getConfig().getGameServerOptions().InventoryLimitFurniture)
.build();
this.setData(p);
From 39cad79279afd007f3d03243073613c4afeedddf Mon Sep 17 00:00:00 2001
From: labalityowo <56186498+labalityowo@users.noreply.github.com>
Date: Thu, 21 Apr 2022 14:01:51 +0700
Subject: [PATCH 19/78] Fix Ayaka and weapon banner titles not showing up
---
data/Banners.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/data/Banners.json b/data/Banners.json
index 959a8b436..a4f724ac9 100644
--- a/data/Banners.json
+++ b/data/Banners.json
@@ -19,7 +19,7 @@
"bannerType": "EVENT",
"prefabPath": "GachaShowPanel_A079",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A079",
- "titlePath": "UI_GACHA_SHOW_PANEL_A079_TITLE",
+ "titlePath": "UI_GACHA_SHOW_PANEL_A048_TITLE",
"costItem": 223,
"beginTime": 0,
"endTime": 1924992000,
@@ -34,7 +34,7 @@
"bannerType": "WEAPON",
"prefabPath": "GachaShowPanel_A080",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A080",
- "titlePath": "UI_GACHA_SHOW_PANEL_A080_TITLE",
+ "titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE",
"costItem": 223,
"beginTime": 0,
"endTime": 1924992000,
From c0e859b17c5639ef219ad56a3d5449fe22f4a8a9 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 00:28:28 -0700
Subject: [PATCH 20/78] Add config entry for OverseaLogPort (default: 8888)
---
src/main/java/emu/grasscutter/Config.java | 1 +
.../java/emu/grasscutter/server/dispatch/DispatchServer.java | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index dddbbfa9e..4d4cf4a38 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -13,6 +13,7 @@ public final class Config {
public String GameServerPublicIp = "";
public int GameServerPort = 22102;
+ public int OverseaLogPort = 8888;
public int UploadLogPort = 80;
public String DatabaseUrl = "mongodb://localhost:27017";
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index f13b9dc2f..6b4336858 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -410,7 +410,7 @@ public final class DispatchServer {
Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
// Logging servers
- HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, 8888), 0);
+ HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().OverseaLogPort), 0);
overseaLogServer.createContext( // overseauspider.yuanshen.com
"/log",
new DispatchHttpJsonHandler("{\"code\":0}")
From 3a0997bb5a1940cd2c81da21f92ba344ff3753b9 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 00:29:06 -0700
Subject: [PATCH 21/78] Make sure SetEntityClientDataNotify is a valid proto
before replaying it to the other players
---
.../packet/recv/HandlerSetEntityClientDataNotify.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java
index 1a60f677b..d194e1465 100644
--- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java
@@ -3,6 +3,7 @@ package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
+import emu.grasscutter.net.proto.SetEntityClientDataNotifyOuterClass.SetEntityClientDataNotify;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession;
@@ -16,8 +17,11 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler {
return;
}
+ // Make sure packet is a valid proto before replaying it to the other players
+ SetEntityClientDataNotify notif = SetEntityClientDataNotify.parseFrom(payload);
+
GenshinPacket packet = new GenshinPacket(PacketOpcodes.SetEntityClientDataNotify, true);
- packet.setData(payload);
+ packet.setData(notif);
session.getPlayer().getScene().broadcastPacketToOthers(session.getPlayer(), packet);
}
From 6a091b254c9843ce36a38af24d04998989592e31 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 18:04:00 +0800
Subject: [PATCH 22/78] Multi-server dispatch support and server run modes
---
src/main/java/emu/grasscutter/Config.java | 19 +++
.../java/emu/grasscutter/Grasscutter.java | 32 +++-
.../grasscutter/database/DatabaseHelper.java | 12 +-
.../grasscutter/database/DatabaseManager.java | 43 ++++-
.../server/dispatch/DispatchServer.java | 161 ++++++++++++------
.../packet/send/PacketPlayerLoginRsp.java | 2 +-
6 files changed, 198 insertions(+), 71 deletions(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index c6748fb41..938cbec77 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -1,5 +1,7 @@
package emu.grasscutter;
+import java.util.ArrayList;
+
public final class Config {
public String DatabaseUrl = "mongodb://localhost:27017";
@@ -11,6 +13,7 @@ public final class Config {
public String DUMPS_FOLDER = "./dumps/";
public String KEY_FOLDER = "./keys/";
+ public String RunMode = "HYBRID"; // HYBRID, DISPATCH_ONLY, GAME_ONLY
public GameServerOptions GameServer = new GameServerOptions();
public DispatchServerOptions DispatchServer = new DispatchServerOptions();
@@ -30,6 +33,19 @@ public final class Config {
public Boolean UseSSL = true;
public boolean AutomaticallyCreateAccounts = false;
+
+ public RegionInfo[] GameServers = {};
+
+ public RegionInfo[] getGameServers() {
+ return GameServers;
+ }
+
+ public static class RegionInfo {
+ public String Name = "os_usa";
+ public String Title = "Test";
+ public String Ip = "127.0.0.1";
+ public int Port = 22102;
+ }
}
public static class GameServerOptions {
@@ -38,6 +54,9 @@ public final class Config {
public String PublicIp = "";
public int Port = 22102;
+ public String DispatchServerDatabaseUrl = "mongodb://localhost:27017";
+ public String DispatchServerDatabaseCollection = "grasscutter";
+
public boolean LOG_PACKETS = false;
public int InventoryLimitWeapon = 2000;
diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java
index 0b8f1efd8..614b67ca1 100644
--- a/src/main/java/emu/grasscutter/Grasscutter.java
+++ b/src/main/java/emu/grasscutter/Grasscutter.java
@@ -73,11 +73,26 @@ public final class Grasscutter {
DatabaseManager.initialize();
// Start servers.
- dispatchServer = new DispatchServer();
- dispatchServer.start();
-
- gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
- gameServer.start();
+ if(getConfig().RunMode.equalsIgnoreCase("HYBRID")) {
+ dispatchServer = new DispatchServer();
+ dispatchServer.start();
+
+ gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
+ gameServer.start();
+ } else if(getConfig().RunMode.equalsIgnoreCase("DISPATCH_ONLY")) {
+ dispatchServer = new DispatchServer();
+ dispatchServer.start();
+ } else if(getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
+ gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
+ gameServer.start();
+ } else {
+ getLogger().error("Invalid server run mode. " + getConfig().RunMode);
+ getLogger().error("Server run mode must be 'HYBRID', 'DISPATCH_ONLY', or 'GAME_ONLY'. Unable to start Grasscutter...");
+ getLogger().error("Shutting down...");
+ System.exit(1);
+ }
+
+
// Open console.
startConsole();
@@ -104,9 +119,14 @@ public final class Grasscutter {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
while ((input = br.readLine()) != null) {
try {
+ if(getConfig().RunMode.equalsIgnoreCase("DISPATCH_ONLY")) {
+ getLogger().error("Commands are not supported in dispatch only mode");
+ return;
+ }
CommandMap.getInstance().invoke(null, input);
} catch (Exception e) {
- Grasscutter.getLogger().error("Command error: " + e.getMessage());
+ Grasscutter.getLogger().error("Command error: ");
+ e.printStackTrace();
}
}
} catch (Exception e) {
diff --git a/src/main/java/emu/grasscutter/database/DatabaseHelper.java b/src/main/java/emu/grasscutter/database/DatabaseHelper.java
index 0289c3e71..ed092e976 100644
--- a/src/main/java/emu/grasscutter/database/DatabaseHelper.java
+++ b/src/main/java/emu/grasscutter/database/DatabaseHelper.java
@@ -74,36 +74,36 @@ public class DatabaseHelper {
}
public static void saveAccount(Account account) {
- DatabaseManager.getDatastore().save(account);
+ DatabaseManager.getAccountDatastore().save(account);
}
public static Account getAccountByName(String username) {
- MorphiaCursor cursor = DatabaseManager.getDatastore().createQuery(Account.class).field("username").equalIgnoreCase(username).find(FIND_ONE);
+ MorphiaCursor cursor = DatabaseManager.getAccountDatastore().createQuery(Account.class).field("username").equalIgnoreCase(username).find(FIND_ONE);
if (!cursor.hasNext()) return null;
return cursor.next();
}
public static Account getAccountByToken(String token) {
if (token == null) return null;
- MorphiaCursor cursor = DatabaseManager.getDatastore().createQuery(Account.class).field("token").equal(token).find(FIND_ONE);
+ MorphiaCursor cursor = DatabaseManager.getAccountDatastore().createQuery(Account.class).field("token").equal(token).find(FIND_ONE);
if (!cursor.hasNext()) return null;
return cursor.next();
}
public static Account getAccountById(String uid) {
- MorphiaCursor cursor = DatabaseManager.getDatastore().createQuery(Account.class).field("_id").equal(uid).find(FIND_ONE);
+ MorphiaCursor cursor = DatabaseManager.getAccountDatastore().createQuery(Account.class).field("_id").equal(uid).find(FIND_ONE);
if (!cursor.hasNext()) return null;
return cursor.next();
}
public static Account getAccountByPlayerId(int playerId) {
- MorphiaCursor cursor = DatabaseManager.getDatastore().createQuery(Account.class).field("playerId").equal(playerId).find(FIND_ONE);
+ MorphiaCursor cursor = DatabaseManager.getAccountDatastore().createQuery(Account.class).field("playerId").equal(playerId).find(FIND_ONE);
if (!cursor.hasNext()) return null;
return cursor.next();
}
public static boolean deleteAccount(String username) {
- Query q = DatabaseManager.getDatastore().createQuery(Account.class).field("username").equalIgnoreCase(username);
+ Query q = DatabaseManager.getAccountDatastore().createQuery(Account.class).field("username").equalIgnoreCase(username);
return DatabaseManager.getDatastore().findAndDelete(q) != null;
}
diff --git a/src/main/java/emu/grasscutter/database/DatabaseManager.java b/src/main/java/emu/grasscutter/database/DatabaseManager.java
index 97e27a81a..530581517 100644
--- a/src/main/java/emu/grasscutter/database/DatabaseManager.java
+++ b/src/main/java/emu/grasscutter/database/DatabaseManager.java
@@ -17,7 +17,10 @@ import emu.grasscutter.game.inventory.GenshinItem;
public final class DatabaseManager {
private static MongoClient mongoClient;
+ private static MongoClient dispatchMongoClient;
+
private static Datastore datastore;
+ private static Datastore dispatchDatastore;
private static final Class>[] mappedClasses = new Class>[] {
DatabaseCounter.class, Account.class, GenshinPlayer.class, GenshinAvatar.class, GenshinItem.class, Friendship.class
@@ -26,18 +29,28 @@ public final class DatabaseManager {
public static MongoClient getMongoClient() {
return mongoClient;
}
-
- public static Datastore getDatastore() {
- return datastore;
- }
-
- public static MongoDatabase getDatabase() {
+
+ public static Datastore getDatastore() {
+ return datastore;
+ }
+
+ public static MongoDatabase getDatabase() {
return getDatastore().getDatabase();
}
+
+ // Yes. I very dislike this method also but I'm lazy. Probably replace it by making the game server connect to the dispatch server instead.
+ public static Datastore getAccountDatastore() {
+ if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
+ return dispatchDatastore;
+ } else {
+ return datastore;
+ }
+ }
public static void initialize() {
// Initialize
mongoClient = new MongoClient(new MongoClientURI(Grasscutter.getConfig().DatabaseUrl));
+ dispatchMongoClient = new MongoClient(new MongoClientURI(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl));
Morphia morphia = new Morphia();
// TODO Update when migrating to Morphia 2.0
@@ -50,6 +63,7 @@ public final class DatabaseManager {
// Build datastore
datastore = morphia.createDatastore(mongoClient, Grasscutter.getConfig().DatabaseCollection);
+ dispatchDatastore = morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection);
// Ensure indexes
try {
@@ -67,6 +81,23 @@ public final class DatabaseManager {
datastore.ensureIndexes();
}
}
+
+ // Ensure indexes for dispatch server
+ try {
+ dispatchDatastore.ensureIndexes();
+ } catch (MongoCommandException e) {
+ Grasscutter.getLogger().info("Mongo index error: ", e);
+ // Duplicate index error
+ if (e.getCode() == 85) {
+ // Drop all indexes and re add them
+ MongoIterable collections = dispatchDatastore.getDatabase().listCollectionNames();
+ for (String name : collections) {
+ dispatchDatastore.getDatabase().getCollection(name).dropIndexes();
+ }
+ // Add back indexes
+ dispatchDatastore.ensureIndexes();
+ }
+ }
}
public static synchronized int getNextId(Class> c) {
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index cda908480..53699b05b 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -9,10 +9,7 @@ import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URLDecoder;
import java.security.KeyStore;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -25,6 +22,7 @@ import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
+import emu.grasscutter.Config;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.Account;
@@ -46,15 +44,18 @@ import com.sun.net.httpserver.HttpServer;
public final class DispatchServer {
private final InetSocketAddress address;
private final Gson gson;
- private QueryCurrRegionHttpRsp currRegion;
+ //private QueryCurrRegionHttpRsp currRegion;
public String regionListBase64;
- public String regionCurrentBase64;
-
+ public HashMap regions;
+ public HashMap usersIngame;
+
public static String query_region_list = "";
public static String query_cur_region = "";
-
+
public DispatchServer() {
+ this.regions = new HashMap();
+ this.usersIngame = new HashMap();
this.address = new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, Grasscutter.getConfig().getDispatchOptions().Port);
this.gson = new GsonBuilder().create();
@@ -70,8 +71,13 @@ public final class DispatchServer {
return gson;
}
- public QueryCurrRegionHttpRsp getCurrRegion() {
- return currRegion;
+ public QueryCurrRegionHttpRsp getCurrRegion(InetSocketAddress address) {
+ if(usersIngame.containsKey(address)) {
+ return regions.get(usersIngame.get(address)).parsedRegionQuery;
+ }
+
+ Grasscutter.getLogger().error("User is not logged in to dispatch server. " + address.getAddress() + ":" + address.getPort());
+ return null;
}
public void loadQueries() {
@@ -100,39 +106,67 @@ public final class DispatchServer {
byte[] decoded2 = Base64.getDecoder().decode(query_cur_region);
QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2);
- RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
- .setName("os_usa")
- .setTitle(Grasscutter.getConfig().getGameServerOptions().Name)
- .setType("DEV_PUBLIC")
- .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
- .build();
-
- RegionSimpleInfo serverTest2 = RegionSimpleInfo.newBuilder()
- .setName("os_euro")
- .setTitle("Grasscutter")
- .setType("DEV_PUBLIC")
- .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
- .build();
-
+ List servers = new ArrayList();
+ List usedNames = new ArrayList(); // List to check for potential naming conflicts
+ if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) { // Automatically add the game server if in hybrid mode
+ String defaultServerName = "os_usa";
+ RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
+ .setName("os_usa")
+ .setTitle(Grasscutter.getConfig().getGameServerOptions().Name)
+ .setType("DEV_PUBLIC")
+ .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region_" + defaultServerName)
+ .build();
+ usedNames.add(defaultServerName);
+ servers.add(server);
+
+ RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
+ .setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp))
+ .setPort(Grasscutter.getConfig().getGameServerOptions().Port)
+ .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
+ .build();
+
+ QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
+ regions.put(defaultServerName, new RegionData(parsedRegionQuery, Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray())));
+
+ } else {
+ if(Grasscutter.getConfig().getDispatchOptions().getGameServers().length == 0) {
+ Grasscutter.getLogger().error("Dispatch server has no game servers available. Exiting due to unplayable state.");
+ System.exit(1);
+ }
+ }
+
+ for (Config.DispatchServerOptions.RegionInfo regionInfo : Grasscutter.getConfig().getDispatchOptions().getGameServers()) {
+ if(usedNames.contains(regionInfo.Name)) {
+ Grasscutter.getLogger().error("Region name already in use.");
+ continue;
+ }
+ RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
+ .setName(regionInfo.Name)
+ .setTitle(regionInfo.Title)
+ .setType("DEV_PUBLIC")
+ .setDispatchUrl("https://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) + ":" + getAddress().getPort() + "/query_cur_region_" + regionInfo.Name)
+ .build();
+ usedNames.add(regionInfo.Name);
+ servers.add(server);
+
+ RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
+ .setIp(regionInfo.Ip)
+ .setPort(regionInfo.Port)
+ .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
+ .build();
+
+ QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
+ regions.put(regionInfo.Name, new RegionData(parsedRegionQuery, Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray())));
+ }
+
QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder()
- .addServers(server)
- .addServers(serverTest2)
+ .addAllServers(servers)
.setClientSecretKey(rl.getClientSecretKey())
.setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted())
.setEnableLoginPc(true)
.build();
-
- RegionInfo currentRegion = regionQuery.getRegionInfo().toBuilder()
- .setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp))
- .setPort(Grasscutter.getConfig().getGameServerOptions().Port)
- .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
- .build();
-
- QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(currentRegion).build();
this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray());
- this.regionCurrentBase64 = Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray());
- this.currRegion = parsedRegionQuery;
} catch (Exception e) {
Grasscutter.getLogger().error("Error while initializing region info!", e);
}
@@ -188,24 +222,36 @@ public final class DispatchServer {
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
- });
- server.createContext("/query_cur_region", t -> {
- // Log
- Grasscutter.getLogger().info("Client request: query_cur_region");
- // Create a response form the request query parameters
- URI uri = t.getRequestURI();
- String response = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw==";
- if (uri.getQuery() != null && uri.getQuery().length() > 0) {
- response = regionCurrentBase64;
+
+ if(usersIngame.containsKey(t.getRemoteAddress())) {
+ usersIngame.remove(t.getRemoteAddress());
}
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
});
+
+ for (String regionName : regions.keySet()) {
+ server.createContext("/query_cur_region_" + regionName, t -> {
+ String regionCurrentBase64 = regions.get(regionName).Base64;
+
+ // Log
+ Grasscutter.getLogger().info("Client request: query_cur_region_" + regionName);
+ // Create a response form the request query parameters
+ URI uri = t.getRequestURI();
+ String response = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw==";
+ if (uri.getQuery() != null && uri.getQuery().length() > 0) {
+ response = regionCurrentBase64;
+ }
+ // Set the response header status and length
+ t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
+ t.sendResponseHeaders(200, response.getBytes().length);
+ // Write the response string
+ OutputStream os = t.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ //Save region info to hashmap for user, this for getCurrRegion();
+ usersIngame.put(t.getRemoteAddress(), regionName);
+ });
+ }
+
// Login via account
server.createContext("/hk4e_global/mdk/shield/api/login", t -> {
// Get post data
@@ -464,4 +510,15 @@ public final class DispatchServer {
}
return result;
}
+
+ public static class RegionData {
+
+ QueryCurrRegionHttpRsp parsedRegionQuery;
+ String Base64;
+
+ public RegionData(QueryCurrRegionHttpRsp prq, String b64) {
+ this.parsedRegionQuery = prq;
+ this.Base64 = b64;
+ }
+ }
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
index 0d0871ca9..eef1a03e6 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
@@ -14,7 +14,7 @@ public class PacketPlayerLoginRsp extends GenshinPacket {
this.setUseDispatchKey(true);
- RegionInfo info = Grasscutter.getDispatchServer().getCurrRegion().getRegionInfo();
+ RegionInfo info = Grasscutter.getDispatchServer().getCurrRegion(session.getAddress()).getRegionInfo();
PlayerLoginRsp p = PlayerLoginRsp.newBuilder()
.setIsUseAbilityHash(true) // true
From 585187bebef5de277603467fde0c82e281dbcc80 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 19:20:49 +0800
Subject: [PATCH 23/78] Fixed null pointer exception in hybrid mode.
---
.../server/dispatch/DispatchServer.java | 27 +++++++++----------
.../packet/send/PacketPlayerLoginRsp.java | 2 +-
2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 6b2661def..37ed6c5ac 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URLDecoder;
@@ -44,18 +45,18 @@ import com.sun.net.httpserver.HttpServer;
public final class DispatchServer {
private final InetSocketAddress address;
private final Gson gson;
+ private final String defaultServerName = "os_usa";
//private QueryCurrRegionHttpRsp currRegion;
public String regionListBase64;
public HashMap regions;
- public HashMap usersIngame;
+ public HashMap usersConnected;
public static String query_region_list = "";
public static String query_cur_region = "";
public DispatchServer() {
this.regions = new HashMap();
- this.usersIngame = new HashMap();
this.address = new InetSocketAddress(Grasscutter.getConfig().getDispatchOptions().Ip, Grasscutter.getConfig().getDispatchOptions().Port);
this.gson = new GsonBuilder().create();
@@ -71,12 +72,13 @@ public final class DispatchServer {
return gson;
}
- public QueryCurrRegionHttpRsp getCurrRegion(InetSocketAddress address) {
- if(usersIngame.containsKey(address)) {
- return regions.get(usersIngame.get(address)).parsedRegionQuery;
+ public QueryCurrRegionHttpRsp getCurrRegion() {
+ // Needs to be fixed by having the game servers connect to the dispatch server.
+ if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) {
+ return regions.get(defaultServerName).parsedRegionQuery;
}
- Grasscutter.getLogger().error("User is not logged in to dispatch server. " + address.getAddress() + ":" + address.getPort());
+ Grasscutter.getLogger().error("Ignore the error below");
return null;
}
@@ -109,7 +111,6 @@ public final class DispatchServer {
List servers = new ArrayList();
List usedNames = new ArrayList(); // List to check for potential naming conflicts
if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("HYBRID")) { // Automatically add the game server if in hybrid mode
- String defaultServerName = "os_usa";
RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
.setName("os_usa")
.setTitle(Grasscutter.getConfig().getGameServerOptions().Name)
@@ -222,16 +223,11 @@ public final class DispatchServer {
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
-
- if(usersIngame.containsKey(t.getRemoteAddress())) {
- usersIngame.remove(t.getRemoteAddress());
- }
});
for (String regionName : regions.keySet()) {
server.createContext("/query_cur_region_" + regionName, t -> {
String regionCurrentBase64 = regions.get(regionName).Base64;
-
// Log
Grasscutter.getLogger().info("Client request: query_cur_region_" + regionName);
// Create a response form the request query parameters
@@ -247,8 +243,6 @@ public final class DispatchServer {
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
- //Save region info to hashmap for user, this for getCurrRegion();
- usersIngame.put(t.getRemoteAddress(), regionName);
});
}
@@ -521,4 +515,9 @@ public final class DispatchServer {
this.Base64 = b64;
}
}
+
+ public static class UserConnnectionData {
+ public InetAddress dispatchConnectedAddress;
+ public String connectedRegion;
+ }
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
index eef1a03e6..0d0871ca9 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
@@ -14,7 +14,7 @@ public class PacketPlayerLoginRsp extends GenshinPacket {
this.setUseDispatchKey(true);
- RegionInfo info = Grasscutter.getDispatchServer().getCurrRegion(session.getAddress()).getRegionInfo();
+ RegionInfo info = Grasscutter.getDispatchServer().getCurrRegion().getRegionInfo();
PlayerLoginRsp p = PlayerLoginRsp.newBuilder()
.setIsUseAbilityHash(true) // true
From ced378cee84a943532e45bab0de38e1e1d21c4da Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 21:41:07 +0800
Subject: [PATCH 24/78] Add port & SSL options to proxy script
Signed-off-by: Jaida Wu
---
proxy.py | 9 ++++++++-
proxy_config.py | 4 +++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/proxy.py b/proxy.py
index 2d2282af9..86145cde6 100644
--- a/proxy.py
+++ b/proxy.py
@@ -16,12 +16,14 @@
# - mitmdump from mitmproxy
#
# @author MlgmXyysd
-# @version 1.0
+# @version 1.1
#
##
from mitmproxy import http
+from proxy_config import USE_SSL
from proxy_config import REMOTE_HOST
+from proxy_config import REMOTE_PORT
class MlgmXyysd_Genshin_Impact_Proxy:
@@ -60,7 +62,12 @@ class MlgmXyysd_Genshin_Impact_Proxy:
def request(self, flow: http.HTTPFlow) -> None:
if flow.request.host in self.LIST_DOMAINS:
+ if USE_SSL:
+ flow.request.scheme = "https"
+ else:
+ flow.request.scheme = "http"
flow.request.host = REMOTE_HOST
+ flow.request.port = REMOTE_PORT
addons = [
MlgmXyysd_Genshin_Impact_Proxy()
diff --git a/proxy_config.py b/proxy_config.py
index f048ef88c..5025a974e 100644
--- a/proxy_config.py
+++ b/proxy_config.py
@@ -1,2 +1,4 @@
# This can also be replaced with another IP address.
-REMOTE_HOST = "localhost"
\ No newline at end of file
+USE_SSL = True
+REMOTE_HOST = "127.0.0.1"
+REMOTE_PORT = 443
\ No newline at end of file
From 65e0799e79d42044df80c192a37914464600b38a Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 21:41:30 +0800
Subject: [PATCH 25/78] Drop independent log server
Signed-off-by: Jaida Wu
---
src/main/java/emu/grasscutter/Config.java | 3 ---
.../server/dispatch/DispatchServer.java | 18 ++++++------------
2 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index 4d4cf4a38..65ada3969 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -13,9 +13,6 @@ public final class Config {
public String GameServerPublicIp = "";
public int GameServerPort = 22102;
- public int OverseaLogPort = 8888;
- public int UploadLogPort = 80;
-
public String DatabaseUrl = "mongodb://localhost:27017";
public String DatabaseCollection = "grasscutter";
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 6b4336858..e59f9d251 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -405,25 +405,18 @@ public final class DispatchServer {
"/perf/config/verify",
new DispatchHttpJsonHandler("{\"code\":0}")
);
- // Start server
- server.start();
- Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
// Logging servers
- HttpServer overseaLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().OverseaLogPort), 0);
- overseaLogServer.createContext( // overseauspider.yuanshen.com
+ server.createContext( // overseauspider.yuanshen.com
"/log",
new DispatchHttpJsonHandler("{\"code\":0}")
);
- overseaLogServer.start();
- Grasscutter.getLogger().info("Log server (overseauspider) started on port " + 8888);
- HttpServer uploadLogServer = HttpServer.create(new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().UploadLogPort), 0);
- uploadLogServer.createContext( // log-upload-os.mihoyo.com
+ server.createContext( // log-upload-os.mihoyo.com
"/crash/dataUpload",
new DispatchHttpJsonHandler("{\"code\":0}")
);
- uploadLogServer.createContext("/gacha", t -> {
+ server.createContext("/gacha", t -> {
//Create a response form the request query parameters
String response = "Gacha";
//Set the response header status and length
@@ -434,8 +427,9 @@ public final class DispatchServer {
os.write(response.getBytes());
os.close();
});
- uploadLogServer.start();
- Grasscutter.getLogger().info("Log server (log-upload-os) started on port " + Grasscutter.getConfig().UploadLogPort);
+ // Start server
+ server.start();
+ Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
}
private Map parseQueryString(String qs) {
From 66c956d10e10d18516ec6be949a259e75db4c2d9 Mon Sep 17 00:00:00 2001
From: xmplay <81370285+xmplay@users.noreply.github.com>
Date: Thu, 21 Apr 2022 15:04:47 +0100
Subject: [PATCH 26/78] bring back the jade chamber and other old scene tags
---
.../server/packet/send/PacketSceneUnlockInfoNotify.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
index fb45bb361..bd1b30685 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
@@ -12,7 +12,7 @@ public class PacketSceneUnlockInfoNotify extends GenshinPacket {
SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder()
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1))
- .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3))
+ .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3).addSceneTagIdList(102).addSceneTagIdList(113).addSceneTagIdList(117))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4).addSceneTagIdList(106).addSceneTagIdList(109))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(5))
.addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(6))
From 1d5408431780e0cccc6899d22a87cd68ded10669 Mon Sep 17 00:00:00 2001
From: zamlty <29914613+zamlty@users.noreply.github.com>
Date: Thu, 21 Apr 2022 22:21:39 +0800
Subject: [PATCH 27/78] Fix artifact & weapon generation by give command
---
.../java/emu/grasscutter/command/commands/GiveCommand.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
index 7d15a4759..a533130bc 100644
--- a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
@@ -95,18 +95,19 @@ public final class GiveCommand implements CommandHandler {
}
private void item(GenshinPlayer player, ItemData itemData, int amount) {
- GenshinItem genshinItem = new GenshinItem(itemData);
if (itemData.isEquip()) {
List items = new LinkedList<>();
for (int i = 0; i < amount; i++) {
- items.add(genshinItem);
+ items.add(new GenshinItem(itemData));
}
player.getInventory().addItems(items);
player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
} else {
+ GenshinItem genshinItem = new GenshinItem(itemData);
genshinItem.setCount(amount);
player.getInventory().addItem(genshinItem);
player.sendPacket(new PacketItemAddHintNotify(genshinItem, ActionReason.SubfieldDrop));
}
}
}
+
From a36f29cdf1bb98596cb8f21ee9926d3ed11cc4f6 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 22:38:01 +0800
Subject: [PATCH 28/78] Fixed null pointer exception in game only mode
PacketPlayerLoginRsp now creates the required QuerryCurrRegionHttpRsp itself.
---
.../packet/send/PacketPlayerLoginRsp.java | 46 +++++++++++++++++--
1 file changed, 43 insertions(+), 3 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
index 0d0871ca9..a5e167100 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerLoginRsp.java
@@ -1,21 +1,61 @@
package emu.grasscutter.server.packet.send;
+import com.google.protobuf.ByteString;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PlayerLoginRspOuterClass.PlayerLoginRsp;
+import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass;
import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo;
import emu.grasscutter.server.game.GameSession;
+import emu.grasscutter.utils.FileUtils;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Base64;
public class PacketPlayerLoginRsp extends GenshinPacket {
+ private static QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionCache;
+
public PacketPlayerLoginRsp(GameSession session) {
super(PacketOpcodes.PlayerLoginRsp, 1);
this.setUseDispatchKey(true);
-
- RegionInfo info = Grasscutter.getDispatchServer().getCurrRegion().getRegionInfo();
-
+
+ RegionInfo info;
+
+ if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
+ if (regionCache == null) {
+ try {
+ File file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt");
+ String query_cur_region = "";
+ if (file.exists()) {
+ query_cur_region = new String(FileUtils.read(file));
+ } else {
+ Grasscutter.getLogger().warn("query_cur_region not found! Using default current region.");
+ }
+
+ byte[] decodedCurRegion = Base64.getDecoder().decode(query_cur_region);
+ QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp.parseFrom(decodedCurRegion);
+
+ RegionInfo serverRegion = regionQuery.getRegionInfo().toBuilder()
+ .setIp((Grasscutter.getConfig().getGameServerOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getGameServerOptions().Ip : Grasscutter.getConfig().getGameServerOptions().PublicIp))
+ .setPort(Grasscutter.getConfig().getGameServerOptions().Port)
+ .setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
+ .build();
+
+ regionCache = regionQuery.toBuilder().setRegionInfo(serverRegion).build();
+ } catch (Exception e) {
+ Grasscutter.getLogger().error("Error while initializing region cache!", e);
+ }
+ }
+
+ info = regionCache.getRegionInfo();
+ } else {
+ info = Grasscutter.getDispatchServer().getCurrRegion().getRegionInfo();
+ }
+
PlayerLoginRsp p = PlayerLoginRsp.newBuilder()
.setIsUseAbilityHash(true) // true
.setAbilityHashCode(1844674) // 1844674
From 63e008cbcf971c81e02fd9d632a7987c46fc41e0 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 22:50:06 +0800
Subject: [PATCH 29/78] DatabaseManager clean up
---
.../grasscutter/database/DatabaseManager.java | 36 ++++++++++---------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/src/main/java/emu/grasscutter/database/DatabaseManager.java b/src/main/java/emu/grasscutter/database/DatabaseManager.java
index 530581517..46dad537d 100644
--- a/src/main/java/emu/grasscutter/database/DatabaseManager.java
+++ b/src/main/java/emu/grasscutter/database/DatabaseManager.java
@@ -38,7 +38,8 @@ public final class DatabaseManager {
return getDatastore().getDatabase();
}
- // Yes. I very dislike this method also but I'm lazy. Probably replace it by making the game server connect to the dispatch server instead.
+ // Yes. I very dislike this method. However, this will be good for now.
+ // TODO: Add dispatch routes for player account management
public static Datastore getAccountDatastore() {
if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
return dispatchDatastore;
@@ -50,7 +51,6 @@ public final class DatabaseManager {
public static void initialize() {
// Initialize
mongoClient = new MongoClient(new MongoClientURI(Grasscutter.getConfig().DatabaseUrl));
- dispatchMongoClient = new MongoClient(new MongoClientURI(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl));
Morphia morphia = new Morphia();
// TODO Update when migrating to Morphia 2.0
@@ -63,7 +63,6 @@ public final class DatabaseManager {
// Build datastore
datastore = morphia.createDatastore(mongoClient, Grasscutter.getConfig().DatabaseCollection);
- dispatchDatastore = morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection);
// Ensure indexes
try {
@@ -82,20 +81,25 @@ public final class DatabaseManager {
}
}
- // Ensure indexes for dispatch server
- try {
- dispatchDatastore.ensureIndexes();
- } catch (MongoCommandException e) {
- Grasscutter.getLogger().info("Mongo index error: ", e);
- // Duplicate index error
- if (e.getCode() == 85) {
- // Drop all indexes and re add them
- MongoIterable collections = dispatchDatastore.getDatabase().listCollectionNames();
- for (String name : collections) {
- dispatchDatastore.getDatabase().getCollection(name).dropIndexes();
- }
- // Add back indexes
+ if(Grasscutter.getConfig().RunMode.equalsIgnoreCase("GAME_ONLY")) {
+ dispatchMongoClient = new MongoClient(new MongoClientURI(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl));
+ dispatchDatastore = morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection);
+
+ // Ensure indexes for dispatch server
+ try {
dispatchDatastore.ensureIndexes();
+ } catch (MongoCommandException e) {
+ Grasscutter.getLogger().info("Mongo index error: ", e);
+ // Duplicate index error
+ if (e.getCode() == 85) {
+ // Drop all indexes and re add them
+ MongoIterable collections = dispatchDatastore.getDatabase().listCollectionNames();
+ for (String name : collections) {
+ dispatchDatastore.getDatabase().getCollection(name).dropIndexes();
+ }
+ // Add back indexes
+ dispatchDatastore.ensureIndexes();
+ }
}
}
}
From dee31057635d9978027d3463a5fd71539c039ad9 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:55:32 +0800
Subject: [PATCH 30/78] Add list command
Signed-off-by: Jaida Wu
---
.../command/commands/ListCommand.java | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 src/main/java/emu/grasscutter/command/commands/ListCommand.java
diff --git a/src/main/java/emu/grasscutter/command/commands/ListCommand.java b/src/main/java/emu/grasscutter/command/commands/ListCommand.java
new file mode 100644
index 000000000..6afca4a6d
--- /dev/null
+++ b/src/main/java/emu/grasscutter/command/commands/ListCommand.java
@@ -0,0 +1,33 @@
+package emu.grasscutter.command.commands;
+
+import emu.grasscutter.Grasscutter;
+import emu.grasscutter.command.Command;
+import emu.grasscutter.command.CommandHandler;
+import emu.grasscutter.game.GenshinPlayer;
+
+import java.util.List;
+import java.util.Map;
+
+@Command(label = "list", description = "List online players")
+public class ListCommand implements CommandHandler {
+
+ @Override
+ public void execute(GenshinPlayer sender, List args) {
+ Map playersMap = Grasscutter.getGameServer().getPlayers();
+
+ CommandHandler.sendMessage(sender, String.format("There are %s player(s) online:", playersMap.size()));
+
+ if (playersMap.size() != 0) {
+ StringBuilder playerSet = new StringBuilder();
+
+ for (Map.Entry entry : playersMap.entrySet()) {
+ playerSet.append(entry.getValue().getNickname());
+ playerSet.append(", ");
+ }
+
+ String players = playerSet.toString();
+
+ CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2));
+ }
+ }
+}
From 72355dd3c5c1cc1db16dfb04c7217084b2c1f184 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 23:00:36 +0800
Subject: [PATCH 31/78] Removed class left over from testing
---
.../java/emu/grasscutter/server/dispatch/DispatchServer.java | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 37ed6c5ac..1978e6b08 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -515,9 +515,4 @@ public final class DispatchServer {
this.Base64 = b64;
}
}
-
- public static class UserConnnectionData {
- public InetAddress dispatchConnectedAddress;
- public String connectedRegion;
- }
}
From 66b5ed8a8399f7a5c7fddfaf4105c190ad0f69ae Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Thu, 21 Apr 2022 23:04:02 +0800
Subject: [PATCH 32/78] Should probably remove this as well...
---
.../java/emu/grasscutter/server/dispatch/DispatchServer.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 1978e6b08..f77c264eb 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -50,7 +50,6 @@ public final class DispatchServer {
public String regionListBase64;
public HashMap regions;
- public HashMap usersConnected;
public static String query_region_list = "";
public static String query_cur_region = "";
From ae086ed18c2f149be4af706a599856dc4e6b2651 Mon Sep 17 00:00:00 2001
From: alt3ri <95161279+alt3ri@users.noreply.github.com>
Date: Thu, 21 Apr 2022 22:45:02 +0700
Subject: [PATCH 33/78] Update README.md
Removed !sethp, added !setstats, !pos, !weather
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 19f2a1e3e..24269f6b9 100644
--- a/README.md
+++ b/README.md
@@ -60,10 +60,14 @@ There is a dummy user named "Server" in every player's friends list that you can
`!resetconst` - Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
-`!sethp [hp]`
+`!setstats [stats] [amount]` - Changes the current character's specified stat.
`!clearartifacts` - Deletes all unequipped and unlocked level 0 artifacts, **including yellow rarity ones** from your inventory
+`!pos` - Gets your current coordinate.
+
+`!weather [weather id]` - Changes the current weather.
+
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
### Bonus
From a1567895fa8e489117a46b225fd440b9ef5a73a9 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:06:25 +0800
Subject: [PATCH 34/78] Refact code
Signed-off-by: Jaida Wu
---
src/main/java/emu/grasscutter/Config.java | 12 +-
.../server/dispatch/DispatchServer.java | 283 ++++++++----------
.../dispatch/json/ComboTokenReqJson.java | 2 +-
.../dispatch/json/ComboTokenResJson.java | 2 +-
.../server/dispatch/json/LoginResultJson.java | 4 +-
5 files changed, 141 insertions(+), 162 deletions(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index 65ada3969..f51e5cd59 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -12,10 +12,10 @@ public final class Config {
public String GameServerIp = "127.0.0.1";
public String GameServerPublicIp = "";
public int GameServerPort = 22102;
-
+
public String DatabaseUrl = "mongodb://localhost:27017";
public String DatabaseCollection = "grasscutter";
-
+
public String RESOURCE_FOLDER = "./resources/";
public String DATA_FOLDER = "./data/";
public String PACKETS_FOLDER = "./packets/";
@@ -25,21 +25,21 @@ public final class Config {
public GameRates Game = new GameRates();
public ServerOptions ServerOptions = new ServerOptions();
-
+
public GameRates getGameRates() {
return Game;
}
-
+
public ServerOptions getServerOptions() {
return ServerOptions;
}
-
+
public static class GameRates {
public float ADVENTURE_EXP_RATE = 1.0f;
public float MORA_RATE = 1.0f;
public float DOMAIN_DROP_RATE = 1.0f;
}
-
+
public static class ServerOptions {
public int InventoryLimitWeapon = 2000;
public int InventoryLimitRelic = 2000;
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index e59f9d251..b4d4993d8 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -1,10 +1,27 @@
package emu.grasscutter.server.dispatch;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.protobuf.ByteString;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import emu.grasscutter.Grasscutter;
+import emu.grasscutter.database.DatabaseHelper;
+import emu.grasscutter.game.Account;
+import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp;
+import emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp;
+import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo;
+import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo;
+import emu.grasscutter.server.dispatch.json.*;
+import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
+import emu.grasscutter.utils.FileUtils;
+import emu.grasscutter.utils.Utils;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import java.io.*;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URLDecoder;
@@ -14,58 +31,27 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.protobuf.ByteString;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpsConfigurator;
-import com.sun.net.httpserver.HttpsServer;
-
-import emu.grasscutter.Grasscutter;
-import emu.grasscutter.database.DatabaseHelper;
-import emu.grasscutter.game.Account;
-import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp;
-import emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp;
-import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo;
-import emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo;
-import emu.grasscutter.server.dispatch.json.ComboTokenReqJson;
-import emu.grasscutter.server.dispatch.json.ComboTokenResJson;
-import emu.grasscutter.server.dispatch.json.LoginAccountRequestJson;
-import emu.grasscutter.server.dispatch.json.LoginResultJson;
-import emu.grasscutter.server.dispatch.json.LoginTokenRequestJson;
-import emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData;
-import emu.grasscutter.utils.FileUtils;
-import emu.grasscutter.utils.Utils;
-
-import com.sun.net.httpserver.HttpServer;
-
public final class DispatchServer {
- private final InetSocketAddress address;
- private final Gson gson;
- private QueryCurrRegionHttpRsp currRegion;
-
- public String regionListBase64;
- public String regionCurrentBase64;
-
public static String query_region_list = "";
public static String query_cur_region = "";
-
+ private final InetSocketAddress address;
+ private final Gson gson;
+ public String regionListBase64;
+ public String regionCurrentBase64;
+ private QueryCurrRegionHttpRsp currRegion;
+
public DispatchServer() {
this.address = new InetSocketAddress(Grasscutter.getConfig().DispatchServerIp, Grasscutter.getConfig().DispatchServerPort);
this.gson = new GsonBuilder().create();
-
+
this.loadQueries();
this.initRegion();
}
-
+
public InetSocketAddress getAddress() {
return address;
}
-
+
public Gson getGsonFactory() {
return gson;
}
@@ -73,17 +59,17 @@ public final class DispatchServer {
public QueryCurrRegionHttpRsp getCurrRegion() {
return currRegion;
}
-
+
public void loadQueries() {
File file;
-
+
file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_region_list.txt");
if (file.exists()) {
query_region_list = new String(FileUtils.read(file));
} else {
Grasscutter.getLogger().warn("query_region_list not found! Using default region list.");
}
-
+
file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt");
if (file.exists()) {
query_cur_region = new String(FileUtils.read(file));
@@ -96,38 +82,38 @@ public final class DispatchServer {
try {
byte[] decoded = Base64.getDecoder().decode(query_region_list);
QueryRegionListHttpRsp rl = QueryRegionListHttpRsp.parseFrom(decoded);
-
+
byte[] decoded2 = Base64.getDecoder().decode(query_cur_region);
QueryCurrRegionHttpRsp regionQuery = QueryCurrRegionHttpRsp.parseFrom(decoded2);
-
+
RegionSimpleInfo server = RegionSimpleInfo.newBuilder()
.setName("os_usa")
.setTitle(Grasscutter.getConfig().GameServerName)
.setType("DEV_PUBLIC")
.setDispatchUrl("https://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
.build();
-
+
RegionSimpleInfo serverTest2 = RegionSimpleInfo.newBuilder()
.setName("os_euro")
.setTitle("Grasscutter")
.setType("DEV_PUBLIC")
.setDispatchUrl("https://" + (Grasscutter.getConfig().DispatchServerPublicIp.isEmpty() ? Grasscutter.getConfig().DispatchServerIp : Grasscutter.getConfig().DispatchServerPublicIp) + ":" + getAddress().getPort() + "/query_cur_region")
.build();
-
+
QueryRegionListHttpRsp regionList = QueryRegionListHttpRsp.newBuilder()
- .addServers(server)
- .addServers(serverTest2)
- .setClientSecretKey(rl.getClientSecretKey())
- .setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted())
- .setEnableLoginPc(true)
- .build();
-
+ .addServers(server)
+ .addServers(serverTest2)
+ .setClientSecretKey(rl.getClientSecretKey())
+ .setClientCustomConfigEncrypted(rl.getClientCustomConfigEncrypted())
+ .setEnableLoginPc(true)
+ .build();
+
RegionInfo currentRegion = regionQuery.getRegionInfo().toBuilder()
.setIp((Grasscutter.getConfig().GameServerPublicIp.isEmpty() ? Grasscutter.getConfig().GameServerIp : Grasscutter.getConfig().GameServerPublicIp))
.setPort(Grasscutter.getConfig().GameServerPort)
.setSecretKey(ByteString.copyFrom(FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin")))
.build();
-
+
QueryCurrRegionHttpRsp parsedRegionQuery = regionQuery.toBuilder().setRegionInfo(currentRegion).build();
this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray());
@@ -140,7 +126,7 @@ public final class DispatchServer {
public void start() throws Exception {
HttpServer server;
- if(Grasscutter.getConfig().UseSSL) {
+ if (Grasscutter.getConfig().UseSSL) {
HttpsServer httpsServer;
httpsServer = HttpsServer.create(getAddress(), 0);
SSLContext sslContext = SSLContext.getInstance("TLS");
@@ -150,9 +136,9 @@ public final class DispatchServer {
ks.load(fis, keystorePassword);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keystorePassword);
-
+
sslContext.init(kmf.getKeyManagers(), null, null);
-
+
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
server = httpsServer;
} catch (Exception e) {
@@ -162,7 +148,7 @@ public final class DispatchServer {
} else {
server = HttpServer.create(getAddress(), 0);
}
-
+
server.createContext("/", t -> {
//Create a response form the request query parameters
String response = "Hello";
@@ -174,7 +160,7 @@ public final class DispatchServer {
os.write(response.getBytes());
os.close();
});
-
+
// Dispatch
server.createContext("/query_region_list", t -> {
// Log
@@ -213,33 +199,38 @@ public final class DispatchServer {
try {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, LoginAccountRequestJson.class);
- } catch (Exception e) {
-
+ } catch (Exception ignored) {
+
}
// Create response json
if (requestData == null) {
return;
}
LoginResultJson responseData = new LoginResultJson();
-
+
// Login
Account account = DatabaseHelper.getAccountByName(requestData.account);
-
+
// Check if account exists, else create a new one.
if (account == null) {
// Account doesnt exist, so we can either auto create it if the config value is set
if (Grasscutter.getConfig().ServerOptions.AutomaticallyCreateAccounts) {
// This account has been created AUTOMATICALLY. There will be no permissions added.
account = DatabaseHelper.createAccountWithId(requestData.account, 0);
-
- responseData.message = "OK";
- responseData.data.account.uid = account.getId();
- responseData.data.account.token = account.generateSessionKey();
- responseData.data.account.email = account.getEmail();
+
+ if (account != null) {
+ responseData.message = "OK";
+ responseData.data.account.uid = account.getId();
+ responseData.data.account.token = account.generateSessionKey();
+ responseData.data.account.email = account.getEmail();
+ } else {
+ responseData.retcode = -201;
+ responseData.message = "Username not found, create failed.";
+ }
} else {
responseData.retcode = -201;
responseData.message = "Username not found.";
- }
+ }
} else {
// Account was found, log the player in
responseData.message = "OK";
@@ -247,16 +238,8 @@ public final class DispatchServer {
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
}
-
- // Create a response
- String response = getGsonFactory().toJson(responseData);
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("application/json"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
+
+ responseJson(t, responseData);
});
// Login via token
server.createContext("/hk4e_global/mdk/shield/api/verify", t -> {
@@ -265,8 +248,8 @@ public final class DispatchServer {
try {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, LoginTokenRequestJson.class);
- } catch (Exception e) {
-
+ } catch (Exception ignored) {
+
}
// Create response json
if (requestData == null) {
@@ -276,7 +259,7 @@ public final class DispatchServer {
// Login
Account account = DatabaseHelper.getAccountById(requestData.uid);
-
+
// Test
if (account == null || !account.getSessionKey().equals(requestData.token)) {
responseData.retcode = -111;
@@ -287,16 +270,8 @@ public final class DispatchServer {
responseData.data.account.token = requestData.token;
responseData.data.account.email = account.getEmail();
}
-
- // Create a response
- String response = getGsonFactory().toJson(responseData);
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("application/json"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
+
+ responseJson(t, responseData);
});
// Exchange for combo token
server.createContext("/hk4e_global/combo/granter/login/v2/login", t -> {
@@ -305,8 +280,8 @@ public final class DispatchServer {
try {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, ComboTokenReqJson.class);
- } catch (Exception e) {
-
+ } catch (Exception ignored) {
+
}
// Create response json
if (requestData == null || requestData.data == null) {
@@ -317,7 +292,7 @@ public final class DispatchServer {
// Login
Account account = DatabaseHelper.getAccountById(loginData.uid);
-
+
// Test
if (account == null || !account.getSessionKey().equals(loginData.token)) {
responseData.retcode = -201;
@@ -328,29 +303,21 @@ public final class DispatchServer {
responseData.data.combo_id = "157795300";
responseData.data.combo_token = account.generateLoginToken();
}
-
- // Create a response
- String response = getGsonFactory().toJson(responseData);
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("application/json"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
+
+ responseJson(t, responseData);
});
// Agreement and Protocol
server.createContext( // hk4e-sdk-os.hoyoverse.com
- "/hk4e_global/mdk/agreement/api/getAgreementInfos",
+ "/hk4e_global/mdk/agreement/api/getAgreementInfos",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"marketing_agreements\":[]}}")
);
server.createContext( // hk4e-sdk-os.hoyoverse.com
- "/hk4e_global/combo/granter/api/compareProtocolVersion",
+ "/hk4e_global/combo/granter/api/compareProtocolVersion",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"modified\":true,\"protocol\":{\"id\":0,\"app_id\":4,\"language\":\"en\",\"user_proto\":\"\",\"priv_proto\":\"\",\"major\":7,\"minimum\":0,\"create_time\":\"0\",\"teenager_proto\":\"\",\"third_proto\":\"\"}}}")
);
// Game data
server.createContext( // hk4e-api-os.hoyoverse.com
- "/common/hk4e_global/announcement/api/getAlertPic",
+ "/common/hk4e_global/announcement/api/getAlertPic",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"total\":0,\"list\":[]}}")
);
server.createContext( // hk4e-api-os.hoyoverse.com
@@ -358,62 +325,62 @@ public final class DispatchServer {
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"alert\":false,\"alert_id\":0,\"remind\":true}}")
);
server.createContext( // hk4e-api-os.hoyoverse.com
- "/common/hk4e_global/announcement/api/getAnnList",
+ "/common/hk4e_global/announcement/api/getAnnList",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0,\"type_list\":[],\"alert\":false,\"alert_id\":0,\"timezone\":0,\"t\":\"" + System.currentTimeMillis() + "\"}}")
);
server.createContext( // hk4e-api-os-static.hoyoverse.com
- "/common/hk4e_global/announcement/api/getAnnContent",
+ "/common/hk4e_global/announcement/api/getAnnContent",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"list\":[],\"total\":0}}")
);
server.createContext( // hk4e-sdk-os.hoyoverse.com
- "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier",
+ "/hk4e_global/mdk/shopwindow/shopwindow/listPriceTier",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"suggest_currency\":\"USD\",\"tiers\":[]}}")
);
// Captcha
server.createContext( // api-account-os.hoyoverse.com
- "/account/risky/api/check",
+ "/account/risky/api/check",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":\"c8820f246a5241ab9973f71df3ddd791\",\"action\":\"\",\"geetest\":{\"challenge\":\"\",\"gt\":\"\",\"new_captcha\":0,\"success\":1}}}")
);
// Config
server.createContext( // sdk-os-static.hoyoverse.com
- "/combo/box/api/config/sdk/combo",
+ "/combo/box/api/config/sdk/combo",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"vals\":{\"disable_email_bind_skip\":\"false\",\"email_bind_remind_interval\":\"7\",\"email_bind_remind\":\"true\"}}}")
);
server.createContext( // hk4e-sdk-os-static.hoyoverse.com
- "/hk4e_global/combo/granter/api/getConfig",
+ "/hk4e_global/combo/granter/api/getConfig",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")
);
server.createContext( // hk4e-sdk-os-static.hoyoverse.com
- "/hk4e_global/mdk/shield/api/loadConfig",
+ "/hk4e_global/mdk/shield/api/loadConfig",
new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")
);
// Test api?
server.createContext( // abtest-api-data-sg.hoyoverse.com
- "/data_abtest_api/config/experiment/list",
+ "/data_abtest_api/config/experiment/list",
new DispatchHttpJsonHandler("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")
);
// Log Server
server.createContext( // log-upload-os.mihoyo.com
- "/log/sdk/upload",
+ "/log/sdk/upload",
new DispatchHttpJsonHandler("{\"code\":0}")
);
server.createContext( // log-upload-os.mihoyo.com
- "/sdk/upload",
+ "/sdk/upload",
new DispatchHttpJsonHandler("{\"code\":0}")
);
server.createContext( // /perf/config/verify?device_id=xxx&platform=x&name=xxx
- "/perf/config/verify",
+ "/perf/config/verify",
new DispatchHttpJsonHandler("{\"code\":0}")
);
-
+
// Logging servers
server.createContext( // overseauspider.yuanshen.com
- "/log",
+ "/log",
new DispatchHttpJsonHandler("{\"code\":0}")
);
-
+
server.createContext( // log-upload-os.mihoyo.com
- "/crash/dataUpload",
+ "/crash/dataUpload",
new DispatchHttpJsonHandler("{\"code\":0}")
);
server.createContext("/gacha", t -> {
@@ -431,31 +398,43 @@ public final class DispatchServer {
server.start();
Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
}
-
+
+ private void responseJson(HttpExchange t, Object data) throws IOException {
+ // Create a response
+ String response = getGsonFactory().toJson(data);
+ // Set the response header status and length
+ t.getResponseHeaders().put("Content-Type", Collections.singletonList("application/json"));
+ t.sendResponseHeaders(200, response.getBytes().length);
+ // Write the response string
+ OutputStream os = t.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+
private Map parseQueryString(String qs) {
- Map result = new HashMap<>();
- if (qs == null)
- return result;
+ Map result = new HashMap<>();
+ if (qs == null)
+ return result;
- int last = 0, next, l = qs.length();
- while (last < l) {
- next = qs.indexOf('&', last);
- if (next == -1)
- next = l;
+ int last = 0, next, l = qs.length();
+ while (last < l) {
+ next = qs.indexOf('&', last);
+ if (next == -1)
+ next = l;
- if (next > last) {
- int eqPos = qs.indexOf('=', last);
- try {
- if (eqPos < 0 || eqPos > next)
- result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");
- else
- result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
- }
- }
- last = next + 1;
- }
- return result;
+ if (next > last) {
+ int eqPos = qs.indexOf('=', last);
+ try {
+ if (eqPos < 0 || eqPos > next)
+ result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");
+ else
+ result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
+ }
+ }
+ last = next + 1;
+ }
+ return result;
}
}
diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java b/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java
index dac26cfa4..b3497f8d4 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java
@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
public String device;
public String sign;
- public class LoginTokenData {
+ public static class LoginTokenData {
public String uid;
public String token;
public boolean guest;
diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java b/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java
index 731d50853..7c49d1278 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java
@@ -5,7 +5,7 @@ public class ComboTokenResJson {
public int retcode;
public LoginData data = new LoginData();
- public class LoginData {
+ public static class LoginData {
public int account_type = 1;
public boolean heartbeat;
public String combo_id;
diff --git a/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java b/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java
index 5988752d8..88e142d4f 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java
@@ -5,7 +5,7 @@ public class LoginResultJson {
public int retcode;
public VerifyData data = new VerifyData();
- public class VerifyData {
+ public static class VerifyData {
public VerifyAccountData account = new VerifyAccountData();
public boolean device_grant_required = false;
public String realname_operation = "NONE";
@@ -13,7 +13,7 @@ public class LoginResultJson {
public boolean safe_mobile_required = false;
}
- public class VerifyAccountData {
+ public static class VerifyAccountData {
public String uid;
public String name = "";
public String email;
From 2df8625b24181912d28bbe330fc5783d079751a6 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:21:28 +0800
Subject: [PATCH 35/78] Fallback to HTTP if no SSL cert
Signed-off-by: Jaida Wu
---
.../java/emu/grasscutter/server/dispatch/DispatchServer.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index b4d4993d8..392609a07 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -142,8 +142,9 @@ public final class DispatchServer {
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
server = httpsServer;
} catch (Exception e) {
- Grasscutter.getLogger().error("No SSL cert found!");
- return;
+ Grasscutter.getLogger().error("No SSL cert found! Falling back to HTTP server.");
+ Grasscutter.getConfig().UseSSL = false;
+ server = HttpServer.create(getAddress(), 0);
}
} else {
server = HttpServer.create(getAddress(), 0);
From b0d2d29b1cdaa76715dbad869abe29d26eafc3c8 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:22:40 +0800
Subject: [PATCH 36/78] Add some log to dispatch server
Signed-off-by: Jaida Wu
---
.../server/dispatch/DispatchServer.java | 100 +++++++++---------
1 file changed, 49 insertions(+), 51 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 392609a07..0e2283652 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -150,48 +150,26 @@ public final class DispatchServer {
server = HttpServer.create(getAddress(), 0);
}
- server.createContext("/", t -> {
- //Create a response form the request query parameters
- String response = "Hello";
- //Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
- t.sendResponseHeaders(200, response.getBytes().length);
- //Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
- });
+ server.createContext("/", t -> responseHTML(t, "Hello"));
// Dispatch
server.createContext("/query_region_list", t -> {
// Log
- Grasscutter.getLogger().info("Client request: query_region_list");
- // Create a response form the request query parameters
- String response = regionListBase64;
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
+ Grasscutter.getLogger().info(String.format("Client %s request: query_region_list", t.getRemoteAddress()));
+
+ responseHTML(t, regionListBase64);
});
server.createContext("/query_cur_region", t -> {
// Log
- Grasscutter.getLogger().info("Client request: query_cur_region");
+ Grasscutter.getLogger().info(String.format("Client %s request: query_cur_region", t.getRemoteAddress()));
// Create a response form the request query parameters
URI uri = t.getRequestURI();
String response = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw==";
if (uri.getQuery() != null && uri.getQuery().length() > 0) {
response = regionCurrentBase64;
}
- // Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
- t.sendResponseHeaders(200, response.getBytes().length);
- // Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
+
+ responseHTML(t, response);
});
// Login via account
server.createContext("/hk4e_global/mdk/shield/api/login", t -> {
@@ -201,7 +179,6 @@ public final class DispatchServer {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, LoginAccountRequestJson.class);
} catch (Exception ignored) {
-
}
// Create response json
if (requestData == null) {
@@ -209,6 +186,8 @@ public final class DispatchServer {
}
LoginResultJson responseData = new LoginResultJson();
+ Grasscutter.getLogger().info(String.format("Client %s is trying to log in", t.getRemoteAddress()));
+
// Login
Account account = DatabaseHelper.getAccountByName(requestData.account);
@@ -224,13 +203,19 @@ public final class DispatchServer {
responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
+
+ Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account %s created", t.getRemoteAddress(), responseData.data.account.uid));
} else {
responseData.retcode = -201;
responseData.message = "Username not found, create failed.";
+
+ Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account create failed", t.getRemoteAddress()));
}
} else {
responseData.retcode = -201;
responseData.message = "Username not found.";
+
+ Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account no found", t.getRemoteAddress()));
}
} else {
// Account was found, log the player in
@@ -238,10 +223,13 @@ public final class DispatchServer {
responseData.data.account.uid = account.getId();
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
+
+ Grasscutter.getLogger().info(String.format("Client %s logged in as %s", t.getRemoteAddress(), responseData.data.account.uid));
}
- responseJson(t, responseData);
+ responseJSON(t, responseData);
});
+
// Login via token
server.createContext("/hk4e_global/mdk/shield/api/verify", t -> {
// Get post data
@@ -250,13 +238,13 @@ public final class DispatchServer {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, LoginTokenRequestJson.class);
} catch (Exception ignored) {
-
}
// Create response json
if (requestData == null) {
return;
}
LoginResultJson responseData = new LoginResultJson();
+ Grasscutter.getLogger().info(String.format("Client %s is trying to log in via token", t.getRemoteAddress()));
// Login
Account account = DatabaseHelper.getAccountById(requestData.uid);
@@ -265,14 +253,18 @@ public final class DispatchServer {
if (account == null || !account.getSessionKey().equals(requestData.token)) {
responseData.retcode = -111;
responseData.message = "Game account cache information error";
+
+ Grasscutter.getLogger().info(String.format("Client %s failed to log in via token", t.getRemoteAddress()));
} else {
responseData.message = "OK";
responseData.data.account.uid = requestData.uid;
responseData.data.account.token = requestData.token;
responseData.data.account.email = account.getEmail();
+
+ Grasscutter.getLogger().info(String.format("Client %s logged in via token as %s", t.getRemoteAddress(), responseData.data.account.uid));
}
- responseJson(t, responseData);
+ responseJSON(t, responseData);
});
// Exchange for combo token
server.createContext("/hk4e_global/combo/granter/login/v2/login", t -> {
@@ -282,7 +274,6 @@ public final class DispatchServer {
String body = Utils.toString(t.getRequestBody());
requestData = getGsonFactory().fromJson(body, ComboTokenReqJson.class);
} catch (Exception ignored) {
-
}
// Create response json
if (requestData == null || requestData.data == null) {
@@ -298,14 +289,18 @@ public final class DispatchServer {
if (account == null || !account.getSessionKey().equals(loginData.token)) {
responseData.retcode = -201;
responseData.message = "Wrong session key.";
+
+ Grasscutter.getLogger().info(String.format("Client %s failed to exchange combo token", t.getRemoteAddress()));
} else {
responseData.message = "OK";
responseData.data.open_id = loginData.uid;
responseData.data.combo_id = "157795300";
responseData.data.combo_token = account.generateLoginToken();
+
+ Grasscutter.getLogger().info(String.format("Client %s succeed to exchange combo token", t.getRemoteAddress()));
}
- responseJson(t, responseData);
+ responseJSON(t, responseData);
});
// Agreement and Protocol
server.createContext( // hk4e-sdk-os.hoyoverse.com
@@ -384,23 +379,13 @@ public final class DispatchServer {
"/crash/dataUpload",
new DispatchHttpJsonHandler("{\"code\":0}")
);
- server.createContext("/gacha", t -> {
- //Create a response form the request query parameters
- String response = "Gacha";
- //Set the response header status and length
- t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
- t.sendResponseHeaders(200, response.getBytes().length);
- //Write the response string
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
- });
+ server.createContext("/gacha", t -> responseHTML(t, "Gacha"));
// Start server
server.start();
Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
}
- private void responseJson(HttpExchange t, Object data) throws IOException {
+ private void responseJSON(HttpExchange t, Object data) throws IOException {
// Create a response
String response = getGsonFactory().toJson(data);
// Set the response header status and length
@@ -412,24 +397,37 @@ public final class DispatchServer {
os.close();
}
+ private void responseHTML(HttpExchange t, String response) throws IOException {
+ // Set the response header status and length
+ t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html; charset=UTF-8"));
+ t.sendResponseHeaders(200, response.getBytes().length);
+ //Write the response string
+ OutputStream os = t.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+
private Map parseQueryString(String qs) {
Map result = new HashMap<>();
- if (qs == null)
+ if (qs == null) {
return result;
+ }
int last = 0, next, l = qs.length();
while (last < l) {
next = qs.indexOf('&', last);
- if (next == -1)
+ if (next == -1) {
next = l;
+ }
if (next > last) {
int eqPos = qs.indexOf('=', last);
try {
- if (eqPos < 0 || eqPos > next)
+ if (eqPos < 0 || eqPos > next) {
result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");
- else
+ } else {
result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));
+ }
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
}
From aacd261206c1149ddaa8bbff5de3eccfd884310b Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:26:28 +0800
Subject: [PATCH 37/78] Add dispatch server log prefix
Signed-off-by: Jaida Wu
---
.../server/dispatch/DispatchServer.java | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index 0e2283652..5b46f9def 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -67,14 +67,14 @@ public final class DispatchServer {
if (file.exists()) {
query_region_list = new String(FileUtils.read(file));
} else {
- Grasscutter.getLogger().warn("query_region_list not found! Using default region list.");
+ Grasscutter.getLogger().warn("[Dispatch] query_region_list not found! Using default region list.");
}
file = new File(Grasscutter.getConfig().DATA_FOLDER + "query_cur_region.txt");
if (file.exists()) {
query_cur_region = new String(FileUtils.read(file));
} else {
- Grasscutter.getLogger().warn("query_cur_region not found! Using default current region.");
+ Grasscutter.getLogger().warn("[Dispatch] query_cur_region not found! Using default current region.");
}
}
@@ -120,7 +120,7 @@ public final class DispatchServer {
this.regionCurrentBase64 = Base64.getEncoder().encodeToString(parsedRegionQuery.toByteString().toByteArray());
this.currRegion = parsedRegionQuery;
} catch (Exception e) {
- Grasscutter.getLogger().error("Error while initializing region info!", e);
+ Grasscutter.getLogger().error("[Dispatch] Error while initializing region info!", e);
}
}
@@ -142,7 +142,7 @@ public final class DispatchServer {
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
server = httpsServer;
} catch (Exception e) {
- Grasscutter.getLogger().error("No SSL cert found! Falling back to HTTP server.");
+ Grasscutter.getLogger().warn("[Dispatch] No SSL cert found! Falling back to HTTP server.");
Grasscutter.getConfig().UseSSL = false;
server = HttpServer.create(getAddress(), 0);
}
@@ -155,13 +155,13 @@ public final class DispatchServer {
// Dispatch
server.createContext("/query_region_list", t -> {
// Log
- Grasscutter.getLogger().info(String.format("Client %s request: query_region_list", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s request: query_region_list", t.getRemoteAddress()));
responseHTML(t, regionListBase64);
});
server.createContext("/query_cur_region", t -> {
// Log
- Grasscutter.getLogger().info(String.format("Client %s request: query_cur_region", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s request: query_cur_region", t.getRemoteAddress()));
// Create a response form the request query parameters
URI uri = t.getRequestURI();
String response = "CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw==";
@@ -186,7 +186,7 @@ public final class DispatchServer {
}
LoginResultJson responseData = new LoginResultJson();
- Grasscutter.getLogger().info(String.format("Client %s is trying to log in", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s is trying to log in", t.getRemoteAddress()));
// Login
Account account = DatabaseHelper.getAccountByName(requestData.account);
@@ -204,18 +204,18 @@ public final class DispatchServer {
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
- Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account %s created", t.getRemoteAddress(), responseData.data.account.uid));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s failed to log in: Account %s created", t.getRemoteAddress(), responseData.data.account.uid));
} else {
responseData.retcode = -201;
responseData.message = "Username not found, create failed.";
- Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account create failed", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s failed to log in: Account create failed", t.getRemoteAddress()));
}
} else {
responseData.retcode = -201;
responseData.message = "Username not found.";
- Grasscutter.getLogger().info(String.format("Client %s failed to log in: Account no found", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s failed to log in: Account no found", t.getRemoteAddress()));
}
} else {
// Account was found, log the player in
@@ -224,7 +224,7 @@ public final class DispatchServer {
responseData.data.account.token = account.generateSessionKey();
responseData.data.account.email = account.getEmail();
- Grasscutter.getLogger().info(String.format("Client %s logged in as %s", t.getRemoteAddress(), responseData.data.account.uid));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s logged in as %s", t.getRemoteAddress(), responseData.data.account.uid));
}
responseJSON(t, responseData);
@@ -244,7 +244,7 @@ public final class DispatchServer {
return;
}
LoginResultJson responseData = new LoginResultJson();
- Grasscutter.getLogger().info(String.format("Client %s is trying to log in via token", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s is trying to log in via token", t.getRemoteAddress()));
// Login
Account account = DatabaseHelper.getAccountById(requestData.uid);
@@ -254,14 +254,14 @@ public final class DispatchServer {
responseData.retcode = -111;
responseData.message = "Game account cache information error";
- Grasscutter.getLogger().info(String.format("Client %s failed to log in via token", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s failed to log in via token", t.getRemoteAddress()));
} else {
responseData.message = "OK";
responseData.data.account.uid = requestData.uid;
responseData.data.account.token = requestData.token;
responseData.data.account.email = account.getEmail();
- Grasscutter.getLogger().info(String.format("Client %s logged in via token as %s", t.getRemoteAddress(), responseData.data.account.uid));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s logged in via token as %s", t.getRemoteAddress(), responseData.data.account.uid));
}
responseJSON(t, responseData);
@@ -290,14 +290,14 @@ public final class DispatchServer {
responseData.retcode = -201;
responseData.message = "Wrong session key.";
- Grasscutter.getLogger().info(String.format("Client %s failed to exchange combo token", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s failed to exchange combo token", t.getRemoteAddress()));
} else {
responseData.message = "OK";
responseData.data.open_id = loginData.uid;
responseData.data.combo_id = "157795300";
responseData.data.combo_token = account.generateLoginToken();
- Grasscutter.getLogger().info(String.format("Client %s succeed to exchange combo token", t.getRemoteAddress()));
+ Grasscutter.getLogger().info(String.format("[Dispatch] Client %s succeed to exchange combo token", t.getRemoteAddress()));
}
responseJSON(t, responseData);
@@ -382,7 +382,7 @@ public final class DispatchServer {
server.createContext("/gacha", t -> responseHTML(t, "Gacha"));
// Start server
server.start();
- Grasscutter.getLogger().info("Dispatch server started on port " + getAddress().getPort());
+ Grasscutter.getLogger().info("[Dispatch] Dispatch server started on port " + getAddress().getPort());
}
private void responseJSON(HttpExchange t, Object data) throws IOException {
From 68deff0c95a52009c12a359545e15b80a1f111e9 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Thu, 21 Apr 2022 22:27:26 +0800
Subject: [PATCH 38/78] Listens to all addresses by default
Signed-off-by: Jaida Wu
---
src/main/java/emu/grasscutter/Config.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java
index f51e5cd59..0b011e576 100644
--- a/src/main/java/emu/grasscutter/Config.java
+++ b/src/main/java/emu/grasscutter/Config.java
@@ -1,16 +1,16 @@
package emu.grasscutter;
public final class Config {
- public String DispatchServerIp = "127.0.0.1";
- public String DispatchServerPublicIp = "";
+ public String DispatchServerIp = "0.0.0.0";
+ public String DispatchServerPublicIp = "127.0.0.1";
public int DispatchServerPort = 443;
public String DispatchServerKeystorePath = "./keystore.p12";
public String DispatchServerKeystorePassword = "";
public Boolean UseSSL = true;
public String GameServerName = "Test";
- public String GameServerIp = "127.0.0.1";
- public String GameServerPublicIp = "";
+ public String GameServerIp = "0.0.0.0";
+ public String GameServerPublicIp = "127.0.0.1";
public int GameServerPort = 22102;
public String DatabaseUrl = "mongodb://localhost:27017";
From ff6958ed1f23608dbe9ca019e0ab47d958738a0b Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Fri, 22 Apr 2022 01:15:05 +0800
Subject: [PATCH 39/78] Forgot a dispatch prefix on error while merging
---
.../java/emu/grasscutter/server/dispatch/DispatchServer.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
index a058bed6b..ad8354867 100644
--- a/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
+++ b/src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
@@ -155,7 +155,7 @@ public final class DispatchServer {
this.regionListBase64 = Base64.getEncoder().encodeToString(regionList.toByteString().toByteArray());
} catch (Exception e) {
- Grasscutter.getLogger().error("Error while initializing region info!", e);
+ Grasscutter.getLogger().error("[Dispatch] Error while initializing region info!", e);
}
}
From 38c0c9eb7c0c10df1abbcc0bbe9fa1252fd3839b Mon Sep 17 00:00:00 2001
From: yarik0chka
Date: Thu, 21 Apr 2022 22:21:24 +0500
Subject: [PATCH 40/78] Add a changing weather id
---
README.md | 2 +-
.../grasscutter/command/commands/WeatherCommand.java | 12 +++++++-----
src/main/java/emu/grasscutter/game/GenshinScene.java | 11 ++++++++++-
.../packet/send/PacketSceneAreaWeatherNotify.java | 2 +-
4 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 24269f6b9..1aef752c0 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@ There is a dummy user named "Server" in every player's friends list that you can
`!pos` - Gets your current coordinate.
-`!weather [weather id]` - Changes the current weather.
+`!weather [weather id] [climate id]` - Changes the current weather.
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
diff --git a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java
index 919432ed1..bb9ae4a42 100644
--- a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java
@@ -8,7 +8,7 @@ import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify;
import java.util.List;
-@Command(label = "weather", usage = "weather ",
+@Command(label = "weather", usage = "weather [climateId]",
description = "Changes the weather.", aliases = {"w"}, permission = "player.weather")
public final class WeatherCommand implements CommandHandler {
@@ -20,20 +20,22 @@ public final class WeatherCommand implements CommandHandler {
}
if (args.size() < 1) {
- CommandHandler.sendMessage(sender, "Usage: weather ");
+ CommandHandler.sendMessage(sender, "Usage: weather [climateId]");
return;
}
try {
int weatherId = Integer.parseInt(args.get(0));
+ int climateId = args.size() > 1 ? Integer.parseInt(args.get(1)) : 1;
- ClimateType climate = ClimateType.getTypeByValue(weatherId);
+ ClimateType climate = ClimateType.getTypeByValue(climateId);
+ sender.getScene().setWeather(weatherId);
sender.getScene().setClimate(climate);
sender.getScene().broadcastPacket(new PacketSceneAreaWeatherNotify(sender));
- CommandHandler.sendMessage(sender, "Changed weather to " + weatherId);
+ CommandHandler.sendMessage(sender, "Changed weather to " + weatherId + " with climate " + climateId);
} catch (NumberFormatException ignored) {
- CommandHandler.sendMessage(sender, "Invalid weather ID.");
+ CommandHandler.sendMessage(sender, "Invalid ID.");
}
}
}
diff --git a/src/main/java/emu/grasscutter/game/GenshinScene.java b/src/main/java/emu/grasscutter/game/GenshinScene.java
index 668902d87..ea462fcdb 100644
--- a/src/main/java/emu/grasscutter/game/GenshinScene.java
+++ b/src/main/java/emu/grasscutter/game/GenshinScene.java
@@ -34,7 +34,8 @@ public class GenshinScene {
private int time;
private ClimateType climate;
-
+ private int weather;
+
public GenshinScene(World world, SceneData sceneData) {
this.world = world;
this.sceneData = sceneData;
@@ -89,10 +90,18 @@ public class GenshinScene {
return climate;
}
+ public int getWeather() {
+ return weather;
+ }
+
public void setClimate(ClimateType climate) {
this.climate = climate;
}
+ public void setWeather(int weather) {
+ this.weather = weather;
+ }
+
public boolean isInScene(GenshinEntity entity) {
return this.entities.containsKey(entity.getId());
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java
index de26dd064..69c40dba0 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketSceneAreaWeatherNotify.java
@@ -12,7 +12,7 @@ public class PacketSceneAreaWeatherNotify extends GenshinPacket {
super(PacketOpcodes.SceneAreaWeatherNotify);
SceneAreaWeatherNotify proto = SceneAreaWeatherNotify.newBuilder()
- .setWeatherAreaId(1)
+ .setWeatherAreaId(player.getScene().getWeather())
.setClimateType(player.getScene().getClimate().getValue())
.build();
From 2cc8d48fde890b7bde8fc2d5de76098d085dcf20 Mon Sep 17 00:00:00 2001
From: alt3ri <95161279+alt3ri@users.noreply.github.com>
Date: Fri, 22 Apr 2022 00:54:06 +0700
Subject: [PATCH 41/78] Fix typo
"When you create a new account via auto register or console server then during scene select a character and write a name on it press it it will get stuck and make the server disconnected. Some can get through and some can't passed it, so currently I'm still on the stable version . even how many times have I deleted the datebase and tried it on some linux and directly on windows too :/ btw https://github.com/Grasscutters/Grasscutter/blob/686360086569d52467a95b289b8bbe5c85cb2fe4/src/main/java/emu/grasscutter/data/ResourceLoader.java#L131 in scene folder there is a typo name "BinOutPut" it should be "BinOutput" so scene file can't be found." - [Yuki#4985](https://discord.com/channels/965284035985305680/965284036333424722/966756877100789760)
Thanks [Yuki#4985](https://discord.com/channels/965284035985305680/965284036333424722/966756877100789760)
---
src/main/java/emu/grasscutter/data/ResourceLoader.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java
index 8a29f5a72..bb95d70e9 100644
--- a/src/main/java/emu/grasscutter/data/ResourceLoader.java
+++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java
@@ -128,7 +128,7 @@ public class ResourceLoader {
private static void loadScenePoints() {
Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)");
- File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutPut/Scene/Point");
+ File folder = new File(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Scene/Point");
if (!folder.isDirectory() || !folder.exists() || folder.listFiles() == null) {
Grasscutter.getLogger().error("Scene point files cannot be found, you cannot use teleport waypoints!");
From a01783ef3c9926d012168e06aa38a22f7966441d Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 02:23:02 +0800
Subject: [PATCH 42/78] Teleport Small Fix
---
src/main/java/emu/grasscutter/game/World.java | 9 ++++++++-
.../server/packet/send/PacketPlayerEnterSceneNotify.java | 2 +-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/World.java b/src/main/java/emu/grasscutter/game/World.java
index f88d3bee4..ffffb1e53 100644
--- a/src/main/java/emu/grasscutter/game/World.java
+++ b/src/main/java/emu/grasscutter/game/World.java
@@ -212,7 +212,10 @@ public class World implements Iterable {
return false;
}
+ Integer oldSceneId = null;
+
if (player.getScene() != null) {
+ oldSceneId = player.getScene().getId();
player.getScene().removePlayer(player);
}
@@ -221,7 +224,11 @@ public class World implements Iterable {
player.getPos().set(pos);
// Teleport packet
- player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterSelf, EnterReason.TransPoint, sceneId, pos));
+ if (oldSceneId.equals(sceneId)) {
+ player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterGoto, EnterReason.TransPoint, sceneId, pos));
+ } else {
+ player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterJump, EnterReason.TransPoint, sceneId, pos));
+ }
return true;
}
diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java
index e2db99153..d66575273 100644
--- a/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java
+++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerEnterSceneNotify.java
@@ -52,7 +52,7 @@ public class PacketPlayerEnterSceneNotify extends GenshinPacket {
.setSceneId(newScene)
.setPos(newPos.toProto())
.setSceneBeginTime(System.currentTimeMillis())
- .setType(EnterType.EnterSelf)
+ .setType(type)
.setTargetUid(target.getUid())
.setEnterSceneToken(player.getEnterSceneToken())
.setWorldLevel(target.getWorld().getWorldLevel())
From 96a252f9dded00c259b29bfab5101806a43135f7 Mon Sep 17 00:00:00 2001
From: alt3ri <95161279+alt3ri@users.noreply.github.com>
Date: Fri, 22 Apr 2022 02:28:52 +0700
Subject: [PATCH 43/78] Added /revive command
Now it's more convenient to revive character without food :>
---
.../grasscutter/command/commands/Revive.java | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 src/main/java/emu/grasscutter/command/commands/Revive.java
diff --git a/src/main/java/emu/grasscutter/command/commands/Revive.java b/src/main/java/emu/grasscutter/command/commands/Revive.java
new file mode 100644
index 000000000..3f830f3e2
--- /dev/null
+++ b/src/main/java/emu/grasscutter/command/commands/Revive.java
@@ -0,0 +1,33 @@
+package emu.grasscutter.command.commands;
+
+import emu.grasscutter.command.Command;
+import emu.grasscutter.command.CommandHandler;
+import emu.grasscutter.game.GenshinPlayer;
+import emu.grasscutter.game.TeamManager;
+//import emu.grasscutter.game.avatar.GenshinAvatar;
+//import emu.grasscutter.game.TeamInfo;
+import emu.grasscutter.game.entity.EntityAvatar;
+import emu.grasscutter.game.props.FightProperty;
+import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
+import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
+
+import java.util.List;
+
+@Command(label = "revive", aliases = {"rev"},
+ usage = "revive|rev", description = "Revive character(s) that died)")
+public class Revive implements CommandHandler {
+ //private Object teamId;
+
+ @Override
+ public void execute(GenshinPlayer player, List args) {
+ for (EntityAvatar entity2 : TeamManager.getActiveTeam()) {
+ entity2.setFightProperty(
+ FightProperty.FIGHT_PROP_CUR_HP,
+ entity2.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f
+ );
+ player.sendPacket(new PacketAvatarFightPropUpdateNotify(entity2.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
+ player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity2.getAvatar()));
+ }
+ player.dropMessage("Character revived.");
+ }
+}
From dca137a93e4a20e699b1dca97ec7e8f208b726ab Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 14:02:17 -0700
Subject: [PATCH 44/78] Fix account dupe key error after selecting starting
character
---
src/main/java/emu/grasscutter/game/GenshinPlayer.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
index 1bc989183..95ae5176d 100644
--- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java
+++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java
@@ -170,7 +170,6 @@ public class GenshinPlayer {
public void setUid(int id) {
this.id = id;
- this.getProfile().syncWithCharacter(this);
}
public long getNextGenshinGuid() {
@@ -353,7 +352,6 @@ public class GenshinPlayer {
public PlayerProfile getProfile() {
if (this.playerProfile == null) {
this.playerProfile = new PlayerProfile(this);
- this.save();
}
return playerProfile;
}
From d19d80fa4e2aef5addf2c09a7d5d1d333671fc19 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 14:44:55 -0700
Subject: [PATCH 45/78] Save config everytime you load so the new options show
up
---
src/main/java/emu/grasscutter/Grasscutter.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java
index 0e34c120d..51d0835cd 100644
--- a/src/main/java/emu/grasscutter/Grasscutter.java
+++ b/src/main/java/emu/grasscutter/Grasscutter.java
@@ -86,8 +86,10 @@ public final class Grasscutter {
public static void loadConfig() {
try (FileReader file = new FileReader(configFile)) {
config = gson.fromJson(file, Config.class);
+ saveConfig();
} catch (Exception e) {
- Grasscutter.config = new Config(); saveConfig();
+ Grasscutter.config = new Config();
+ saveConfig();
}
}
From eb44fc88c4dcf9217cf0d3a028e65a1fe1daf1e9 Mon Sep 17 00:00:00 2001
From: Melledy <52122272+Melledy@users.noreply.github.com>
Date: Thu, 21 Apr 2022 14:47:04 -0700
Subject: [PATCH 46/78] Refactor Revive Command + fix syntax error
No idea how I missed the syntax error while reviewing
---
.../{Revive.java => ReviveCommand.java} | 66 +++++++++----------
1 file changed, 33 insertions(+), 33 deletions(-)
rename src/main/java/emu/grasscutter/command/commands/{Revive.java => ReviveCommand.java} (88%)
diff --git a/src/main/java/emu/grasscutter/command/commands/Revive.java b/src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
similarity index 88%
rename from src/main/java/emu/grasscutter/command/commands/Revive.java
rename to src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
index 3f830f3e2..554af4a50 100644
--- a/src/main/java/emu/grasscutter/command/commands/Revive.java
+++ b/src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
@@ -1,33 +1,33 @@
-package emu.grasscutter.command.commands;
-
-import emu.grasscutter.command.Command;
-import emu.grasscutter.command.CommandHandler;
-import emu.grasscutter.game.GenshinPlayer;
-import emu.grasscutter.game.TeamManager;
-//import emu.grasscutter.game.avatar.GenshinAvatar;
-//import emu.grasscutter.game.TeamInfo;
-import emu.grasscutter.game.entity.EntityAvatar;
-import emu.grasscutter.game.props.FightProperty;
-import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
-import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
-
-import java.util.List;
-
-@Command(label = "revive", aliases = {"rev"},
- usage = "revive|rev", description = "Revive character(s) that died)")
-public class Revive implements CommandHandler {
- //private Object teamId;
-
- @Override
- public void execute(GenshinPlayer player, List args) {
- for (EntityAvatar entity2 : TeamManager.getActiveTeam()) {
- entity2.setFightProperty(
- FightProperty.FIGHT_PROP_CUR_HP,
- entity2.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f
- );
- player.sendPacket(new PacketAvatarFightPropUpdateNotify(entity2.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
- player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity2.getAvatar()));
- }
- player.dropMessage("Character revived.");
- }
-}
+package emu.grasscutter.command.commands;
+
+import emu.grasscutter.command.Command;
+import emu.grasscutter.command.CommandHandler;
+import emu.grasscutter.game.GenshinPlayer;
+import emu.grasscutter.game.TeamManager;
+//import emu.grasscutter.game.avatar.GenshinAvatar;
+//import emu.grasscutter.game.TeamInfo;
+import emu.grasscutter.game.entity.EntityAvatar;
+import emu.grasscutter.game.props.FightProperty;
+import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
+import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
+
+import java.util.List;
+
+@Command(label = "revive", aliases = {"rev"},
+ usage = "revive|rev", description = "Revive character(s) that died)")
+public class ReviveCommand implements CommandHandler {
+ //private Object teamId;
+
+ @Override
+ public void execute(GenshinPlayer player, List args) {
+ for (EntityAvatar entity2 : player.getTeamManager().getActiveTeam()) {
+ entity2.setFightProperty(
+ FightProperty.FIGHT_PROP_CUR_HP,
+ entity2.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f
+ );
+ player.sendPacket(new PacketAvatarFightPropUpdateNotify(entity2.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
+ player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity2.getAvatar()));
+ }
+ player.dropMessage("Character revived.");
+ }
+}
From 6b8b6b48998e9a34d8b678d61d3adfb858d87535 Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 07:37:25 +0800
Subject: [PATCH 47/78] fetter try
---
.../emu/grasscutter/data/GenshinData.java | 15 +
.../emu/grasscutter/data/def/AvatarData.java | 9 +
.../emu/grasscutter/data/def/FetterData.java | 24 +
.../game/avatar/GenshinAvatar.java | 34 +-
.../grasscutter/game/props/FetterState.java | 42 +
.../AvatarFetterDataNotifyOuterClass.java | 810 ++++++++++++++++++
.../AvatarFetterLevelRewardReqOuterClass.java | 610 +++++++++++++
.../AvatarFetterLevelRewardRspOuterClass.java | 751 ++++++++++++++++
8 files changed, 2293 insertions(+), 2 deletions(-)
create mode 100644 src/main/java/emu/grasscutter/data/def/FetterData.java
create mode 100644 src/main/java/emu/grasscutter/game/props/FetterState.java
create mode 100644 src/main/java/emu/grasscutter/net/proto/AvatarFetterDataNotifyOuterClass.java
create mode 100644 src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardReqOuterClass.java
create mode 100644 src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardRspOuterClass.java
diff --git a/src/main/java/emu/grasscutter/data/GenshinData.java b/src/main/java/emu/grasscutter/data/GenshinData.java
index 7dc5a5f7c..1996bf074 100644
--- a/src/main/java/emu/grasscutter/data/GenshinData.java
+++ b/src/main/java/emu/grasscutter/data/GenshinData.java
@@ -1,7 +1,9 @@
package emu.grasscutter.data;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import emu.grasscutter.Grasscutter;
@@ -54,6 +56,7 @@ public class GenshinData {
private static final Int2ObjectMap avatarCostumeDataItemIdMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>();
+ private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>();
public static Int2ObjectMap> getMapByResourceDef(Class> resourceDefinition) {
Int2ObjectMap> map = null;
@@ -221,4 +224,16 @@ public class GenshinData {
public static Int2ObjectMap getSceneDataMap() {
return sceneDataMap;
}
+
+ public static Map> getFetterDataEntries() {
+ // Can I do this?
+ Map> fetters = new HashMap<>();
+ fetterDataMap.forEach((k, v) -> {
+ if (!fetters.containsKey(v.getAvatarId())) {
+ fetters.put(v.getAvatarId(), new ArrayList<>());
+ }
+ fetters.get(v.getAvatarId()).add(k);
+ });
+ return fetters;
+ }
}
diff --git a/src/main/java/emu/grasscutter/data/def/AvatarData.java b/src/main/java/emu/grasscutter/data/def/AvatarData.java
index dcc503994..8097e04a7 100644
--- a/src/main/java/emu/grasscutter/data/def/AvatarData.java
+++ b/src/main/java/emu/grasscutter/data/def/AvatarData.java
@@ -55,6 +55,8 @@ public class AvatarData extends GenshinResource {
private float[] defenseGrowthCurve;
private AvatarSkillDepotData skillDepot;
private IntList abilities;
+
+ private List fetters;
@Override
public int getId(){
@@ -193,9 +195,16 @@ public class AvatarData extends GenshinResource {
return abilities;
}
+ public List getFetters() {
+ return fetters;
+ }
+
@Override
public void onLoad() {
this.skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.SkillDepotId);
+
+ // Get fetters from GenshinData
+ this.fetters = GenshinData.getFetterDataEntries().get(this.Id);
int size = GenshinData.getAvatarCurveDataMap().size();
this.hpGrowthCurve = new float[size];
diff --git a/src/main/java/emu/grasscutter/data/def/FetterData.java b/src/main/java/emu/grasscutter/data/def/FetterData.java
new file mode 100644
index 000000000..d17c940d1
--- /dev/null
+++ b/src/main/java/emu/grasscutter/data/def/FetterData.java
@@ -0,0 +1,24 @@
+package emu.grasscutter.data.def;
+
+import emu.grasscutter.data.GenshinResource;
+import emu.grasscutter.data.ResourceType;
+import emu.grasscutter.data.ResourceType.LoadPriority;
+
+@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
+public class FetterData extends GenshinResource {
+ private int AvatarId;
+ private int FetterId;
+
+ @Override
+ public int getId() {
+ return FetterId;
+ }
+
+ public int getAvatarId() {
+ return AvatarId;
+ }
+
+ @Override
+ public void onLoad() {
+ }
+}
diff --git a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
index 9723c23d7..e5dccc42d 100644
--- a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
@@ -1,7 +1,9 @@
package emu.grasscutter.game.avatar;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -39,9 +41,11 @@ import emu.grasscutter.game.inventory.EquipType;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.EntityIdType;
+import emu.grasscutter.game.props.FetterState;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
+import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData;
import emu.grasscutter.net.proto.AvatarInfoOuterClass.AvatarInfo;
import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarEquipChangeNotify;
@@ -73,6 +77,8 @@ public class GenshinAvatar {
@Transient private final Int2FloatOpenHashMap fightProp;
@Transient private Set extraAbilityEmbryos;
+ private List fetters;
+
private Map skillLevelMap; // Talent levels
private Map proudSkillBonusMap; // Talent bonus levels (from const)
private int skillDepotId;
@@ -89,7 +95,8 @@ public class GenshinAvatar {
this.equips = new Int2ObjectOpenHashMap<>();
this.fightProp = new Int2FloatOpenHashMap();
this.extraAbilityEmbryos = new HashSet<>();
- this.proudSkillBonusMap = new HashMap<>(); // TODO Move to genshin avatar
+ this.proudSkillBonusMap = new HashMap<>();
+ this.fetters = new ArrayList<>(); // TODO Move to genshin avatar
}
// On creation
@@ -266,6 +273,14 @@ public class GenshinAvatar {
return extraAbilityEmbryos;
}
+ public void setFetterList(List fetterList) {
+ this.fetterList = fetterList;
+ }
+
+ public List getFetterList() {
+ return fetterList;
+ }
+
public float getCurrentHp() {
return currentHp;
}
@@ -385,6 +400,9 @@ public class GenshinAvatar {
// Extra ability embryos
Set prevExtraAbilityEmbryos = this.getExtraAbilityEmbryos();
this.extraAbilityEmbryos = new HashSet<>();
+
+ // Fetters
+ this.setFetterList(data.getFetters());
// Get hp percent, set to 100% if none
float hpPercent = this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) <= 0 ? 1f : this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) / this.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
@@ -683,6 +701,18 @@ public class GenshinAvatar {
}
public AvatarInfo toProto() {
+ AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
+ .setExpLevel(10)
+ .setExpNumber(6325); // Highest Level
+
+ for (int i = 0; i < this.getFetterList().size(); i++) {
+ avatarFetter.addFetterList(
+ FetterData.newBuilder()
+ .setFetterId(this.getFetterList().get(i))
+ .setFetterState(FetterState.FINISH.getValue())
+ );
+ }
+
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
.setAvatarId(this.getAvatarId())
.setGuid(this.getGuid())
@@ -696,7 +726,7 @@ public class GenshinAvatar {
.putAllProudSkillExtraLevel(getProudSkillBonusMap())
.setAvatarType(1)
.setBornTime(this.getBornTime())
- .setFetterInfo(AvatarFetterInfo.newBuilder().setExpLevel(1))
+ .setFetterInfo(avatarFetter)
.setWearingFlycloakId(this.getFlyCloak())
.setCostumeId(this.getCostume());
diff --git a/src/main/java/emu/grasscutter/game/props/FetterState.java b/src/main/java/emu/grasscutter/game/props/FetterState.java
new file mode 100644
index 000000000..346060e19
--- /dev/null
+++ b/src/main/java/emu/grasscutter/game/props/FetterState.java
@@ -0,0 +1,42 @@
+package emu.grasscutter.game.props;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+
+public enum FetterState {
+ NONE(0),
+ NOT_OPEN(1),
+ OPEN(1),
+ FINISH(3);
+
+ private final int value;
+ private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>();
+ private static final Map stringMap = new HashMap<>();
+
+ static {
+ Stream.of(values()).forEach(e -> {
+ map.put(e.getValue(), e);
+ stringMap.put(e.name(), e);
+ });
+ }
+
+ private FetterState(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public static FetterState getTypeByValue(int value) {
+ return map.getOrDefault(value, NONE);
+ }
+
+ public static FetterState getTypeByName(String name) {
+ return stringMap.getOrDefault(name, NONE);
+ }
+}
diff --git a/src/main/java/emu/grasscutter/net/proto/AvatarFetterDataNotifyOuterClass.java b/src/main/java/emu/grasscutter/net/proto/AvatarFetterDataNotifyOuterClass.java
new file mode 100644
index 000000000..08eb7158d
--- /dev/null
+++ b/src/main/java/emu/grasscutter/net/proto/AvatarFetterDataNotifyOuterClass.java
@@ -0,0 +1,810 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: AvatarFetterDataNotify.proto
+
+package emu.grasscutter.net.proto;
+
+public final class AvatarFetterDataNotifyOuterClass {
+ private AvatarFetterDataNotifyOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface AvatarFetterDataNotifyOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:AvatarFetterDataNotify)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ int getFetterInfoMapCount();
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ boolean containsFetterInfoMap(
+ long key);
+ /**
+ * Use {@link #getFetterInfoMapMap()} instead.
+ */
+ @java.lang.Deprecated
+ java.util.Map
+ getFetterInfoMap();
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ java.util.Map
+ getFetterInfoMapMap();
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ /* nullable */
+emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrDefault(
+ long key,
+ /* nullable */
+emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo defaultValue);
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrThrow(
+ long key);
+ }
+ /**
+ * Protobuf type {@code AvatarFetterDataNotify}
+ */
+ public static final class AvatarFetterDataNotify extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:AvatarFetterDataNotify)
+ AvatarFetterDataNotifyOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use AvatarFetterDataNotify.newBuilder() to construct.
+ private AvatarFetterDataNotify(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private AvatarFetterDataNotify() {
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new AvatarFetterDataNotify();
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private AvatarFetterDataNotify(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10: {
+ if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+ fetterInfoMap_ = com.google.protobuf.MapField.newMapField(
+ FetterInfoMapDefaultEntryHolder.defaultEntry);
+ mutable_bitField0_ |= 0x00000001;
+ }
+ com.google.protobuf.MapEntry
+ fetterInfoMap__ = input.readMessage(
+ FetterInfoMapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+ fetterInfoMap_.getMutableMap().put(
+ fetterInfoMap__.getKey(), fetterInfoMap__.getValue());
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_descriptor;
+ }
+
+ @SuppressWarnings({"rawtypes"})
+ @java.lang.Override
+ protected com.google.protobuf.MapField internalGetMapField(
+ int number) {
+ switch (number) {
+ case 1:
+ return internalGetFetterInfoMap();
+ default:
+ throw new RuntimeException(
+ "Invalid map field number: " + number);
+ }
+ }
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.class, emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.Builder.class);
+ }
+
+ public static final int FETTERINFOMAP_FIELD_NUMBER = 1;
+ private static final class FetterInfoMapDefaultEntryHolder {
+ static final com.google.protobuf.MapEntry<
+ java.lang.Long, emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo> defaultEntry =
+ com.google.protobuf.MapEntry
+ .newDefaultInstance(
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_descriptor,
+ com.google.protobuf.WireFormat.FieldType.UINT64,
+ 0L,
+ com.google.protobuf.WireFormat.FieldType.MESSAGE,
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo.getDefaultInstance());
+ }
+ private com.google.protobuf.MapField<
+ java.lang.Long, emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo> fetterInfoMap_;
+ private com.google.protobuf.MapField
+ internalGetFetterInfoMap() {
+ if (fetterInfoMap_ == null) {
+ return com.google.protobuf.MapField.emptyMapField(
+ FetterInfoMapDefaultEntryHolder.defaultEntry);
+ }
+ return fetterInfoMap_;
+ }
+
+ public int getFetterInfoMapCount() {
+ return internalGetFetterInfoMap().getMap().size();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ @java.lang.Override
+ public boolean containsFetterInfoMap(
+ long key) {
+
+ return internalGetFetterInfoMap().getMap().containsKey(key);
+ }
+ /**
+ * Use {@link #getFetterInfoMapMap()} instead.
+ */
+ @java.lang.Override
+ @java.lang.Deprecated
+ public java.util.Map getFetterInfoMap() {
+ return getFetterInfoMapMap();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public java.util.Map getFetterInfoMapMap() {
+ return internalGetFetterInfoMap().getMap();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrDefault(
+ long key,
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo defaultValue) {
+
+ java.util.Map map =
+ internalGetFetterInfoMap().getMap();
+ return map.containsKey(key) ? map.get(key) : defaultValue;
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrThrow(
+ long key) {
+
+ java.util.Map map =
+ internalGetFetterInfoMap().getMap();
+ if (!map.containsKey(key)) {
+ throw new java.lang.IllegalArgumentException();
+ }
+ return map.get(key);
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ com.google.protobuf.GeneratedMessageV3
+ .serializeLongMapTo(
+ output,
+ internalGetFetterInfoMap(),
+ FetterInfoMapDefaultEntryHolder.defaultEntry,
+ 1);
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (java.util.Map.Entry entry
+ : internalGetFetterInfoMap().getMap().entrySet()) {
+ com.google.protobuf.MapEntry
+ fetterInfoMap__ = FetterInfoMapDefaultEntryHolder.defaultEntry.newBuilderForType()
+ .setKey(entry.getKey())
+ .setValue(entry.getValue())
+ .build();
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, fetterInfoMap__);
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify)) {
+ return super.equals(obj);
+ }
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify other = (emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify) obj;
+
+ if (!internalGetFetterInfoMap().equals(
+ other.internalGetFetterInfoMap())) return false;
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (!internalGetFetterInfoMap().getMap().isEmpty()) {
+ hash = (37 * hash) + FETTERINFOMAP_FIELD_NUMBER;
+ hash = (53 * hash) + internalGetFetterInfoMap().hashCode();
+ }
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code AvatarFetterDataNotify}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:AvatarFetterDataNotify)
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotifyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_descriptor;
+ }
+
+ @SuppressWarnings({"rawtypes"})
+ protected com.google.protobuf.MapField internalGetMapField(
+ int number) {
+ switch (number) {
+ case 1:
+ return internalGetFetterInfoMap();
+ default:
+ throw new RuntimeException(
+ "Invalid map field number: " + number);
+ }
+ }
+ @SuppressWarnings({"rawtypes"})
+ protected com.google.protobuf.MapField internalGetMutableMapField(
+ int number) {
+ switch (number) {
+ case 1:
+ return internalGetMutableFetterInfoMap();
+ default:
+ throw new RuntimeException(
+ "Invalid map field number: " + number);
+ }
+ }
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.class, emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.Builder.class);
+ }
+
+ // Construct using emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ internalGetMutableFetterInfoMap().clear();
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.internal_static_AvatarFetterDataNotify_descriptor;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify getDefaultInstanceForType() {
+ return emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify build() {
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify buildPartial() {
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify result = new emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify(this);
+ int from_bitField0_ = bitField0_;
+ result.fetterInfoMap_ = internalGetFetterInfoMap();
+ result.fetterInfoMap_.makeImmutable();
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify) {
+ return mergeFrom((emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify other) {
+ if (other == emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify.getDefaultInstance()) return this;
+ internalGetMutableFetterInfoMap().mergeFrom(
+ other.internalGetFetterInfoMap());
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ private com.google.protobuf.MapField<
+ java.lang.Long, emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo> fetterInfoMap_;
+ private com.google.protobuf.MapField
+ internalGetFetterInfoMap() {
+ if (fetterInfoMap_ == null) {
+ return com.google.protobuf.MapField.emptyMapField(
+ FetterInfoMapDefaultEntryHolder.defaultEntry);
+ }
+ return fetterInfoMap_;
+ }
+ private com.google.protobuf.MapField
+ internalGetMutableFetterInfoMap() {
+ onChanged();;
+ if (fetterInfoMap_ == null) {
+ fetterInfoMap_ = com.google.protobuf.MapField.newMapField(
+ FetterInfoMapDefaultEntryHolder.defaultEntry);
+ }
+ if (!fetterInfoMap_.isMutable()) {
+ fetterInfoMap_ = fetterInfoMap_.copy();
+ }
+ return fetterInfoMap_;
+ }
+
+ public int getFetterInfoMapCount() {
+ return internalGetFetterInfoMap().getMap().size();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ @java.lang.Override
+ public boolean containsFetterInfoMap(
+ long key) {
+
+ return internalGetFetterInfoMap().getMap().containsKey(key);
+ }
+ /**
+ * Use {@link #getFetterInfoMapMap()} instead.
+ */
+ @java.lang.Override
+ @java.lang.Deprecated
+ public java.util.Map getFetterInfoMap() {
+ return getFetterInfoMapMap();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public java.util.Map getFetterInfoMapMap() {
+ return internalGetFetterInfoMap().getMap();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrDefault(
+ long key,
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo defaultValue) {
+
+ java.util.Map map =
+ internalGetFetterInfoMap().getMap();
+ return map.containsKey(key) ? map.get(key) : defaultValue;
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ @java.lang.Override
+
+ public emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo getFetterInfoMapOrThrow(
+ long key) {
+
+ java.util.Map map =
+ internalGetFetterInfoMap().getMap();
+ if (!map.containsKey(key)) {
+ throw new java.lang.IllegalArgumentException();
+ }
+ return map.get(key);
+ }
+
+ public Builder clearFetterInfoMap() {
+ internalGetMutableFetterInfoMap().getMutableMap()
+ .clear();
+ return this;
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ public Builder removeFetterInfoMap(
+ long key) {
+
+ internalGetMutableFetterInfoMap().getMutableMap()
+ .remove(key);
+ return this;
+ }
+ /**
+ * Use alternate mutation accessors instead.
+ */
+ @java.lang.Deprecated
+ public java.util.Map
+ getMutableFetterInfoMap() {
+ return internalGetMutableFetterInfoMap().getMutableMap();
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+ public Builder putFetterInfoMap(
+ long key,
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo value) {
+
+ if (value == null) {
+ throw new NullPointerException("map value");
+}
+
+ internalGetMutableFetterInfoMap().getMutableMap()
+ .put(key, value);
+ return this;
+ }
+ /**
+ * map<uint64, .AvatarFetterInfo> fetterInfoMap = 1;
+ */
+
+ public Builder putAllFetterInfoMap(
+ java.util.Map values) {
+ internalGetMutableFetterInfoMap().getMutableMap()
+ .putAll(values);
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:AvatarFetterDataNotify)
+ }
+
+ // @@protoc_insertion_point(class_scope:AvatarFetterDataNotify)
+ private static final emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify();
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AvatarFetterDataNotify parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new AvatarFetterDataNotify(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_AvatarFetterDataNotify_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_AvatarFetterDataNotify_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\034AvatarFetterDataNotify.proto\032\026AvatarFe" +
+ "tterInfo.proto\"\244\001\n\026AvatarFetterDataNotif" +
+ "y\022A\n\rfetterInfoMap\030\001 \003(\0132*.AvatarFetterD" +
+ "ataNotify.FetterInfoMapEntry\032G\n\022FetterIn" +
+ "foMapEntry\022\013\n\003key\030\001 \001(\004\022 \n\005value\030\002 \001(\0132\021" +
+ ".AvatarFetterInfo:\0028\001B\033\n\031emu.grasscutter" +
+ ".net.protob\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.getDescriptor(),
+ });
+ internal_static_AvatarFetterDataNotify_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_AvatarFetterDataNotify_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_AvatarFetterDataNotify_descriptor,
+ new java.lang.String[] { "FetterInfoMap", });
+ internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_descriptor =
+ internal_static_AvatarFetterDataNotify_descriptor.getNestedTypes().get(0);
+ internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_AvatarFetterDataNotify_FetterInfoMapEntry_descriptor,
+ new java.lang.String[] { "Key", "Value", });
+ emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.getDescriptor();
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardReqOuterClass.java b/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardReqOuterClass.java
new file mode 100644
index 000000000..be66bde26
--- /dev/null
+++ b/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardReqOuterClass.java
@@ -0,0 +1,610 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: AvatarFetterLevelRewardReq.proto
+
+package emu.grasscutter.net.proto;
+
+public final class AvatarFetterLevelRewardReqOuterClass {
+ private AvatarFetterLevelRewardReqOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface AvatarFetterLevelRewardReqOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:AvatarFetterLevelRewardReq)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * uint64 avatarGuid = 1;
+ * @return The avatarGuid.
+ */
+ long getAvatarGuid();
+
+ /**
+ * uint32 fetterLevel = 2;
+ * @return The fetterLevel.
+ */
+ int getFetterLevel();
+ }
+ /**
+ * Protobuf type {@code AvatarFetterLevelRewardReq}
+ */
+ public static final class AvatarFetterLevelRewardReq extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:AvatarFetterLevelRewardReq)
+ AvatarFetterLevelRewardReqOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use AvatarFetterLevelRewardReq.newBuilder() to construct.
+ private AvatarFetterLevelRewardReq(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private AvatarFetterLevelRewardReq() {
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new AvatarFetterLevelRewardReq();
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private AvatarFetterLevelRewardReq(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 8: {
+
+ avatarGuid_ = input.readUInt64();
+ break;
+ }
+ case 16: {
+
+ fetterLevel_ = input.readUInt32();
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.internal_static_AvatarFetterLevelRewardReq_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.internal_static_AvatarFetterLevelRewardReq_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.class, emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.Builder.class);
+ }
+
+ public static final int AVATARGUID_FIELD_NUMBER = 1;
+ private long avatarGuid_;
+ /**
+ * uint64 avatarGuid = 1;
+ * @return The avatarGuid.
+ */
+ @java.lang.Override
+ public long getAvatarGuid() {
+ return avatarGuid_;
+ }
+
+ public static final int FETTERLEVEL_FIELD_NUMBER = 2;
+ private int fetterLevel_;
+ /**
+ * uint32 fetterLevel = 2;
+ * @return The fetterLevel.
+ */
+ @java.lang.Override
+ public int getFetterLevel() {
+ return fetterLevel_;
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (avatarGuid_ != 0L) {
+ output.writeUInt64(1, avatarGuid_);
+ }
+ if (fetterLevel_ != 0) {
+ output.writeUInt32(2, fetterLevel_);
+ }
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (avatarGuid_ != 0L) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(1, avatarGuid_);
+ }
+ if (fetterLevel_ != 0) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(2, fetterLevel_);
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq)) {
+ return super.equals(obj);
+ }
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq other = (emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq) obj;
+
+ if (getAvatarGuid()
+ != other.getAvatarGuid()) return false;
+ if (getFetterLevel()
+ != other.getFetterLevel()) return false;
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (37 * hash) + AVATARGUID_FIELD_NUMBER;
+ hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+ getAvatarGuid());
+ hash = (37 * hash) + FETTERLEVEL_FIELD_NUMBER;
+ hash = (53 * hash) + getFetterLevel();
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code AvatarFetterLevelRewardReq}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:AvatarFetterLevelRewardReq)
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReqOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.internal_static_AvatarFetterLevelRewardReq_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.internal_static_AvatarFetterLevelRewardReq_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.class, emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.Builder.class);
+ }
+
+ // Construct using emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ avatarGuid_ = 0L;
+
+ fetterLevel_ = 0;
+
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.internal_static_AvatarFetterLevelRewardReq_descriptor;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq getDefaultInstanceForType() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq build() {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq buildPartial() {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq result = new emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq(this);
+ result.avatarGuid_ = avatarGuid_;
+ result.fetterLevel_ = fetterLevel_;
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq) {
+ return mergeFrom((emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq other) {
+ if (other == emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq.getDefaultInstance()) return this;
+ if (other.getAvatarGuid() != 0L) {
+ setAvatarGuid(other.getAvatarGuid());
+ }
+ if (other.getFetterLevel() != 0) {
+ setFetterLevel(other.getFetterLevel());
+ }
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+
+ private long avatarGuid_ ;
+ /**
+ * uint64 avatarGuid = 1;
+ * @return The avatarGuid.
+ */
+ @java.lang.Override
+ public long getAvatarGuid() {
+ return avatarGuid_;
+ }
+ /**
+ * uint64 avatarGuid = 1;
+ * @param value The avatarGuid to set.
+ * @return This builder for chaining.
+ */
+ public Builder setAvatarGuid(long value) {
+
+ avatarGuid_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint64 avatarGuid = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearAvatarGuid() {
+
+ avatarGuid_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ private int fetterLevel_ ;
+ /**
+ * uint32 fetterLevel = 2;
+ * @return The fetterLevel.
+ */
+ @java.lang.Override
+ public int getFetterLevel() {
+ return fetterLevel_;
+ }
+ /**
+ * uint32 fetterLevel = 2;
+ * @param value The fetterLevel to set.
+ * @return This builder for chaining.
+ */
+ public Builder setFetterLevel(int value) {
+
+ fetterLevel_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint32 fetterLevel = 2;
+ * @return This builder for chaining.
+ */
+ public Builder clearFetterLevel() {
+
+ fetterLevel_ = 0;
+ onChanged();
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:AvatarFetterLevelRewardReq)
+ }
+
+ // @@protoc_insertion_point(class_scope:AvatarFetterLevelRewardReq)
+ private static final emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq();
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AvatarFetterLevelRewardReq parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new AvatarFetterLevelRewardReq(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_AvatarFetterLevelRewardReq_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_AvatarFetterLevelRewardReq_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n AvatarFetterLevelRewardReq.proto\"E\n\032Av" +
+ "atarFetterLevelRewardReq\022\022\n\navatarGuid\030\001" +
+ " \001(\004\022\023\n\013fetterLevel\030\002 \001(\rB\033\n\031emu.grasscu" +
+ "tter.net.protob\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ });
+ internal_static_AvatarFetterLevelRewardReq_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_AvatarFetterLevelRewardReq_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_AvatarFetterLevelRewardReq_descriptor,
+ new java.lang.String[] { "AvatarGuid", "FetterLevel", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardRspOuterClass.java b/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardRspOuterClass.java
new file mode 100644
index 000000000..6801ce7ec
--- /dev/null
+++ b/src/main/java/emu/grasscutter/net/proto/AvatarFetterLevelRewardRspOuterClass.java
@@ -0,0 +1,751 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: AvatarFetterLevelRewardRsp.proto
+
+package emu.grasscutter.net.proto;
+
+public final class AvatarFetterLevelRewardRspOuterClass {
+ private AvatarFetterLevelRewardRspOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registerAllExtensions(
+ (com.google.protobuf.ExtensionRegistryLite) registry);
+ }
+ public interface AvatarFetterLevelRewardRspOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:AvatarFetterLevelRewardRsp)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * int32 retcode = 1;
+ * @return The retcode.
+ */
+ int getRetcode();
+
+ /**
+ * uint64 avatarGuid = 2;
+ * @return The avatarGuid.
+ */
+ long getAvatarGuid();
+
+ /**
+ * uint32 fetterLevel = 3;
+ * @return The fetterLevel.
+ */
+ int getFetterLevel();
+
+ /**
+ * uint32 rewardId = 4;
+ * @return The rewardId.
+ */
+ int getRewardId();
+ }
+ /**
+ * Protobuf type {@code AvatarFetterLevelRewardRsp}
+ */
+ public static final class AvatarFetterLevelRewardRsp extends
+ com.google.protobuf.GeneratedMessageV3 implements
+ // @@protoc_insertion_point(message_implements:AvatarFetterLevelRewardRsp)
+ AvatarFetterLevelRewardRspOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use AvatarFetterLevelRewardRsp.newBuilder() to construct.
+ private AvatarFetterLevelRewardRsp(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+ private AvatarFetterLevelRewardRsp() {
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(
+ UnusedPrivateParameter unused) {
+ return new AvatarFetterLevelRewardRsp();
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private AvatarFetterLevelRewardRsp(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ this();
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 8: {
+
+ retcode_ = input.readInt32();
+ break;
+ }
+ case 16: {
+
+ avatarGuid_ = input.readUInt64();
+ break;
+ }
+ case 24: {
+
+ fetterLevel_ = input.readUInt32();
+ break;
+ }
+ case 32: {
+
+ rewardId_ = input.readUInt32();
+ break;
+ }
+ default: {
+ if (!parseUnknownField(
+ input, unknownFields, extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.internal_static_AvatarFetterLevelRewardRsp_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.internal_static_AvatarFetterLevelRewardRsp_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.class, emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.Builder.class);
+ }
+
+ public static final int RETCODE_FIELD_NUMBER = 1;
+ private int retcode_;
+ /**
+ * int32 retcode = 1;
+ * @return The retcode.
+ */
+ @java.lang.Override
+ public int getRetcode() {
+ return retcode_;
+ }
+
+ public static final int AVATARGUID_FIELD_NUMBER = 2;
+ private long avatarGuid_;
+ /**
+ * uint64 avatarGuid = 2;
+ * @return The avatarGuid.
+ */
+ @java.lang.Override
+ public long getAvatarGuid() {
+ return avatarGuid_;
+ }
+
+ public static final int FETTERLEVEL_FIELD_NUMBER = 3;
+ private int fetterLevel_;
+ /**
+ * uint32 fetterLevel = 3;
+ * @return The fetterLevel.
+ */
+ @java.lang.Override
+ public int getFetterLevel() {
+ return fetterLevel_;
+ }
+
+ public static final int REWARDID_FIELD_NUMBER = 4;
+ private int rewardId_;
+ /**
+ * uint32 rewardId = 4;
+ * @return The rewardId.
+ */
+ @java.lang.Override
+ public int getRewardId() {
+ return rewardId_;
+ }
+
+ private byte memoizedIsInitialized = -1;
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ if (retcode_ != 0) {
+ output.writeInt32(1, retcode_);
+ }
+ if (avatarGuid_ != 0L) {
+ output.writeUInt64(2, avatarGuid_);
+ }
+ if (fetterLevel_ != 0) {
+ output.writeUInt32(3, fetterLevel_);
+ }
+ if (rewardId_ != 0) {
+ output.writeUInt32(4, rewardId_);
+ }
+ unknownFields.writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (retcode_ != 0) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, retcode_);
+ }
+ if (avatarGuid_ != 0L) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(2, avatarGuid_);
+ }
+ if (fetterLevel_ != 0) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(3, fetterLevel_);
+ }
+ if (rewardId_ != 0) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(4, rewardId_);
+ }
+ size += unknownFields.getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp)) {
+ return super.equals(obj);
+ }
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp other = (emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp) obj;
+
+ if (getRetcode()
+ != other.getRetcode()) return false;
+ if (getAvatarGuid()
+ != other.getAvatarGuid()) return false;
+ if (getFetterLevel()
+ != other.getFetterLevel()) return false;
+ if (getRewardId()
+ != other.getRewardId()) return false;
+ if (!unknownFields.equals(other.unknownFields)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (37 * hash) + RETCODE_FIELD_NUMBER;
+ hash = (53 * hash) + getRetcode();
+ hash = (37 * hash) + AVATARGUID_FIELD_NUMBER;
+ hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+ getAvatarGuid());
+ hash = (37 * hash) + FETTERLEVEL_FIELD_NUMBER;
+ hash = (53 * hash) + getFetterLevel();
+ hash = (37 * hash) + REWARDID_FIELD_NUMBER;
+ hash = (53 * hash) + getRewardId();
+ hash = (29 * hash) + unknownFields.hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ java.nio.ByteBuffer data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input);
+ }
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3
+ .parseWithIOException(PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+ public static Builder newBuilder(emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE
+ ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code AvatarFetterLevelRewardRsp}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageV3.Builder implements
+ // @@protoc_insertion_point(builder_implements:AvatarFetterLevelRewardRsp)
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRspOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.internal_static_AvatarFetterLevelRewardRsp_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.internal_static_AvatarFetterLevelRewardRsp_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.class, emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.Builder.class);
+ }
+
+ // Construct using emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3
+ .alwaysUseFieldBuilders) {
+ }
+ }
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ retcode_ = 0;
+
+ avatarGuid_ = 0L;
+
+ fetterLevel_ = 0;
+
+ rewardId_ = 0;
+
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.internal_static_AvatarFetterLevelRewardRsp_descriptor;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp getDefaultInstanceForType() {
+ return emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp build() {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp buildPartial() {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp result = new emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp(this);
+ result.retcode_ = retcode_;
+ result.avatarGuid_ = avatarGuid_;
+ result.fetterLevel_ = fetterLevel_;
+ result.rewardId_ = rewardId_;
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.setField(field, value);
+ }
+ @java.lang.Override
+ public Builder clearField(
+ com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+ @java.lang.Override
+ public Builder clearOneof(
+ com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp) {
+ return mergeFrom((emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp other) {
+ if (other == emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp.getDefaultInstance()) return this;
+ if (other.getRetcode() != 0) {
+ setRetcode(other.getRetcode());
+ }
+ if (other.getAvatarGuid() != 0L) {
+ setAvatarGuid(other.getAvatarGuid());
+ }
+ if (other.getFetterLevel() != 0) {
+ setFetterLevel(other.getFetterLevel());
+ }
+ if (other.getRewardId() != 0) {
+ setRewardId(other.getRewardId());
+ }
+ this.mergeUnknownFields(other.unknownFields);
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp) e.getUnfinishedMessage();
+ throw e.unwrapIOException();
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+
+ private int retcode_ ;
+ /**
+ * int32 retcode = 1;
+ * @return The retcode.
+ */
+ @java.lang.Override
+ public int getRetcode() {
+ return retcode_;
+ }
+ /**
+ * int32 retcode = 1;
+ * @param value The retcode to set.
+ * @return This builder for chaining.
+ */
+ public Builder setRetcode(int value) {
+
+ retcode_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * int32 retcode = 1;
+ * @return This builder for chaining.
+ */
+ public Builder clearRetcode() {
+
+ retcode_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private long avatarGuid_ ;
+ /**
+ * uint64 avatarGuid = 2;
+ * @return The avatarGuid.
+ */
+ @java.lang.Override
+ public long getAvatarGuid() {
+ return avatarGuid_;
+ }
+ /**
+ * uint64 avatarGuid = 2;
+ * @param value The avatarGuid to set.
+ * @return This builder for chaining.
+ */
+ public Builder setAvatarGuid(long value) {
+
+ avatarGuid_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint64 avatarGuid = 2;
+ * @return This builder for chaining.
+ */
+ public Builder clearAvatarGuid() {
+
+ avatarGuid_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ private int fetterLevel_ ;
+ /**
+ * uint32 fetterLevel = 3;
+ * @return The fetterLevel.
+ */
+ @java.lang.Override
+ public int getFetterLevel() {
+ return fetterLevel_;
+ }
+ /**
+ * uint32 fetterLevel = 3;
+ * @param value The fetterLevel to set.
+ * @return This builder for chaining.
+ */
+ public Builder setFetterLevel(int value) {
+
+ fetterLevel_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint32 fetterLevel = 3;
+ * @return This builder for chaining.
+ */
+ public Builder clearFetterLevel() {
+
+ fetterLevel_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private int rewardId_ ;
+ /**
+ * uint32 rewardId = 4;
+ * @return The rewardId.
+ */
+ @java.lang.Override
+ public int getRewardId() {
+ return rewardId_;
+ }
+ /**
+ * uint32 rewardId = 4;
+ * @param value The rewardId to set.
+ * @return This builder for chaining.
+ */
+ public Builder setRewardId(int value) {
+
+ rewardId_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * uint32 rewardId = 4;
+ * @return This builder for chaining.
+ */
+ public Builder clearRewardId() {
+
+ rewardId_ = 0;
+ onChanged();
+ return this;
+ }
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:AvatarFetterLevelRewardRsp)
+ }
+
+ // @@protoc_insertion_point(class_scope:AvatarFetterLevelRewardRsp)
+ private static final emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp DEFAULT_INSTANCE;
+ static {
+ DEFAULT_INSTANCE = new emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp();
+ }
+
+ public static emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser
+ PARSER = new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AvatarFetterLevelRewardRsp parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new AvatarFetterLevelRewardRsp(input, extensionRegistry);
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_AvatarFetterLevelRewardRsp_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_AvatarFetterLevelRewardRsp_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n AvatarFetterLevelRewardRsp.proto\"h\n\032Av" +
+ "atarFetterLevelRewardRsp\022\017\n\007retcode\030\001 \001(" +
+ "\005\022\022\n\navatarGuid\030\002 \001(\004\022\023\n\013fetterLevel\030\003 \001" +
+ "(\r\022\020\n\010rewardId\030\004 \001(\rB\033\n\031emu.grasscutter." +
+ "net.protob\006proto3"
+ };
+ descriptor = com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ });
+ internal_static_AvatarFetterLevelRewardRsp_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_AvatarFetterLevelRewardRsp_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_AvatarFetterLevelRewardRsp_descriptor,
+ new java.lang.String[] { "Retcode", "AvatarGuid", "FetterLevel", "RewardId", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
From a3f528ede0d28b11d6033fd9bf872bfb5ab10d96 Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 07:42:17 +0800
Subject: [PATCH 48/78] typo
---
src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
index e5dccc42d..d3b4d7147 100644
--- a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
@@ -77,7 +77,7 @@ public class GenshinAvatar {
@Transient private final Int2FloatOpenHashMap fightProp;
@Transient private Set extraAbilityEmbryos;
- private List fetters;
+ private List fetters;
private Map skillLevelMap; // Talent levels
private Map proudSkillBonusMap; // Talent bonus levels (from const)
From 1c6aa32cea905c62a9e1b5afd8155b6524fb98a1 Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 07:49:35 +0800
Subject: [PATCH 49/78] ee, forget to change variables when copying from local
---
src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
index d3b4d7147..0560ba4e5 100644
--- a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
@@ -274,11 +274,11 @@ public class GenshinAvatar {
}
public void setFetterList(List fetterList) {
- this.fetterList = fetterList;
+ this.fetters = fetterList;
}
public List getFetterList() {
- return fetterList;
+ return fetters;
}
public float getCurrentHp() {
From a47655db7a8723e17979f8482ec927d61170751d Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Fri, 22 Apr 2022 08:08:47 +0800
Subject: [PATCH 50/78] add fullfp command
---
.../command/commands/FullHpCommand.java | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 src/main/java/emu/grasscutter/command/commands/FullHpCommand.java
diff --git a/src/main/java/emu/grasscutter/command/commands/FullHpCommand.java b/src/main/java/emu/grasscutter/command/commands/FullHpCommand.java
new file mode 100644
index 000000000..f27533a8d
--- /dev/null
+++ b/src/main/java/emu/grasscutter/command/commands/FullHpCommand.java
@@ -0,0 +1,36 @@
+package emu.grasscutter.command.commands;
+
+import emu.grasscutter.command.Command;
+import emu.grasscutter.command.CommandHandler;
+import emu.grasscutter.game.GenshinPlayer;
+import emu.grasscutter.game.props.FightProperty;
+import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
+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;
+
+@Command(label = "fullhp", usage = "fullhp|fhp",
+ description = "Recover all characters in your current team to full health.", aliases = {"fhp"}, permission = "player.fullhp")
+public class FullHpCommand implements CommandHandler {
+ @Override
+ public void execute(GenshinPlayer sender, List args) {
+ if (sender == null) {
+ CommandHandler.sendMessage(null, "Run this command in-game.");
+ return;
+ }
+ sender.getTeamManager().getActiveTeam().forEach(entity -> {
+ boolean isAlive = entity.isAlive();
+ entity.setFightProperty(
+ FightProperty.FIGHT_PROP_CUR_HP,
+ entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)
+ );
+ entity.getWorld().broadcastPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
+ if (!isAlive) {
+ entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
+ }
+ });
+ CommandHandler.sendMessage(sender, "All hp recover to full.");
+ }
+}
From 85fd060561254e4ed56d4e814361b0cc2cb7f148 Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Fri, 22 Apr 2022 08:26:48 +0800
Subject: [PATCH 51/78] remove revive command
---
.../command/commands/ReviveCommand.java | 33 -------------------
1 file changed, 33 deletions(-)
delete mode 100644 src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
diff --git a/src/main/java/emu/grasscutter/command/commands/ReviveCommand.java b/src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
deleted file mode 100644
index 554af4a50..000000000
--- a/src/main/java/emu/grasscutter/command/commands/ReviveCommand.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package emu.grasscutter.command.commands;
-
-import emu.grasscutter.command.Command;
-import emu.grasscutter.command.CommandHandler;
-import emu.grasscutter.game.GenshinPlayer;
-import emu.grasscutter.game.TeamManager;
-//import emu.grasscutter.game.avatar.GenshinAvatar;
-//import emu.grasscutter.game.TeamInfo;
-import emu.grasscutter.game.entity.EntityAvatar;
-import emu.grasscutter.game.props.FightProperty;
-import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
-import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
-
-import java.util.List;
-
-@Command(label = "revive", aliases = {"rev"},
- usage = "revive|rev", description = "Revive character(s) that died)")
-public class ReviveCommand implements CommandHandler {
- //private Object teamId;
-
- @Override
- public void execute(GenshinPlayer player, List args) {
- for (EntityAvatar entity2 : player.getTeamManager().getActiveTeam()) {
- entity2.setFightProperty(
- FightProperty.FIGHT_PROP_CUR_HP,
- entity2.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .4f
- );
- player.sendPacket(new PacketAvatarFightPropUpdateNotify(entity2.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
- player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity2.getAvatar()));
- }
- player.dropMessage("Character revived.");
- }
-}
From cb043e0644927ae1907a219c122d1d829e7874e0 Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 08:30:02 +0800
Subject: [PATCH 52/78] no more NullPointerException pls
---
.../emu/grasscutter/game/avatar/GenshinAvatar.java | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
index 0560ba4e5..6906d3896 100644
--- a/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
+++ b/src/main/java/emu/grasscutter/game/avatar/GenshinAvatar.java
@@ -705,12 +705,14 @@ public class GenshinAvatar {
.setExpLevel(10)
.setExpNumber(6325); // Highest Level
- for (int i = 0; i < this.getFetterList().size(); i++) {
- avatarFetter.addFetterList(
- FetterData.newBuilder()
- .setFetterId(this.getFetterList().get(i))
- .setFetterState(FetterState.FINISH.getValue())
- );
+ if (this.getFetterList() != null) {
+ for (int i = 0; i < this.getFetterList().size(); i++) {
+ avatarFetter.addFetterList(
+ FetterData.newBuilder()
+ .setFetterId(this.getFetterList().get(i))
+ .setFetterState(FetterState.FINISH.getValue())
+ );
+ }
}
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
From fd42dd558fa9c4bb67b393dbcb24e763d023688f Mon Sep 17 00:00:00 2001
From: fengyuecanzhu <1021300691@qq.com>
Date: Fri, 22 Apr 2022 08:45:46 +0800
Subject: [PATCH 53/78] change fhp to heal
---
.../commands/{FullHpCommand.java => HealCommand.java} | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
rename src/main/java/emu/grasscutter/command/commands/{FullHpCommand.java => HealCommand.java} (81%)
diff --git a/src/main/java/emu/grasscutter/command/commands/FullHpCommand.java b/src/main/java/emu/grasscutter/command/commands/HealCommand.java
similarity index 81%
rename from src/main/java/emu/grasscutter/command/commands/FullHpCommand.java
rename to src/main/java/emu/grasscutter/command/commands/HealCommand.java
index f27533a8d..511e52812 100644
--- a/src/main/java/emu/grasscutter/command/commands/FullHpCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/HealCommand.java
@@ -11,9 +11,9 @@ import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
import java.util.List;
-@Command(label = "fullhp", usage = "fullhp|fhp",
- description = "Recover all characters in your current team to full health.", aliases = {"fhp"}, permission = "player.fullhp")
-public class FullHpCommand implements CommandHandler {
+@Command(label = "heal", usage = "heal|h",
+ description = "Heal all characters in your current team.", aliases = {"h"}, permission = "player.heal")
+public class HealCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List args) {
if (sender == null) {
@@ -31,6 +31,6 @@ public class FullHpCommand implements CommandHandler {
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
}
});
- CommandHandler.sendMessage(sender, "All hp recover to full.");
+ CommandHandler.sendMessage(sender, "All characters are healed.");
}
}
From d37543beaf4385482e672fdc07e259399c47e0fc Mon Sep 17 00:00:00 2001
From: Yazawazi <47273265+Yazawazi@users.noreply.github.com>
Date: Fri, 22 Apr 2022 10:39:25 +0800
Subject: [PATCH 54/78] cache fetters
---
.../emu/grasscutter/data/GenshinData.java | 20 +++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/main/java/emu/grasscutter/data/GenshinData.java b/src/main/java/emu/grasscutter/data/GenshinData.java
index 1996bf074..7e14b1b46 100644
--- a/src/main/java/emu/grasscutter/data/GenshinData.java
+++ b/src/main/java/emu/grasscutter/data/GenshinData.java
@@ -57,6 +57,9 @@ public class GenshinData {
private static final Int2ObjectMap sceneDataMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap fetterDataMap = new Int2ObjectOpenHashMap<>();
+
+ // Cache
+ private static Map> fetters = new HashMap<>();
public static Int2ObjectMap> getMapByResourceDef(Class> resourceDefinition) {
Int2ObjectMap> map = null;
@@ -226,14 +229,15 @@ public class GenshinData {
}
public static Map> getFetterDataEntries() {
- // Can I do this?
- Map> fetters = new HashMap<>();
- fetterDataMap.forEach((k, v) -> {
- if (!fetters.containsKey(v.getAvatarId())) {
- fetters.put(v.getAvatarId(), new ArrayList<>());
- }
- fetters.get(v.getAvatarId()).add(k);
- });
+ if (fetters.isEmpty()) {
+ fetterDataMap.forEach((k, v) -> {
+ if (!fetters.containsKey(v.getAvatarId())) {
+ fetters.put(v.getAvatarId(), new ArrayList<>());
+ }
+ fetters.get(v.getAvatarId()).add(k);
+ });
+ }
+
return fetters;
}
}
From c157aaec5ba2f247769cdae8f1c132654afd8009 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Fri, 22 Apr 2022 11:32:49 +0800
Subject: [PATCH 55/78] Make proxy daemon run imperceptibly
Signed-off-by: Jaida Wu
---
run.cmd => start.cmd | 84 ++++++++++++++++++++++++++------------------
1 file changed, 49 insertions(+), 35 deletions(-)
rename run.cmd => start.cmd (61%)
diff --git a/run.cmd b/start.cmd
similarity index 61%
rename from run.cmd
rename to start.cmd
index 36a20d811..e3425d0e4 100644
--- a/run.cmd
+++ b/start.cmd
@@ -4,67 +4,90 @@
@if "%DEBUG%" == "" echo off
pushd %~dp0
+set CUR_PATH=%~dp0
title Grasscutter
-call :LOG [INFO] Grasscutter
+call :LOG [INFO] Welcome to Grasscutter
+call :LOG [INFO] To proper exit this console, use [Ctrl + C] and enter N not Y.
+call :LOG [INFO]
call :LOG [INFO] Initializing...
-@rem This will not work if your java or mitmproxy is in a different location, plugin as necessary
-@rem this just saves you from changing your PATH
-set JAVA_PATH=C:\Program Files\Java\jdk1.8.0_202\
-set MITMPROXY_PATH=%~dp0
-set PROXY_SCRIPT=proxy
@rem TODO: MongoDB integration
-set SERVER_PATH=%~dp0
+set JAVA_PATH=DO_NOT_CHECK_PATH
+set MITMDUMP_PATH=DO_NOT_CHECK_PATH
+
+set SERVER_JAR_PATH=%CUR_PATH%
+
+set SERVER_JAR_NAME=grasscutter.jar
+set PROXY_SCRIPT_NAME=proxy
+
+if not "%JAVA_PATH%" == "DO_NOT_CHECK_PATH" (
+ if not exist "%JAVA_PATH%java.exe" (
+ call :LOG [ERROR] Java not found.
+ goto :EXIT
+ )
+) else set JAVA_PATH=
+if not exist "%SERVER_PATH%grasscutter.jar" (
+ call :LOG [ERROR] Server jar not found.
+ goto :EXIT
+)
@rem mitmproxy not found, server only
-if not exist "%MITMPROXY_PATH%mitmdump.exe" (
- call :LOG [WARN] mitmproxy not found, server only mode.
- goto :SERVER
-)
+if not "%MITMDUMP_PATH%" == "DO_NOT_CHECK_PATH" (
+ if not exist "%MITMDUMP_PATH%mitmdump.exe" (
+ call :LOG [WARN] mitmdump not found, server only mode.
+ goto :SERVER
+ )
+) else set MITMDUMP_PATH=
@rem proxy script not found, server only
-if not exist "%PROXY_SCRIPT%.py" (
- if not exist "%PROXY_SCRIPT%.pyc" (
+if not exist "%PROXY_SCRIPT_NAME%.py" (
+ if not exist "%PROXY_SCRIPT_NAME%.pyc" (
call :LOG [WARN] Missing proxy script or compiled proxy script, server only mode.
goto :SERVER
- ) else set PROXY_SCRIPT=%PROXY_SCRIPT%.pyc
-) else set PROXY_SCRIPT=%PROXY_SCRIPT%.py
+ ) else set PROXY_SCRIPT_NAME=%PROXY_SCRIPT_NAME%.pyc
+) else set PROXY_SCRIPT_NAME=%PROXY_SCRIPT_NAME%.py
:PROXY
@rem UAC Administrator privileges
>nul 2>&1 reg query "HKU\S-1-5-19" || (
call :LOG [WARN] Currently running with non Administrator privileges, raising...
echo set UAC = CreateObject^("Shell.Application"^) > "%temp%\UAC.vbs"
- echo UAC.ShellExecute "%~f0", "%1", "", "runas", 1 >> "%temp%\UAC.vbs"
+ echo UAC.ShellExecute "%~f0","%1","","runas",1 >> "%temp%\UAC.vbs"
"%temp%\UAC.vbs"
del /f /q "%temp%\UAC.vbs" >nul 2>nul
exit /b
)
+call :LOG [INFO] Starting proxy daemon...
+
set PROXY=true
+
@rem Store original proxy settings
for /f "tokens=2*" %%a in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable 2^>nul') do set "ORIG_PROXY_ENABLE=%%b"
for /f "tokens=2*" %%a in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer 2^>nul') do set "ORIG_PROXY_SERVER=%%b"
-call :LOG [INFO] Starting proxy daemon...
@rem TODO: External proxy when ORIG_PROXY_ENABLE == 0x1
-start /min "" "%MITMPROXY_PATH%mitmdump.exe" -s %PROXY_SCRIPT% --ssl-insecure
+echo set ws = createobject("wscript.shell") > "%temp%\proxy.vbs"
+echo ws.currentdirectory = "%MITMDUMP_PATH%" >> "%temp%\proxy.vbs"
+echo ws.run "cmd /c mitmdump.exe -s "^&chr(34)^&"%PROXY_SCRIPT_NAME%"^&chr(34)^&" -k",0 >> "%temp%\proxy.vbs"
+"%temp%\proxy.vbs"
+del /f /q "%temp%\proxy.vbs" >nul 2>nul
-@rem CA certificate for possible HTTPS scheme
+@rem CA certificate for HTTPS scheme
call :LOG [INFO] Waiting for CA certificate generation...
set CA_CERT_FILE="%USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer"
-set /A TIMEOUT_COUNT=0
+set /a TIMEOUT_COUNT=0
:CERT_CA_CHECK
if not exist %CA_CERT_FILE% (
- timeout /T 1 >nul 2>nul
- set /A TIMEOUT_COUNT+=1
+ timeout /t 1 >nul 2>nul
+ set /a TIMEOUT_COUNT+=1
goto CERT_CA_CHECK
)
:EXTRA_TIMEOUT
if %TIMEOUT_COUNT% LEQ 2 (
- timeout /T 1 >nul 2>nul
- set /A TIMEOUT_COUNT+=1
+ timeout /t 1 >nul 2>nul
+ set /a TIMEOUT_COUNT+=1
goto EXTRA_TIMEOUT
)
call :LOG [INFO] Adding CA certificate to store...
@@ -75,21 +98,13 @@ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v Pr
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "127.0.0.1:8080" /f >nul 2>nul
:SERVER
-if not exist "%JAVA_PATH%bin\java.exe" (
- call :LOG [ERROR] Java not found.
- goto :EXIT
-)
-if not exist "%SERVER_PATH%grasscutter.jar" (
- call :LOG [ERROR] Server jar not found.
- goto :EXIT
-)
call :LOG [INFO] Starting server...
-"%JAVA_PATH%bin\java.exe" -jar "%SERVER_PATH%grasscutter.jar"
+"%JAVA_PATH%java.exe" -jar "%SERVER_PATH%grasscutter.jar"
call :LOG [INFO] Server stopped
:EXIT
if "%PROXY%" == "" (
- call :LOG [INFO] Proxy not started, no need to clean up.
+ call :LOG [INFO] Proxy daemon not started, no need to clean up.
) else (
call :LOG [INFO] Restoring network settings...
@@ -100,7 +115,6 @@ if "%PROXY%" == "" (
taskkill /t /f /im mitmdump.exe >nul 2>nul
call :LOG [INFO] Removing CA certificate...
-
for /F "tokens=2" %%s in ('certutil -dump %CA_CERT_FILE% ^| findstr ^"^sha1^"') do (
set SERIAL=%%s
)
From 1133ffd9aad7f8ad604886213eeba50c01aaa579 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Fri, 22 Apr 2022 11:33:54 +0800
Subject: [PATCH 56/78] Integrate MongoDB into C2R
Signed-off-by: Jaida Wu
---
start.cmd | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/start.cmd b/start.cmd
index e3425d0e4..bf154bfd5 100644
--- a/start.cmd
+++ b/start.cmd
@@ -11,11 +11,12 @@ call :LOG [INFO] To proper exit this console, use [Ctrl + C] and enter N not Y.
call :LOG [INFO]
call :LOG [INFO] Initializing...
-@rem TODO: MongoDB integration
set JAVA_PATH=DO_NOT_CHECK_PATH
set MITMDUMP_PATH=DO_NOT_CHECK_PATH
+set MONGODB_PATH=DO_NOT_CHECK_PATH
set SERVER_JAR_PATH=%CUR_PATH%
+set DATABASE_STORAGE_PATH=%CUR_PATH%resources\Database
set SERVER_JAR_NAME=grasscutter.jar
set PROXY_SCRIPT_NAME=proxy
@@ -98,11 +99,35 @@ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v Pr
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "127.0.0.1:8080" /f >nul 2>nul
:SERVER
+if not "%MONGODB_PATH%" == "DO_NOT_CHECK_PATH" (
+ if not exist "%MONGODB_PATH%mongod.exe" (
+ call :LOG [WARN] MongoDB daemon not found, server only mode.
+ goto :GAME
+ )
+) else set MONGODB_PATH=
+call :LOG [INFO] Starting MongoDB daemon...
+set DATABASE=true
+
+mkdir "%DATABASE_STORAGE_PATH%" >nul 2>nul
+
+echo set ws = createobject("wscript.shell") > "%temp%\db.vbs"
+echo ws.currentdirectory = "%MONGODB_PATH%" >> "%temp%\db.vbs"
+echo ws.run "cmd /c mongod.exe --dbpath "^&chr(34)^&"%DATABASE_STORAGE_PATH%"^&chr(34)^&"",0 >> "%temp%\db.vbs"
+"%temp%\db.vbs"
+del /f /q "%temp%\db.vbs" >nul 2>nul
+
+:GAME
call :LOG [INFO] Starting server...
"%JAVA_PATH%java.exe" -jar "%SERVER_PATH%grasscutter.jar"
call :LOG [INFO] Server stopped
:EXIT
+if "%DATABASE%" == "" (
+ call :LOG [INFO] MongoDB daemon not started, no need to clean up.
+) else (
+ call :LOG [INFO] Shutting down MongoDB daemon...
+ taskkill /t /f /im mongod.exe >nul 2>nul
+)
if "%PROXY%" == "" (
call :LOG [INFO] Proxy daemon not started, no need to clean up.
) else (
From 8d78897a29daeaf788a00971f7b5c3c3c328df94 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Fri, 22 Apr 2022 11:34:22 +0800
Subject: [PATCH 57/78] Allow configuration overrides
Signed-off-by: Jaida Wu
---
start.cmd | 6 ++++++
start_config.cmd | 25 +++++++++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 start_config.cmd
diff --git a/start.cmd b/start.cmd
index bf154bfd5..8c89f359e 100644
--- a/start.cmd
+++ b/start.cmd
@@ -11,6 +11,8 @@ call :LOG [INFO] To proper exit this console, use [Ctrl + C] and enter N not Y.
call :LOG [INFO]
call :LOG [INFO] Initializing...
+set CONFIG=start_config
+
set JAVA_PATH=DO_NOT_CHECK_PATH
set MITMDUMP_PATH=DO_NOT_CHECK_PATH
set MONGODB_PATH=DO_NOT_CHECK_PATH
@@ -21,6 +23,10 @@ set DATABASE_STORAGE_PATH=%CUR_PATH%resources\Database
set SERVER_JAR_NAME=grasscutter.jar
set PROXY_SCRIPT_NAME=proxy
+if exist "%CUR_PATH%%CONFIG%.cmd" (
+ call "%CUR_PATH%%CONFIG%.cmd" >nul 2>nul
+)
+
if not "%JAVA_PATH%" == "DO_NOT_CHECK_PATH" (
if not exist "%JAVA_PATH%java.exe" (
call :LOG [ERROR] Java not found.
diff --git a/start_config.cmd b/start_config.cmd
new file mode 100644
index 000000000..575e4d8df
--- /dev/null
+++ b/start_config.cmd
@@ -0,0 +1,25 @@
+@rem
+@rem Copyright (C) 2002-2022 MlgmXyysd All Rights Reserved.
+@rem
+
+@echo off
+pushd %~dp0
+set CUR_PATH=%~dp0
+
+@rem This will not work if your java or mitmproxy is in a different location, plugin as necessary
+@rem this just saves you from changing your PATH
+
+@rem Executable Path
+@rem Note: Fill DO_NOT_CHECK_PATH if you need to run it from PATH
+@rem without detecting whether the executable file exists
+set JAVA_PATH=C:\Program Files\Java\jdk1.8.0_202\bin\
+set MITMDUMP_PATH=%CUR_PATH%
+set MONGODB_PATH=%CUR_PATH%
+
+@rem Utility Path
+set SERVER_JAR_PATH=%CUR_PATH%
+set DATABASE_STORAGE_PATH=%CUR_PATH%resources\Database
+
+@rem Utility Name
+set SERVER_JAR_NAME=grasscutter.jar
+set PROXY_SCRIPT_NAME=proxy
\ No newline at end of file
From 195b602fcc5c6955327eb0a366943214959a9983 Mon Sep 17 00:00:00 2001
From: Jaida Wu
Date: Fri, 22 Apr 2022 11:46:55 +0800
Subject: [PATCH 58/78] Update README.md
---
README.md | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
index 1aef752c0..853c37ae3 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,9 @@ A WIP server reimplementation for *some anime game* 2.3-2.6
* Friends list
* Co-op *partially* work
# Quick setup guide
+### Note
+* If you update from an older version, delete `config.json` for regeneration
+
### Prerequisites
* JDK-8u202 ([mirror link](https://mirrors.huaweicloud.com/java/jdk/8u202-b08/) since Oracle required an account to download old builds)
* Mongodb (recommended 4.0+)
@@ -26,7 +29,7 @@ A WIP server reimplementation for *some anime game* 2.3-2.6
### Connecting with the client
½. Create an account using *server console command* below
1. Run a proxy daemon: (choose either one)
- - mitmdump: `mitmdump -s proxy.py --ssl-insecure`
+ - mitmdump: `mitmdump -s proxy.py -k`
- Fiddler Classic: Run Fiddler Classic, turn on `Decrypt https traffic` in setting and change the default port there (Tools -> Options -> Connections) to anything other than `8888`, and load [this script](https://github.lunatic.moe/fiddlerscript).
- [Hosts file](https://github.com/Melledy/Grasscutter/wiki/Running#traffic-route-map)
2. Trust CA certificate:
@@ -37,36 +40,33 @@ A WIP server reimplementation for *some anime game* 2.3-2.6
* or you can use `run.cmd` to start Server & Proxy daemon with one click
# Grasscutter commands
-### Server console commands
+There is a dummy user named "Server" in every player's friends list that you can message to use commands. Commands also work in other chat rooms, such as private/team chats.
`account create [username] {playerid}` - Creates an account with the specified username and the in-game uid for that account. The playerid parameter is optional and will be auto generated if not set.
-### In-Game commands
-There is a dummy user named "Server" in every player's friends list that you can message to use commands. Commands also work in other chat rooms, such as private/team chats.
+`spawn [monster id] [level] [amount]`
-`!spawn [monster id] [level] [amount]`
+`give [item id] [amount]`
-`!give [item id] [amount]`
+`givechar [avatar id] [level]`
-`!givechar [avatar id] [level]`
+`drop [item id] [amount]`
-`!drop [item id] [amount]`
+`killall`
-`!killall`
+`setworldlevel [level]` - Relog to see effects properly
-`!setworldlevel [level]` - Relog to see effects properly
+`godmode` - Prevents you from taking damage
-`!godmode` - Prevents you from taking damage
+`resetconst` - Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
-`!resetconst` - Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
+`setstats [stats] [amount]` - Changes the current character's specified stat.
-`!setstats [stats] [amount]` - Changes the current character's specified stat.
+`clearartifacts` - Deletes all unequipped and unlocked level 0 artifacts, **including yellow rarity ones** from your inventory
-`!clearartifacts` - Deletes all unequipped and unlocked level 0 artifacts, **including yellow rarity ones** from your inventory
+`pos` - Gets your current coordinate.
-`!pos` - Gets your current coordinate.
-
-`!weather [weather id] [climate id]` - Changes the current weather.
+`weather [weather id] [climate id]` - Changes the current weather.
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
From 523329d1a04ee7a3952510b2d666537530aa18c0 Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 20:52:23 -0700
Subject: [PATCH 59/78] create empty action file
---
.github/workflows/build.yml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 .github/workflows/build.yml
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..e69de29bb
From 976d84183785716d89bffec35f4911a79ca57678 Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 20:55:43 -0700
Subject: [PATCH 60/78] begin compile env setup
---
.github/workflows/build.yml | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e69de29bb..8e5b8391a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -0,0 +1,12 @@
+name: "Build"
+on: "Push"
+jobs:
+ Build-Server-Jar:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-java@v3
+ with:
+ distribution: temurin
+ java-version: '8'
+ - run: gradlew
From 671d2f1898b63661f3f9116985ac4c075892f21a Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 20:57:30 -0700
Subject: [PATCH 61/78] Update build.yml
---
.github/workflows/build.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8e5b8391a..ce4f17416 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,12 +1,12 @@
name: "Build"
-on: "Push"
+on: "push"
jobs:
Build-Server-Jar:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- with:
- distribution: temurin
- java-version: '8'
+ with:
+ distribution: temurin
+ java-version: '8'
- run: gradlew
From dde88db8953b3fadcc72c6adb1e38e68126d9a2b Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 21:04:00 -0700
Subject: [PATCH 62/78] build steps
---
.github/workflows/build.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ce4f17416..29bbfdd04 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,9 +4,10 @@ jobs:
Build-Server-Jar:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v2
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: '8'
- - run: gradlew
+ - run: .\gradlew.bat
+ - run: .\gradlew jar
From e4fc815cd8f47ba825b1d85ac6c725ff7b13288d Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 21:13:38 -0700
Subject: [PATCH 63/78] upload artifact
---
.github/workflows/build.yml | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 29bbfdd04..b8efbad05 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -4,10 +4,18 @@ jobs:
Build-Server-Jar:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-java@v3
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Setup Java
+ uses: actions/setup-java@v3
with:
distribution: temurin
java-version: '8'
- - run: .\gradlew.bat
- - run: .\gradlew jar
+ - name: Run Gradle
+ run: .\gradlew.bat && .\gradlew jar
+ - name: Upload build
+ uses: actions/upload-artifact@v3
+ with:
+ name: Grasscutter
+ path: grasscutter.jar
+
From 1989d552b92c81af8d57340b471eb4a524dc20b3 Mon Sep 17 00:00:00 2001
From: SpikeHD
Date: Thu, 21 Apr 2022 21:21:08 -0700
Subject: [PATCH 64/78] only build on stable
---
.github/workflows/build.yml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b8efbad05..8457bf7ac 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,5 +1,8 @@
name: "Build"
-on: "push"
+on:
+ push:
+ branches:
+ - "stable"
jobs:
Build-Server-Jar:
runs-on: windows-latest
From c63835930261643d79c2713b3273dc94ec007102 Mon Sep 17 00:00:00 2001
From: Benjamin Elsdon
Date: Fri, 22 Apr 2022 13:05:06 +0800
Subject: [PATCH 65/78] Log files
---
.gitignore | 7 ++++---
src/main/resources/logback.xml | 11 +++++++++++
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 1cd17e099..9df6d0071 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,12 +47,13 @@ tmp/
# Grasscutter
resources/*
+logs/*
data/AbilityEmbryos.json
data/OpenConfig.json
proto/auto/
proto/protoc.exe
GM Handbook.txt
-config.json
-mitmdump.exe
-grasscutter.jar
+config.json
+mitmdump.exe
+grasscutter.jar
mongod.exe
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index 666b53b42..477c1ac5b 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -4,8 +4,19 @@
[%d{HH:mm:ss}] [%highlight(%level)] %msg%n
+
+ logs/latest.log
+
+ logs/log.%d{yyyy-MM-dd}_%d{HH}.log.tar.gz
+ 24
+
+
+ %d{yyyy-MM-dd'T'HH:mm:ss'Z'} - %m%n
+
+
+
\ No newline at end of file
From fe6e9967db78d50f4154c166c677fa940c1ddfd8 Mon Sep 17 00:00:00 2001
From: fumbling <104180076+fumbling644o@users.noreply.github.com>
Date: Fri, 22 Apr 2022 02:32:27 -0400
Subject: [PATCH 66/78] Explicitly load and save UTF-8 for the handbook
This fixes potential output issues for non-Latin scripts when exporting the handbook by changing the filename in the code.
---
src/main/java/emu/grasscutter/tools/Tools.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java
index 6f6466773..638d61e12 100644
--- a/src/main/java/emu/grasscutter/tools/Tools.java
+++ b/src/main/java/emu/grasscutter/tools/Tools.java
@@ -3,6 +3,7 @@ package emu.grasscutter.tools;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -30,13 +31,13 @@ public final class Tools {
ResourceLoader.loadResources();
Map map;
- try (FileReader fileReader = new FileReader(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMapEN.json"))) {
+ try (FileReader fileReader = new FileReader(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMap/TextMapEN.json"), StandardCharsets.UTF_8)) {
map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken