package net.fretux.skillengine.api; import net.fretux.skillengine.SkillEngine; import net.fretux.skillengine.capability.PlayerSkillData; import net.fretux.skillengine.capability.SkillEngineCapabilities; import net.fretux.skillengine.client.ClientSkillEngineBridge; import net.fretux.skillengine.events.SkillPointsChangedEvent; import net.fretux.skillengine.skilltree.AbilityNode; import net.fretux.skillengine.skilltree.AbilityNodeRegistry; import net.fretux.skillengine.skilltree.SkillLogic; import net.fretux.skillengine.skilltree.SkillNode; import net.fretux.skillengine.skilltree.SkillNodeRegistry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.loading.FMLEnvironment; import java.util.List; import java.util.Set; public final class SkillEngineAPI { private SkillEngineAPI() {} public static ResourceLocation id(String path) { return ResourceLocation.fromNamespaceAndPath(SkillEngine.MODID, path); } public static ResourceLocation rl(String namespace, String path) { return ResourceLocation.fromNamespaceAndPath(namespace, path); } public static SkillNode getSkillNode(ResourceLocation id) { return SkillNodeRegistry.get(id); } public static AbilityNode getAbilityNode(ResourceLocation id) { return AbilityNodeRegistry.get(id); } public static boolean hasSkillNode(ResourceLocation id) { return SkillNodeRegistry.get(id) != null; } public static boolean hasAbilityNode(ResourceLocation id) { return AbilityNodeRegistry.get(id) != null; } public static List getAllSkillNodes() { return List.copyOf(SkillNodeRegistry.all()); } public static List getAllAbilityNodes() { return List.copyOf(AbilityNodeRegistry.all()); } public static PlayerSkillData getPlayerData(Player player) { return player.getCapability(SkillEngineCapabilities.PLAYER_SKILLS).orElse(null); } public static int getSkillPoints(Player player) { PlayerSkillData data = getPlayerData(player); return data != null ? data.getSkillPoints() : 0; } public static void addSkillPoints(Player player, int amount) { PlayerSkillData data = getPlayerData(player); if (data != null) { data.addSkillPoints(amount); if (amount != 0) { MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, Math.abs(amount), amount > 0 ? SkillPointsChangedEvent.Reason.GAINED : SkillPointsChangedEvent.Reason.SPENT, null )); } } } public static boolean consumeSkillPoints(Player player, int amount) { if (amount <= 0) return false; PlayerSkillData data = getPlayerData(player); if (data != null && data.getSkillPoints() >= amount) { data.addSkillPoints(-amount); MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, amount, SkillPointsChangedEvent.Reason.SPENT, null )); return true; } return false; } public static Set getUnlockedSkillNodes(Player player) { PlayerSkillData data = getPlayerData(player); return data != null ? data.getUnlockedNodes() : Set.of(); } public static boolean isSkillUnlocked(Player player, ResourceLocation id) { PlayerSkillData data = getPlayerData(player); return data != null && data.isUnlocked(id); } public static boolean unlockSkill(Player player, ResourceLocation id) { PlayerSkillData data = getPlayerData(player); if (data == null) return false; SkillNode node = SkillNodeRegistry.get(id); if (node == null) return false; List unlockPlan = SkillLogic.getUnlockPlan(data, player, node).orElse(null); if (unlockPlan == null) return false; for (SkillNode plannedNode : unlockPlan) { data.unlockNode(plannedNode); if (plannedNode.getCost() > 0) { MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, plannedNode.getCost(), SkillPointsChangedEvent.Reason.SPENT, plannedNode.getId() )); } } return true; } public static boolean refundSkill(Player player, ResourceLocation id) { PlayerSkillData data = getPlayerData(player); SkillNode node = SkillNodeRegistry.get(id); if (data == null || node == null || !data.refundNode(id)) return false; MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, node.getCost(), SkillPointsChangedEvent.Reason.REFUNDED, id )); return true; } public static int refundBranch(Player player, ResourceLocation rootId) { PlayerSkillData data = getPlayerData(player); if (data == null) return 0; int refunded = data.refundBranch(rootId); if (refunded > 0) { MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, refunded, SkillPointsChangedEvent.Reason.REFUNDED, rootId )); } return refunded; } public static int resetSkills(Player player) { PlayerSkillData data = getPlayerData(player); if (data == null) return 0; int refunded = data.resetAllNodesPreserveEarnedPoints(); if (refunded > 0) { MinecraftForge.EVENT_BUS.post(new SkillPointsChangedEvent( player, refunded, SkillPointsChangedEvent.Reason.REFUNDED, null )); } return refunded; } public static boolean isAbilityUnlocked(Player player, ResourceLocation id) { PlayerSkillData data = getPlayerData(player); return data != null && data.isAbilityUnlocked(id); } public static Set getUnlockedAbilities(Player player) { PlayerSkillData data = getPlayerData(player); return data != null ? data.getUnlockedAbilities() : Set.of(); } public static boolean unlockAbility(Player player, ResourceLocation id) { PlayerSkillData data = getPlayerData(player); if (data == null) return false; AbilityNode ability = AbilityNodeRegistry.get(id); if (ability == null) return false; data.unlockAbility(ability); return true; } public static void bindAbility(Player player, int slot, ResourceLocation abilityId) { PlayerSkillData data = getPlayerData(player); if (data == null) return; data.bindAbility(slot, abilityId); } public static ResourceLocation getAbilityInSlot(Player player, int slot) { PlayerSkillData data = getPlayerData(player); return data != null ? data.getAbilityInSlot(slot) : null; } public static ResourceLocation[] getAbilitySlots(Player player) { PlayerSkillData data = getPlayerData(player); return data != null ? data.getAbilitySlots() : new ResourceLocation[3]; } public static boolean clientHasSkill(ResourceLocation id) { if (FMLEnvironment.dist != Dist.CLIENT) { return false; } return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> ClientSkillEngineBridge.clientHasSkill(id)); } public static int clientGetAbilitySlot(ResourceLocation id) { if (FMLEnvironment.dist != Dist.CLIENT) { return -1; } return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> ClientSkillEngineBridge.clientGetAbilitySlot(id)); } public static ResourceLocation[] clientGetAbilitySlots() { if (FMLEnvironment.dist != Dist.CLIENT) { return new ResourceLocation[3]; } return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> ClientSkillEngineBridge::clientGetAbilitySlots); } }