Commit b9f7c657 authored by Benjamin Elsdon's avatar Benjamin Elsdon
Browse files

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

parents eb495807 782618cd
...@@ -30,6 +30,9 @@ hs_err_pid* ...@@ -30,6 +30,9 @@ hs_err_pid*
build/ build/
out/ out/
# Ignore Gradle properties
gradle.properties
# Eclipse # Eclipse
.project .project
.classpath .classpath
...@@ -53,9 +56,10 @@ resources/* ...@@ -53,9 +56,10 @@ resources/*
logs/* logs/*
data/AbilityEmbryos.json data/AbilityEmbryos.json
data/OpenConfig.json data/OpenConfig.json
proto/*
GM Handbook.txt GM Handbook.txt
config.json config.json
mitmdump.exe mitmdump.exe
grasscutter.jar *.jar
mongod.exe mongod.exe
\ No newline at end of file /src/generated/
/*.sh
\ No newline at end of file
[submodule "Grasscutter-Protos"]
path = Grasscutter-Protos
url = https://github.com/Melledy/Grasscutter-Protos
Subproject commit ba0eab7d629b5adeb145bc430e14ffcb4bdf3d6a
...@@ -75,7 +75,7 @@ Grasscutter uses Gradle to handle dependencies & building. ...@@ -75,7 +75,7 @@ Grasscutter uses Gradle to handle dependencies & building.
**Requirements:** **Requirements:**
- Java SE Development Kits - 16 - Java SE Development Kits - 17
- Git - Git
##### Windows ##### Windows
......
...@@ -75,7 +75,7 @@ Grasscutter 使用 Gradle 来处理依赖及构建. ...@@ -75,7 +75,7 @@ Grasscutter 使用 Gradle 来处理依赖及构建.
**依赖:** **依赖:**
- Java SE Development Kits - 16 - Java SE Development Kits - 17
- Git - Git
##### Windows ##### Windows
......
...@@ -6,24 +6,52 @@ ...@@ -6,24 +6,52 @@
* User Manual available at https://docs.gradle.org/5.6.3/userguide/tutorial_java_projects.html * User Manual available at https://docs.gradle.org/5.6.3/userguide/tutorial_java_projects.html
*/ */
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18'
}
}
plugins { plugins {
// Apply the java plugin to add support for Java // Apply the java plugin to add support for Java
id 'java' id 'java'
// Apply the protobuf auto generator
id 'com.google.protobuf' version "0.8.18"
id 'idea'
// Apply the application plugin to add support for building a CLI application // Apply the application plugin to add support for building a CLI application
id 'application' id 'application'
id 'maven-publish'
id 'signing'
} }
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
group = 'tech.xigam'
version = '1.0.0-dev'
sourceCompatibility = 17 sourceCompatibility = 17
targetCompatibility = 17 targetCompatibility = 17
java {
withJavadocJar()
withSourcesJar()
}
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation fileTree(dir: 'lib', include: ['*.jar']) implementation fileTree(dir: 'lib', include: ['*.jar'])
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.32' implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.32'
implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.9' implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.9'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9' implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.9'
...@@ -38,6 +66,9 @@ dependencies { ...@@ -38,6 +66,9 @@ dependencies {
implementation group: 'org.greenrobot', name: 'eventbus-java', version: '3.3.1' implementation group: 'org.greenrobot', name: 'eventbus-java', version: '3.3.1'
implementation group: 'org.danilopianini', name: 'java-quadtree', version: '0.1.9' implementation group: 'org.danilopianini', name: 'java-quadtree', version: '0.1.9'
protobuf files('proto/')
} }
application { application {
...@@ -65,3 +96,102 @@ jar { ...@@ -65,3 +96,102 @@ jar {
destinationDir = file(".") destinationDir = file(".")
} }
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = 'grasscutter'
from components.java
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
pom {
name = 'Grasscutter'
description = 'A server software reimplementation for an anime game.'
url = 'https://github.com/Grasscutters/Grasscutter'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'melledy'
name = 'Melledy'
email = 'melledy@xigam.tech' // not a real email kek
}
developer {
id = 'magix'
name = 'Magix'
email = 'magix@xigam.tech'
}
}
scm {
connection = 'scm:git:git@github.com:Grasscutters/Grasscutter.git'
developerConnection = 'scm:git:ssh://github.com:Grasscutters/Grasscutter.git'
url = 'https://github.com/Grasscutters/Grasscutter'
}
}
}
}
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
def releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
def snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
name = 'sonatype'
credentials(PasswordCredentials)
}
}
}
clean {
delete protobuf.generatedFilesBaseDir
}
protobuf {
protoc {
// The artifact spec for the Protobuf Compiler
artifact = 'com.google.protobuf:protoc:3.18.1'
}
// generatedFilesBaseDir = "$projectDir/src/main/java/emu/grasscutter/net/proto/"
generatedFilesBaseDir = "$projectDir/src/generated/"
}
sourceSets {
main {
proto {
// In addition to the default 'src/main/proto'
srcDir 'src/generated'
}
java {
srcDir 'src/java'
}
}
}
idea {
module {
// proto files and generated Java files are automatically added as
// source dirs.
// If you have additional sources, add them here:
sourceDirs += file("/proto/");
}
}
signing {
sign publishing.publications.mavenJava
}
javadoc {
if(JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
}
\ No newline at end of file
...@@ -36,7 +36,7 @@ public final class Grasscutter { ...@@ -36,7 +36,7 @@ public final class Grasscutter {
private static GameServer gameServer; private static GameServer gameServer;
private static PluginManager pluginManager; private static PluginManager pluginManager;
public static final Reflections reflector = new Reflections(); public static final Reflections reflector = new Reflections("emu.grasscutter");
static { static {
// Declare logback configuration. // Declare logback configuration.
...@@ -70,13 +70,13 @@ public final class Grasscutter { ...@@ -70,13 +70,13 @@ public final class Grasscutter {
// Database // Database
DatabaseManager.initialize(); DatabaseManager.initialize();
// Create plugin manager instance.
pluginManager = new PluginManager();
// Create server instances. // Create server instances.
dispatchServer = new DispatchServer(); dispatchServer = new DispatchServer();
gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port)); gameServer = new GameServer(new InetSocketAddress(getConfig().getGameServerOptions().Ip, getConfig().getGameServerOptions().Port));
// Create plugin manager instance.
pluginManager = new PluginManager();
// Start servers. // Start servers.
if(getConfig().RunMode.equalsIgnoreCase("HYBRID")) { if(getConfig().RunMode.equalsIgnoreCase("HYBRID")) {
dispatchServer.start(); dispatchServer.start();
......
...@@ -14,4 +14,6 @@ public @interface Command { ...@@ -14,4 +14,6 @@ public @interface Command {
String[] aliases() default {}; String[] aliases() default {};
String permission() default ""; String permission() default "";
boolean threading() default false;
} }
...@@ -11,7 +11,6 @@ import java.util.*; ...@@ -11,7 +11,6 @@ import java.util.*;
public final class CommandMap { public final class CommandMap {
private final Map<String, CommandHandler> commands = new HashMap<>(); private final Map<String, CommandHandler> commands = new HashMap<>();
private final Map<String, Command> annotations = new HashMap<>(); private final Map<String, Command> annotations = new HashMap<>();
public CommandMap() { public CommandMap() {
this(false); this(false);
} }
...@@ -106,8 +105,9 @@ public final class CommandMap { ...@@ -106,8 +105,9 @@ public final class CommandMap {
*/ */
public void invoke(GenshinPlayer player, String rawMessage) { public void invoke(GenshinPlayer player, String rawMessage) {
rawMessage = rawMessage.trim(); rawMessage = rawMessage.trim();
if(rawMessage.length() == 0) { if (rawMessage.length() == 0) {
CommandHandler.sendMessage(player, "No command specified."); return; CommandHandler.sendMessage(player, "No command specified.");
return;
} }
// Remove prefix if present. // Remove prefix if present.
...@@ -118,7 +118,6 @@ public final class CommandMap { ...@@ -118,7 +118,6 @@ public final class CommandMap {
String[] split = rawMessage.split(" "); String[] split = rawMessage.split(" ");
List<String> args = new LinkedList<>(Arrays.asList(split)); List<String> args = new LinkedList<>(Arrays.asList(split));
String label = args.remove(0); String label = args.remove(0);
// Get command handler. // Get command handler.
CommandHandler handler = this.commands.get(label); CommandHandler handler = this.commands.get(label);
if (handler == null) { if (handler == null) {
...@@ -130,14 +129,22 @@ public final class CommandMap { ...@@ -130,14 +129,22 @@ public final class CommandMap {
if (player != null) { if (player != null) {
String permissionNode = this.annotations.get(label).permission(); String permissionNode = this.annotations.get(label).permission();
Account account = player.getAccount(); Account account = player.getAccount();
if(!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) { if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) {
CommandHandler.sendMessage(player, "You do not have permission to run this command."); CommandHandler.sendMessage(player, "You do not have permission to run this command.");
return; return;
} }
} }
// Invoke execute method for handler. // Invoke execute method for handler.
handler.execute(player, args); boolean threading = this.annotations.get(label).threading();
Runnable runnable = () -> handler.execute(player, args);
if(threading) {
Thread command = new Thread(runnable);
command.start();
}
else {
runnable.run();
}
} }
/** /**
......
...@@ -3,15 +3,10 @@ package emu.grasscutter.command.commands; ...@@ -3,15 +3,10 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command; import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler; import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.inventory.ItemType;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List; import java.util.List;
@Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid] @Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid]
...@@ -33,62 +28,62 @@ public final class ClearCommand implements CommandHandler { ...@@ -33,62 +28,62 @@ public final class ClearCommand implements CommandHandler {
try { try {
target = Integer.parseInt(args.get(0)); target = Integer.parseInt(args.get(0));
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target); GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null && sender != null) { if (targetPlayer == null) {
target = sender.getUid(); target = sender.getUid();
} else { } else {
switch (cmdSwitch){ switch (cmdSwitch) {
case "wp": case "wp" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_WEAPON) .filter(item -> item.getItemType() == ItemType.ITEM_WEAPON)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared weapons for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared weapons for " + targetPlayer.getNickname() + " .");
break; }
case "art": case "art" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY) .filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY)
.filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> item.getLevel() == 1 && item.getExp() == 0)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " .");
break; }
case "mat": case "mat" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL) .filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL)
.filter(item -> item.getLevel() == 1 && item.getExp() == 0) .filter(item -> item.getLevel() == 1 && item.getExp() == 0)
.filter(item -> !item.isLocked() && !item.isEquipped()) .filter(item -> !item.isLocked() && !item.isEquipped())
.forEach(item -> playerInventory.removeItem(item, item.getCount())); .forEach(item -> playerInventory.removeItem(item, item.getCount()));
sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared artifacts for " + targetPlayer.getNickname() + " .");
break; }
case "all": case "all" -> {
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY) .filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY)
.filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0) .filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0)
.filter(item1 -> !item1.isLocked() && !item1.isEquipped()) .filter(item1 -> !item1.isLocked() && !item1.isEquipped())
.forEach(item1 -> playerInventory.removeItem(item1, item1.getCount())); .forEach(item1 -> playerInventory.removeItem(item1, item1.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL) .filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL)
.filter(item2 -> !item2.isLocked() && !item2.isEquipped()) .filter(item2 -> !item2.isLocked() && !item2.isEquipped())
.forEach(item2 -> playerInventory.removeItem(item2, item2.getCount())); .forEach(item2 -> playerInventory.removeItem(item2, item2.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON) .filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON)
.filter(item3 -> item3.getLevel() == 1 && item3.getExp() == 0) .filter(item3 -> item3.getLevel() == 1 && item3.getExp() == 0)
.filter(item3 -> !item3.isLocked() && !item3.isEquipped()) .filter(item3 -> !item3.isLocked() && !item3.isEquipped())
.forEach(item3 -> playerInventory.removeItem(item3, item3.getCount())); .forEach(item3 -> playerInventory.removeItem(item3, item3.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE) .filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE)
.filter(item4 -> !item4.isLocked() && !item4.isEquipped()) .filter(item4 -> !item4.isLocked() && !item4.isEquipped())
.forEach(item4 -> playerInventory.removeItem(item4, item4.getCount())); .forEach(item4 -> playerInventory.removeItem(item4, item4.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY) .filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY)
.filter(item5 -> !item5.isLocked() && !item5.isEquipped()) .filter(item5 -> !item5.isLocked() && !item5.isEquipped())
.forEach(item5 -> playerInventory.removeItem(item5, item5.getCount())); .forEach(item5 -> playerInventory.removeItem(item5, item5.getCount()));
playerInventory.getItems().values().stream() playerInventory.getItems().values().stream()
.filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL) .filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL)
.filter(item6 -> !item6.isLocked() && !item6.isEquipped()) .filter(item6 -> !item6.isLocked() && !item6.isEquipped())
.forEach(item6 -> playerInventory.removeItem(item6, item6.getCount())); .forEach(item6 -> playerInventory.removeItem(item6, item6.getCount()));
sender.dropMessage("Cleared everything for " + targetPlayer.getNickname() + " ."); sender.dropMessage("Cleared everything for " + targetPlayer.getNickname() + " .");
break; }
} }
} }
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
......
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.ItemType;
import java.util.*;
@Command(label = "giveall", usage = "giveall [player] <amount>",
description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true)
public class GiveAllCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
int target, amount = 99999;
switch (args.size()) {
case 0: // *no args*
if (sender == null) {
CommandHandler.sendMessage(null, "This usage can only be run in-game");
return;
}
target = sender.getUid();
break;
case 1: // [player]
try {
target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
CommandHandler.sendMessage(sender, "Invalid player ID.");
return;
}
}catch (NumberFormatException ignored){
CommandHandler.sendMessage(sender, "Invalid player ID.");
return;
}
break;
case 2: // [player] [amount]
try {
target = Integer.parseInt(args.get(0));
if (Grasscutter.getGameServer().getPlayerByUid(target) == null) {
target = sender.getUid();
amount = Integer.parseInt(args.get(0));
} else {
amount = Integer.parseInt(args.get(1));
}
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid amount or player ID.");
return;
}
break;
default: // invalid
CommandHandler.sendMessage(null, "Usage: giveall [player] <amount>");
return;
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
}
this.giveAllItems(targetPlayer, amount);
CommandHandler.sendMessage(sender, "Giving all items done");
}
public void giveAllItems(GenshinPlayer player, int amount) {
CommandHandler.sendMessage(player, "Giving all items...");
for (AvatarData avatarData: GenshinData.getAvatarDataMap().values()) {
//Exclude test avatar
if (isTestAvatar(avatarData.getId())) continue;
GenshinAvatar avatar = new GenshinAvatar(avatarData);
avatar.setLevel(90);
avatar.setPromoteLevel(6);
for (int i = 1; i <= 6; ++i) {
avatar.getTalentIdList().add((avatar.getAvatarId() - 10000000) * 10 + i);
}
// This will handle stats and talents
avatar.recalcStats();
player.addAvatar(avatar);
}
//some test items
List<GenshinItem> genshinItemList = new ArrayList<>();
for (ItemData itemdata: GenshinData.getItemDataMap().values()) {
//Exclude test item
if (isTestItem(itemdata.getId())) continue;
if (itemdata.isEquip()) {
for (int i = 0; i < 10; ++i) {
GenshinItem genshinItem = new GenshinItem(itemdata);
if (itemdata.getItemType() == ItemType.ITEM_WEAPON) {
genshinItem.setLevel(90);
genshinItem.setPromoteLevel(6);
genshinItem.setRefinement(4);
}
genshinItemList.add(genshinItem);
}
}
else {
GenshinItem genshinItem = new GenshinItem(itemdata);
genshinItem.setCount(amount);
genshinItemList.add(genshinItem);
}
}
int packetNum = 20;
int itemLength = genshinItemList.size();
int number = itemLength / packetNum;
int remainder = itemLength % packetNum;
int offset = 0;
for (int i = 0; i < packetNum; ++i) {
if (remainder > 0) {
player.getInventory().addItems(genshinItemList.subList(i * number + offset, (i + 1) * number + offset + 1));
--remainder;
++offset;
}
else {
player.getInventory().addItems(genshinItemList.subList(i * number + offset, (i + 1) * number + offset));
}
}
}
public boolean isTestAvatar(int avatarId) {
return avatarId < 10000002 || avatarId >= 11000000;
}
public boolean isTestItem(int itemId) {
for (Range range: testItemRanges) {
if (range.check(itemId)) {
return true;
}
}
if (testItemsList.contains(itemId)) {
return true;
}
return false;
}
static class Range {
private int min;
private int max;
public Range(int min, int max) {
if(min > max){
min ^= max;
max ^= min;
min ^= max;
}
this.min = min;
this.max = max;
}
public boolean check(int value) {
return value >= this.min && value <= this.max;
}
}
private static final Range[] testItemRanges = new Range[] {
new Range(106, 139),
new Range(1000, 1099),
new Range(2001, 2008),
new Range(2017, 2029),
// new Range(108001, 108387) //food
};
private static final Integer[] testItemsIds = new Integer[] {
210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202, 2800,
100001, 100002, 100244, 100305, 100312, 100313, 101212, 11411, 11506, 11507, 11508, 12505,
12506, 12508, 12509, 13503, 13506, 14411, 14503, 14505, 14508, 15411, 15504, 15505,
15506, 15508, 20001, 10002, 10003, 10004, 10005, 10006, 10008 //9
};
private static final Collection<Integer> testItemsList = Arrays.asList(testItemsIds);
}
...@@ -6,20 +6,19 @@ import emu.grasscutter.game.GenshinPlayer; ...@@ -6,20 +6,19 @@ import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
import java.util.List; import java.util.List;
@Command(label = "heal", usage = "heal|h", @Command(label = "heal", usage = "heal|h", aliases = {"h"},
description = "Heal all characters in your current team.", aliases = {"h"}, permission = "player.heal") description = "Heal all characters in your current team.", permission = "player.heal")
public class HealCommand implements CommandHandler { public final class HealCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) { if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game."); CommandHandler.sendMessage(null, "Run this command in-game.");
return; return;
} }
sender.getTeamManager().getActiveTeam().forEach(entity -> { sender.getTeamManager().getActiveTeam().forEach(entity -> {
boolean isAlive = entity.isAlive(); boolean isAlive = entity.isAlive();
entity.setFightProperty( entity.setFightProperty(
...@@ -31,6 +30,6 @@ public class HealCommand implements CommandHandler { ...@@ -31,6 +30,6 @@ public class HealCommand implements CommandHandler {
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
} }
}); });
CommandHandler.sendMessage(sender, "All characters are healed."); CommandHandler.sendMessage(sender, "All characters have been healed.");
} }
} }
...@@ -9,7 +9,7 @@ import java.util.List; ...@@ -9,7 +9,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
@Command(label = "list", description = "List online players") @Command(label = "list", description = "List online players")
public class ListCommand implements CommandHandler { public final class ListCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
...@@ -19,14 +19,10 @@ public class ListCommand implements CommandHandler { ...@@ -19,14 +19,10 @@ public class ListCommand implements CommandHandler {
if (playersMap.size() != 0) { if (playersMap.size() != 0) {
StringBuilder playerSet = new StringBuilder(); StringBuilder playerSet = new StringBuilder();
playersMap.values().forEach(player ->
for (Map.Entry<Integer, GenshinPlayer> entry : playersMap.entrySet()) { playerSet.append(player.getNickname()).append(", "));
playerSet.append(entry.getValue().getNickname());
playerSet.append(", ");
}
String players = playerSet.toString(); String players = playerSet.toString();
CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2)); CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2));
} }
} }
......
...@@ -43,7 +43,7 @@ public final class SetFetterLevelCommand implements CommandHandler { ...@@ -43,7 +43,7 @@ public final class SetFetterLevelCommand implements CommandHandler {
sender.sendPacket(new PacketAvatarFetterDataNotify(avatar)); sender.sendPacket(new PacketAvatarFetterDataNotify(avatar));
CommandHandler.sendMessage(sender, "Fetter level set to " + fetterLevel); CommandHandler.sendMessage(sender, "Fetter level set to " + fetterLevel);
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, "Invalid fetter level."); CommandHandler.sendMessage(sender, "Invalid fetter level.");
} }
} }
......
...@@ -13,7 +13,7 @@ import java.util.List; ...@@ -13,7 +13,7 @@ import java.util.List;
@Command(label = "talent", usage = "talent <talentID> <value>", @Command(label = "talent", usage = "talent <talentID> <value>",
description = "Set talent level for your current active character", permission = "player.settalent") description = "Set talent level for your current active character", permission = "player.settalent")
public class TalentCommand implements CommandHandler { public final class TalentCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
......
...@@ -9,7 +9,7 @@ import java.util.List; ...@@ -9,7 +9,7 @@ import java.util.List;
@Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"}, @Command(label = "teleport", usage = "teleport <x> <y> <z>", aliases = {"tp"},
description = "Change the player's position.", permission = "player.teleport") description = "Change the player's position.", permission = "player.teleport")
public class TelePortCommand implements CommandHandler { public final class TeleportCommand implements CommandHandler {
@Override @Override
public void execute(GenshinPlayer sender, List<String> args) { public void execute(GenshinPlayer sender, List<String> args) {
......
...@@ -140,7 +140,7 @@ public class ResourceLoader { ...@@ -140,7 +140,7 @@ public class ResourceLoader {
} }
List<ScenePointEntry> scenePointList = new ArrayList<>(); List<ScenePointEntry> scenePointList = new ArrayList<>();
for (File file : folder.listFiles()) { for (File file : Objects.requireNonNull(folder.listFiles())) {
ScenePointConfig config = null; ScenePointConfig config = null;
Integer sceneId = null; Integer sceneId = null;
...@@ -190,7 +190,7 @@ public class ResourceLoader { ...@@ -190,7 +190,7 @@ public class ResourceLoader {
} else { } else {
// Load from BinOutput // Load from BinOutput
Pattern pattern = Pattern.compile("(?<=ConfigAvatar_)(.*?)(?=.json)"); Pattern pattern = Pattern.compile("(?<=ConfigAvatar_)(.*?)(?=.json)");
embryoList = new LinkedList<>(); embryoList = new LinkedList<>();
File folder = new File(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Avatar/")); File folder = new File(Utils.toFilePath(Grasscutter.getConfig().RESOURCE_FOLDER + "BinOutput/Avatar/"));
File[] files = folder.listFiles(); File[] files = folder.listFiles();
...@@ -198,29 +198,29 @@ public class ResourceLoader { ...@@ -198,29 +198,29 @@ public class ResourceLoader {
Grasscutter.getLogger().error("Error loading ability embryos: no files found in " + folder.getAbsolutePath()); Grasscutter.getLogger().error("Error loading ability embryos: no files found in " + folder.getAbsolutePath());
return; return;
} }
for (File file : files) { for (File file : files) {
AvatarConfig config; AvatarConfig config;
String avatarName; String avatarName;
Matcher matcher = pattern.matcher(file.getName()); Matcher matcher = pattern.matcher(file.getName());
if (matcher.find()) { if (matcher.find()) {
avatarName = matcher.group(0); avatarName = matcher.group(0);
} else { } else {
continue; continue;
} }
try (FileReader fileReader = new FileReader(file)) { try (FileReader fileReader = new FileReader(file)) {
config = Grasscutter.getGsonFactory().fromJson(fileReader, AvatarConfig.class); config = Grasscutter.getGsonFactory().fromJson(fileReader, AvatarConfig.class);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
continue; continue;
} }
if (config.abilities == null) { if (config.abilities == null) {
continue; continue;
} }
int s = config.abilities.size(); int s = config.abilities.size();
AbilityEmbryoEntry al = new AbilityEmbryoEntry(avatarName, config.abilities.stream().map(Object::toString).toArray(size -> new String[s])); AbilityEmbryoEntry al = new AbilityEmbryoEntry(avatarName, config.abilities.stream().map(Object::toString).toArray(size -> new String[s]));
embryoList.add(al); embryoList.add(al);
...@@ -331,7 +331,7 @@ public class ResourceLoader { ...@@ -331,7 +331,7 @@ public class ResourceLoader {
GenshinData.getOpenConfigEntries().put(entry.getName(), entry); GenshinData.getOpenConfigEntries().put(entry.getName(), entry);
} }
} }
// BinOutput configs // BinOutput configs
private static class AvatarConfig { private static class AvatarConfig {
......
package emu.grasscutter.data.def;
import emu.grasscutter.data.ResourceType;
@ResourceType(name = "CombineExcelConfigData.json")
public class CombineData {
}
...@@ -31,9 +31,10 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType; ...@@ -31,9 +31,10 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType; import emu.grasscutter.net.proto.MpSettingTypeOuterClass.MpSettingType;
import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo; import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason; import emu.grasscutter.net.proto.PlayerApplyEnterMpReasonOuterClass.PlayerApplyEnterMpReason;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.WorldPlayerLocationInfoOuterClass.WorldPlayerLocationInfo;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify; import emu.grasscutter.server.packet.send.PacketAbilityInvocationsNotify;
...@@ -97,7 +98,7 @@ public class GenshinPlayer { ...@@ -97,7 +98,7 @@ public class GenshinPlayer {
private TeamManager teamManager; private TeamManager teamManager;
private PlayerGachaInfo gachaInfo; private PlayerGachaInfo gachaInfo;
private PlayerProfile playerProfile; private PlayerProfile playerProfile;
private MpSettingType mpSetting = MpSettingType.MpSettingEnterAfterApply; private MpSettingType mpSetting = MpSettingType.MP_SETTING_ENTER_AFTER_APPLY;
private boolean showAvatar; private boolean showAvatar;
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels; private Set<Integer> rewardedLevels;
...@@ -659,7 +660,7 @@ public class GenshinPlayer { ...@@ -659,7 +660,7 @@ public class GenshinPlayer {
// Add to inventory // Add to inventory
boolean success = getInventory().addItem(item); boolean success = getInventory().addItem(item);
if (success) { if (success) {
this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.InteractPickItem)); this.sendPacket(new PacketGadgetInteractRsp(drop, InteractType.INTERACT_PICK_ITEM));
this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop)); this.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop));
} }
} }
...@@ -689,7 +690,7 @@ public class GenshinPlayer { ...@@ -689,7 +690,7 @@ public class GenshinPlayer {
.setMpSettingType(this.getMpSetting()) .setMpSettingType(this.getMpSetting())
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())); .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId());
if (this.getWorld() != null) { if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1); onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1);
...@@ -724,21 +725,19 @@ public class GenshinPlayer { ...@@ -724,21 +725,19 @@ public class GenshinPlayer {
public SocialDetail.Builder getSocialDetail() { public SocialDetail.Builder getSocialDetail() {
SocialDetail.Builder social = SocialDetail.newBuilder() SocialDetail.Builder social = SocialDetail.newBuilder()
.setUid(this.getUid()) .setUid(this.getUid())
.setAvatar(HeadImage.newBuilder().setAvatarId(this.getHeadImage())) .setAvatarId(HeadImage.newBuilder().setAvatarId(this.getHeadImage()).getAvatarId())
.setNickname(this.getNickname()) .setNickname(this.getNickname())
.setSignature(this.getSignature()) .setSignature(this.getSignature())
.setLevel(this.getLevel()) .setLevel(this.getLevel())
.setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty()) .setBirthday(this.getBirthday().getFilledProtoWhenNotEmpty())
.setWorldLevel(this.getWorldLevel()) .setWorldLevel(this.getWorldLevel())
.setUnk1(1)
.setUnk3(1)
.setNameCardId(this.getNameCardId()) .setNameCardId(this.getNameCardId())
.setFinishAchievementNum(0); .setFinishAchievementNum(0);
return social; return social;
} }
public WorldPlayerLocationInfo getWorldPlayerLocationInfo() { public PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo getWorldPlayerLocationInfo() {
return WorldPlayerLocationInfo.newBuilder() return PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo.newBuilder()
.setSceneId(this.getSceneId()) .setSceneId(this.getSceneId())
.setPlayerLoc(this.getPlayerLocationInfo()) .setPlayerLoc(this.getPlayerLocationInfo())
.build(); .build();
...@@ -763,7 +762,7 @@ public class GenshinPlayer { ...@@ -763,7 +762,7 @@ public class GenshinPlayer {
while (it.hasNext()) { while (it.hasNext()) {
CoopRequest req = it.next(); CoopRequest req = it.next();
if (req.isExpired()) { if (req.isExpired()) {
req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpReason.SystemJudge)); req.getRequester().sendPacket(new PacketPlayerApplyEnterMpResultNotify(this, false, PlayerApplyEnterMpResultNotifyOuterClass.PlayerApplyEnterMpResultNotify.Reason.SYSTEM_JUDGE));
it.remove(); it.remove();
} }
} }
......
...@@ -202,7 +202,7 @@ public class GenshinScene { ...@@ -202,7 +202,7 @@ public class GenshinScene {
private void removePlayerAvatars(GenshinPlayer player) { private void removePlayerAvatars(GenshinPlayer player) {
Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator(); Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator();
while (it.hasNext()) { while (it.hasNext()) {
this.removeEntity(it.next(), VisionType.VisionRemove); this.removeEntity(it.next(), VisionType.VISION_REMOVE);
it.remove(); it.remove();
} }
} }
...@@ -233,7 +233,7 @@ public class GenshinScene { ...@@ -233,7 +233,7 @@ public class GenshinScene {
this.addEntityDirectly(entity); this.addEntityDirectly(entity);
} }
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_BORN));
} }
private GenshinEntity removeEntityDirectly(GenshinEntity entity) { private GenshinEntity removeEntityDirectly(GenshinEntity entity) {
...@@ -241,7 +241,7 @@ public class GenshinScene { ...@@ -241,7 +241,7 @@ public class GenshinScene {
} }
public void removeEntity(GenshinEntity entity) { public void removeEntity(GenshinEntity entity) {
this.removeEntity(entity, VisionType.VisionDie); this.removeEntity(entity, VisionType.VISION_DIE);
} }
public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) { public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) {
...@@ -254,8 +254,8 @@ public class GenshinScene { ...@@ -254,8 +254,8 @@ public class GenshinScene {
public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) { public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) {
this.removeEntityDirectly(oldEntity); this.removeEntityDirectly(oldEntity);
this.addEntityDirectly(newEntity); this.addEntityDirectly(newEntity);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VisionReplace)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_REPLACE));
this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VisionReplace, oldEntity.getId())); this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_REPLACE, oldEntity.getId()));
} }
public void showOtherEntities(GenshinPlayer player) { public void showOtherEntities(GenshinPlayer player) {
...@@ -269,7 +269,7 @@ public class GenshinScene { ...@@ -269,7 +269,7 @@ public class GenshinScene {
entities.add(entity); entities.add(entity);
} }
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionMeet)); player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
} }
public void handleAttack(AttackResult result) { public void handleAttack(AttackResult result) {
...@@ -381,11 +381,11 @@ public class GenshinScene { ...@@ -381,11 +381,11 @@ public class GenshinScene {
if (toAdd.size() > 0) { if (toAdd.size() > 0) {
toAdd.stream().forEach(this::addEntityDirectly); toAdd.stream().forEach(this::addEntityDirectly);
this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VisionBorn)); this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
} }
if (toRemove.size() > 0) { if (toRemove.size() > 0) {
toRemove.stream().forEach(this::removeEntityDirectly); toRemove.stream().forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VisionRemove)); this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE));
} }
} }
...@@ -425,7 +425,7 @@ public class GenshinScene { ...@@ -425,7 +425,7 @@ public class GenshinScene {
return; return;
} }
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VisionDie)); this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_DIE));
} }
// Broadcasting // Broadcasting
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment