Implement !clean command and f affinity

This commit is contained in:
阁主
2025-11-26 09:05:08 +08:00
committed by Melledy
parent 008cd06b32
commit 3a7d12c7b7
5 changed files with 159 additions and 4 deletions

View File

@@ -73,7 +73,8 @@ Server commands need to be run in the server console OR in the signature edit me
```
!account {create | delete} [email] (reserved player uid) = Creates or deletes an account.
!char [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) = Changes the properties of the targeted characters.
!char [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) f(affinity level) = Changes the properties of the targeted characters.
!clean [all | {id} ...] [items|resources] = Removes items/resources from the targeted player.
!disc [all | {discId}] lv(level) a(ascension) c(crescendo level) = Changes the properties of the targeted discs.
!give [item id] x[amount] = Gives the targeted player an item through the mail.
!giveall [characters | discs | materials] = Gives the targeted player items.

View File

@@ -26,6 +26,7 @@ public class CommandArgs {
private int advance = -1;
private int talent = -1;
private int skill = -1;
private int affinity = -1;
private Int2IntMap map;
private ObjectSet<String> flags;
@@ -61,6 +62,9 @@ public class CommandArgs {
} else if (arg.startsWith("s")) { // Skill
this.skill = Utils.parseSafeInt(arg.substring(1));
it.remove();
} else if (arg.startsWith("f")) { // Affinity level
this.affinity = Utils.parseSafeInt(arg.substring(1));
it.remove();
}
} else if (arg.startsWith("-")) { // Flag
if (this.flags == null) this.flags = new ObjectOpenHashSet<>();
@@ -190,6 +194,16 @@ public class CommandArgs {
hasChanged = true;
}
if (this.getAffinity() >= 0) {
int target = this.getAffinity();
if (target > 50) target = 50;
if (target < 0) target = 0;
if (character.getAffinityLevel() != target) {
character.setAffinityLevel(target);
hasChanged = true;
}
}
return hasChanged;
}

View File

@@ -16,8 +16,8 @@ import emu.nebula.command.CommandHandler;
label = "character",
aliases = {"c", "char"},
permission = "player.character",
requireTarget = true,
desc = "!c [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level)"
requireTarget = true,
desc = "!c [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) f(affinity level)"
)
public class CharacterCommand implements CommandHandler {
@@ -51,6 +51,7 @@ public class CharacterCommand implements CommandHandler {
// Sanity check
if (characters.isEmpty()) {
args.sendMessage("Error: No characters selected");
return;
}
@@ -72,6 +73,7 @@ public class CharacterCommand implements CommandHandler {
}
if (modified.isEmpty()) {
args.sendMessage("No changes applied");
return;
}
@@ -83,5 +85,6 @@ public class CharacterCommand implements CommandHandler {
}
player.addNextPackage(NetMsgId.chars_final_notify, proto);
args.sendMessage("Updated " + modified.size() + " character(s)");
}
}

View File

@@ -0,0 +1,132 @@
package emu.nebula.command.commands;
import emu.nebula.command.Command;
import emu.nebula.command.CommandArgs;
import emu.nebula.command.CommandHandler;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.ItemDef;
import emu.nebula.game.inventory.GameItem;
import emu.nebula.game.inventory.GameResource;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.inventory.ItemType;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.net.NetMsgId;
import emu.nebula.util.Utils;
import java.util.HashSet;
@Command(
label = "clean",
aliases = {"cl", "clear"},
permission = "player.inventory",
requireTarget = true,
desc = "!clean [all | {id} ...] [items|resources]. Removes items/resources from the targeted player."
)
public class CleanCommand implements CommandHandler {
@Override
public void execute(CommandArgs args) {
var player = args.getTarget();
var inv = player.getInventory();
boolean doItems = true;
boolean doResources = true;
boolean all = false;
var ids = new HashSet<Integer>();
for (String arg : args.getList()) {
arg = arg.toLowerCase();
switch (arg) {
case "items" -> {
doResources = false;
continue;
}
case "resources", "res" -> {
doItems = false;
continue;
}
case "all" -> {
all = true;
continue;
}
}
int id = Utils.parseSafeInt(arg);
if (id > 0) {
ids.add(id);
}
}
var change = new PlayerChangeInfo();
var removeMap = new ItemParamMap();
if (all) {
if (doItems) {
for (GameItem item : inv.getItems().values()) {
removeMap.add(item.getItemId(), item.getCount());
}
}
if (doResources) {
for (GameResource res : inv.getResources().values()) {
removeMap.add(res.getResourceId(), res.getCount());
}
}
} else {
for (int id : ids) {
ItemDef data = GameData.getItemDataTable().get(id);
if (data != null) {
ItemType type = data.getItemType();
switch (type) {
case Res -> {
if (doResources) {
int count = inv.getResourceCount(id);
if (count > 0) removeMap.add(id, count);
}
}
case Item -> {
if (doItems) {
int count = inv.getItemCount(id);
if (count > 0) removeMap.add(id, count);
}
}
case Disc, Char, CharacterSkin, Title, Honor -> {
}
default -> {
if (doItems) {
int count = inv.getItemCount(id);
if (count > 0) {
removeMap.add(id, count);
break;
}
}
if (doResources) {
int count = inv.getResourceCount(id);
if (count > 0) removeMap.add(id, count);
}
}
}
} else {
args.sendMessage("Error: Invalid item id " + id);
}
}
}
if (!removeMap.isEmpty()) {
change = inv.removeItems(removeMap, change);
}
if (change.isEmpty()) {
args.sendMessage("No items/resources removed");
return;
}
player.addNextPackage(NetMsgId.items_change_notify, change.toProto());
args.sendMessage("Inventory cleaned");
}
}

View File

@@ -123,7 +123,12 @@ public class GameCharacter implements GameDatabaseObject {
public void setAdvance(int advance) {
this.advance = advance;
}
public void setAffinityLevel(int level) {
this.affinityLevel = Math.max(level, 0);
this.affinityExp = 0;
}
public int getMaxGainableExp() {
if (this.getLevel() >= this.getMaxLevel()) {
return 0;