Commit 56efeb2f authored by memetrollsXD's avatar memetrollsXD Committed by GitHub
Browse files

Merge branch 'development' into memetrollsXD-patch-1

parents 8d1c571c 027bd28a
---
name: Issues
about: Create an issue if you need any help
title: '[Issue] '
labels: 'help wanted, question'
assignees: ''
---
**Did you look for other closed issues that have the same problem?**
<!--- It will be easier for us to solve your problem if there is less duplication of problems -->
**Describe the issue**
<!--- A clear and concise description of what the issue is. -->
**Which branch did you use?**
<!--- Stable branch / Development branch -->
**Screenshots**
<!--- If applicable, add screenshots to help explain your problem. -->
**Additional context**
<!--- Add any other context about the problem here. -->
---
name: Bug report
about: Create a bug report to help us improve Grasscutter
title: '[Bug] '
labels: 'bug'
assignees: ''
---
<!--- ONLY USE this form for bug reporting. If you need help or support, please USE issue report form instead. -->
**Describe the bug**
<!--- A clear and concise description of what the bug is. -->
**Which branch did you use?**
<!--- Stable branch / Development branch -->
**Screenshots**
<!--- If applicable, add screenshots to help explain your problem. -->
**Additional context**
<!--- Add any other context about the problem here. -->
---
name: Feature request
about: Suggest an idea for Grasscutter
title: '[Feature Request] '
labels: 'enhancement, suggestion'
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!--- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
**Describe the solution you'd like**
<!--- A clear and concise description of what you want to happen. -->
**Describe alternatives you've considered**
<!--- A clear and concise description of any alternative solutions or features you've considered. -->
**Additional context**
<!--- Add any other context or screenshots about the feature request here. -->
blank_issues_enabled: false
contact_links:
- name: Grasscutter Discord
url: https://discord.gg/T5vZU6UyeG
about: For support, discuss and and other things with Grasscutter.
\ No newline at end of file
## Description
Please carefully read the [Contributing note](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md) and [Code of conduct](https://github.com/Grasscutters/Grasscutter/blob/development/CODE_OF_CONDUCT.md) before making any pull requests.
And, **Do not make a pull request to merge into stable unless it is a hotfix. Use the development branch instead.**
## Issues fixed by this PR
<!--- Put the links of issues that may be fixed by this PR here (if any). -->
## Type of changes
<!--- Put an `x` in all the boxes that apply your changes. -->
- [ ] Bug fix
- [ ] New feature
- [ ] Enhancement
- [ ] Documentation
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] My pull request is unique and no other pull requests have been opened for these changes
- [ ] I have read the [Contributing note](https://github.com/Grasscutters/Grasscutter/blob/stable/CONTRIBUTING.md) and [Code of conduct](https://github.com/Grasscutters/Grasscutter/blob/development/CODE_OF_CONDUCT.md)
- [ ] I am responsible for any copyright issues with my code if it occurs in the future.
\ No newline at end of file
...@@ -20,13 +20,13 @@ EN | [中文](README_zh-CN.md) ...@@ -20,13 +20,13 @@ EN | [中文](README_zh-CN.md)
## Quick setup guide ## Quick setup guide
**Note:** for support please join our [Discord](https://discord.gg/T5vZU6UyeG) **Note:** For support please join our [Discord](https://discord.gg/T5vZU6UyeG).
### Requirements ### Requirements
* Java SE - 17 ([mirror link](https://github.com/adoptium/temurin17-binaries/releases/tag/jdk-17.0.3+7) since Oracle required an account to download old builds) * Java SE - 17 ([link](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html))
**Note:** If you just want to **run it**, then **jre** is fine **Note:** If you just want to **run it**, then **jre** only is fine.
* MongoDB (recommended 4.0+) * MongoDB (recommended 4.0+)
...@@ -34,12 +34,12 @@ EN | [中文](README_zh-CN.md) ...@@ -34,12 +34,12 @@ EN | [中文](README_zh-CN.md)
### Running ### Running
**Note:** If you update from an older version, delete `config.json` for regeneration **Note:** If you updated from an older version, delete `config.json` to regenerate it.
1. Get `grasscutter.jar` 1. Get `grasscutter.jar`
- Download from [actions](https://nightly.link/Grasscutters/Grasscutter/workflows/build/stable/Grasscutter.zip) - Download from [actions](https://nightly.link/Grasscutters/Grasscutter/workflows/build/stable/Grasscutter.zip)
- [Build by yourself](#Building) - [Build by yourself](#Building)
2. Create a `resources` folder in the directory where grasscutter.jar is located and bring your `BinOutput` and `ExcelBinOutput` folders into it *(Check the [wiki](https://github.com/Grasscutters/Grasscutter/wiki) for more details how to get those.)* 2. Create a `resources` folder in the directory where grasscutter.jar is located and move your `BinOutput` and `ExcelBinOutput` folders there *(Check the [wiki](https://github.com/Grasscutters/Grasscutter/wiki) for more details how to get those.)*
3. Run Grasscutter with `java -jar grasscutter.jar`. **Make sure mongodb service is running as well.** 3. Run Grasscutter with `java -jar grasscutter.jar`. **Make sure mongodb service is running as well.**
### Connecting with the client ### Connecting with the client
...@@ -96,7 +96,7 @@ chmod +x gradlew ...@@ -96,7 +96,7 @@ chmod +x gradlew
./gradlew jar # Compile ./gradlew jar # Compile
``` ```
You can find the output jar in the root of the project folder You can find the output jar in the root of the project folder.
## Commands ## Commands
...@@ -106,33 +106,36 @@ There is a dummy user named "Server" in every player's friends list that you can ...@@ -106,33 +106,36 @@ There is a dummy user named "Server" in every player's friends list that you can
| Commands | Usage | Permission node | Availability | description | Alias | | Commands | Usage | Permission node | Availability | description | Alias |
| -------------- | ------------------------------------------------- | ------------------------- | ------------ | ------------------------------------------------------------ | ----------------------------------------------- | | -------------- | ------------------------------------------------- | ------------------------- | ------------ | ------------------------------------------------------------ | ----------------------------------------------- |
| account | account <create\|delete> <username> [uid] | | Server only | Creates an account with the specified username and the in-game uid for that account. The uid will be auto generated if not set. | | | account | account <create\|delete> <username> [UID] | | Server only | Creates an account with the specified username and the in-game UID for that account. The UID will be auto generated if not set. | |
| broadcast | broadcast <message> | server.broadcast | Both side | Sends a message to all the players. | b | | broadcast | broadcast <message> | server.broadcast | Both side | Sends a message to all the players. | b |
| coop | coop <playerId> <target playerId> | server.coop | Both side | Forces someone to join the world of others. | |
| changescene | changescene <scene id> | player.changescene | Client only | Switch scenes by scene ID. | scene | | changescene | changescene <scene id> | player.changescene | Client only | Switch scenes by scene ID. | scene |
| clearartifacts | clearartifacts | player.clearartifacts | Client only | Deletes all unequipped and unlocked level 0 artifacts, including yellow rarity ones from your inventory. | clearart | | clearartifacts | clearartifacts | player.clearartifacts | Client only | Deletes all unequipped and unlocked level 0 artifacts, including 5-star rarity ones from your inventory. | clearart |
| clearweapons | clearweapons | player.clearweapons | Client only | Deletes all unequipped and unlocked weapons, including yellow rarity ones from your inventory. | clearwpns | | clearweapons | clearweapons | player.clearweapons | Client only | Deletes all unequipped and unlocked weapons, including 5-star rarity ones from your inventory. | clearwpns |
| drop | drop <itemID\|itemName> [amount] | server.drop | Client only | Drops an item around you. | `d` `dropitem` | | drop | drop <itemID\|itemName> [amount] | server.drop | Client only | Drops an item around you. | `d` `dropitem` |
| give | give [player] <itemId\|itemName> [amount] [level] | player.give | Both side | Gives item(s) to you or the specified player. | `g` `item` `giveitem` | | give | give [player] <itemId\|itemName> [amount] [level] | player.give | Both side | Gives item(s) to you or the specified player. | `g` `item` `giveitem` |
| givechar | givechar <uid> <avatarId> [level] | player.givechar | Both side | Gives the player a specified character. | givec | | givechar | givechar <uid> <avatarId> | player.givechar | Both side | Gives the player a specified character. | givec |
| giveall | giveall [uid] [amount] | player.giveall | Both side | Gives all items. | givea |
| godmode | godmode [uid] | player.godmode | Client only | Prevents you from taking damage. | | | godmode | godmode [uid] | player.godmode | Client only | Prevents you from taking damage. | |
| heal | heal | player.heal | Client only | Heal all characters in your current team. | h | | heal | heal | player.heal | Client only | Heals all characters in your current team. | h |
| help | help [command] | | Both side | Sends the help message or shows information about a specified command. | | | help | help [command] | | Both side | Sends the help message or shows information about a specified command. | |
| kick | kick <player> | server.kick | Both side | Kicks the specified player from the server. (WIP) | k | | kick | kick <player> | server.kick | Both side | Kicks the specified player from the server. (WIP) | k |
| killall | killall [playerUid] [sceneId] | server.killall | Both side | Kill all entities in the current scene or specified scene of the corresponding player. | | | killall | killall [playerUid] [sceneId] | server.killall | Both side | Kills all entities in the current scene or specified scene of the corresponding player. | |
| list | list | | Both side | List online players. | | | list | list | | Both side | Lists online players. | |
| permission | permission <add\|remove> <username> <permission> | * | Both side | Grants or removes a permission for a user. | | | permission | permission <add\|remove> <username> <permission> | * | Both side | Grants or removes a permission for a user. | |
| position | position | | Client only | Get coordinates. | pos | | position | position | | Client only | Sends your current coordinates. | pos |
| reload | reload | server.reload | Both side | Reload server config | | | reload | reload | server.reload | Both side | Reloads the server config | |
| resetconst | resetconst [all] | player.resetconstellation | Client only | Resets the constellation level on your current active character, will need to relog after using the command to see any changes. | resetconstellation | | resetconst | resetconst [all] | player.resetconstellation | Client only | Resets the constellation level on your currently selected character, will need to relog after using the command to see any changes. | resetconstellation |
| restart | | | Both side | Restarts the current session | | | restart | | | Both side | Restarts the current session | |
| say | say <player> <message> | server.sendmessage | Both side | Sends a message to a player as the server | `sendservmsg` `sendservermessage` `sendmessage` | | say | say <player> <message> | server.sendmessage | Both side | Sends a message to a player as the server | `sendservmsg` `sendservermessage` `sendmessage` |
| setfetterlevel | setfetterlevel <level> | player.setfetterlevel | Client only | Sets your fetter level for your current active character | setfetterlvl | | setfetterlevel | setfetterlevel <level> | player.setfetterlevel | Client only | Sets the friendship level for your currently selected character | setfetterlvl |
| setstats | setstats <stat> <value> | player.setstats | Client only | Set fight property for your current active character | stats | | setstats | setstats <stat> <value> | player.setstats | Client only | Sets a stat for your currently selected character | stats |
| setworldlevel | setworldlevel <level> | player.setworldlevel | Client only | Sets your world level (Relog to see proper effects) | setworldlvl | | setworldlevel | setworldlevel <level> | player.setworldlevel | Client only | Sets your world level (Relog to see proper effects) | setworldlvl |
| spawn | spanw <entityID\|entityName> [level] [amount] | server.spawn | Client only | Spawns an entity near you | | | spawn | spanw <entityID\|entityName> [level] [amount] | server.spawn | Client only | Spawns an entity near you | |
| stop | stop | server.stop | Both side | Stops the server | | | stop | stop | server.stop | Both side | Stops the server | |
| talent | talent <talentID> <value> | player.settalent | Client only | Set talent level for your current active character | | | talent | talent <talentID> <value> | player.settalent | Client only | Sets talent level for your currently selected character | |
| teleport | teleport <x> <y> <z> | player.teleport | Client only | Change the player's position. | tp | | teleport | teleport <x> <y> <z> | player.teleport | Client only | Change the player's position. | tp |
| tpall | | player.tpall | Client only | Teleports all players in your world to your position | |
| weather | weather <weatherID> <climateID> | player.weather | Client only | Changes the weather | w | | weather | weather <weatherID> <climateID> | player.weather | Client only | Changes the weather | w |
### Bonus ### Bonus
...@@ -147,4 +150,5 @@ You can also specify a set Y coordinate by renaming the map marker. ...@@ -147,4 +150,5 @@ You can also specify a set Y coordinate by renaming the map marker.
* If compiling wasn't successful, please check your JDK installation (JDK 17 and validated JDK's bin PATH variable) * If compiling wasn't successful, please check your JDK installation (JDK 17 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 * 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 Fiddler make sure it running on another port except 8888
* Startup sequence: Mongodb > Grasscutter > Proxy daemon (mitmdump, fiddler, etc.) > Game * Startup sequence: Mongodb > Grasscutter > Proxy daemon (mitmdump, fiddler, etc.) > Game
...@@ -109,12 +109,14 @@ chmod +x gradlew ...@@ -109,12 +109,14 @@ chmod +x gradlew
| -------------- | -------------------------------------------- | ------------------------- | -------- | ------------------------------------------ | ----------------------------------------------- | | -------------- | -------------------------------------------- | ------------------------- | -------- | ------------------------------------------ | ----------------------------------------------- |
| account | account <create\|delete> <用户名> [uid] | | 仅服务端 | 通过指定用户名和uid增删账户 | | | account | account <create\|delete> <用户名> [uid] | | 仅服务端 | 通过指定用户名和uid增删账户 | |
| broadcast | broadcast <消息内容> | server.broadcast | 均可使用 | 给所有玩家发送公告 | b | | broadcast | broadcast <消息内容> | server.broadcast | 均可使用 | 给所有玩家发送公告 | b |
| coop | coop <uid> <目标uid> | server.coop | 均可使用 | 强制某位玩家进入指定玩家的多人世界 | |
| changescene | changescene <场景ID> | player.changescene | 仅客户端 | 切换到指定场景 | scene | | changescene | changescene <场景ID> | player.changescene | 仅客户端 | 切换到指定场景 | scene |
| clearartifacts | clearartifacts | player.clearartifacts | 仅客户端 | 删除所有未装备及未解锁的圣遗物,包括五星 | clearart | | clearartifacts | clearartifacts | player.clearartifacts | 仅客户端 | 删除所有未装备及未解锁的圣遗物,包括五星 | clearart |
| clearweapons | clearweapons | player.clearweapons | 仅客户端 | 删除所有未装备及未解锁的武器,包括五星 | clearwp | | clearweapons | clearweapons | player.clearweapons | 仅客户端 | 删除所有未装备及未解锁的武器,包括五星 | clearwp |
| drop | drop <物品ID\|物品名称> [数量] | server.drop | 仅客户端 | 在指定玩家周围掉落指定物品 | `d` `dropitem` | | drop | drop <物品ID\|物品名称> [数量] | server.drop | 仅客户端 | 在指定玩家周围掉落指定物品 | `d` `dropitem` |
| give | give [uid] <物品ID\|物品名称> [数量] [等级] | | | 给予指定玩家一定数量及等级的物品 | `g` `item` `giveitem` | | give | give [uid] <物品ID\|物品名称> [数量] [等级] | | | 给予指定玩家一定数量及等级的物品 | `g` `item` `giveitem` |
| givechar | givechar <uid> <角色ID> [等级] | player.givechar | 均可使用 | 给予指定玩家对应角色 | givec | | givechar | givechar <uid> <角色ID> [等级] | player.givechar | 均可使用 | 给予指定玩家对应角色 | givec |
| giveall | giveall [uid] [数量] | player.giveall | 均可使用 | 给予指定玩家全部物品 | givea |
| godmode | godmode [uid] | player.godmode | 仅客户端 | 保护你不受到任何伤害(依然会被击退) | | | godmode | godmode [uid] | player.godmode | 仅客户端 | 保护你不受到任何伤害(依然会被击退) | |
| heal | heal | player.heal | 仅客户端 | 治疗队伍中所有角色 | h | | heal | heal | player.heal | 仅客户端 | 治疗队伍中所有角色 | h |
| help | help [命令] | | 均可使用 | 显示帮助或展示指定命令的帮助 | | | help | help [命令] | | 均可使用 | 显示帮助或展示指定命令的帮助 | |
...@@ -134,6 +136,7 @@ chmod +x gradlew ...@@ -134,6 +136,7 @@ chmod +x gradlew
| stop | stop | server.stop | 均可使用 | 停止服务器 | | | stop | stop | server.stop | 均可使用 | 停止服务器 | |
| talent | talent <天赋ID> <等级> | player.settalent | 仅客户端 | 设置当前角色的天赋等级 | | | talent | talent <天赋ID> <等级> | player.settalent | 仅客户端 | 设置当前角色的天赋等级 | |
| teleport | teleport <x> <y> <z> | player.teleport | 仅客户端 | 传送玩家到指定坐标 | tp | | teleport | teleport <x> <y> <z> | player.teleport | 仅客户端 | 传送玩家到指定坐标 | tp |
| tpall | | player.tpall | 仅客户端 | 传送多人世界中所有的玩家到自身地点 | |
| weather | weather <天气ID> <气候ID> | player.weather | 仅客户端 | 改变天气 | w | | weather | weather <天气ID> <气候ID> | player.weather | 仅客户端 | 改变天气 | w |
### 额外功能 ### 额外功能
......
This diff is collapsed.
[
{
"shopId": 1004,
"items": [
{
"goodsId": 1004202,
"goodsItem": {
"Id": 202,
"Count": 1000000
},
"scoin": 1,
"buyLimit": 500,
"beginTime": 1575129600,
"endTime": 2051193600,
"minLevel": 1,
"maxLevel": 99,
"costItemList": [
{
"Id": 223,
"Count": 100
}
]
},
{
"goodsId": 10048006,
"goodsItem": {
"Id": 108006,
"Count": 20
},
"scoin": 100,
"hcoin": 100,
"mcoin": 100,
"buyLimit": 50000,
"beginTime": 1575129600,
"endTime": 2051193600,
"minLevel": 1,
"maxLevel": 99
},
{
"goodsId": 10048033,
"goodsItem": {
"Id": 108033,
"Count": 20
},
"scoin": 1,
"buyLimit": 50000,
"beginTime": 1575129600,
"endTime": 2051193600,
"minLevel": 1,
"maxLevel": 99
}
]
}
]
\ No newline at end of file
...@@ -33,6 +33,7 @@ public final class Config { ...@@ -33,6 +33,7 @@ public final class Config {
public Boolean FrontHTTPS = true; public Boolean FrontHTTPS = true;
public boolean AutomaticallyCreateAccounts = false; public boolean AutomaticallyCreateAccounts = false;
public String[] defaultPermissions = new String[] { "" };
public RegionInfo[] GameServers = {}; public RegionInfo[] GameServers = {};
......
package emu.grasscutter.command.commands; package emu.grasscutter.command.commands;
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.database.DatabaseHelper; import emu.grasscutter.database.DatabaseHelper;
...@@ -7,8 +8,7 @@ import emu.grasscutter.game.player.Player; ...@@ -7,8 +8,7 @@ import emu.grasscutter.game.player.Player;
import java.util.List; import java.util.List;
@Command(label = "account", usage = "account <create|delete> <username> [uid]", @Command(label = "account", usage = "account <create|delete> <username> [uid]", description = "Modify user accounts")
description = "Modify user accounts")
public final class AccountCommand implements CommandHandler { public final class AccountCommand implements CommandHandler {
@Override @Override
...@@ -46,9 +46,10 @@ public final class AccountCommand implements CommandHandler { ...@@ -46,9 +46,10 @@ public final class AccountCommand implements CommandHandler {
CommandHandler.sendMessage(null, "Account already exists."); CommandHandler.sendMessage(null, "Account already exists.");
return; return;
} else { } else {
CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerUid() + "."); account.addPermission("*");
account.addPermission("*"); // Grant the player superuser permissions.
account.save(); // Save account to database. account.save(); // Save account to database.
CommandHandler.sendMessage(null, "Account created with UID " + account.getPlayerUid() + ".");
} }
return; return;
case "delete": case "delete":
......
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import java.util.List;
@Command(label = "coop", usage = "coop",
description = "Forces someone to join the world of others", permission = "server.coop")
public class CoopCommand implements CommandHandler {
@Override
public void execute(Player sender, List<String> args) {
if (args.size() < 2) {
CommandHandler.sendMessage(sender, "Usage: coop <playerId> <target playerId>");
return;
}
try {
int tid = Integer.parseInt(args.get(0));
int hostId = Integer.parseInt(args.get(1));
Player host = sender.getServer().getPlayerByUid(hostId);
Player want = sender.getServer().getPlayerByUid(tid);
if (host == null || want == null) {
CommandHandler.sendMessage(sender, "Player is offline.");
return;
}
if (want.isInMultiplayer()) {
sender.getServer().getMultiplayerManager().leaveCoop(want);
}
sender.getServer().getMultiplayerManager().applyEnterMp(want, hostId);
sender.getServer().getMultiplayerManager().applyEnterMpReply(host, tid, true);
} catch (Exception e) {
CommandHandler.sendMessage(sender, "Player id is not valid.");
}
}
}
...@@ -13,7 +13,7 @@ import emu.grasscutter.game.player.Player; ...@@ -13,7 +13,7 @@ import emu.grasscutter.game.player.Player;
import java.util.*; import java.util.*;
@Command(label = "giveall", usage = "giveall [player] <amount>", @Command(label = "giveall", usage = "giveall [player] [amount]",
description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true) description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true)
public class GiveAllCommand implements CommandHandler { public class GiveAllCommand implements CommandHandler {
...@@ -59,7 +59,7 @@ public class GiveAllCommand implements CommandHandler { ...@@ -59,7 +59,7 @@ public class GiveAllCommand implements CommandHandler {
break; break;
default: // invalid default: // invalid
CommandHandler.sendMessage(null, "Usage: giveall [player] <amount>"); CommandHandler.sendMessage(null, "Usage: giveall [player] [amount]");
return; return;
} }
...@@ -175,7 +175,6 @@ public class GiveAllCommand implements CommandHandler { ...@@ -175,7 +175,6 @@ public class GiveAllCommand implements CommandHandler {
new Range(2017, 2029), new Range(2017, 2029),
// new Range(108001, 108387) //food // new Range(108001, 108387) //food
}; };
private static final Integer[] testItemsIds = new Integer[] { private static final Integer[] testItemsIds = new Integer[] {
210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202, 2800, 210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202, 2800,
100001, 100002, 100244, 100305, 100312, 100313, 101212, 11411, 11506, 11507, 11508, 12505, 100001, 100002, 100244, 100305, 100312, 100313, 101212, 11411, 11506, 11507, 11508, 12505,
......
...@@ -4,6 +4,7 @@ import emu.grasscutter.Grasscutter; ...@@ -4,6 +4,7 @@ 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.game.entity.EntityMonster; import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
...@@ -53,10 +54,12 @@ public final class KillAllCommand implements CommandHandler { ...@@ -53,10 +54,12 @@ public final class KillAllCommand implements CommandHandler {
return; return;
} }
mainScene.getEntities().values().stream() // Separate into list to avoid concurrency issue
List<GameEntity> toKill = mainScene.getEntities().values().stream()
.filter(entity -> entity instanceof EntityMonster) .filter(entity -> entity instanceof EntityMonster)
.forEach(entity -> mainScene.killEntity(entity, 0)); .toList();
CommandHandler.sendMessage(sender, "Killing all monsters in scene " + mainScene.getId()); toKill.stream().forEach(entity -> mainScene.killEntity(entity, 0));
CommandHandler.sendMessage(sender, "Killing " + toKill.size() + " monsters in scene " + mainScene.getId());
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid arguments."); CommandHandler.sendMessage(sender, "Invalid arguments.");
} }
......
...@@ -16,6 +16,8 @@ public final class ReloadCommand implements CommandHandler { ...@@ -16,6 +16,8 @@ public final class ReloadCommand implements CommandHandler {
CommandHandler.sendMessage(sender, "Reloading config."); CommandHandler.sendMessage(sender, "Reloading config.");
Grasscutter.loadConfig(); Grasscutter.loadConfig();
Grasscutter.getGameServer().getGachaManager().load(); Grasscutter.getGameServer().getGachaManager().load();
Grasscutter.getGameServer().getDropManager().load();
Grasscutter.getGameServer().getShopManager().load();
Grasscutter.getDispatchServer().loadQueries(); Grasscutter.getDispatchServer().loadQueries();
CommandHandler.sendMessage(sender, "Reload complete."); CommandHandler.sendMessage(sender, "Reload complete.");
} }
......
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.utils.Position;
import java.util.List;
@Command(label = "tpall", usage = "tpall",
description = "Teleports all players in your world to your position", permission = "player.tpall")
public class TpallCommand implements CommandHandler {
@Override
public void execute(Player sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return;
}
if (!sender.getWorld().isMultiplayer()) {
CommandHandler.sendMessage(sender, "You only can use this command in MP mode.");
return;
}
for (Player gp : sender.getWorld().getPlayers()) {
if (gp.equals(sender))
continue;
Position pos = sender.getPos();
gp.getWorld().transferPlayerToScene(gp, sender.getSceneId(), pos);
}
}
}
...@@ -15,6 +15,7 @@ public class GadgetData extends GameResource { ...@@ -15,6 +15,7 @@ public class GadgetData extends GameResource {
private String InteeIconName; private String InteeIconName;
private long NameTextMapHash; private long NameTextMapHash;
private int CampID; private int CampID;
private String LODPatternName;
@Override @Override
public int getId() { public int getId() {
...@@ -53,6 +54,8 @@ public class GadgetData extends GameResource { ...@@ -53,6 +54,8 @@ public class GadgetData extends GameResource {
return CampID; return CampID;
} }
public String getLODPatternName() { return LODPatternName; }
@Override @Override
public void onLoad() { public void onLoad() {
......
package emu.grasscutter.game.drop;
public class DropData {
private int minWeight;
private int maxWeight;
private int itemId;
private int minCount;
private int maxCount;
private boolean share = false;
private boolean give = false;
public boolean isGive() {
return give;
}
public void setGive(boolean give) {
this.give = give;
}
public int getItemId() {
return itemId;
}
public void setItemId(int itemId) {
this.itemId = itemId;
}
public int getMinCount() {
return minCount;
}
public int getMaxCount() {
return maxCount;
}
public int getMinWeight() {
return minWeight;
}
public int getMaxWeight() {
return maxWeight;
}
public boolean isShare() {
return share;
}
public void setIsShare(boolean share) {
this.share = share;
}
}
package emu.grasscutter.game.drop;
import java.util.List;
public class DropInfo {
public int getMonsterId() {
return monsterId;
}
public List<DropData> getDropDataList() {
return dropDataList;
}
private int monsterId;
private List<DropData> dropDataList;
}
package emu.grasscutter.game.drop;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.util.Collection;
import java.util.List;
public class DropManager {
public GameServer getGameServer() {
return gameServer;
}
private final GameServer gameServer;
public Int2ObjectMap<List<DropData>> getDropData() {
return dropData;
}
private final Int2ObjectMap<List<DropData>> dropData;
public DropManager(GameServer gameServer) {
this.gameServer = gameServer;
this.dropData = new Int2ObjectOpenHashMap<>();
this.load();
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Drop.json")) {
getDropData().clear();
List<DropInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType());
if(banners.size() > 0) {
for (DropInfo di : banners) {
getDropData().put(di.getMonsterId(), di.getDropDataList());
}
Grasscutter.getLogger().info("Drop data successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load drop data. Drop data size is 0.");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void addDropEntity(DropData dd, Scene dropScene, ItemData itemData, Position pos, int num, Player target) {
if (!dd.isGive() && (itemData.getItemType() != ItemType.ITEM_VIRTUAL || itemData.getGadgetId() != 0)) {
EntityItem entity = new EntityItem(dropScene, target, itemData, pos, num, dd.isShare());
if (!dd.isShare())
dropScene.addEntityToSingleClient(target, entity);
else
dropScene.addEntity(entity);
} else {
if (target != null) {
target.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true);
} else {
// target is null if items will be added are shared. no one could pick it up because of the combination(give + shared)
// so it will be sent to all players' inventories directly.
dropScene.getPlayers().forEach(x -> {
x.getInventory().addItem(new GameItem(itemData, num), ActionReason.SubfieldDrop, true);
});
}
}
}
private void processDrop(DropData dd, EntityMonster em, Player gp) {
int target = Utils.randomRange(1, 10000);
if (target >= dd.getMinWeight() && target < dd.getMaxWeight()) {
ItemData itemData = GameData.getItemDataMap().get(dd.getItemId());
int num = Utils.randomRange(dd.getMinCount(), dd.getMaxCount());
if (itemData == null) {
return;
}
if (itemData.isEquip()) {
for (int i = 0; i < num; i++) {
float range = (5f + (.1f * num));
Position pos = em.getPosition().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
addDropEntity(dd, em.getScene(), itemData, pos, num, gp);
}
} else {
Position pos = em.getPosition().clone().addY(3f);
addDropEntity(dd, em.getScene(), itemData, pos, num, gp);
}
}
}
public void callDrop(EntityMonster em) {
int id = em.getMonsterData().getId();
if (getDropData().containsKey(id)) {
for (DropData dd : getDropData().get(id)) {
if (dd.isShare())
processDrop(dd, em, null);
else {
for (Player gp : em.getScene().getPlayers()) {
processDrop(dd, em, gp);
}
}
}
}
}
}
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