mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-25 04:15:34 +08:00
[BREAKING] Deobfuscate codex field, slight refactor (#1809)
* Deobfuscate codex field, slight refactor * Fix relic sets in codex
This commit is contained in:
parent
5ffc07cf59
commit
c2e620bf7c
@ -1,38 +1,26 @@
|
|||||||
package emu.grasscutter.data.excels;
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import emu.grasscutter.data.GameResource;
|
import emu.grasscutter.data.GameResource;
|
||||||
import emu.grasscutter.data.ResourceType;
|
import emu.grasscutter.data.ResourceType;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
@ResourceType(name = {"AnimalCodexExcelConfigData.json"})
|
@ResourceType(name = {"AnimalCodexExcelConfigData.json"})
|
||||||
public class CodexAnimalData extends GameResource {
|
public class CodexAnimalData extends GameResource {
|
||||||
private int Id;
|
private int Id;
|
||||||
private String type;
|
@Getter private String type;
|
||||||
private int describeId;
|
@Getter private int describeId;
|
||||||
private int sortOrder;
|
@Getter private int sortOrder;
|
||||||
private CodexAnimalUnlockCondition OCCLHPBCDGL;
|
@SerializedName(value="countType", alternate={"OCCLHPBCDGL"})
|
||||||
|
@Getter private CountType countType;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
public enum CountType {
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDescribeId() {
|
|
||||||
return describeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSortOrder() {
|
|
||||||
return sortOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodexAnimalUnlockCondition getUnlockCondition() {
|
|
||||||
return OCCLHPBCDGL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CodexAnimalUnlockCondition {
|
|
||||||
CODEX_COUNT_TYPE_KILL,
|
CODEX_COUNT_TYPE_KILL,
|
||||||
CODEX_COUNT_TYPE_CAPTURE
|
CODEX_COUNT_TYPE_CAPTURE
|
||||||
}
|
}
|
||||||
|
@ -3,57 +3,44 @@ package emu.grasscutter.data.excels;
|
|||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.GameResource;
|
import emu.grasscutter.data.GameResource;
|
||||||
import emu.grasscutter.data.ResourceType;
|
import emu.grasscutter.data.ResourceType;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntCollection;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
@ResourceType(name = {"ReliquaryCodexExcelConfigData.json"})
|
@ResourceType(name = {"ReliquaryCodexExcelConfigData.json"})
|
||||||
public class CodexReliquaryData extends GameResource {
|
public class CodexReliquaryData extends GameResource {
|
||||||
private int Id;
|
@Getter private int Id;
|
||||||
private int suitId;
|
@Getter private int suitId;
|
||||||
private int level;
|
@Getter private int level;
|
||||||
private int cupId;
|
@Getter private int cupId;
|
||||||
private int leatherId;
|
@Getter private int leatherId;
|
||||||
private int capId;
|
@Getter private int capId;
|
||||||
private int flowerId;
|
@Getter private int flowerId;
|
||||||
private int sandId;
|
@Getter private int sandId;
|
||||||
private int sortOrder;
|
@Getter private int sortOrder;
|
||||||
|
private transient IntCollection ids;
|
||||||
|
|
||||||
public int getSortOrder() {
|
public boolean containsId(int id) {
|
||||||
return sortOrder;
|
return getIds().contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public IntCollection getIds() {
|
||||||
return Id;
|
if (this.ids == null) {
|
||||||
}
|
int[] idsArr = {cupId, leatherId, capId, flowerId, sandId};
|
||||||
|
this.ids = IntList.of(idsArr);
|
||||||
public int getSuitId() {
|
}
|
||||||
return suitId;
|
return this.ids;
|
||||||
}
|
|
||||||
|
|
||||||
public int getLevel() {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCupId() {
|
|
||||||
return cupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLeatherId() {
|
|
||||||
return leatherId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCapId() {
|
|
||||||
return capId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFlowerId() {
|
|
||||||
return flowerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSandId() {
|
|
||||||
return sandId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
|
// Normalize all itemIds to the 0-substat form
|
||||||
|
cupId = (cupId/10) * 10;
|
||||||
|
leatherId = (leatherId/10) * 10;
|
||||||
|
capId = (capId/10) * 10;
|
||||||
|
flowerId = (flowerId/10) * 10;
|
||||||
|
sandId = (sandId/10) * 10;
|
||||||
|
|
||||||
GameData.getcodexReliquaryArrayList().add(this);
|
GameData.getcodexReliquaryArrayList().add(this);
|
||||||
GameData.getcodexReliquaryIdMap().put(getSuitId(), this);
|
GameData.getcodexReliquaryIdMap().put(getSuitId(), this);
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,12 @@ import dev.morphia.annotations.Entity;
|
|||||||
import dev.morphia.annotations.Transient;
|
import dev.morphia.annotations.Transient;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.excels.CodexAnimalData;
|
import emu.grasscutter.data.excels.CodexAnimalData;
|
||||||
import emu.grasscutter.data.excels.CodexReliquaryData;
|
|
||||||
import emu.grasscutter.game.entity.EntityMonster;
|
import emu.grasscutter.game.entity.EntityMonster;
|
||||||
import emu.grasscutter.game.entity.GameEntity;
|
import emu.grasscutter.game.entity.GameEntity;
|
||||||
import emu.grasscutter.game.inventory.GameItem;
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
import emu.grasscutter.game.inventory.ItemType;
|
|
||||||
import emu.grasscutter.game.inventory.MaterialType;
|
|
||||||
import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify;
|
import emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -19,14 +18,14 @@ public class PlayerCodex {
|
|||||||
@Transient private Player player;
|
@Transient private Player player;
|
||||||
|
|
||||||
//itemId is not codexId!
|
//itemId is not codexId!
|
||||||
private Set<Integer> unlockedWeapon;
|
@Getter private Set<Integer> unlockedWeapon;
|
||||||
private Map<Integer, Integer> unlockedAnimal;
|
@Getter private Map<Integer, Integer> unlockedAnimal;
|
||||||
private Set<Integer> unlockedMaterial;
|
@Getter private Set<Integer> unlockedMaterial;
|
||||||
private Set<Integer> unlockedBook;
|
@Getter private Set<Integer> unlockedBook;
|
||||||
private Set<Integer> unlockedTip;
|
@Getter private Set<Integer> unlockedTip;
|
||||||
private Set<Integer> unlockedView;
|
@Getter private Set<Integer> unlockedView;
|
||||||
private Set<Integer> unlockedReliquary;
|
@Getter private Set<Integer> unlockedReliquary;
|
||||||
private Set<Integer> unlockedReliquarySuitCodex;
|
@Getter private Set<Integer> unlockedReliquarySuitCodex;
|
||||||
|
|
||||||
public PlayerCodex(){
|
public PlayerCodex(){
|
||||||
this.unlockedWeapon = new HashSet<>();
|
this.unlockedWeapon = new HashSet<>();
|
||||||
@ -46,120 +45,86 @@ public class PlayerCodex {
|
|||||||
|
|
||||||
public void setPlayer(Player player) {
|
public void setPlayer(Player player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
this.fixReliquaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkAddedItem(GameItem item){
|
public void checkAddedItem(GameItem item){
|
||||||
ItemType type = item.getItemData().getItemType();
|
val itemData = item.getItemData();
|
||||||
if (type == ItemType.ITEM_WEAPON){
|
val itemId = item.getItemId();
|
||||||
if(!getUnlockedWeapon().contains(item.getItemId())){
|
switch (itemData.getItemType()) {
|
||||||
getUnlockedWeapon().add(item.getItemId());
|
case ITEM_WEAPON -> {
|
||||||
var codexItem = GameData.getCodexWeaponDataIdMap().get(item.getItemId());
|
Optional.ofNullable(GameData.getCodexWeaponDataIdMap().get(itemId))
|
||||||
if(codexItem != null){
|
.ifPresent(codexData -> {
|
||||||
player.save();
|
if (this.getUnlockedWeapon().add(itemId)) {
|
||||||
this.player.sendPacket(new PacketCodexDataUpdateNotify(2, codexItem.getId()));
|
this.player.save();
|
||||||
}
|
this.player.sendPacket(new PacketCodexDataUpdateNotify(2, codexData.getId()));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
case ITEM_MATERIAL -> {
|
||||||
else if(type == ItemType.ITEM_MATERIAL){
|
switch (itemData.getMaterialType()) {
|
||||||
if( item.getItemData().getMaterialType() == MaterialType.MATERIAL_FOOD ||
|
// Is this check even needed?
|
||||||
item.getItemData().getMaterialType() == MaterialType.MATERIAL_WIDGET||
|
case MATERIAL_FOOD, MATERIAL_WIDGET, MATERIAL_EXCHANGE, MATERIAL_AVATAR_MATERIAL, MATERIAL_NOTICE_ADD_HP -> {
|
||||||
item.getItemData().getMaterialType() == MaterialType.MATERIAL_EXCHANGE||
|
Optional.ofNullable(GameData.getCodexMaterialDataIdMap().get(itemId))
|
||||||
item.getItemData().getMaterialType() == MaterialType.MATERIAL_AVATAR_MATERIAL||
|
.ifPresent(codexData -> {
|
||||||
item.getItemData().getMaterialType() == MaterialType.MATERIAL_NOTICE_ADD_HP){
|
if (this.getUnlockedMaterial().add(itemId)) {
|
||||||
if (!getUnlockedMaterial().contains(item.getItemId())) {
|
this.player.save();
|
||||||
var codexMaterial = GameData.getCodexMaterialDataIdMap().get(item.getItemId());
|
this.player.sendPacket(new PacketCodexDataUpdateNotify(4, codexData.getId()));
|
||||||
if (codexMaterial != null) {
|
}
|
||||||
getUnlockedMaterial().add(item.getItemId());
|
});
|
||||||
player.save();
|
|
||||||
this.player.sendPacket(new PacketCodexDataUpdateNotify(4, codexMaterial.getId()));
|
|
||||||
}
|
}
|
||||||
|
default -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
case ITEM_RELIQUARY -> {
|
||||||
else if(type == ItemType.ITEM_RELIQUARY) {
|
val reliquaryId = (itemId/10) * 10; // Normalize to 0-substat form
|
||||||
if(!getUnlockedReliquary().contains(item.getItemId())){
|
if (this.getUnlockedReliquary().add(reliquaryId))
|
||||||
getUnlockedReliquary().add(item.getItemId());
|
checkUnlockedSuits(reliquaryId);
|
||||||
checkUnlockedSuits(item);
|
|
||||||
}
|
}
|
||||||
|
default -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkAnimal(GameEntity target, CodexAnimalData.CodexAnimalUnlockCondition condition){
|
public void checkAnimal(GameEntity target, CodexAnimalData.CountType countType){
|
||||||
if(target instanceof EntityMonster){
|
if (target instanceof EntityMonster) {
|
||||||
var monsterId = ((EntityMonster)target).getMonsterData().getId();
|
val monsterId = ((EntityMonster) target).getMonsterData().getId();
|
||||||
var codexAnimal = GameData.getCodexAnimalDataMap().get(monsterId);
|
val codexAnimal = GameData.getCodexAnimalDataMap().get(monsterId);
|
||||||
|
if (codexAnimal == null) return;
|
||||||
|
|
||||||
|
val animalCountType = codexAnimal.getCountType();
|
||||||
|
if (animalCountType != countType && animalCountType != null) return;
|
||||||
|
|
||||||
|
this.getUnlockedAnimal().merge(monsterId, 1, (i, j) -> i + 1);
|
||||||
|
|
||||||
if(!getUnlockedAnimal().containsKey(monsterId)) {
|
|
||||||
if (codexAnimal != null) {
|
|
||||||
if(codexAnimal.getUnlockCondition() == condition || codexAnimal.getUnlockCondition() == null){
|
|
||||||
getUnlockedAnimal().put(monsterId, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
getUnlockedAnimal().put(monsterId, getUnlockedAnimal().get(monsterId) + 1);
|
|
||||||
}
|
|
||||||
player.save();
|
player.save();
|
||||||
this.player.sendPacket(new PacketCodexDataUpdateNotify(3, monsterId));
|
this.player.sendPacket(new PacketCodexDataUpdateNotify(3, monsterId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkUnlockedSuits(GameItem item){
|
public void checkUnlockedSuits(int reliquaryId){
|
||||||
int reliquaryId = item.getItemId();
|
GameData.getcodexReliquaryArrayList().stream()
|
||||||
Optional<CodexReliquaryData> excelReliquarySuitList = GameData.getcodexReliquaryArrayList().stream().filter(
|
.filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId()))
|
||||||
x -> x.getCupId() == reliquaryId
|
.filter(x -> x.containsId(reliquaryId))
|
||||||
|| x.getLeatherId() == reliquaryId
|
.filter(x -> this.getUnlockedReliquary().containsAll(x.getIds()))
|
||||||
|| x.getCapId() == reliquaryId
|
.forEach(x -> {
|
||||||
|| x.getFlowerId() == reliquaryId
|
int id = x.getId();
|
||||||
|| x.getSandId() == reliquaryId
|
this.getUnlockedReliquarySuitCodex().add(id);
|
||||||
).findFirst();
|
this.player.save();
|
||||||
if(excelReliquarySuitList.isPresent()) {
|
this.player.sendPacket(new PacketCodexDataUpdateNotify(8, id));
|
||||||
var excelReliquarySuit = excelReliquarySuitList.get();
|
});
|
||||||
if(!getUnlockedReliquarySuitCodex().contains(excelReliquarySuit.getId())){
|
|
||||||
if(
|
|
||||||
getUnlockedReliquary().contains(excelReliquarySuit.getCupId()) &&
|
|
||||||
getUnlockedReliquary().contains(excelReliquarySuit.getLeatherId()) &&
|
|
||||||
getUnlockedReliquary().contains(excelReliquarySuit.getCapId()) &&
|
|
||||||
getUnlockedReliquary().contains(excelReliquarySuit.getFlowerId()) &&
|
|
||||||
getUnlockedReliquary().contains(excelReliquarySuit.getSandId())
|
|
||||||
){
|
|
||||||
getUnlockedReliquarySuitCodex().add(excelReliquarySuit.getId());
|
|
||||||
player.save();
|
|
||||||
this.player.sendPacket(new PacketCodexDataUpdateNotify(8, excelReliquarySuit.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getUnlockedWeapon() {
|
@Deprecated // Maybe remove this if we ever stop caring about older dbs
|
||||||
return unlockedWeapon;
|
private void fixReliquaries() {
|
||||||
}
|
// Migrate older database entries which were using non-canonical forms of itemIds
|
||||||
|
val newReliquaries = new HashSet<Integer>();
|
||||||
|
this.unlockedReliquary.forEach(i -> newReliquaries.add((i/10)*10));
|
||||||
|
this.unlockedReliquary = newReliquaries;
|
||||||
|
|
||||||
public Map<Integer, Integer> getUnlockedAnimal() {
|
GameData.getcodexReliquaryArrayList().stream()
|
||||||
return unlockedAnimal;
|
.filter(x -> !this.getUnlockedReliquarySuitCodex().contains(x.getId()))
|
||||||
|
.filter(x -> this.getUnlockedReliquary().containsAll(x.getIds()))
|
||||||
|
.forEach(x -> this.getUnlockedReliquarySuitCodex().add(x.getId()));
|
||||||
|
this.player.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getUnlockedMaterial() {
|
|
||||||
return unlockedMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getUnlockedBook() {
|
|
||||||
return unlockedBook;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getUnlockedTip() {
|
|
||||||
return unlockedTip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getUnlockedView() {
|
|
||||||
return unlockedView;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getUnlockedReliquary() {
|
|
||||||
return unlockedReliquary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getUnlockedReliquarySuitCodex() {
|
|
||||||
return unlockedReliquarySuitCodex;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -312,10 +312,10 @@ public class Scene {
|
|||||||
if (attacker instanceof EntityClientGadget gadgetAttacker) {
|
if (attacker instanceof EntityClientGadget gadgetAttacker) {
|
||||||
var clientGadgetOwner = getEntityById(gadgetAttacker.getOwnerEntityId());
|
var clientGadgetOwner = getEntityById(gadgetAttacker.getOwnerEntityId());
|
||||||
if (clientGadgetOwner instanceof EntityAvatar) {
|
if (clientGadgetOwner instanceof EntityAvatar) {
|
||||||
((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
|
((EntityClientGadget) attacker).getOwner().getCodex().checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL);
|
||||||
}
|
}
|
||||||
} else if (attacker instanceof EntityAvatar avatarAttacker) {
|
} else if (attacker instanceof EntityAvatar avatarAttacker) {
|
||||||
avatarAttacker.getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
|
avatarAttacker.getPlayer().getCodex().checkAnimal(target, CodexAnimalData.CountType.CODEX_COUNT_TYPE_KILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user