Commit 9fc8cc1c authored by Kengxxiao's avatar Kengxxiao Committed by GitHub
Browse files

Merge pull request #1 from Grasscutters/development

merge
parents 627a2f1e d1fc8c1f
......@@ -3,6 +3,7 @@ on:
push:
branches:
- "stable"
- "development"
pull_request:
types:
- opened
......@@ -25,4 +26,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: Grasscutter
path: grasscutter.jar
path: grasscutter-*-dev.jar
......@@ -56,9 +56,10 @@ resources/*
logs/*
data/AbilityEmbryos.json
data/OpenConfig.json
proto/*
GM Handbook.txt
config.json
mitmdump.exe
grasscutter.jar
*.jar
mongod.exe
/src/generated/
/*.sh
\ No newline at end of file
[submodule "Grasscutter-Protos"]
path = Grasscutter-Protos
url = https://github.com/Melledy/Grasscutter-Protos
Subproject commit 0537e9cc4c7856a7c6f88bbbaa908a80c4ee677e
......@@ -75,7 +75,7 @@ Grasscutter uses Gradle to handle dependencies & building.
**Requirements:**
- Java SE Development Kits - 16
- Java SE Development Kits - 17
- Git
##### Windows
......
......@@ -75,7 +75,7 @@ Grasscutter 使用 Gradle 来处理依赖及构建.
**依赖:**
- Java SE Development Kits - 16
- Java SE Development Kits - 17
- Git
##### Windows
......
......@@ -6,10 +6,25 @@
* 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 {
// Apply the java plugin to add support for Java
id 'java'
// Apply the protobuf auto generator
id 'com.google.protobuf' version "0.8.18"
id 'idea'
id 'eclipse'
// Apply the application plugin to add support for building a CLI application
id 'application'
......@@ -17,6 +32,10 @@ plugins {
id 'signing'
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
group = 'tech.xigam'
version = '1.0.0-dev'
......@@ -49,6 +68,12 @@ dependencies {
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.quartz-scheduler', name: 'quartz', version: '2.3.2'
implementation group: 'org.quartz-scheduler', name: 'quartz-jobs', version: '2.3.2'
protobuf files('proto/')
}
application {
......@@ -132,6 +157,48 @@ publishing {
}
}
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/");
}
}
eclipse {
classpath {
file.whenMerged { cp ->
cp.entries.add( new org.gradle.plugins.ide.eclipse.model.SourceFolder('src/generated/main/java', null) )
}
}
}
signing {
sign publishing.publications.mavenJava
}
......@@ -141,3 +208,7 @@ javadoc {
options.addBooleanOption('html5', true)
}
}
processResources {
dependsOn "generateProto"
}
\ No newline at end of file
......@@ -5,7 +5,7 @@ import java.util.Arrays;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.Utils;
public final class GenshinConstants {
public final class GameConstants {
public static String VERSION = "2.6.0";
public static final int MAX_TEAMS = 4;
......
......@@ -14,4 +14,6 @@ public @interface Command {
String[] aliases() default {};
String permission() default "";
boolean threading() default false;
}
package emu.grasscutter.command;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -12,7 +12,7 @@ public interface CommandHandler {
* @param player The player to send the message to, or null for the server console.
* @param message The message to send.
*/
static void sendMessage(GenshinPlayer player, String message) {
static void sendMessage(Player player, String message) {
if (player == null) {
Grasscutter.getLogger().info(message);
} else {
......@@ -25,6 +25,6 @@ public interface CommandHandler {
* @param sender The player/console that invoked the command.
* @param args The arguments to the command.
*/
default void execute(GenshinPlayer sender, List<String> args) {
default void execute(Player sender, List<String> args) {
}
}
......@@ -2,7 +2,8 @@ package emu.grasscutter.command;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.Account;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import org.reflections.Reflections;
import java.util.*;
......@@ -11,7 +12,6 @@ import java.util.*;
public final class CommandMap {
private final Map<String, CommandHandler> commands = new HashMap<>();
private final Map<String, Command> annotations = new HashMap<>();
public CommandMap() {
this(false);
}
......@@ -104,10 +104,11 @@ public final class CommandMap {
* @param player The player invoking the command or null for the server console.
* @param rawMessage The messaged used to invoke the command.
*/
public void invoke(GenshinPlayer player, String rawMessage) {
public void invoke(Player player, String rawMessage) {
rawMessage = rawMessage.trim();
if(rawMessage.length() == 0) {
CommandHandler.sendMessage(player, "No command specified."); return;
if (rawMessage.length() == 0) {
CommandHandler.sendMessage(player, "No command specified.");
return;
}
// Remove prefix if present.
......@@ -118,7 +119,6 @@ public final class CommandMap {
String[] split = rawMessage.split(" ");
List<String> args = new LinkedList<>(Arrays.asList(split));
String label = args.remove(0);
// Get command handler.
CommandHandler handler = this.commands.get(label);
if (handler == null) {
......@@ -130,14 +130,22 @@ public final class CommandMap {
if (player != null) {
String permissionNode = this.annotations.get(label).permission();
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.");
return;
}
}
// 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,7 +3,7 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -12,7 +12,7 @@ import java.util.List;
public final class AccountCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
if (sender != null) {
CommandHandler.sendMessage(sender, "This command can only be run from the console.");
return;
......
......@@ -3,7 +3,7 @@ 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 emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -12,7 +12,7 @@ import java.util.List;
public final class BroadcastCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
if (args.size() < 1) {
CommandHandler.sendMessage(sender, "Usage: broadcast <message>");
return;
......@@ -20,7 +20,7 @@ public final class BroadcastCommand implements CommandHandler {
String message = String.join(" ", args.subList(0, args.size()));
for (GenshinPlayer p : Grasscutter.getGameServer().getPlayers().values()) {
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
CommandHandler.sendMessage(p, message);
}
......
......@@ -2,7 +2,7 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -10,7 +10,7 @@ import java.util.List;
description = "Changes your scene", aliases = {"scene"}, permission = "player.changescene")
public final class ChangeSceneCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return;
......
......@@ -3,9 +3,9 @@ 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 emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -16,7 +16,7 @@ import java.util.List;
public final class ClearCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
int target;
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
......@@ -27,7 +27,7 @@ public final class ClearCommand implements CommandHandler {
Inventory playerInventory = sender.getInventory();
try {
target = Integer.parseInt(args.get(0));
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
target = sender.getUid();
} else {
......@@ -92,7 +92,7 @@ public final class ClearCommand implements CommandHandler {
return;
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
......
......@@ -2,10 +2,10 @@ package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.utils.Position;
import java.util.List;
......@@ -15,7 +15,7 @@ import java.util.List;
public final class DropCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return;
......@@ -31,7 +31,7 @@ public final class DropCommand implements CommandHandler {
int amount = 1;
if (args.size() > 1) amount = Integer.parseInt(args.get(1));
ItemData itemData = GenshinData.getItemDataMap().get(item);
ItemData itemData = GameData.getItemDataMap().get(item);
if (itemData == null) {
CommandHandler.sendMessage(sender, "Invalid item id.");
return;
......
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
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(Player 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;
}
Player 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(Player player, int amount) {
CommandHandler.sendMessage(player, "Giving all items...");
for (AvatarData avatarData: GameData.getAvatarDataMap().values()) {
//Exclude test avatar
if (isTestAvatar(avatarData.getId())) continue;
Avatar avatar = new Avatar(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<GameItem> itemList = new ArrayList<>();
for (ItemData itemdata: GameData.getItemDataMap().values()) {
//Exclude test item
if (isTestItem(itemdata.getId())) continue;
if (itemdata.isEquip()) {
for (int i = 0; i < 10; ++i) {
GameItem item = new GameItem(itemdata);
if (itemdata.getItemType() == ItemType.ITEM_WEAPON) {
item.setLevel(90);
item.setPromoteLevel(6);
item.setRefinement(4);
}
itemList.add(item);
}
}
else {
GameItem item = new GameItem(itemdata);
item.setCount(amount);
itemList.add(item);
}
}
int packetNum = 20;
int itemLength = itemList.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(itemList.subList(i * number + offset, (i + 1) * number + offset + 1));
--remainder;
++offset;
}
else {
player.getInventory().addItems(itemList.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);
}
......@@ -3,10 +3,10 @@ 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.GameData;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.avatar.GenshinAvatar;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -15,7 +15,7 @@ import java.util.List;
public final class GiveCharCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
int target, avatarId, level = 1, ascension;
if (sender == null && args.size() < 2) {
......@@ -61,13 +61,13 @@ public final class GiveCharCommand implements CommandHandler {
break;
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
}
AvatarData avatarData = GenshinData.getAvatarDataMap().get(avatarId);
AvatarData avatarData = GameData.getAvatarDataMap().get(avatarId);
if (avatarData == null) {
CommandHandler.sendMessage(sender, "Invalid avatar id.");
return;
......@@ -80,7 +80,7 @@ public final class GiveCharCommand implements CommandHandler {
ascension = (int) Math.ceil(level / 10f) - 3;
}
GenshinAvatar avatar = new GenshinAvatar(avatarId);
Avatar avatar = new Avatar(avatarId);
avatar.setLevel(level);
avatar.setPromoteLevel(ascension);
......
......@@ -3,10 +3,10 @@ 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.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.inventory.GenshinItem;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.server.packet.send.PacketItemAddHintNotify;
......@@ -18,7 +18,7 @@ import java.util.List;
public final class GiveCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
int target, item, lvl, amount = 1;
if (sender == null && args.size() < 2) {
CommandHandler.sendMessage(null, "Usage: give <player> <itemId|itemName> [amount] [level]");
......@@ -99,14 +99,14 @@ public final class GiveCommand implements CommandHandler {
break;
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
}
ItemData itemData = GenshinData.getItemDataMap().get(item);
ItemData itemData = GameData.getItemDataMap().get(item);
if (itemData == null) {
CommandHandler.sendMessage(sender, "Invalid item id.");
return;
......@@ -121,11 +121,11 @@ public final class GiveCommand implements CommandHandler {
String.format("Given %s with level %s %s times to %s", item, lvl, amount, target));
}
private void item(GenshinPlayer player, ItemData itemData, int amount, int lvl) {
private void item(Player player, ItemData itemData, int amount, int lvl) {
if (itemData.isEquip()) {
List<GenshinItem> items = new LinkedList<>();
List<GameItem> items = new LinkedList<>();
for (int i = 0; i < amount; i++) {
GenshinItem item = new GenshinItem(itemData);
GameItem item = new GameItem(itemData);
item.setCount(amount);
item.setLevel(lvl);
item.setPromoteLevel(0);
......@@ -144,13 +144,11 @@ public final class GiveCommand implements CommandHandler {
}
items.add(item);
}
player.getInventory().addItems(items);
player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop));
player.getInventory().addItems(items, ActionReason.SubfieldDrop);
} else {
GenshinItem genshinItem = new GenshinItem(itemData);
genshinItem.setCount(amount);
player.getInventory().addItem(genshinItem);
player.sendPacket(new PacketItemAddHintNotify(genshinItem, ActionReason.SubfieldDrop));
GameItem item = new GameItem(itemData);
item.setCount(amount);
player.getInventory().addItem(item, ActionReason.SubfieldDrop);
}
}
}
......@@ -3,7 +3,7 @@ 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 emu.grasscutter.game.player.Player;
import java.util.List;
......@@ -12,7 +12,7 @@ import java.util.List;
public final class GodModeCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
public void execute(Player sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return; // TODO: toggle player's godmode statue from console or other players
......@@ -32,7 +32,7 @@ public final class GodModeCommand implements CommandHandler {
} else {
target = sender.getUid();
}
GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(target);
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, "Player not found.");
return;
......
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