Simply implement achievement system and add achievement command (#2068)

* Implement achievement system

* Update src/main/java/emu/grasscutter/command/commands/AchievementCommand.java

Co-authored-by: Der Chien <b03902015@ntu.edu.tw>

* fix: redundant codes

* fix: redundant codes

* Update language files

---------

Co-authored-by: Der Chien <b03902015@ntu.edu.tw>
This commit is contained in:
hamusuke
2023-02-26 14:14:27 +09:00
committed by GitHub
parent 51479e2abd
commit 3ab3d5bc04
35 changed files with 7418 additions and 1 deletions

View File

@@ -41,6 +41,8 @@ public class GameData {
// ExcelConfigs
@Getter private static final ArrayList<CodexReliquaryData> codexReliquaryArrayList = new ArrayList<>();
private static final Int2ObjectMap<AchievementData> achievementDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<AchievementGoalData> achievementGoalDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<ActivityData> activityDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<ActivityShopData> activityShopDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<ActivityWatcherData> activityWatcherDataMap = new Int2ObjectOpenHashMap<>();
@@ -233,4 +235,9 @@ public class GameData {
return shopGoods;
}
public static Int2ObjectMap<AchievementData> getAchievementDataMap() {
AchievementData.divideIntoGroups();
return achievementDataMap;
}
}

View File

@@ -0,0 +1,96 @@
package emu.grasscutter.data.excels;
import com.github.davidmoten.guavamini.Lists;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import lombok.Getter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
@Getter
@ResourceType(name = "AchievementExcelConfigData.json")
public class AchievementData extends GameResource {
private static final AtomicBoolean isDivided = new AtomicBoolean();
private int goalId;
private int preStageAchievementId;
private Set<Integer> groupAchievementIdList = new HashSet<>();
private boolean isParent;
private long titleTextMapHash;
private long descTextMapHash;
private int finishRewardId;
private boolean isDeleteWatcherAfterFinish;
private int id;
private BattlePassMissionData.TriggerConfig triggerConfig;
private int progress;
private boolean isDisuse;
public boolean hasPreStageAchievement() {
return this.preStageAchievementId != 0;
}
public boolean hasGroupAchievements() {
return !this.groupAchievementIdList.isEmpty();
}
public boolean isUsed() {
return !this.isDisuse;
}
public Set<Integer> getGroupAchievementIdList() {
return this.groupAchievementIdList.stream().collect(Collectors.toUnmodifiableSet());
}
public Set<Integer> getExcludedGroupAchievementIdList() {
return this.groupAchievementIdList.stream().filter(integer -> integer != this.getId()).collect(Collectors.toUnmodifiableSet());
}
public static void divideIntoGroups() {
if (isDivided.get()) {
return;
}
isDivided.set(true);
var map = GameData.getAchievementDataMap();
var achievementDataList = map.values().stream().filter(AchievementData::isUsed).toList();
for (var data : achievementDataList) {
if (!data.hasPreStageAchievement() || data.hasGroupAchievements()) {
continue;
}
List<Integer> ids = Lists.newArrayList();
int parentId = data.getId();
while (true) {
var next = map.get(parentId + 1);
if (next == null || parentId != next.getPreStageAchievementId()) {
break;
}
parentId++;
}
map.get(parentId).isParent = true;
while (true) {
ids.add(parentId);
var previous = map.get(--parentId);
if (previous == null) {
break;
} else if (!previous.hasPreStageAchievement()) {
ids.add(parentId);
break;
}
}
for (int i : ids) {
map.get(i).groupAchievementIdList.addAll(ids);
}
}
map.values().stream().filter(a -> !a.hasGroupAchievements() && a.isUsed()).forEach(a -> a.isParent = true);
}
}

View File

@@ -0,0 +1,13 @@
package emu.grasscutter.data.excels;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "AchievementGoalExcelConfigData.json")
public class AchievementGoalData extends GameResource {
private int id;
private long nameTextMapHash;
private int finishRewardId;
}