Commit 01b190bc authored by Magix's avatar Magix Committed by GitHub
Browse files

UPGRADE TO 1.1.0 POG

Merge `development` into `stable`
parents 6b81b888 1beddf16
package emu.grasscutter.command.commands;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.utils.Language;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "setstats", usage = "setstats|stats <stat> <value>",
description = "Set fight property for your current active character", aliases = {"stats"}, permission = "player.setstats")
public final class SetStatsCommand implements CommandHandler {
static class Stat {
String name;
FightProperty prop;
boolean percent;
@Override
public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return;
public Stat(String name, FightProperty prop, boolean percent) {
this.name = name;
this.prop = prop;
this.percent = percent;
}
if (args.size() < 2){
CommandHandler.sendMessage(sender, "Usage: setstats|stats <stat> <value>");
return;
}
String stat = args.get(0);
switch (stat) {
default:
CommandHandler.sendMessage(sender, "Usage: /setstats|stats <hp | def | atk | em | er | crate | cdmg> <value> for basic stats");
CommandHandler.sendMessage(sender, "Usage: /stats <epyro | ecryo | ehydro | egeo | edend | eelec | ephys> <amount> for elemental bonus");
return;
case "hp":
try {
int health = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
CommandHandler.sendMessage(sender, "HP set to " + health + ".");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid HP value.");
return;
}
break;
case "def":
try {
int def = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, def);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_DEFENSE));
CommandHandler.sendMessage(sender, "DEF set to " + def + ".");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid DEF value.");
return;
}
break;
case "atk":
try {
int atk = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, atk);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_ATTACK));
CommandHandler.sendMessage(sender, "ATK set to " + atk + ".");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid ATK value.");
return;
}
break;
case "em":
try {
int em = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
entity.setFightProperty(FightProperty.FIGHT_PROP_ELEMENT_MASTERY, em);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_ELEMENT_MASTERY));
CommandHandler.sendMessage(sender, "Elemental Mastery set to " + em + ".");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid EM value.");
return;
}
break;
case "er":
try {
float er = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float erecharge = er / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, erecharge);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY));
float iger = erecharge * 100;
CommandHandler.sendMessage(sender, "Energy recharge set to " + iger + "%.");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid ER value.");
return;
}
break;
case "crate":
try {
float cr = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float crate = cr / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL, crate);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CRITICAL));
float igcrate = crate * 100;
CommandHandler.sendMessage(sender, "Crit Rate set to " + igcrate + "%.");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Crit Rate value.");
return;
}
break;
case "cdmg":
try {
float cdmg = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float cdamage = cdmg / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL_HURT, cdamage);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CRITICAL_HURT));
float igcdmg = cdamage * 100;
CommandHandler.sendMessage(sender, "Crit DMG set to " + igcdmg + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Crit DMG value.");
return;
Map<String, Stat> stats = new HashMap<>();
public SetStatsCommand() {
// Default stats
stats.put("maxhp", new Stat(FightProperty.FIGHT_PROP_MAX_HP.toString(), FightProperty.FIGHT_PROP_MAX_HP, false));
stats.put("hp", new Stat(FightProperty.FIGHT_PROP_CUR_HP.toString(), FightProperty.FIGHT_PROP_CUR_HP, false));
stats.put("atk", new Stat(FightProperty.FIGHT_PROP_CUR_ATTACK.toString(), FightProperty.FIGHT_PROP_CUR_ATTACK, false));
stats.put("atkb", new Stat(FightProperty.FIGHT_PROP_BASE_ATTACK.toString(), FightProperty.FIGHT_PROP_BASE_ATTACK, false)); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
stats.put("def", new Stat(FightProperty.FIGHT_PROP_DEFENSE.toString(), FightProperty.FIGHT_PROP_DEFENSE, false));
stats.put("em", new Stat(FightProperty.FIGHT_PROP_ELEMENT_MASTERY.toString(), FightProperty.FIGHT_PROP_ELEMENT_MASTERY, false));
stats.put("er", new Stat(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY.toString(), FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, true));
stats.put("crate", new Stat(FightProperty.FIGHT_PROP_CRITICAL.toString(), FightProperty.FIGHT_PROP_CRITICAL, true));
stats.put("cdmg", new Stat(FightProperty.FIGHT_PROP_CRITICAL_HURT.toString(), FightProperty.FIGHT_PROP_CRITICAL_HURT, true));
stats.put("dmg", new Stat(FightProperty.FIGHT_PROP_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ADD_HURT, true)); // This seems to get reset after attacks
stats.put("eanemo", new Stat(FightProperty.FIGHT_PROP_WIND_ADD_HURT.toString(), FightProperty.FIGHT_PROP_WIND_ADD_HURT, true));
stats.put("ecryo", new Stat(FightProperty.FIGHT_PROP_ICE_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ICE_ADD_HURT, true));
stats.put("edendro", new Stat(FightProperty.FIGHT_PROP_GRASS_ADD_HURT.toString(), FightProperty.FIGHT_PROP_GRASS_ADD_HURT, true));
stats.put("eelectro", new Stat(FightProperty.FIGHT_PROP_ELEC_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ELEC_ADD_HURT, true));
stats.put("egeo", new Stat(FightProperty.FIGHT_PROP_ROCK_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ROCK_ADD_HURT, true));
stats.put("ehydro", new Stat(FightProperty.FIGHT_PROP_WATER_ADD_HURT.toString(), FightProperty.FIGHT_PROP_WATER_ADD_HURT, true));
stats.put("epyro", new Stat(FightProperty.FIGHT_PROP_FIRE_ADD_HURT.toString(), FightProperty.FIGHT_PROP_FIRE_ADD_HURT, true));
stats.put("ephys", new Stat(FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT.toString(), FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, true));
stats.put("resall", new Stat(FightProperty.FIGHT_PROP_SUB_HURT.toString(), FightProperty.FIGHT_PROP_SUB_HURT, true)); // This seems to get reset after attacks
stats.put("resanemo", new Stat(FightProperty.FIGHT_PROP_WIND_SUB_HURT.toString(), FightProperty.FIGHT_PROP_WIND_SUB_HURT, true));
stats.put("rescryo", new Stat(FightProperty.FIGHT_PROP_ICE_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ICE_SUB_HURT, true));
stats.put("resdendro", new Stat(FightProperty.FIGHT_PROP_GRASS_SUB_HURT.toString(), FightProperty.FIGHT_PROP_GRASS_SUB_HURT, true));
stats.put("reselectro", new Stat(FightProperty.FIGHT_PROP_ELEC_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ELEC_SUB_HURT, true));
stats.put("resgeo", new Stat(FightProperty.FIGHT_PROP_ROCK_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ROCK_SUB_HURT, true));
stats.put("reshydro", new Stat(FightProperty.FIGHT_PROP_WATER_SUB_HURT.toString(), FightProperty.FIGHT_PROP_WATER_SUB_HURT, true));
stats.put("respyro", new Stat(FightProperty.FIGHT_PROP_FIRE_SUB_HURT.toString(), FightProperty.FIGHT_PROP_FIRE_SUB_HURT, true));
stats.put("resphys", new Stat(FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT.toString(), FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, true));
stats.put("cdr", new Stat(FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO.toString(), FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO, true));
stats.put("heal", new Stat(FightProperty.FIGHT_PROP_HEAL_ADD.toString(), FightProperty.FIGHT_PROP_HEAL_ADD, true));
stats.put("heali", new Stat(FightProperty.FIGHT_PROP_HEALED_ADD.toString(), FightProperty.FIGHT_PROP_HEALED_ADD, true));
stats.put("shield", new Stat(FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO.toString(), FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO, true));
stats.put("defi", new Stat(FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO.toString(), FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO, true));
// Compatibility aliases
stats.put("mhp", stats.get("maxhp"));
stats.put("cr", stats.get("crate"));
stats.put("cd", stats.get("cdmg"));
stats.put("edend", stats.get("edendro"));
stats.put("eelec", stats.get("eelectro"));
stats.put("ethunder", stats.get("eelectro"));
// Full FightProperty enum that won't be advertised but can be used by devs
// They have a prefix to avoid the "hp" clash
stats.put("_none", new Stat("NONE", FightProperty.FIGHT_PROP_NONE, true));
stats.put("_base_hp", new Stat("BASE_HP", FightProperty.FIGHT_PROP_BASE_HP, false));
stats.put("_hp", new Stat("HP", FightProperty.FIGHT_PROP_HP, false));
stats.put("_hp_percent", new Stat("HP_PERCENT", FightProperty.FIGHT_PROP_HP_PERCENT, true));
stats.put("_base_attack", new Stat("BASE_ATTACK", FightProperty.FIGHT_PROP_BASE_ATTACK, false));
stats.put("_attack", new Stat("ATTACK", FightProperty.FIGHT_PROP_ATTACK, false));
stats.put("_attack_percent", new Stat("ATTACK_PERCENT", FightProperty.FIGHT_PROP_ATTACK_PERCENT, true));
stats.put("_base_defense", new Stat("BASE_DEFENSE", FightProperty.FIGHT_PROP_BASE_DEFENSE, false));
stats.put("_defense", new Stat("DEFENSE", FightProperty.FIGHT_PROP_DEFENSE, false));
stats.put("_defense_percent", new Stat("DEFENSE_PERCENT", FightProperty.FIGHT_PROP_DEFENSE_PERCENT, true));
stats.put("_base_speed", new Stat("BASE_SPEED", FightProperty.FIGHT_PROP_BASE_SPEED, true));
stats.put("_speed_percent", new Stat("SPEED_PERCENT", FightProperty.FIGHT_PROP_SPEED_PERCENT, true));
stats.put("_hp_mp_percent", new Stat("HP_MP_PERCENT", FightProperty.FIGHT_PROP_HP_MP_PERCENT, true));
stats.put("_attack_mp_percent", new Stat("ATTACK_MP_PERCENT", FightProperty.FIGHT_PROP_ATTACK_MP_PERCENT, true));
stats.put("_critical", new Stat("CRITICAL", FightProperty.FIGHT_PROP_CRITICAL, true));
stats.put("_anti_critical", new Stat("ANTI_CRITICAL", FightProperty.FIGHT_PROP_ANTI_CRITICAL, true));
stats.put("_critical_hurt", new Stat("CRITICAL_HURT", FightProperty.FIGHT_PROP_CRITICAL_HURT, true));
stats.put("_charge_efficiency", new Stat("CHARGE_EFFICIENCY", FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, true));
stats.put("_add_hurt", new Stat("ADD_HURT", FightProperty.FIGHT_PROP_ADD_HURT, true));
stats.put("_sub_hurt", new Stat("SUB_HURT", FightProperty.FIGHT_PROP_SUB_HURT, true));
stats.put("_heal_add", new Stat("HEAL_ADD", FightProperty.FIGHT_PROP_HEAL_ADD, true));
stats.put("_healed_add", new Stat("HEALED_ADD", FightProperty.FIGHT_PROP_HEALED_ADD, false));
stats.put("_element_mastery", new Stat("ELEMENT_MASTERY", FightProperty.FIGHT_PROP_ELEMENT_MASTERY, true));
stats.put("_physical_sub_hurt", new Stat("PHYSICAL_SUB_HURT", FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, true));
stats.put("_physical_add_hurt", new Stat("PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, true));
stats.put("_defence_ignore_ratio", new Stat("DEFENCE_IGNORE_RATIO", FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO, true));
stats.put("_defence_ignore_delta", new Stat("DEFENCE_IGNORE_DELTA", FightProperty.FIGHT_PROP_DEFENCE_IGNORE_DELTA, true));
stats.put("_fire_add_hurt", new Stat("FIRE_ADD_HURT", FightProperty.FIGHT_PROP_FIRE_ADD_HURT, true));
stats.put("_elec_add_hurt", new Stat("ELEC_ADD_HURT", FightProperty.FIGHT_PROP_ELEC_ADD_HURT, true));
stats.put("_water_add_hurt", new Stat("WATER_ADD_HURT", FightProperty.FIGHT_PROP_WATER_ADD_HURT, true));
stats.put("_grass_add_hurt", new Stat("GRASS_ADD_HURT", FightProperty.FIGHT_PROP_GRASS_ADD_HURT, true));
stats.put("_wind_add_hurt", new Stat("WIND_ADD_HURT", FightProperty.FIGHT_PROP_WIND_ADD_HURT, true));
stats.put("_rock_add_hurt", new Stat("ROCK_ADD_HURT", FightProperty.FIGHT_PROP_ROCK_ADD_HURT, true));
stats.put("_ice_add_hurt", new Stat("ICE_ADD_HURT", FightProperty.FIGHT_PROP_ICE_ADD_HURT, true));
stats.put("_hit_head_add_hurt", new Stat("HIT_HEAD_ADD_HURT", FightProperty.FIGHT_PROP_HIT_HEAD_ADD_HURT, true));
stats.put("_fire_sub_hurt", new Stat("FIRE_SUB_HURT", FightProperty.FIGHT_PROP_FIRE_SUB_HURT, true));
stats.put("_elec_sub_hurt", new Stat("ELEC_SUB_HURT", FightProperty.FIGHT_PROP_ELEC_SUB_HURT, true));
stats.put("_water_sub_hurt", new Stat("WATER_SUB_HURT", FightProperty.FIGHT_PROP_WATER_SUB_HURT, true));
stats.put("_grass_sub_hurt", new Stat("GRASS_SUB_HURT", FightProperty.FIGHT_PROP_GRASS_SUB_HURT, true));
stats.put("_wind_sub_hurt", new Stat("WIND_SUB_HURT", FightProperty.FIGHT_PROP_WIND_SUB_HURT, true));
stats.put("_rock_sub_hurt", new Stat("ROCK_SUB_HURT", FightProperty.FIGHT_PROP_ROCK_SUB_HURT, true));
stats.put("_ice_sub_hurt", new Stat("ICE_SUB_HURT", FightProperty.FIGHT_PROP_ICE_SUB_HURT, true));
stats.put("_effect_hit", new Stat("EFFECT_HIT", FightProperty.FIGHT_PROP_EFFECT_HIT, true));
stats.put("_effect_resist", new Stat("EFFECT_RESIST", FightProperty.FIGHT_PROP_EFFECT_RESIST, true));
stats.put("_freeze_resist", new Stat("FREEZE_RESIST", FightProperty.FIGHT_PROP_FREEZE_RESIST, true));
stats.put("_torpor_resist", new Stat("TORPOR_RESIST", FightProperty.FIGHT_PROP_TORPOR_RESIST, true));
stats.put("_dizzy_resist", new Stat("DIZZY_RESIST", FightProperty.FIGHT_PROP_DIZZY_RESIST, true));
stats.put("_freeze_shorten", new Stat("FREEZE_SHORTEN", FightProperty.FIGHT_PROP_FREEZE_SHORTEN, true));
stats.put("_torpor_shorten", new Stat("TORPOR_SHORTEN", FightProperty.FIGHT_PROP_TORPOR_SHORTEN, true));
stats.put("_dizzy_shorten", new Stat("DIZZY_SHORTEN", FightProperty.FIGHT_PROP_DIZZY_SHORTEN, true));
stats.put("_max_fire_energy", new Stat("MAX_FIRE_ENERGY", FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, true));
stats.put("_max_elec_energy", new Stat("MAX_ELEC_ENERGY", FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, true));
stats.put("_max_water_energy", new Stat("MAX_WATER_ENERGY", FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, true));
stats.put("_max_grass_energy", new Stat("MAX_GRASS_ENERGY", FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY, true));
stats.put("_max_wind_energy", new Stat("MAX_WIND_ENERGY", FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, true));
stats.put("_max_ice_energy", new Stat("MAX_ICE_ENERGY", FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, true));
stats.put("_max_rock_energy", new Stat("MAX_ROCK_ENERGY", FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, true));
stats.put("_skill_cd_minus_ratio", new Stat("SKILL_CD_MINUS_RATIO", FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO, true));
stats.put("_shield_cost_minus_ratio", new Stat("SHIELD_COST_MINUS_RATIO", FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO, true));
stats.put("_cur_fire_energy", new Stat("CUR_FIRE_ENERGY", FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, false));
stats.put("_cur_elec_energy", new Stat("CUR_ELEC_ENERGY", FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, false));
stats.put("_cur_water_energy", new Stat("CUR_WATER_ENERGY", FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, false));
stats.put("_cur_grass_energy", new Stat("CUR_GRASS_ENERGY", FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, false));
stats.put("_cur_wind_energy", new Stat("CUR_WIND_ENERGY", FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, false));
stats.put("_cur_ice_energy", new Stat("CUR_ICE_ENERGY", FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, false));
stats.put("_cur_rock_energy", new Stat("CUR_ROCK_ENERGY", FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, false));
stats.put("_cur_hp", new Stat("CUR_HP", FightProperty.FIGHT_PROP_CUR_HP, false));
stats.put("_max_hp", new Stat("MAX_HP", FightProperty.FIGHT_PROP_MAX_HP, false));
stats.put("_cur_attack", new Stat("CUR_ATTACK", FightProperty.FIGHT_PROP_CUR_ATTACK, false));
stats.put("_cur_defense", new Stat("CUR_DEFENSE", FightProperty.FIGHT_PROP_CUR_DEFENSE, false));
stats.put("_cur_speed", new Stat("CUR_SPEED", FightProperty.FIGHT_PROP_CUR_SPEED, true));
stats.put("_nonextra_attack", new Stat("NONEXTRA_ATTACK", FightProperty.FIGHT_PROP_NONEXTRA_ATTACK, true));
stats.put("_nonextra_defense", new Stat("NONEXTRA_DEFENSE", FightProperty.FIGHT_PROP_NONEXTRA_DEFENSE, true));
stats.put("_nonextra_critical", new Stat("NONEXTRA_CRITICAL", FightProperty.FIGHT_PROP_NONEXTRA_CRITICAL, true));
stats.put("_nonextra_anti_critical", new Stat("NONEXTRA_ANTI_CRITICAL", FightProperty.FIGHT_PROP_NONEXTRA_ANTI_CRITICAL, true));
stats.put("_nonextra_critical_hurt", new Stat("NONEXTRA_CRITICAL_HURT", FightProperty.FIGHT_PROP_NONEXTRA_CRITICAL_HURT, true));
stats.put("_nonextra_charge_efficiency", new Stat("NONEXTRA_CHARGE_EFFICIENCY", FightProperty.FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY, true));
stats.put("_nonextra_element_mastery", new Stat("NONEXTRA_ELEMENT_MASTERY", FightProperty.FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY, true));
stats.put("_nonextra_physical_sub_hurt", new Stat("NONEXTRA_PHYSICAL_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT, true));
stats.put("_nonextra_fire_add_hurt", new Stat("NONEXTRA_FIRE_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT, true));
stats.put("_nonextra_elec_add_hurt", new Stat("NONEXTRA_ELEC_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT, true));
stats.put("_nonextra_water_add_hurt", new Stat("NONEXTRA_WATER_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WATER_ADD_HURT, true));
stats.put("_nonextra_grass_add_hurt", new Stat("NONEXTRA_GRASS_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT, true));
stats.put("_nonextra_wind_add_hurt", new Stat("NONEXTRA_WIND_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WIND_ADD_HURT, true));
stats.put("_nonextra_rock_add_hurt", new Stat("NONEXTRA_ROCK_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT, true));
stats.put("_nonextra_ice_add_hurt", new Stat("NONEXTRA_ICE_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ICE_ADD_HURT, true));
stats.put("_nonextra_fire_sub_hurt", new Stat("NONEXTRA_FIRE_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT, true));
stats.put("_nonextra_elec_sub_hurt", new Stat("NONEXTRA_ELEC_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT, true));
stats.put("_nonextra_water_sub_hurt", new Stat("NONEXTRA_WATER_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WATER_SUB_HURT, true));
stats.put("_nonextra_grass_sub_hurt", new Stat("NONEXTRA_GRASS_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT, true));
stats.put("_nonextra_wind_sub_hurt", new Stat("NONEXTRA_WIND_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WIND_SUB_HURT, true));
stats.put("_nonextra_rock_sub_hurt", new Stat("NONEXTRA_ROCK_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT, true));
stats.put("_nonextra_ice_sub_hurt", new Stat("NONEXTRA_ICE_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ICE_SUB_HURT, true));
stats.put("_nonextra_skill_cd_minus_ratio", new Stat("NONEXTRA_SKILL_CD_MINUS_RATIO", FightProperty.FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO, true));
stats.put("_nonextra_shield_cost_minus_ratio", new Stat("NONEXTRA_SHIELD_COST_MINUS_RATIO", FightProperty.FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO, true));
stats.put("_nonextra_physical_add_hurt", new Stat("NONEXTRA_PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT, true));
}
break;
case "epyro":
try {
float epyro = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float pyro = epyro / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_FIRE_ADD_HURT, pyro);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_FIRE_ADD_HURT));
float igpyro = pyro * 100;
CommandHandler.sendMessage(sender, "Pyro DMG Bonus set to " + igpyro + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Pyro DMG Bonus value.");
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
String syntax = sender == null ? translate("commands.setStats.usage_console") : translate("commands.setStats.ingame");
String usage = syntax + translate("commands.setStats.help_message");
String statStr;
String valueStr;
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
break;
case "ecryo":
try {
float ecryo = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float cryo = ecryo / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_ICE_ADD_HURT, cryo);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_ICE_ADD_HURT));
float igcyro = cryo * 100;
CommandHandler.sendMessage(sender, "Cyro DMG Bonus set to " + igcyro + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Cryo DMG Bonus value.");
if (args.size() == 2) {
statStr = args.get(0).toLowerCase();
valueStr = args.get(1);
} else {
CommandHandler.sendMessage(sender, usage);
return;
}
break;
case "ehydro":
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
float value;
try {
float ehydro = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float hydro = ehydro / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_WATER_ADD_HURT, hydro);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_WATER_ADD_HURT));
float ighydro = hydro * 100;
CommandHandler.sendMessage(sender, "Hydro DMG Bonus set to " + ighydro + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Hydro DMG Bonus value.");
return;
if (valueStr.endsWith("%")) {
value = Float.parseFloat(valueStr.substring(0, valueStr.length()-1))/100f;
} else {
value = Float.parseFloat(valueStr);
}
break;
case "eanemo":
try {
float eanemo = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float anemo = eanemo / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_WIND_ADD_HURT, anemo);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_WIND_ADD_HURT));
float iganemo = anemo * 100;
CommandHandler.sendMessage(sender, "Anemo DMG Bonus set to " + iganemo + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Anemo DMG Bonus value.");
CommandHandler.sendMessage(sender, translate("commands.setStats.value_error"));
return;
}
break;
case "egeo":
try {
float egeo = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float geo = egeo / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_ROCK_ADD_HURT, geo);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_ROCK_ADD_HURT));
float iggeo = geo * 100;
CommandHandler.sendMessage(sender, "Geo DMG Bonus set to " + iggeo + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Geo DMG Bonus value.");
return;
if (stats.containsKey(statStr)) {
Stat stat = stats.get(statStr);
entity.setFightProperty(stat.prop, value);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, stat.prop));
if (stat.percent) {
valueStr = String.format("%.1f%%", value*100f);
} else {
valueStr = String.format("%.0f", value);
}
break;
case "ethunder":
case "eelec":
try {
float eelec = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float elec = eelec / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_CRITICAL_HURT, elec);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CRITICAL_HURT));
float igelec = elec * 100;
CommandHandler.sendMessage(sender, "Electro DMG Bonus set to " + igelec + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Electro DMG Bonus value.");
return;
if (targetPlayer == sender) {
CommandHandler.sendMessage(sender, translate("commands.setStats.set_self", stat.name, valueStr));
} else {
String uidStr = targetPlayer.getAccount().getId();
CommandHandler.sendMessage(sender, translate("commands.setStats.set_self", stat.name, uidStr, valueStr));
}
break;
case "ephys":
try {
float ephys = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float phys = ephys / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, phys);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT));
float igphys = phys * 100;
CommandHandler.sendMessage(sender, "Physical DMG Bonus set to " + igphys + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Physical DMG Bonus value.");
return;
} else {
CommandHandler.sendMessage(sender, usage);
}
break;
case "edend":
try {
float edend = Integer.parseInt(args.get(1));
EntityAvatar entity = sender.getTeamManager().getCurrentAvatarEntity();
float dend = edend / 10000;
entity.setFightProperty(FightProperty.FIGHT_PROP_GRASS_ADD_HURT, dend);
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_GRASS_ADD_HURT));
float igdend = dend * 100;
CommandHandler.sendMessage(sender, "Dendro DMG Bonus set to " + igdend + "%");
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid Dendro DMG Bonus value.");
return;
}
break;
}
}
}
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.props.PlayerProperty;
import emu.grasscutter.game.player.Player;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "setworldlevel", usage = "setworldlevel <level>",
description = "Sets your world level (Relog to see proper effects)",
aliases = {"setworldlvl"}, permission = "player.setworldlevel")
public final class SetWorldLevelCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
return; // TODO: set player's world level from console or other players
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
if (args.size() < 1) {
CommandHandler.sendMessage(sender, "Usage: setworldlevel <level>");
CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.usage"));
return;
}
try {
int level = Integer.parseInt(args.get(0));
if (level > 8 || level < 0) {
CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.value_error"));
return;
}
// Set in both world and player props
sender.getWorld().setWorldLevel(level);
sender.setProperty(PlayerProperty.PROP_PLAYER_WORLD_LEVEL, level);
targetPlayer.getWorld().setWorldLevel(level);
targetPlayer.setWorldLevel(level);
sender.dropMessage("World level set to " + level + ".");
CommandHandler.sendMessage(sender, translate("commands.setWorldLevel.success", Integer.toString(level)));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(null, "Invalid world level.");
CommandHandler.sendMessage(null, translate("commands.setWorldLevel.invalid_world_level"));
}
}
}
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.data.def.GadgetData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.utils.Position;
import emu.grasscutter.game.world.Scene;
import javax.swing.text.html.parser.Entity;
import java.util.List;
import java.util.Random;
@Command(label = "spawn", usage = "spawn <entityId|entityName> [level] [amount]",
import static emu.grasscutter.utils.Language.translate;
@Command(label = "spawn", usage = "spawn <entityId> [amount] [level(monster only)]",
description = "Spawns an entity near you", permission = "server.spawn")
public final class SpawnCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
if (args.size() < 1) {
CommandHandler.sendMessage(sender, "Usage: spawn <entityId|entityName> [amount]");
int id = 0; // This is just to shut up the linter, it's not a real default
int amount = 1;
int level = 1;
switch (args.size()) {
case 3:
try {
level = Integer.parseInt(args.get(2));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.execution.argument_error"));
} // Fallthrough
case 2:
try {
amount = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.generic.error.amount"));
} // Fallthrough
case 1:
try {
id = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.generic.error.entityId"));
}
break;
default:
CommandHandler.sendMessage(sender, translate("commands.spawn.usage"));
return;
}
try {
int entity = Integer.parseInt(args.get(0));
int level = args.size() > 1 ? Integer.parseInt(args.get(1)) : 1;
int amount = args.size() > 2 ? Integer.parseInt(args.get(2)) : 1;
MonsterData entityData = GenshinData.getMonsterDataMap().get(entity);
if (entityData == null) {
CommandHandler.sendMessage(sender, "Invalid entity id.");
MonsterData monsterData = GameData.getMonsterDataMap().get(id);
GadgetData gadgetData = GameData.getGadgetDataMap().get(id);
ItemData itemData = GameData.getItemDataMap().get(id);
if (monsterData == null && gadgetData == null && itemData == null) {
CommandHandler.sendMessage(sender, translate("commands.generic.error.entityId"));
return;
}
Scene scene = targetPlayer.getScene();
float range = (5f + (.1f * amount));
double maxRadius = Math.sqrt(amount * 0.2 / Math.PI);
for (int i = 0; i < amount; i++) {
Position pos = sender.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2));
EntityMonster monster = new EntityMonster(sender.getScene(), entityData, pos, level);
sender.getScene().addEntity(monster);
Position pos = GetRandomPositionInCircle(targetPlayer.getPos(), maxRadius).addY(3);
GameEntity entity = null;
if (itemData != null) {
entity = new EntityItem(scene, null, itemData, pos, 1, true);
}
CommandHandler.sendMessage(sender, String.format("Spawned %s of %s.", amount, entity));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid item or player ID.");
if (gadgetData != null) {
entity = new EntityVehicle(scene, targetPlayer.getSession().getPlayer(), gadgetData.getId(), 0, pos, targetPlayer.getRotation()); // TODO: does targetPlayer.getSession().getPlayer() have some meaning?
int gadgetId = gadgetData.getId();
switch (gadgetId) {
// TODO: Not hardcode this. Waverider (skiff)
case 45001001, 45001002 -> {
entity.addFightProperty(FightProperty.FIGHT_PROP_BASE_HP, 10000);
entity.addFightProperty(FightProperty.FIGHT_PROP_BASE_ATTACK, 100);
entity.addFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, 100);
entity.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 10000);
entity.addFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, 0);
entity.addFightProperty(FightProperty.FIGHT_PROP_CUR_SPEED, 0);
entity.addFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 0);
entity.addFightProperty(FightProperty.FIGHT_PROP_MAX_HP, 10000);
}
default -> {}
}
}
if (monsterData != null) {
entity = new EntityMonster(scene, monsterData, pos, level);
}
scene.addEntity(entity);
}
CommandHandler.sendMessage(sender, translate("commands.spawn.success", Integer.toString(amount), Integer.toString(id)));
}
private Position GetRandomPositionInCircle(Position origin, double radius){
Position target = origin.clone();
double angle = Math.random() * 360;
double r = Math.sqrt(Math.random() * radius * radius);
target.addX((float) (r * Math.cos(angle))).addZ((float) (r * Math.sin(angle)));
return target;
}
}
......@@ -3,21 +3,23 @@ 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;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "stop", usage = "stop",
description = "Stops the server", permission = "server.stop")
public final class StopCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
CommandHandler.sendMessage(null, "Server shutting down...");
for (GenshinPlayer p : Grasscutter.getGameServer().getPlayers().values()) {
CommandHandler.sendMessage(p, "Server shutting down...");
public void execute(Player sender, Player targetPlayer, List<String> args) {
CommandHandler.sendMessage(null, translate("commands.stop.success"));
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
CommandHandler.sendMessage(p, translate("commands.stop.success"));
}
System.exit(1);
System.exit(1000);
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.def.AvatarSkillDepotData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.PacketAvatarSkillChangeNotify;
import emu.grasscutter.server.packet.send.PacketAvatarSkillUpgradeRsp;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "talent", usage = "talent <talentID> <value>",
description = "Set talent level for your current active character", permission = "player.settalent")
public final class TalentCommand implements CommandHandler {
private void setTalentLevel(Player sender, Player player, Avatar avatar, int talentId, int talentLevel) {
int oldLevel = avatar.getSkillLevelMap().get(talentId);
if (talentLevel < 0 || talentLevel > 15) {
CommandHandler.sendMessage(sender, translate("commands.talent.lower_16"));
return;
}
// Upgrade skill
avatar.getSkillLevelMap().put(talentLevel, talentLevel);
avatar.save();
// Packet
player.sendPacket(new PacketAvatarSkillChangeNotify(avatar, talentId, oldLevel, talentLevel));
player.sendPacket(new PacketAvatarSkillUpgradeRsp(avatar, talentId, oldLevel, talentLevel));
String successMessage = "commands.talent.set_id";
AvatarSkillDepotData depot = avatar.getData().getSkillDepot();
if (talentId == depot.getSkills().get(0)) {
successMessage = "commands.talent.set_atk";
} else if (talentId == depot.getSkills().get(1)) {
successMessage = "commands.talent.set_e";
} else if (talentId == depot.getEnergySkill()) {
successMessage = "commands.talent.set_q";
}
CommandHandler.sendMessage(sender, translate(successMessage, talentLevel));
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
if (args.size() < 1){
CommandHandler.sendMessage(sender, translate("commands.talent.usage_1"));
CommandHandler.sendMessage(sender, translate("commands.talent.usage_2"));
CommandHandler.sendMessage(sender, translate("commands.talent.usage_3"));
return;
}
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
Avatar avatar = entity.getAvatar();
String cmdSwitch = args.get(0);
switch (cmdSwitch) {
default -> {
CommandHandler.sendMessage(sender, translate("commands.talent.usage_1"));
CommandHandler.sendMessage(sender, translate("commands.talent.usage_2"));
CommandHandler.sendMessage(sender, translate("commands.talent.usage_3"));
return;
}
case "set" -> {
if (args.size() < 3) {
CommandHandler.sendMessage(sender, translate("commands.talent.usage_1"));
CommandHandler.sendMessage(sender, translate("commands.talent.usage_3"));
return;
}
try {
int skillId = Integer.parseInt(args.get(1));
int newLevel = Integer.parseInt(args.get(2));
setTalentLevel(sender, targetPlayer, avatar, skillId, newLevel);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.talent.invalid_skill_id"));
return;
}
}
case "n", "e", "q" -> {
if (args.size() < 2) {
CommandHandler.sendMessage(sender, translate("commands.talent.usage_2"));
return;
}
AvatarSkillDepotData SkillDepot = avatar.getData().getSkillDepot();
int skillId = switch (cmdSwitch) {
default -> SkillDepot.getSkills().get(0);
case "e" -> SkillDepot.getSkills().get(1);
case "q" -> SkillDepot.getEnergySkill();
};
try {
int newLevel = Integer.parseInt(args.get(1));
setTalentLevel(sender, targetPlayer, avatar, skillId, newLevel);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.talent.invalid_level"));
return;
}
}
case "getid" -> {
int skillIdNorAtk = avatar.getData().getSkillDepot().getSkills().get(0);
int skillIdE = avatar.getData().getSkillDepot().getSkills().get(1);
int skillIdQ = avatar.getData().getSkillDepot().getEnergySkill();
CommandHandler.sendMessage(sender, translate("commands.talent.normal_attack_id", Integer.toString(skillIdNorAtk)));
CommandHandler.sendMessage(sender, translate("commands.talent.e_skill_id", Integer.toString(skillIdE)));
CommandHandler.sendMessage(sender, translate("commands.talent.q_skill_id", Integer.toString(skillIdQ)));
}
}
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
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;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "tpall", usage = "tpall",
description = "Teleports all players in your world to your position", permission = "player.tpall")
public final class TeleportAllCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
if (!targetPlayer.getWorld().isMultiplayer()) {
CommandHandler.sendMessage(sender, translate("commands.teleportAll.error"));
return;
}
for (Player player : targetPlayer.getWorld().getPlayers()) {
if (player.equals(targetPlayer))
continue;
Position pos = targetPlayer.getPos();
player.getWorld().transferPlayerToScene(player, targetPlayer.getSceneId(), pos);
}
CommandHandler.sendMessage(sender, translate("commands.teleportAll.success"));
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
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;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "teleport", usage = "teleport <x> <y> <z> [scene id]", aliases = {"tp"},
description = "Change the player's position.", permission = "player.teleport")
public final class TeleportCommand implements CommandHandler {
private float parseRelative(String input, Float current) { // TODO: Maybe this will be useful elsewhere later
if (input.contains("~")) { // Relative
if (!input.equals("~")) { // Relative with offset
current += Float.parseFloat(input.replace("~", ""));
} // Else no offset, no modification
} else { // Absolute
current = Float.parseFloat(input);
}
return current;
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
Position pos = targetPlayer.getPos();
float x = pos.getX();
float y = pos.getY();
float z = pos.getZ();
int sceneId = targetPlayer.getSceneId();
switch (args.size()) {
case 4:
try {
sceneId = Integer.parseInt(args.get(3));
}catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.execution.argument_error"));
} // Fallthrough
case 3:
try {
x = parseRelative(args.get(0), x);
y = parseRelative(args.get(1), y);
z = parseRelative(args.get(2), z);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.teleport.invalid_position"));
}
break;
default:
CommandHandler.sendMessage(sender, translate("commands.teleport.usage"));
return;
}
Position target_pos = new Position(x, y, z);
boolean result = targetPlayer.getWorld().transferPlayerToScene(targetPlayer, sceneId, target_pos);
if (!result) {
CommandHandler.sendMessage(sender, translate("commands.teleport.invalid_position"));
} else {
CommandHandler.sendMessage(sender, translate("commands.teleport.success",
targetPlayer.getNickname(), Float.toString(x), Float.toString(y),
Float.toString(z), Integer.toString(sceneId))
);
}
}
}
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 emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify;
import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "weather", usage = "weather <weatherId> [climateId]",
description = "Changes the weather.", aliases = {"w"}, permission = "player.weather")
public final class WeatherCommand implements CommandHandler {
@Override
public void execute(GenshinPlayer sender, List<String> args) {
if (sender == null) {
CommandHandler.sendMessage(null, "Run this command in-game.");
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (targetPlayer == null) {
CommandHandler.sendMessage(sender, translate("commands.execution.need_target"));
return;
}
if (args.size() < 1) {
CommandHandler.sendMessage(sender, "Usage: weather <weatherId> [climateId]");
return;
int weatherId = 0;
int climateId = 1;
switch (args.size()) {
case 2:
try {
climateId = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.weather.invalid_id"));
}
case 1:
try {
int weatherId = Integer.parseInt(args.get(0));
int climateId = args.size() > 1 ? Integer.parseInt(args.get(1)) : 1;
weatherId = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate("commands.weather.invalid_id"));
}
break;
default:
CommandHandler.sendMessage(sender, translate("commands.weather.usage"));
return;
}
ClimateType climate = ClimateType.getTypeByValue(climateId);
sender.getScene().setWeather(weatherId);
sender.getScene().setClimate(climate);
sender.getScene().broadcastPacket(new PacketSceneAreaWeatherNotify(sender));
CommandHandler.sendMessage(sender, "Changed weather to " + weatherId + " with climate " + climateId);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, "Invalid ID.");
}
targetPlayer.getScene().setWeather(weatherId);
targetPlayer.getScene().setClimate(climate);
targetPlayer.getScene().broadcastPacket(new PacketSceneAreaWeatherNotify(targetPlayer));
CommandHandler.sendMessage(sender, translate("commands.weather.success", Integer.toString(weatherId), Integer.toString(climateId)));
}
}
......@@ -15,8 +15,10 @@ import emu.grasscutter.data.def.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
public class GenshinData {
public class GameData {
// BinOutputs
private static final Int2ObjectMap<String> abilityHashes = new Int2ObjectOpenHashMap<>();
private static final Map<String, AbilityEmbryoEntry> abilityEmbryos = new HashMap<>();
......@@ -31,6 +33,7 @@ public class GenshinData {
private static final Int2ObjectMap<AvatarSkillDepotData> avatarSkillDepotDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarSkillData> avatarSkillDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap<AvatarFetterLevelData> avatarFetterLevelDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarPromoteData> avatarPromoteDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<AvatarTalentData> avatarTalentDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<ProudSkillData> proudSkillDataMap = new Int2ObjectOpenHashMap<>();
......@@ -57,15 +60,27 @@ public class GenshinData {
private static final Int2ObjectMap<SceneData> sceneDataMap = new Int2ObjectLinkedOpenHashMap<>();
private static final Int2ObjectMap<FetterData> fetterDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<WorldLevelData> worldLevelDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<DailyDungeonData> dailyDungeonDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<DungeonData> dungeonDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<ShopGoodsData> shopGoodsDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<CombineData> combineDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<RewardPreviewData> rewardPreviewDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<TowerFloorData> towerFloorDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<TowerLevelData> towerLevelDataMap = new Int2ObjectOpenHashMap<>();
// Cache
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
private static Map<Integer, List<ShopGoodsData>> shopGoods = new HashMap<>();
private static final IntList scenePointIdList = new IntArrayList();
public static Int2ObjectMap<?> getMapByResourceDef(Class<?> resourceDefinition) {
Int2ObjectMap<?> map = null;
try {
Field field = GenshinData.class.getDeclaredField(Utils.lowerCaseFirstChar(resourceDefinition.getSimpleName()) + "Map");
Field field = GameData.class.getDeclaredField(Utils.lowerCaseFirstChar(resourceDefinition.getSimpleName()) + "Map");
field.setAccessible(true);
map = (Int2ObjectMap<?>) field.get(null);
......@@ -94,6 +109,11 @@ public class GenshinData {
return scenePointEntries;
}
// TODO optimize
public static ScenePointEntry getScenePointEntryById(int sceneId, int pointId) {
return getScenePointEntries().get(sceneId + "_" + pointId);
}
public static Int2ObjectMap<AvatarData> getAvatarDataMap() {
return avatarDataMap;
}
......@@ -114,6 +134,14 @@ public class GenshinData {
return playerLevelDataMap;
}
public static Int2ObjectMap<AvatarFetterLevelData> getAvatarFetterLevelDataMap() {
return avatarFetterLevelDataMap;
}
public static Int2ObjectMap<FetterCharacterCardData> getFetterCharacterCardDataMap() {
return fetterCharacterCardDataMap;
}
public static Int2ObjectMap<AvatarLevelData> getAvatarLevelDataMap() {
return avatarLevelDataMap;
}
......@@ -176,6 +204,11 @@ public class GenshinData {
return levelData != null ? levelData.getExp() : 0;
}
public static int getAvatarFetterLevelExpRequired(int level) {
AvatarFetterLevelData levelData = avatarFetterLevelDataMap.get(level);
return levelData != null ? levelData.getExp() : 0;
}
public static Int2ObjectMap<ProudSkillData> getProudSkillDataMap() {
return proudSkillDataMap;
}
......@@ -228,6 +261,10 @@ public class GenshinData {
return sceneDataMap;
}
public static Int2ObjectMap<RewardData> getRewardDataMap() {
return rewardDataMap;
}
public static Map<Integer, List<Integer>> getFetterDataEntries() {
if (fetters.isEmpty()) {
fetterDataMap.forEach((k, v) -> {
......@@ -240,4 +277,47 @@ public class GenshinData {
return fetters;
}
public static Int2ObjectMap<WorldLevelData> getWorldLevelDataMap() {
return worldLevelDataMap;
}
public static Int2ObjectMap<DungeonData> getDungeonDataMap() {
return dungeonDataMap;
}
public static Int2ObjectMap<DailyDungeonData> getDailyDungeonDataMap() {
return dailyDungeonDataMap;
}
public static Map<Integer, List<ShopGoodsData>> getShopGoodsDataEntries() {
if (shopGoods.isEmpty()) {
shopGoodsDataMap.forEach((k, v) -> {
if (!shopGoods.containsKey(v.getShopType()))
shopGoods.put(v.getShopType(), new ArrayList<>());
shopGoods.get(v.getShopType()).add(v);
});
}
return shopGoods;
}
public static Int2ObjectMap<RewardPreviewData> getRewardPreviewDataMap() {
return rewardPreviewDataMap;
}
public static IntList getScenePointIdList() {
return scenePointIdList;
}
public static Int2ObjectMap<CombineData> getCombineDataMap() {
return combineDataMap;
}
public static Int2ObjectMap<TowerFloorData> getTowerFloorDataMap(){
return towerFloorDataMap;
}
public static Int2ObjectMap<TowerLevelData> getTowerLevelDataMap(){
return towerLevelDataMap;
}
}
......@@ -3,26 +3,33 @@ package emu.grasscutter.data;
import java.util.ArrayList;
import java.util.List;
import org.danilopianini.util.FlexibleQuadTree;
import org.danilopianini.util.SpatialIndex;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.def.ReliquaryAffixData;
import emu.grasscutter.data.def.ReliquaryMainPropData;
import emu.grasscutter.game.world.SpawnDataEntry;
import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry;
import emu.grasscutter.utils.WeightedList;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GenshinDepot {
public class GameDepot {
private static Int2ObjectMap<WeightedList<ReliquaryMainPropData>> relicMainPropDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<List<ReliquaryAffixData>> relicAffixDepot = new Int2ObjectOpenHashMap<>();
private static Int2ObjectMap<SpatialIndex<SpawnGroupEntry>> spawnLists = new Int2ObjectOpenHashMap<>();
public static void load() {
for (ReliquaryMainPropData data : GenshinData.getReliquaryMainPropDataMap().values()) {
for (ReliquaryMainPropData data : GameData.getReliquaryMainPropDataMap().values()) {
if (data.getWeight() <= 0 || data.getPropDepotId() <= 0) {
continue;
}
WeightedList<ReliquaryMainPropData> list = relicMainPropDepot.computeIfAbsent(data.getPropDepotId(), k -> new WeightedList<>());
list.add(data.getWeight(), data);
}
for (ReliquaryAffixData data : GenshinData.getReliquaryAffixDataMap().values()) {
for (ReliquaryAffixData data : GameData.getReliquaryAffixDataMap().values()) {
if (data.getWeight() <= 0 || data.getDepotId() <= 0) {
continue;
}
......@@ -46,4 +53,12 @@ public class GenshinDepot {
public static List<ReliquaryAffixData> getRandomRelicAffixList(int depot) {
return relicAffixDepot.get(depot);
}
public static Int2ObjectMap<SpatialIndex<SpawnGroupEntry>> getSpawnLists() {
return spawnLists;
}
public static SpatialIndex<SpawnGroupEntry> getSpawnListById(int sceneId) {
return getSpawnLists().computeIfAbsent(sceneId, id -> new FlexibleQuadTree<>());
}
}
package emu.grasscutter.data;
public abstract class GenshinResource {
public abstract class GameResource {
public int getId() {
return 0;
......
......@@ -7,6 +7,7 @@ import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.gson.Gson;
import emu.grasscutter.utils.Utils;
import org.reflections.Reflections;
......@@ -19,13 +20,15 @@ import emu.grasscutter.data.common.ScenePointConfig;
import emu.grasscutter.data.custom.AbilityEmbryoEntry;
import emu.grasscutter.data.custom.OpenConfigEntry;
import emu.grasscutter.data.custom.ScenePointEntry;
import emu.grasscutter.game.world.SpawnDataEntry;
import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
public class ResourceLoader {
public static List<Class<?>> getResourceDefClasses() {
Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName());
Set<?> classes = reflections.getSubTypesOf(GenshinResource.class);
Set<?> classes = reflections.getSubTypesOf(GameResource.class);
List<Class<?>> classList = new ArrayList<>(classes.size());
classes.forEach(o -> {
......@@ -46,12 +49,15 @@ public class ResourceLoader {
loadOpenConfig();
// Load resources
loadResources();
loadScenePoints();
// Process into depots
GenshinDepot.load();
GameDepot.load();
// Load spawn data
loadSpawnData();
// Load scene points - must be done AFTER resources are loaded
loadScenePoints();
// Custom - TODO move this somewhere else
try {
GenshinData.getAvatarSkillDepotDataMap().get(504).setAbilities(
GameData.getAvatarSkillDepotDataMap().get(504).setAbilities(
new AbilityEmbryoEntry(
"",
new String[] {
......@@ -64,7 +70,7 @@ public class ResourceLoader {
"Avatar_Player_WindBreathe_CameraController"
}
));
GenshinData.getAvatarSkillDepotDataMap().get(704).setAbilities(
GameData.getAvatarSkillDepotDataMap().get(704).setAbilities(
new AbilityEmbryoEntry(
"",
new String[] {
......@@ -91,7 +97,7 @@ public class ResourceLoader {
}
@SuppressWarnings("rawtypes")
Int2ObjectMap map = GenshinData.getMapByResourceDef(resourceDefinition);
Int2ObjectMap map = GameData.getMapByResourceDef(resourceDefinition);
if (map == null) {
continue;
......@@ -115,16 +121,17 @@ public class ResourceLoader {
@SuppressWarnings({"rawtypes", "unchecked"})
protected static void loadFromResource(Class<?> c, String fileName, Int2ObjectMap map) throws Exception {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "ExcelBinOutput/" + fileName)) {
List list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, c).getType());
FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "ExcelBinOutput/" + fileName);
Gson gson = Grasscutter.getGsonFactory();
List list = gson.fromJson(fileReader, List.class);
for (Object o : list) {
GenshinResource res = (GenshinResource) o;
Map<String, Object> tempMap = Utils.switchPropertiesUpperLowerCase((Map<String, Object>) o, c);
GameResource res = gson.fromJson(gson.toJson(tempMap), TypeToken.get(c).getType());
res.onLoad();
map.put(res.getId(), res);
}
}
}
private static void loadScenePoints() {
Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)");
......@@ -136,7 +143,7 @@ public class ResourceLoader {
}
List<ScenePointEntry> scenePointList = new ArrayList<>();
for (File file : folder.listFiles()) {
for (File file : Objects.requireNonNull(folder.listFiles())) {
ScenePointConfig config = null;
Integer sceneId = null;
......@@ -160,13 +167,17 @@ public class ResourceLoader {
for (Map.Entry<String, JsonElement> entry : config.points.entrySet()) {
PointData pointData = Grasscutter.getGsonFactory().fromJson(entry.getValue(), PointData.class);
pointData.setId(Integer.parseInt(entry.getKey()));
ScenePointEntry sl = new ScenePointEntry(sceneId + "_" + entry.getKey(), pointData);
scenePointList.add(sl);
GameData.getScenePointIdList().add(pointData.getId());
pointData.updateDailyDungeon();
}
for (ScenePointEntry entry : scenePointList) {
GenshinData.getScenePointEntries().put(entry.getName(), entry);
GameData.getScenePointEntries().put(entry.getName(), entry);
}
}
}
......@@ -229,7 +240,34 @@ public class ResourceLoader {
}
for (AbilityEmbryoEntry entry : embryoList) {
GenshinData.getAbilityEmbryoInfo().put(entry.getName(), entry);
GameData.getAbilityEmbryoInfo().put(entry.getName(), entry);
}
}
private static void loadSpawnData() {
// Read from cached file if exists
File spawnDataEntries = new File(Grasscutter.getConfig().DATA_FOLDER + "Spawns.json");
List<SpawnGroupEntry> spawnEntryList = null;
if (spawnDataEntries.exists()) {
// Load from cache
try (FileReader fileReader = new FileReader(spawnDataEntries)) {
spawnEntryList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
} catch (Exception e) {
e.printStackTrace();
}
}
if (spawnEntryList == null || spawnEntryList.isEmpty()) {
Grasscutter.getLogger().error("No spawn data loaded!");
return;
}
for (SpawnGroupEntry entry : spawnEntryList) {
entry.getSpawns().stream().forEach(s -> {
s.setGroup(entry);
});
GameDepot.getSpawnListById(entry.getSceneId()).insert(entry, entry.getPos().getX(), entry.getPos().getZ());
}
}
......@@ -271,18 +309,7 @@ public class ResourceLoader {
}
for (Entry<String, OpenConfigData[]> e : config.entrySet()) {
List<String> abilityList = new ArrayList<>();
int extraTalentIndex = 0;
for (OpenConfigData entry : e.getValue()) {
if (entry.$type.contains("AddAbility")) {
abilityList.add(entry.abilityName);
} else if (entry.talentIndex > 0) {
extraTalentIndex = entry.talentIndex;
}
}
OpenConfigEntry entry = new OpenConfigEntry(e.getKey(), abilityList, extraTalentIndex);
OpenConfigEntry entry = new OpenConfigEntry(e.getKey(), e.getValue());
map.put(entry.getName(), entry);
}
}
......@@ -297,7 +324,7 @@ public class ResourceLoader {
}
for (OpenConfigEntry entry : list) {
GenshinData.getOpenConfigEntries().put(entry.getName(), entry);
GameData.getOpenConfigEntries().put(entry.getName(), entry);
}
}
......@@ -318,9 +345,11 @@ public class ResourceLoader {
public OpenConfigData[] data;
}
private static class OpenConfigData {
public static class OpenConfigData {
public String $type;
public String abilityName;
public int talentIndex;
public int skillID;
public int pointDelta;
}
}
......@@ -4,6 +4,12 @@ public class ItemParamData {
private int Id;
private int Count;
public ItemParamData() {}
public ItemParamData(int id, int count) {
this.Id = id;
this.Count = count;
}
public int getId() {
return Id;
}
......
package emu.grasscutter.data.common;
public class ItemParamStringData {
private int Id;
private String Count;
public ItemParamStringData() {}
public int getId() {
return Id;
}
public String getCount() {
return Count;
}
public ItemParamData toItemParamData() {
if (Count.contains(";")) {
String[] split = Count.split(";");
Count = Count.split(";")[split.length - 1];
} else if (Count.contains(".")) {
return new ItemParamData(Id, (int) Math.ceil(Double.parseDouble(Count)));
}
return new ItemParamData(Id, Integer.parseInt(Count));
}
}
package emu.grasscutter.data.common;
import java.util.List;
public class OpenCondData {
private String CondType;
private List<Integer> ParamList;
public String getCondType() {
return CondType;
}
public void setCondType(String condType) {
CondType = condType;
}
public List<Integer> getParamList() {
return ParamList;
}
public void setParamList(List<Integer> paramList) {
ParamList = paramList;
}
}
package emu.grasscutter.data.common;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.DailyDungeonData;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
public class PointData {
private pos tranPos;
private int id;
private String $type;
private Position tranPos;
private int[] dungeonIds;
private int[] dungeonRandomList;
public pos getTranPos() {
return tranPos;
private int tranSceneId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setTranPos(pos tranPos) {
this.tranPos = tranPos;
public String getType() {
return $type;
}
public class pos {
private float x;
private float y;
private float z;
public Position getTranPos() {
return tranPos;
}
public float getX() {
return x;
public int[] getDungeonIds() {
return dungeonIds;
}
public void setX(float x) {
this.x = x;
public int[] getDungeonRandomList() {
return dungeonRandomList;
}
public float getY() {
return y;
public int getTranSceneId() {
return tranSceneId;
}
public void setY(float y) {
this.y = y;
public void setTranSceneId(int tranSceneId) {
this.tranSceneId = tranSceneId;
}
public float getZ() {
return z;
public void updateDailyDungeon() {
if (getDungeonRandomList() == null) {
return;
}
public void setZ(float z) {
this.z = z;
IntList newDungeons = new IntArrayList();
int day = Grasscutter.getCurrentDayOfWeek();
for (int randomId : getDungeonRandomList()) {
DailyDungeonData data = GameData.getDailyDungeonDataMap().get(randomId);
if (data != null) {
int[] addDungeons = data.getDungeonsByDay(day);
for (int d : addDungeons) {
newDungeons.add(d);
}
}
}
this.dungeonIds = newDungeons.toIntArray();
}
}
package emu.grasscutter.data.common;
public class RewardItemData {
private int ItemId;
private int ItemCount;
public int getItemId() {
return ItemId;
}
public void setItemId(int itemId) {
ItemId = itemId;
}
public int getItemCount() {
return ItemCount;
}
public void setItemCount(int itemCount) {
ItemCount = itemCount;
}
}
package emu.grasscutter.data.custom;
import java.util.ArrayList;
import java.util.List;
import emu.grasscutter.data.ResourceLoader.OpenConfigData;
public class OpenConfigEntry {
private String name;
private String[] addAbilities;
private int extraTalentIndex;
private SkillPointModifier[] skillPointModifiers;
public OpenConfigEntry(String name, List<String> abilityList, int extraTalentIndex) {
public OpenConfigEntry(String name, OpenConfigData[] data) {
this.name = name;
this.extraTalentIndex = extraTalentIndex;
List<String> abilityList = new ArrayList<>();
List<SkillPointModifier> modList = new ArrayList<>();
for (OpenConfigData entry : data) {
if (entry.$type.contains("AddAbility")) {
abilityList.add(entry.abilityName);
} else if (entry.talentIndex > 0) {
this.extraTalentIndex = entry.talentIndex;
} else if (entry.$type.contains("ModifySkillPoint")) {
modList.add(new SkillPointModifier(entry.skillID, entry.pointDelta));
}
}
if (abilityList.size() > 0) {
this.addAbilities = abilityList.toArray(new String[0]);
}
if (modList.size() > 0) {
this.skillPointModifiers = modList.toArray(new SkillPointModifier[0]);
}
}
public String getName() {
......@@ -26,4 +47,26 @@ public class OpenConfigEntry {
public int getExtraTalentIndex() {
return extraTalentIndex;
}
public SkillPointModifier[] getSkillPointModifiers() {
return skillPointModifiers;
}
public static class SkillPointModifier {
private int skillId;
private int delta;
public SkillPointModifier(int skillId, int delta) {
this.skillId = skillId;
this.delta = delta;
}
public int getSkillId() {
return skillId;
}
public int getDelta() {
return delta;
}
}
}
package emu.grasscutter.data.def;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
@ResourceType(name = "AvatarCostumeExcelConfigData.json")
public class AvatarCostumeData extends GenshinResource {
public class AvatarCostumeData extends GameResource {
private int CostumeId;
private int ItemId;
private int AvatarId;
......@@ -25,6 +25,6 @@ public class AvatarCostumeData extends GenshinResource {
@Override
public void onLoad() {
GenshinData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this);
GameData.getAvatarCostumeDataItemIdMap().put(this.getItemId(), this);
}
}
......@@ -4,12 +4,12 @@ import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import emu.grasscutter.data.GenshinResource;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.common.CurveInfo;
@ResourceType(name = "AvatarCurveExcelConfigData.json")
public class AvatarCurveData extends GenshinResource {
public class AvatarCurveData extends GameResource {
private int Level;
private CurveInfo[] CurveInfos;
......
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