diff --git a/src/main/java/net/fretux/skillengine/client/SkilltreeScreen.java b/src/main/java/net/fretux/skillengine/client/SkilltreeScreen.java index b846ac8..7c69d9e 100644 --- a/src/main/java/net/fretux/skillengine/client/SkilltreeScreen.java +++ b/src/main/java/net/fretux/skillengine/client/SkilltreeScreen.java @@ -59,6 +59,14 @@ public class SkilltreeScreen extends Screen { if (button == 0) { SkillNode clicked = findNodeAt(mouseX, mouseY); if (clicked != null) { + boolean lockedByExclusivity = clicked.getExclusiveWith().stream() + .anyMatch(SkilltreeClientState::isUnlocked); + if (lockedByExclusivity) { + Minecraft.getInstance().player.playSound( + net.minecraft.sounds.SoundEvents.VILLAGER_NO, 1f, 1f + ); + return true; + } if (SkilltreeClientState.isUnlocked(clicked.getId())) { return true; } @@ -70,7 +78,6 @@ public class SkilltreeScreen extends Screen { lastMouseX = mouseX; lastMouseY = mouseY; } - return super.mouseClicked(mouseX, mouseY, button); } @@ -162,6 +169,11 @@ public class SkilltreeScreen extends Screen { int r = 12; boolean unlocked = SkilltreeClientState.isUnlocked(node.getId()); int color = unlocked ? 0xFF44CC44 : 0xFF444444; + boolean lockedByExclusivity = node.getExclusiveWith().stream() + .anyMatch(SkilltreeClientState::isUnlocked); + if (lockedByExclusivity) { + color = 0xFFCC3333; + } if (node == hoveredNode) color = 0xFF777777; if (node == selectedNode) color = 0xFF999933; gfx.fill(pos[0] - r, pos[1] - r, pos[0] + r, pos[1] + r, color); @@ -197,6 +209,9 @@ public class SkilltreeScreen extends Screen { } private void renderOverlay(GuiGraphics gfx, SkillNode node) { + boolean lockedByExclusivity = node.getExclusiveWith().stream() + .anyMatch(SkilltreeClientState::isUnlocked); + if (lockedByExclusivity) return; int w = 240; int h = 180; int x = (width - w) / 2; diff --git a/src/main/java/net/fretux/skillengine/network/ServerboundUnlockNodePacket.java b/src/main/java/net/fretux/skillengine/network/ServerboundUnlockNodePacket.java index ff08e2d..88ebcab 100644 --- a/src/main/java/net/fretux/skillengine/network/ServerboundUnlockNodePacket.java +++ b/src/main/java/net/fretux/skillengine/network/ServerboundUnlockNodePacket.java @@ -48,8 +48,6 @@ public class ServerboundUnlockNodePacket { if (SkillLogic.canUnlock(data, player, node)) { data.unlockNode(node); SkillEngine.LOGGER.info("Node {} unlocked for {}", msg.nodeId, player.getGameProfile().getName()); - - // Send client an immediate update about the unlocked node and the new remaining points PacketHandler.CHANNEL.send( PacketDistributor.PLAYER.with(() -> player), new ClientboundNodeUnlockedPacket(node.getId(), data.getSkillPoints()) diff --git a/src/main/java/net/fretux/skillengine/skilltree/SkillLogic.java b/src/main/java/net/fretux/skillengine/skilltree/SkillLogic.java index 5807b44..223e47c 100644 --- a/src/main/java/net/fretux/skillengine/skilltree/SkillLogic.java +++ b/src/main/java/net/fretux/skillengine/skilltree/SkillLogic.java @@ -17,6 +17,11 @@ public class SkillLogic { for (ResourceLocation neighborId : node.getLinks()) { if (data.isUnlocked(neighborId)) return true; } + for (ResourceLocation excl : node.getExclusiveWith()) { + if (data.isUnlocked(excl)) { + return false; + } + } return false; } public static boolean meetsAscendPrerequisites(Player player, SkillNode node) { diff --git a/src/main/java/net/fretux/skillengine/skilltree/SkillNode.java b/src/main/java/net/fretux/skillengine/skilltree/SkillNode.java index eb0570a..d9c1fc7 100644 --- a/src/main/java/net/fretux/skillengine/skilltree/SkillNode.java +++ b/src/main/java/net/fretux/skillengine/skilltree/SkillNode.java @@ -18,6 +18,7 @@ public class SkillNode { private final List tags; private final ResourceLocation icons; private final Map prereqAttributes; + private final List exclusiveWith; public SkillNode(ResourceLocation id, Component title, @@ -27,7 +28,8 @@ public class SkillNode { List links, List tags, ResourceLocation icons, - Map prereqAttributes) { + Map prereqAttributes, + List exclusiveWith){ this.id = id; this.title = title; @@ -39,6 +41,7 @@ public class SkillNode { this.tags = List.copyOf(tags); this.icons = icons; this.prereqAttributes = Map.copyOf(prereqAttributes); + this.exclusiveWith = List.copyOf(exclusiveWith); } public ResourceLocation getId() { @@ -81,6 +84,10 @@ public class SkillNode { return prereqAttributes; } + public List getExclusiveWith() { + return exclusiveWith; + } + public boolean isRoot() { return links.isEmpty(); } diff --git a/src/main/java/net/fretux/skillengine/skilltree/SkillNodeLoader.java b/src/main/java/net/fretux/skillengine/skilltree/SkillNodeLoader.java index 43ea4fd..63201cf 100644 --- a/src/main/java/net/fretux/skillengine/skilltree/SkillNodeLoader.java +++ b/src/main/java/net/fretux/skillengine/skilltree/SkillNodeLoader.java @@ -61,6 +61,11 @@ public class SkillNodeLoader extends SimpleJsonResourceReloadListener { prereqAttributes.put(entry.getKey(), entry.getValue().getAsInt()); } } + List exclusiveWith = new ArrayList<>(); + if (obj.has("exclusive_with")) { + obj.getAsJsonArray("exclusive_with").forEach(e -> + exclusiveWith.add(new ResourceLocation(e.getAsString()))); + } SkillNode node = new SkillNode( nodeId, Component.literal(title), @@ -70,8 +75,10 @@ public class SkillNodeLoader extends SimpleJsonResourceReloadListener { links, tags, icons, - prereqAttributes + prereqAttributes, + exclusiveWith ); + SkillNodeRegistry.put(node); }); SkillEngine.LOGGER.info("Loaded {} skill nodes", SkillNodeRegistry.all().size());