mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-10 04:12:54 +08:00
Merge remote-tracking branch 'upstream/development' into dev-mail
This commit is contained in:
commit
c25e809f5c
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -3,9 +3,14 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "stable"
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
jobs:
|
||||
Build-Server-Jar:
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
@ -13,12 +18,11 @@ jobs:
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '8'
|
||||
java-version: '16'
|
||||
- name: Run Gradle
|
||||
run: .\gradlew.bat && .\gradlew jar
|
||||
run: ./gradlew && ./gradlew jar
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Grasscutter
|
||||
path: grasscutter.jar
|
||||
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -50,8 +50,7 @@ resources/*
|
||||
logs/*
|
||||
data/AbilityEmbryos.json
|
||||
data/OpenConfig.json
|
||||
proto/auto/
|
||||
proto/protoc.exe
|
||||
proto/*
|
||||
GM Handbook.txt
|
||||
config.json
|
||||
mitmdump.exe
|
||||
|
26
README.md
26
README.md
@ -10,10 +10,10 @@ A WIP server reimplementation for *some anime game* 2.3-2.6
|
||||
* Inventory features (recieving items/characters, upgrading items/characters, etc)
|
||||
* Gacha system
|
||||
* Friends list
|
||||
* Co-op *partially* work
|
||||
* Co-op *partially* works
|
||||
# Quick setup guide
|
||||
### Note
|
||||
* If you update from an older version, delete `config.json` for regeneration
|
||||
* If you updated from an older version, delete `config.json` to regenerate it.
|
||||
|
||||
### Prerequisites
|
||||
* Java 16
|
||||
@ -21,15 +21,15 @@ A WIP server reimplementation for *some anime game* 2.3-2.6
|
||||
* Proxy daemon: mitmproxy (mitmdump, recommended), Fiddler Classic, etc.
|
||||
|
||||
### Starting up Grasscutter server (Assuming you are on Windows)
|
||||
1. Setup compile environment `gradlew.bat`
|
||||
1. Setup the compile environment with `gradlew.bat`
|
||||
2. Compile Grasscutter with `gradlew jar`
|
||||
3. Create a folder named `resources` in your Grasscutter directory, bring your `BinOutput` and `ExcelBinOutput` folders into it *(Check the wiki for more details how to get those.)*
|
||||
3. Create a folder named `resources` in your Grasscutter directory, move your `BinOutput` and `ExcelBinOutput` folders there *(Check the wiki for more details on how to get those.)*
|
||||
4. Run Grasscutter with `java -jar grasscutter.jar`. Make sure mongodb service is running as well.
|
||||
|
||||
### 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 -k`
|
||||
- mitmdump: `mitmdump -s proxy.py -k --allow-hosts ".*\.yuanshen\.com|.*\.mihoyo\.com|.*\.hoyoverse\.com"`
|
||||
- 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:
|
||||
@ -46,7 +46,7 @@ There is a dummy user named "Server" in every player's friends list that you can
|
||||
|
||||
`spawn [monster id] [level] [amount]`
|
||||
|
||||
`give [item id] [amount]`
|
||||
`give [item id] [amount] [level]`
|
||||
|
||||
`givechar [avatar id] [level]`
|
||||
|
||||
@ -54,26 +54,26 @@ There is a dummy user named "Server" in every player's friends list that you can
|
||||
|
||||
`killall`
|
||||
|
||||
`setworldlevel [level]` - Relog to see effects properly
|
||||
`setworldlevel [level]` - Changes your world level, relog to see effects properly
|
||||
|
||||
`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 currently selected 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 currently selected 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 5-star rarity ones** from your inventory
|
||||
|
||||
`pos` - Gets your current coordinate.
|
||||
`pos` - Gets your current coordinates.
|
||||
|
||||
`weather [weather id] [climate id]` - Changes the current weather.
|
||||
|
||||
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
|
||||
|
||||
### Bonus
|
||||
When you want to teleport to somewhere, use the ingame marking function on Map, click Confirm. You will see your character falling from a very high destination, exact location that you marked.
|
||||
When you want to teleport somewhere, use the in-game marking function on the Map, click Confirm. You will see your character falling from a very high spot at the exact location you marked.
|
||||
|
||||
# Quick Troubleshooting
|
||||
* If compiling wasn't successful, please check your JDK installation (must be JDK 8 and validated JDK's bin PATH variable)
|
||||
* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is *the issue*, if using Fiddler make sure it running on another port except 8888
|
||||
* My client doesn't connect, doesn't login, 4206, etc... - Mostly your proxy daemon setup is *the issue*, if you're using Fiddler make sure it's running on a port other than 8888
|
||||
* Startup sequence: Mongodb > Grasscutter > Proxy daemon (mitmdump, fiddler, etc.) > Client
|
||||
|
@ -13,16 +13,15 @@ import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "give", usage = "give [player] <itemId|itemName> [amount]",
|
||||
description = "Gives an item to you or the specified player", aliases = {"g", "item", "giveitem"}, permission = "player.give")
|
||||
@Command(label = "give", usage = "give [player] <itemId|itemName> [amount] [level]", description = "Gives an item to you or the specified player", aliases = {
|
||||
"g", "item", "giveitem" }, permission = "player.give")
|
||||
public final class GiveCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(GenshinPlayer sender, List<String> args) {
|
||||
int target, item, amount = 1;
|
||||
|
||||
int target, item, lvl, amount = 1;
|
||||
if (sender == null && args.size() < 2) {
|
||||
CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount]");
|
||||
CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount] [level]");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -34,6 +33,7 @@ public final class GiveCommand implements CommandHandler {
|
||||
try {
|
||||
item = Integer.parseInt(args.get(0));
|
||||
target = sender.getUid();
|
||||
lvl = 1;
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, "Invalid item id.");
|
||||
@ -43,6 +43,7 @@ public final class GiveCommand implements CommandHandler {
|
||||
case 2: // <itemId|itemName> [amount] | [player] <itemId|itemName>
|
||||
try {
|
||||
target = Integer.parseInt(args.get(0));
|
||||
lvl = 1;
|
||||
|
||||
if (Grasscutter.getGameServer().getPlayerByUid(target) == null && sender != null) {
|
||||
target = sender.getUid();
|
||||
@ -57,17 +58,39 @@ public final class GiveCommand implements CommandHandler {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3: // [player] <itemId|itemName> [amount]
|
||||
case 3: // [player] <itemId|itemName> [amount] | <itemId|itemName> [amount] [level]
|
||||
try {
|
||||
target = Integer.parseInt(args.get(0));
|
||||
|
||||
if (Grasscutter.getGameServer().getPlayerByUid(target) == null && sender != null) {
|
||||
target = sender.getUid();
|
||||
item = Integer.parseInt(args.get(0));
|
||||
amount = Integer.parseInt(args.get(1));
|
||||
lvl = Integer.parseInt(args.get(2));
|
||||
} else {
|
||||
item = Integer.parseInt(args.get(1));
|
||||
amount = Integer.parseInt(args.get(2));
|
||||
lvl = 1;
|
||||
}
|
||||
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, "Invalid item or player ID.");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4: // [player] <itemId|itemName> [amount] [level]
|
||||
try {
|
||||
target = Integer.parseInt(args.get(0));
|
||||
|
||||
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
|
||||
CommandHandler.sendMessage(sender, "Invalid player ID.");
|
||||
return;
|
||||
} else {
|
||||
item = Integer.parseInt(args.get(1));
|
||||
amount = Integer.parseInt(args.get(2));
|
||||
lvl = Integer.parseInt(args.get(3));
|
||||
}
|
||||
|
||||
item = Integer.parseInt(args.get(1));
|
||||
amount = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, "Invalid item or player ID.");
|
||||
@ -89,16 +112,37 @@ public final class GiveCommand implements CommandHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
this.item(targetPlayer, itemData, amount);
|
||||
this.item(targetPlayer, itemData, amount, lvl);
|
||||
|
||||
CommandHandler.sendMessage(sender, String.format("Given %s of %s to %s.", amount, item, target));
|
||||
if (!itemData.isEquip())
|
||||
CommandHandler.sendMessage(sender, String.format("Given %s of %s to %s.", amount, item, target));
|
||||
else
|
||||
CommandHandler.sendMessage(sender,
|
||||
String.format("Given %s with level %s %s times to %s", item, lvl, amount, target));
|
||||
}
|
||||
|
||||
private void item(GenshinPlayer player, ItemData itemData, int amount) {
|
||||
private void item(GenshinPlayer player, ItemData itemData, int amount, int lvl) {
|
||||
if (itemData.isEquip()) {
|
||||
List<GenshinItem> items = new LinkedList<>();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
items.add(new GenshinItem(itemData));
|
||||
GenshinItem item = new GenshinItem(itemData);
|
||||
item.setCount(amount);
|
||||
item.setLevel(lvl);
|
||||
item.setPromoteLevel(0);
|
||||
if (lvl > 20) { // 20/40
|
||||
item.setPromoteLevel(1);
|
||||
} else if (lvl > 40) { // 40/50
|
||||
item.setPromoteLevel(2);
|
||||
} else if (lvl > 50) { // 50/60
|
||||
item.setPromoteLevel(3);
|
||||
} else if (lvl > 60) { // 60/70
|
||||
item.setPromoteLevel(4);
|
||||
} else if (lvl > 70) { // 70/80
|
||||
item.setPromoteLevel(5);
|
||||
} else if (lvl > 80) { // 80/90
|
||||
item.setPromoteLevel(6);
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
player.getInventory().addItems(items);
|
||||
player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
|
||||
@ -110,4 +154,3 @@ public final class GiveCommand implements CommandHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
@ -16,7 +17,29 @@ public final class GodModeCommand implements CommandHandler {
|
||||
CommandHandler.sendMessage(null, "Run this command in-game.");
|
||||
return; // TODO: toggle player's godmode statue from console or other players
|
||||
}
|
||||
sender.setGodmode(!sender.inGodmode());
|
||||
sender.dropMessage("Godmode is now " + (sender.inGodmode() ? "enabled" : "disabled") + ".");
|
||||
|
||||
int target;
|
||||
if (args.size() == 1) {
|
||||
try {
|
||||
target = Integer.parseInt(args.get(0));
|
||||
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
|
||||
target = sender.getUid();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
CommandHandler.sendMessage(sender, "Invalid player id.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
target = sender.getUid();
|
||||
}
|
||||
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendMessage(sender, "Player not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.setGodmode(!targetPlayer.inGodmode());
|
||||
sender.dropMessage("Godmode is now " + (targetPlayer.inGodmode() ? "enabled" : "disabled") +
|
||||
"for " + targetPlayer.getNickname() + " .");
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public final class PositionCommand implements CommandHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
sender.dropMessage(String.format("Coord: %.3f, %.3f, %.3f", sender.getPos().getX(), sender.getPos().getY(), sender.getPos().getZ()));
|
||||
sender.dropMessage(String.format("Coord: %.3f, %.3f, %.3f\nScene id: %d",
|
||||
sender.getPos().getX(), sender.getPos().getY(), sender.getPos().getZ(), sender.getSceneId()));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GenshinData;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
import emu.grasscutter.game.avatar.GenshinAvatar;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify;
|
||||
|
||||
@Command(label = "setfetterlevel", usage = "setfetterlevel <level>",
|
||||
description = "Sets your fetter level for your current active character",
|
||||
aliases = {"setfetterlvl"}, permission = "player.setfetterlevel")
|
||||
public final class SetFetterLevelCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(GenshinPlayer sender, List<String> args) {
|
||||
if (sender == null) {
|
||||
CommandHandler.sendMessage(null, "Run this command in-game.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() < 1) {
|
||||
CommandHandler.sendMessage(sender, "Usage: setfetterlevel <level>");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int fetterLevel = Integer.parseInt(args.get(0));
|
||||
if (fetterLevel < 0 || fetterLevel > 10) {
|
||||
CommandHandler.sendMessage(sender, "Fetter level must be between 0 and 10.");
|
||||
return;
|
||||
}
|
||||
GenshinAvatar avatar = sender.getTeamManager().getCurrentAvatarEntity().getAvatar();
|
||||
|
||||
avatar.setFetterLevel(fetterLevel);
|
||||
avatar.setFetterExp(GenshinData.getAvatarFetterLevelDataMap().get(fetterLevel).getExp());
|
||||
avatar.save();
|
||||
|
||||
sender.sendPacket(new PacketAvatarFetterDataNotify(avatar));
|
||||
CommandHandler.sendMessage(sender, "Fetter level set to " + fetterLevel);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(null, "Invalid fetter level.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"},
|
||||
description = "Change the player's position.", permission = "player.teleport")
|
||||
public class TelePortCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(GenshinPlayer sender, List<String> args) {
|
||||
if (sender == null) {
|
||||
CommandHandler.sendMessage(null, "Run this command in-game.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() < 3){
|
||||
CommandHandler.sendMessage(sender, "Usage: /tp <x> <y> <z> [scene id]");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float z = 0f;
|
||||
if (args.get(0).contains("~")) {
|
||||
if (args.get(0).equals("~")) {
|
||||
x = sender.getPos().getX();
|
||||
} else {
|
||||
x = Float.parseFloat(args.get(0).replace("~", "")) + sender.getPos().getX();
|
||||
}
|
||||
} else {
|
||||
x = Float.parseFloat(args.get(0));
|
||||
}
|
||||
if (args.get(1).contains("~")) {
|
||||
if (args.get(1).equals("~")) {
|
||||
y = sender.getPos().getY();
|
||||
} else {
|
||||
y = Float.parseFloat(args.get(1).replace("~", "")) + sender.getPos().getY();
|
||||
}
|
||||
} else {
|
||||
y = Float.parseFloat(args.get(1));
|
||||
}
|
||||
if (args.get(2).contains("~")) {
|
||||
if (args.get(2).equals("~")) {
|
||||
z = sender.getPos().getZ();
|
||||
} else {
|
||||
z = Float.parseFloat(args.get(2).replace("~", "")) + sender.getPos().getZ();
|
||||
}
|
||||
} else {
|
||||
z = Float.parseFloat(args.get(2));
|
||||
}
|
||||
int sceneId = sender.getSceneId();
|
||||
if (args.size() == 4){
|
||||
sceneId = Integer.parseInt(args.get(3));
|
||||
}
|
||||
Position target = new Position(x, y, z);
|
||||
boolean result = sender.getWorld().transferPlayerToScene(sender, sceneId, target);
|
||||
if (!result) {
|
||||
CommandHandler.sendMessage(sender, "Invalid position.");
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, "Invalid position.");
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ public class GenshinData {
|
||||
private static final Int2ObjectMap<AvatarSkillDepotData> avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<AvatarSkillData> avatarSkillDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>();
|
||||
private static final Int2ObjectMap<AvatarFetterLevelData> avatarFetterLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<AvatarPromoteData> avatarPromoteDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<AvatarTalentData> avatarTalentDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<ProudSkillData> proudSkillDataMap = new Int2ObjectOpenHashMap<>();
|
||||
@ -57,6 +58,8 @@ public class GenshinData {
|
||||
|
||||
private static final Int2ObjectMap<SceneData> sceneDataMap = new Int2ObjectLinkedOpenHashMap<>();
|
||||
private static final Int2ObjectMap<FetterData> fetterDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
// Cache
|
||||
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
|
||||
@ -114,6 +117,14 @@ public class GenshinData {
|
||||
return playerLevelDataMap;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<AvatarFetterLevelData> getAvatarFetterLevelDataMap() {
|
||||
return avatarFetterLevelDataMap;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<FetterCharacterCardData> getFetterCharacterCardDataMap() {
|
||||
return fetterCharacterCardDataMap;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<AvatarLevelData> getAvatarLevelDataMap() {
|
||||
return avatarLevelDataMap;
|
||||
}
|
||||
@ -175,6 +186,11 @@ public class GenshinData {
|
||||
AvatarLevelData levelData = avatarLevelDataMap.get(level);
|
||||
return levelData != null ? levelData.getExp() : 0;
|
||||
}
|
||||
|
||||
public static int getAvatarFetterLevelExpRequired(int level) {
|
||||
AvatarFetterLevelData levelData = avatarFetterLevelDataMap.get(level);
|
||||
return levelData != null ? levelData.getExp() : 0;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<ProudSkillData> getProudSkillDataMap() {
|
||||
return proudSkillDataMap;
|
||||
@ -228,6 +244,10 @@ public class GenshinData {
|
||||
return sceneDataMap;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<RewardData> getRewardDataMap() {
|
||||
return rewardDataMap;
|
||||
}
|
||||
|
||||
public static Map<Integer, List<Integer>> getFetterDataEntries() {
|
||||
if (fetters.isEmpty()) {
|
||||
fetterDataMap.forEach((k, v) -> {
|
||||
|
24
src/main/java/emu/grasscutter/data/common/OpenCondData.java
Normal file
24
src/main/java/emu/grasscutter/data/common/OpenCondData.java
Normal file
@ -0,0 +1,24 @@
|
||||
package emu.grasscutter.data.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OpenCondData {
|
||||
private String CondType;
|
||||
private List<Integer> ParamList;
|
||||
|
||||
public String getCondType() {
|
||||
return CondType;
|
||||
}
|
||||
|
||||
public void setCondType(String condType) {
|
||||
CondType = condType;
|
||||
}
|
||||
|
||||
public List<Integer> getParamList() {
|
||||
return ParamList;
|
||||
}
|
||||
|
||||
public void setParamList(List<Integer> paramList) {
|
||||
ParamList = paramList;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package emu.grasscutter.data.common;
|
||||
|
||||
public class RewardItemData {
|
||||
private int ItemId;
|
||||
private int ItemCount;
|
||||
|
||||
public int getItemId() {
|
||||
return ItemId;
|
||||
}
|
||||
|
||||
public void setItemId(int itemId) {
|
||||
ItemId = itemId;
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return ItemCount;
|
||||
}
|
||||
|
||||
public void setItemCount(int itemCount) {
|
||||
ItemCount = itemCount;
|
||||
}
|
||||
}
|
@ -57,6 +57,8 @@ public class AvatarData extends GenshinResource {
|
||||
private IntList abilities;
|
||||
|
||||
private List<Integer> fetters;
|
||||
private int nameCardRewardId;
|
||||
private int nameCardId;
|
||||
|
||||
@Override
|
||||
public int getId(){
|
||||
@ -199,12 +201,28 @@ public class AvatarData extends GenshinResource {
|
||||
return fetters;
|
||||
}
|
||||
|
||||
public int getNameCardRewardId() {
|
||||
return nameCardRewardId;
|
||||
}
|
||||
|
||||
public int getNameCardId() {
|
||||
return nameCardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.skillDepot = GenshinData.getAvatarSkillDepotDataMap().get(this.SkillDepotId);
|
||||
|
||||
// Get fetters from GenshinData
|
||||
this.fetters = GenshinData.getFetterDataEntries().get(this.Id);
|
||||
|
||||
if (GenshinData.getFetterCharacterCardDataMap().get(this.Id) != null) {
|
||||
this.nameCardRewardId = GenshinData.getFetterCharacterCardDataMap().get(this.Id).getRewardId();
|
||||
}
|
||||
|
||||
if (GenshinData.getRewardDataMap().get(this.nameCardRewardId) != null) {
|
||||
this.nameCardId = GenshinData.getRewardDataMap().get(this.nameCardRewardId).getRewardItemList().get(0).getItemId();
|
||||
}
|
||||
|
||||
int size = GenshinData.getAvatarCurveDataMap().size();
|
||||
this.hpGrowthCurve = new float[size];
|
||||
|
@ -0,0 +1,23 @@
|
||||
package emu.grasscutter.data.def;
|
||||
|
||||
import emu.grasscutter.data.GenshinResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
|
||||
@ResourceType(name = "AvatarFettersLevelExcelConfigData.json")
|
||||
public class AvatarFetterLevelData extends GenshinResource {
|
||||
private int FetterLevel;
|
||||
private int NeedExp;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.FetterLevel;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return FetterLevel;
|
||||
}
|
||||
|
||||
public int getExp() {
|
||||
return NeedExp;
|
||||
}
|
||||
}
|
@ -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 = "FetterCharacterCardExcelConfigData.json", loadPriority = LoadPriority.HIGHEST)
|
||||
public class FetterCharacterCardData extends GenshinResource {
|
||||
private int AvatarId;
|
||||
private int RewardId;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return AvatarId;
|
||||
}
|
||||
|
||||
public int getRewardId() {
|
||||
return RewardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
}
|
@ -1,13 +1,17 @@
|
||||
package emu.grasscutter.data.def;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.data.GenshinResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.ResourceType.LoadPriority;
|
||||
import emu.grasscutter.data.common.OpenCondData;
|
||||
|
||||
@ResourceType(name = {"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json"}, loadPriority = LoadPriority.HIGHEST)
|
||||
public class FetterData extends GenshinResource {
|
||||
private int AvatarId;
|
||||
private int FetterId;
|
||||
private List<OpenCondData> OpenCond;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
@ -18,6 +22,10 @@ public class FetterData extends GenshinResource {
|
||||
return AvatarId;
|
||||
}
|
||||
|
||||
public List<OpenCondData> getOpenConds() {
|
||||
return OpenCond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
|
27
src/main/java/emu/grasscutter/data/def/RewardData.java
Normal file
27
src/main/java/emu/grasscutter/data/def/RewardData.java
Normal file
@ -0,0 +1,27 @@
|
||||
package emu.grasscutter.data.def;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.data.GenshinResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
import emu.grasscutter.data.common.RewardItemData;
|
||||
|
||||
@ResourceType(name = "RewardExcelConfigData.json")
|
||||
public class RewardData extends GenshinResource {
|
||||
public int RewardId;
|
||||
public List<RewardItemData> RewardItemList;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return RewardId;
|
||||
}
|
||||
|
||||
public List<RewardItemData> getRewardItemList() {
|
||||
return RewardItemList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
@ -101,7 +101,7 @@ public final class DatabaseManager {
|
||||
}
|
||||
|
||||
public static synchronized int getNextId(Class<?> c) {
|
||||
DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getName())).first();
|
||||
DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first();
|
||||
if (counter == null) {
|
||||
counter = new DatabaseCounter(c.getSimpleName());
|
||||
}
|
||||
|
@ -35,7 +35,30 @@ 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.*;
|
||||
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarAddNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarDataNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarGainCostumeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarGainFlycloakNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketClientAbilityInitFinishNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketCombatInvocationsNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketPlayerApplyEnterMpResultNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketPlayerDataNotify;
|
||||
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.PacketPlayerLevelRewardUpdateNotify;
|
||||
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.server.packet.send.PacketMailChangeNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
@ -75,6 +98,7 @@ public class GenshinPlayer {
|
||||
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply;
|
||||
private boolean showAvatar;
|
||||
private ArrayList<AvatarProfileData> shownAvatars;
|
||||
private Set<Integer> rewardedLevels;
|
||||
private ArrayList<Mail> mail;
|
||||
|
||||
private int sceneId;
|
||||
@ -125,6 +149,7 @@ public class GenshinPlayer {
|
||||
this.clientAbilityInitFinishHandler = new InvokeHandler(PacketClientAbilityInitFinishNotify.class);
|
||||
|
||||
this.birthday = new PlayerBirthday();
|
||||
this.rewardedLevels = new HashSet<>();
|
||||
}
|
||||
|
||||
// On player creation
|
||||
@ -648,6 +673,14 @@ public class GenshinPlayer {
|
||||
this.updateProfile();
|
||||
}
|
||||
|
||||
public Set<Integer> getRewardedLevels() {
|
||||
return rewardedLevels;
|
||||
}
|
||||
|
||||
public void setRewardedLevels(Set<Integer> rewardedLevels) {
|
||||
this.rewardedLevels = rewardedLevels;
|
||||
}
|
||||
|
||||
public SocialDetail.Builder getSocialDetail() {
|
||||
SocialDetail.Builder social = SocialDetail.newBuilder()
|
||||
.setUid(this.getUid())
|
||||
@ -765,6 +798,7 @@ public class GenshinPlayer {
|
||||
session.send(new PacketAvatarDataNotify(this));
|
||||
|
||||
session.send(new PacketPlayerEnterSceneNotify(this)); // Enter game world
|
||||
session.send(new PacketPlayerLevelRewardUpdateNotify(rewardedLevels));
|
||||
session.send(new PacketOpenStateUpdateNotify());
|
||||
|
||||
// First notify packets sent
|
||||
|
@ -89,6 +89,12 @@ public class GenshinAvatar {
|
||||
private int flyCloak;
|
||||
private int costume;
|
||||
private int bornTime;
|
||||
|
||||
private int fetterLevel = 1;
|
||||
private int fetterExp;
|
||||
|
||||
private int nameCardRewardId;
|
||||
private int nameCardId;
|
||||
|
||||
public GenshinAvatar() {
|
||||
// Morhpia only!
|
||||
@ -107,6 +113,8 @@ public class GenshinAvatar {
|
||||
public GenshinAvatar(AvatarData data) {
|
||||
this();
|
||||
this.avatarId = data.getId();
|
||||
this.nameCardRewardId = data.getNameCardRewardId();
|
||||
this.nameCardId = data.getNameCardId();
|
||||
this.data = data;
|
||||
this.bornTime = (int) (System.currentTimeMillis() / 1000);
|
||||
this.flyCloak = 140001;
|
||||
@ -169,6 +177,14 @@ public class GenshinAvatar {
|
||||
this.satiation = satiation;
|
||||
}
|
||||
|
||||
public int getNameCardRewardId() {
|
||||
return nameCardRewardId;
|
||||
}
|
||||
|
||||
public void setNameCardRewardId(int nameCardRewardId) {
|
||||
this.nameCardRewardId = nameCardRewardId;
|
||||
}
|
||||
|
||||
public int getSatiationPenalty() {
|
||||
return satiationPenalty;
|
||||
}
|
||||
@ -281,6 +297,30 @@ public class GenshinAvatar {
|
||||
return fetters;
|
||||
}
|
||||
|
||||
public int getFetterLevel() {
|
||||
return fetterLevel;
|
||||
}
|
||||
|
||||
public void setFetterLevel(int fetterLevel) {
|
||||
this.fetterLevel = fetterLevel;
|
||||
}
|
||||
|
||||
public int getFetterExp() {
|
||||
return fetterExp;
|
||||
}
|
||||
|
||||
public void setFetterExp(int fetterExp) {
|
||||
this.fetterExp = fetterExp;
|
||||
}
|
||||
|
||||
public int getNameCardId() {
|
||||
return nameCardId;
|
||||
}
|
||||
|
||||
public void setNameCardId(int nameCardId) {
|
||||
this.nameCardId = nameCardId;
|
||||
}
|
||||
|
||||
public float getCurrentHp() {
|
||||
return currentHp;
|
||||
}
|
||||
@ -403,6 +443,8 @@ public class GenshinAvatar {
|
||||
|
||||
// Fetters
|
||||
this.setFetterList(data.getFetters());
|
||||
this.setNameCardRewardId(data.getNameCardRewardId());
|
||||
this.setNameCardId(data.getNameCardId());
|
||||
|
||||
// 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);
|
||||
@ -702,8 +744,8 @@ public class GenshinAvatar {
|
||||
|
||||
public AvatarInfo toProto() {
|
||||
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
|
||||
.setExpLevel(10)
|
||||
.setExpNumber(6325); // Highest Level
|
||||
.setExpLevel(this.getFetterLevel())
|
||||
.setExpNumber(this.getFetterExp());
|
||||
|
||||
if (this.getFetterList() != null) {
|
||||
for (int i = 0; i < this.getFetterList().size(); i++) {
|
||||
@ -715,6 +757,13 @@ public class GenshinAvatar {
|
||||
}
|
||||
}
|
||||
|
||||
int rewardId = this.getNameCardRewardId();
|
||||
int cardId = this.getNameCardId();
|
||||
|
||||
if (this.getPlayer().getNameCardList().contains(cardId)) {
|
||||
avatarFetter.addRewardedFetterLevelList(rewardId);
|
||||
}
|
||||
|
||||
AvatarInfo.Builder avatarInfo = AvatarInfo.newBuilder()
|
||||
.setAvatarId(this.getAvatarId())
|
||||
.setGuid(this.getGuid())
|
||||
|
@ -90,7 +90,7 @@ public class GenshinItem {
|
||||
|
||||
// Equip data
|
||||
if (getItemType() == ItemType.ITEM_WEAPON) {
|
||||
this.level = 1;
|
||||
this.level = this.count > 1 ? this.count : 1;
|
||||
this.affixes = new ArrayList<>(2);
|
||||
if (getItemData().getSkillAffix() != null) {
|
||||
for (int skillAffix : getItemData().getSkillAffix()) {
|
||||
|
@ -711,6 +711,31 @@ public class InventoryManager {
|
||||
player.sendPacket(new PacketAvatarUpgradeRsp(avatar, oldLevel, oldPropMap));
|
||||
}
|
||||
|
||||
public void upgradeAvatarFetterLevel(GenshinPlayer player, GenshinAvatar avatar, int expGain) {
|
||||
// May work. Not test.
|
||||
int maxLevel = 10; // Keep it until I think of a more "elegant" way
|
||||
int level = avatar.getFetterLevel();
|
||||
int exp = avatar.getFetterExp();
|
||||
int reqExp = GenshinData.getAvatarFetterLevelExpRequired(level);
|
||||
|
||||
while (expGain > 0 && reqExp > 0 && level < maxLevel) {
|
||||
int toGain = Math.min(expGain, reqExp - exp);
|
||||
exp += toGain;
|
||||
expGain -= toGain;
|
||||
if (exp >= reqExp) {
|
||||
exp = 0;
|
||||
level += 1;
|
||||
reqExp = GenshinData.getAvatarFetterLevelExpRequired(level);
|
||||
}
|
||||
}
|
||||
|
||||
avatar.setFetterLevel(level);
|
||||
avatar.setFetterExp(exp);
|
||||
avatar.save();
|
||||
|
||||
player.sendPacket(new PacketAvatarPropNotify(avatar));
|
||||
}
|
||||
|
||||
public void upgradeAvatarSkill(GenshinPlayer player, long guid, int skillId) {
|
||||
// Sanity checks
|
||||
GenshinAvatar avatar = player.getAvatars().getAvatarByGuid(guid);
|
||||
|
@ -0,0 +1,53 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.data.GenshinData;
|
||||
import emu.grasscutter.data.def.RewardData;
|
||||
import emu.grasscutter.game.avatar.GenshinAvatar;
|
||||
import emu.grasscutter.game.inventory.GenshinItem;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFetterLevelRewardRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
|
||||
@Opcodes(PacketOpcodes.AvatarFetterLevelRewardReq)
|
||||
public class HandlerAvatarFetterLevelRewardReq extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
AvatarFetterLevelRewardReq req = AvatarFetterLevelRewardReq.parseFrom(payload);
|
||||
if (req.getFetterLevel() < 10) {
|
||||
// You don't have a full level of fetter level, why do you want to get a divorce certificate?
|
||||
session.send(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel()));
|
||||
} else {
|
||||
long avatarGuid = req.getAvatarGuid();
|
||||
|
||||
GenshinAvatar avatar = session
|
||||
.getPlayer()
|
||||
.getAvatars()
|
||||
.getAvatarByGuid(avatarGuid);
|
||||
|
||||
int rewardId = avatar.getNameCardRewardId();
|
||||
|
||||
RewardData card = GenshinData.getRewardDataMap().get(rewardId);
|
||||
int cardId = card.getRewardItemList().get(0).getItemId();
|
||||
|
||||
if (session.getPlayer().getNameCardList().contains(cardId)) {
|
||||
// Already got divorce certificate.
|
||||
session.getPlayer().sendPacket(new PacketAvatarFetterLevelRewardRsp(req.getAvatarGuid(), req.getFetterLevel(), rewardId));
|
||||
return;
|
||||
}
|
||||
|
||||
GenshinItem item = new GenshinItem(cardId);
|
||||
session.getPlayer().getInventory().addItem(item);
|
||||
session.getPlayer().sendPacket(new PacketItemAddHintNotify(item, ActionReason.FetterLevelReward));
|
||||
session.getPlayer().sendPacket(new PacketUnlockNameCardNotify(cardId));
|
||||
session.send(new PacketAvatarFetterLevelRewardRsp(avatarGuid, req.getFetterLevel(), rewardId));
|
||||
session.send(new PacketAvatarFetterDataNotify(avatar));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GenshinData;
|
||||
import emu.grasscutter.data.common.RewardItemData;
|
||||
import emu.grasscutter.game.inventory.GenshinItem;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.TakePlayerLevelRewardReqOuterClass.TakePlayerLevelRewardReq;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketTakePlayerLevelRewardRsp;
|
||||
|
||||
@Opcodes(PacketOpcodes.TakePlayerLevelRewardReq)
|
||||
public class HandlerTakePlayerLevelRewardReq extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
TakePlayerLevelRewardReq req = TakePlayerLevelRewardReq.parseFrom(payload);
|
||||
|
||||
int level = req.getLevel();
|
||||
int rewardId = GenshinData.getPlayerLevelDataMap().get(level).getRewardId();
|
||||
|
||||
if (rewardId != 0) {
|
||||
List<RewardItemData> rewardItems = GenshinData.getRewardDataMap().get(rewardId).getRewardItemList();
|
||||
List<GenshinItem> items = new LinkedList<>();
|
||||
for (RewardItemData rewardItem : rewardItems) {
|
||||
if (rewardItem != null) {
|
||||
if (rewardItem.getItemId() != 0) {
|
||||
items.add(new GenshinItem(rewardItem.getItemId(), rewardItem.getItemCount()));
|
||||
}
|
||||
}
|
||||
}
|
||||
session.getPlayer().getInventory().addItems(items);
|
||||
session.getPlayer().sendPacket(new PacketItemAddHintNotify(items, ActionReason.PlayerUpgradeReward));
|
||||
Set<Integer> rewardedLevels = session.getPlayer().getRewardedLevels();
|
||||
rewardedLevels.add(level);
|
||||
session.getPlayer().setRewardedLevels(rewardedLevels);
|
||||
}
|
||||
|
||||
session.send(new PacketTakePlayerLevelRewardRsp(level, rewardId));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.game.avatar.GenshinAvatar;
|
||||
import emu.grasscutter.game.props.FetterState;
|
||||
import emu.grasscutter.net.packet.GenshinPacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AvatarFetterDataNotifyOuterClass.AvatarFetterDataNotify;
|
||||
import emu.grasscutter.net.proto.AvatarFetterInfoOuterClass.AvatarFetterInfo;
|
||||
import emu.grasscutter.net.proto.FetterDataOuterClass.FetterData;
|
||||
|
||||
public class PacketAvatarFetterDataNotify extends GenshinPacket {
|
||||
|
||||
public PacketAvatarFetterDataNotify(GenshinAvatar avatar) {
|
||||
super(PacketOpcodes.AvatarFetterDataNotify);
|
||||
|
||||
AvatarFetterInfo.Builder avatarFetter = AvatarFetterInfo.newBuilder()
|
||||
.setExpLevel(avatar.getFetterLevel())
|
||||
.setExpNumber(avatar.getFetterExp());
|
||||
|
||||
if (avatar.getFetterList() != null) {
|
||||
for (int i = 0; i < avatar.getFetterList().size(); i++) {
|
||||
avatarFetter.addFetterList(
|
||||
FetterData.newBuilder()
|
||||
.setFetterId(avatar.getFetterList().get(i))
|
||||
.setFetterState(FetterState.FINISH.getValue())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int rewardId = avatar.getNameCardRewardId();
|
||||
int cardId = avatar.getNameCardId();
|
||||
|
||||
if (avatar.getPlayer().getNameCardList().contains(cardId)) {
|
||||
avatarFetter.addRewardedFetterLevelList(rewardId);
|
||||
}
|
||||
|
||||
AvatarFetterInfo avatarFetterInfo = avatarFetter.build();
|
||||
|
||||
AvatarFetterDataNotify proto = AvatarFetterDataNotify.newBuilder()
|
||||
.putFetterInfoMap(avatar.getGuid(), avatarFetterInfo)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.GenshinPacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AvatarFetterLevelRewardRspOuterClass.AvatarFetterLevelRewardRsp;
|
||||
|
||||
public class PacketAvatarFetterLevelRewardRsp extends GenshinPacket {
|
||||
|
||||
public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel, int rewardId) {
|
||||
super(PacketOpcodes.AvatarFetterLevelRewardRsp);
|
||||
|
||||
AvatarFetterLevelRewardRsp proto = AvatarFetterLevelRewardRsp.newBuilder()
|
||||
.setAvatarGuid(guid)
|
||||
.setFetterLevel(fetterLevel)
|
||||
.setRetcode(0)
|
||||
.setRewardId(rewardId)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
|
||||
public PacketAvatarFetterLevelRewardRsp(long guid, int fetterLevel) {
|
||||
super(PacketOpcodes.AvatarFetterLevelRewardRsp);
|
||||
|
||||
AvatarFetterLevelRewardRsp proto = AvatarFetterLevelRewardRsp.newBuilder()
|
||||
.setAvatarGuid(guid)
|
||||
.setFetterLevel(fetterLevel)
|
||||
.setRetcode(1)
|
||||
.setRewardId(0)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import emu.grasscutter.net.packet.GenshinPacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.PlayerLevelRewardUpdateNotifyOuterClass.PlayerLevelRewardUpdateNotify;
|
||||
|
||||
public class PacketPlayerLevelRewardUpdateNotify extends GenshinPacket {
|
||||
|
||||
public PacketPlayerLevelRewardUpdateNotify(Set<Integer> rewardedLevels) {
|
||||
super(PacketOpcodes.PlayerLevelRewardUpdateNotify);
|
||||
|
||||
PlayerLevelRewardUpdateNotify.Builder proto = PlayerLevelRewardUpdateNotify.newBuilder();
|
||||
|
||||
for (Integer level : rewardedLevels) {
|
||||
proto.addLevelList(level);
|
||||
}
|
||||
|
||||
this.setData(proto.build());
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.GenshinPacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.TakePlayerLevelRewardRspOuterClass.TakePlayerLevelRewardRsp;
|
||||
|
||||
public class PacketTakePlayerLevelRewardRsp extends GenshinPacket {
|
||||
|
||||
public PacketTakePlayerLevelRewardRsp(int level, int rewardId) {
|
||||
super(PacketOpcodes.TakePlayerLevelRewardRsp);
|
||||
|
||||
int retcode = 0;
|
||||
|
||||
if (rewardId == 0) {
|
||||
retcode = 1;
|
||||
}
|
||||
|
||||
TakePlayerLevelRewardRsp proto = TakePlayerLevelRewardRsp.newBuilder()
|
||||
.setLevel(level)
|
||||
.setRewardId(rewardId)
|
||||
.setRetcode(retcode)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
@ -74,10 +74,11 @@ for /f "tokens=2*" %%a in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVe
|
||||
|
||||
@rem TODO: External proxy when ORIG_PROXY_ENABLE == 0x1
|
||||
echo set ws = createobject("wscript.shell") > "%temp%\proxy.vbs"
|
||||
|
||||
if not "%MITMDUMP_PATH%" == "" (
|
||||
echo ws.currentdirectory = "%MITMDUMP_PATH%" >> "%temp%\proxy.vbs"
|
||||
)
|
||||
echo ws.run "cmd /c mitmdump.exe -s "^&chr(34)^&"%CUR_PATH%%PROXY_SCRIPT_NAME%"^&chr(34)^&" -k",0 >> "%temp%\proxy.vbs"
|
||||
echo ws.run "cmd /c mitmdump.exe -s "^&chr(34)^&"%CUR_PATH%%PROXY_SCRIPT_NAME%"^&chr(34)^&" -k --allow-hosts "^&chr(34)^&".*\.yuanshen\.com|.*\.mihoyo\.com|.*\.hoyoverse\.com"^&chr(34),0 >> "%temp%\proxy.vbs"
|
||||
"%temp%\proxy.vbs"
|
||||
del /f /q "%temp%\proxy.vbs" >nul 2>nul
|
||||
|
||||
@ -161,4 +162,4 @@ call :LOG [INFO] See you again :)
|
||||
goto :EOF
|
||||
|
||||
:LOG
|
||||
echo [%time:~0,8%] %*
|
||||
echo [%time:~0,8%] %*
|
||||
|
Loading…
Reference in New Issue
Block a user