Files
SkillEngine/src/main/java/net/fretux/skillengine/skilltree/SkillLogic.java
T

114 lines
3.9 KiB
Java

package net.fretux.skillengine.skilltree;
import net.fretux.skillengine.api.PrerequisiteProviderRegistry;
import net.fretux.skillengine.capability.PlayerSkillData;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class SkillLogic {
public static boolean canUnlock(PlayerSkillData data, Player player, SkillNode node) {
return getUnlockPlan(data, player, node).isPresent();
}
public static Optional<List<SkillNode>> getUnlockPlan(PlayerSkillData data, Player player, SkillNode node) {
if (data == null || player == null || node == null || data.isUnlocked(node.getId())) {
return Optional.empty();
}
List<SkillNode> plan = new ArrayList<>();
Set<ResourceLocation> planned = new HashSet<>();
Set<ResourceLocation> visiting = new HashSet<>();
if (!collectUnlockPlan(data, player, node, plan, planned, visiting)) {
return Optional.empty();
}
int totalCost = 0;
for (SkillNode plannedNode : plan) {
totalCost += plannedNode.getCost();
}
if (data.getSkillPoints() < totalCost) {
return Optional.empty();
}
return Optional.of(List.copyOf(plan));
}
public static boolean meetsAscendPrerequisites(Player player, SkillNode node) {
if (node.getPrereqAttributes().isEmpty()) return true;
if (!(player instanceof ServerPlayer serverPlayer)) return true;
for (Map.Entry<String, Integer> req : node.getPrereqAttributes().entrySet()) {
if (!PrerequisiteProviderRegistry.meets(serverPlayer, node, req.getKey(), req.getValue())) {
return false;
}
}
return true;
}
private static boolean collectUnlockPlan(PlayerSkillData data,
Player player,
SkillNode node,
List<SkillNode> plan,
Set<ResourceLocation> planned,
Set<ResourceLocation> visiting) {
ResourceLocation id = node.getId();
if (data.isUnlocked(id) || planned.contains(id)) {
return true;
}
if (!visiting.add(id)) {
return false;
}
if (!meetsAscendPrerequisites(player, node) || conflictsWithUnlocked(data, node)) {
visiting.remove(id);
return false;
}
for (ResourceLocation parentId : node.getLinks()) {
if (data.isUnlocked(parentId)) {
continue;
}
SkillNode parent = SkillNodeRegistry.get(parentId);
if (parent == null || !collectUnlockPlan(data, player, parent, plan, planned, visiting)) {
visiting.remove(id);
return false;
}
}
if (conflictsWithPlanned(node, planned)) {
visiting.remove(id);
return false;
}
visiting.remove(id);
planned.add(id);
plan.add(node);
return true;
}
private static boolean conflictsWithUnlocked(PlayerSkillData data, SkillNode node) {
for (ResourceLocation excl : node.getExclusiveWith()) {
if (data.isUnlocked(excl)) {
return true;
}
}
return false;
}
private static boolean conflictsWithPlanned(SkillNode node, Set<ResourceLocation> planned) {
for (ResourceLocation excl : node.getExclusiveWith()) {
if (planned.contains(excl)) {
return true;
}
}
return false;
}
}