From e27f7361672f179db13135c52962cc5025dc393a Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:10:23 +0300 Subject: [PATCH 1/7] Add files via upload --- mods/guikit-fabric/build.gradle | 55 +++++++++ mods/guikit-fabric/settings.gradle | 9 ++ .../java/net/runtoolkit/guikit/Guikit.java | 17 +++ .../net/runtoolkit/guikit/cond/Condition.java | 27 +++++ .../guikit/cond/ConditionChecker.java | 99 ++++++++++++++++ .../runtoolkit/guikit/menu/GuikitMenu.java | 108 ++++++++++++++++++ .../guikit/menu/GuikitMenuDefinition.java | 28 +++++ .../guikit/menu/GuikitMenuDefinitions.java | 26 +++++ .../guikit/menu/GuikitMenuOpening.java | 18 +++ .../runtoolkit/guikit/menu/GuikitMenus.java | 37 ++++++ .../net/runtoolkit/guikit/menu/Payment.java | 45 ++++++++ .../src/main/resources/fabric.mod.json | 18 +++ 12 files changed, 487 insertions(+) create mode 100644 mods/guikit-fabric/build.gradle create mode 100644 mods/guikit-fabric/settings.gradle create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/Guikit.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/Condition.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/ConditionChecker.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenu.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinition.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinitions.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuOpening.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenus.java create mode 100644 mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/Payment.java create mode 100644 mods/guikit-fabric/src/main/resources/fabric.mod.json diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle new file mode 100644 index 00000000..e9532a42 --- /dev/null +++ b/mods/guikit-fabric/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'fabric-loom' version '1.15.0' + id 'maven-publish' +} + +version = project.mod_version +group = project.maven_group + +repositories { + mavenCentral() +} + +dependencies { + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings loom.officialMojangMappings() + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +} + +processResources { + inputs.property "version", project.version + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +java { + withSourcesJar() + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 + toolchain.languageVersion = JavaLanguageVersion.of(25) +} + +// ---- Custom tasks ---- + +tasks.register('printModInfo') { + group = 'guikit' + description = 'Prints mod id, version and target Minecraft version.' + doLast { + println "mod=${project.name} version=${project.mod_version} minecraft=${project.minecraft_version}" + } +} + +tasks.register('checkLicenses') { + group = 'guikit' + description = 'Fails the build if NOTICE.md or a bundled third-party license is missing.' + doLast { + def notice = file("${projectDir}/NOTICE.md") + if (!notice.exists()) { + throw new GradleException("NOTICE.md is missing — third-party attribution (macroEngine / StringLib / PlayerAction) must ship with every build.") + } + } +} + +build.dependsOn checkLicenses diff --git a/mods/guikit-fabric/settings.gradle b/mods/guikit-fabric/settings.gradle new file mode 100644 index 00000000..dced839d --- /dev/null +++ b/mods/guikit-fabric/settings.gradle @@ -0,0 +1,9 @@ +pluginManagement { + repositories { + maven { url 'https://maven.fabricmc.net/' } + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = 'guikit' diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/Guikit.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/Guikit.java new file mode 100644 index 00000000..9352a493 --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/Guikit.java @@ -0,0 +1,17 @@ +package net.runtoolkit.guikit; + +import net.fabricmc.api.ModInitializer; +import net.runtoolkit.guikit.menu.GuikitMenus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Guikit implements ModInitializer { + public static final String MOD_ID = "guikit"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + + @Override + public void onInitialize() { + GuikitMenus.register(); + LOGGER.info("guikit loaded (Fabric port, server-authoritative menus)"); + } +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/Condition.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/Condition.java new file mode 100644 index 00000000..1ef7f6e0 --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/Condition.java @@ -0,0 +1,27 @@ +package net.runtoolkit.guikit.cond; + +import net.minecraft.resources.ResourceLocation; + +import java.util.List; + +/** + * Java port of storage guikit:cond {type:"...", ..., not:1b}. + * Every variant carries its own `not`, same as the datapack. Unlike the datapack, `not` is + * applied uniformly here (including on all/any) -- the datapack's README documented an + * inconsistent quirk on leaf types with an unknown key ("known quirk"); that quirk is not + * reproduced here, since nothing depended on it deliberately. + */ +public sealed interface Condition { + boolean not(); + + record Score(String objective, Integer min, Integer max, boolean not) implements Condition {} + record ItemCount(ResourceLocation item, int min, boolean not) implements Condition {} + record Tag(String tag, boolean not) implements Condition {} + record Gamemode(String mode, boolean not) implements Condition {} + record Advancement(ResourceLocation advancement, boolean not) implements Condition {} + record PredicateCond(ResourceLocation predicate, boolean not) implements Condition {} + record Level(Integer min, Integer max, boolean not) implements Condition {} + record Dimension(ResourceLocation dimension, boolean not) implements Condition {} + record All(List of, boolean not) implements Condition {} + record Any(List of, boolean not) implements Condition {} +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/ConditionChecker.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/ConditionChecker.java new file mode 100644 index 00000000..c865a902 --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/cond/ConditionChecker.java @@ -0,0 +1,99 @@ +package net.runtoolkit.guikit.cond; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; + +/** + * Java port of guikit:cond/check and the cond/t_*.mcfunction chain. + * + * UNVERIFIED, higher risk than the rest of this scaffold: + * - Score: player.getServer().getScoreboard() access pattern (getOrCreatePlayerScore / + * ScoreHolder / ScoreAccess) has changed shape across recent versions. Check against + * your exact Mojang-mapped Scoreboard class before relying on this. + * - Advancement: server.getAdvancements().get(ResourceLocation) -> AdvancementHolder, then + * player.getAdvancements().getOrStartProgress(holder).isDone() -- verify the exact method + * names for 26.3, this area of the API moves often. + * Everything else here (tag, gamemode, level, dimension, item count) is on stable, + * long-unchanged API and is lower risk. + */ +public final class ConditionChecker { + private ConditionChecker() {} + + public static boolean check(ServerPlayer player, Condition cond) { + boolean result = evaluate(player, cond); + return cond.not() != result; // XOR + } + + private static boolean evaluate(ServerPlayer player, Condition cond) { + return switch (cond) { + case Condition.Score c -> checkScore(player, c); + case Condition.ItemCount c -> countItem(player, c.item()) >= c.min(); + case Condition.Tag c -> player.getTags().contains(c.tag()); + case Condition.Gamemode c -> { + GameType wanted = switch (c.mode()) { + case "survival" -> GameType.SURVIVAL; + case "creative" -> GameType.CREATIVE; + case "adventure" -> GameType.ADVENTURE; + case "spectator" -> GameType.SPECTATOR; + default -> null; + }; + yield wanted != null && player.gameMode.getGameModeForPlayer() == wanted; + } + case Condition.Level c -> { + int level = player.experienceLevel; + boolean min = c.min() == null || level >= c.min(); + boolean max = c.max() == null || level <= c.max(); + yield min && max; + } + case Condition.Dimension c -> player.level().dimension().location().equals(c.dimension()); + case Condition.Advancement c -> checkAdvancement(player, c); + case Condition.PredicateCond c -> checkPredicate(player, c); + case Condition.All c -> { + for (Condition child : c.of()) { + if (!check(player, child)) yield false; + } + yield true; // empty list passes, same as the datapack + } + case Condition.Any c -> { + for (Condition child : c.of()) { + if (check(player, child)) yield true; + } + yield false; // no child passed (including the empty-list case), same as the datapack + } + }; + } + + private static boolean checkScore(ServerPlayer player, Condition.Score c) { + MinecraftServer server = player.getServer(); + if (server == null) return false; + // UNVERIFIED -- see class javadoc. Sketch only: + // var score = server.getScoreboard().getOrCreatePlayerScore(player, objective); + // int value = score.get(); + throw new UnsupportedOperationException( + "guikit: wire this to your Scoreboard API shape before use -- see ConditionChecker javadoc"); + } + + private static int countItem(ServerPlayer player, net.minecraft.resources.ResourceLocation item) { + int total = 0; + for (ItemStack stack : player.getInventory().items) { + if (!stack.isEmpty() && stack.getItem().builtInRegistryHolder().key().location().equals(item)) { + total += stack.getCount(); + } + } + return total; + } + + private static boolean checkAdvancement(ServerPlayer player, Condition.Advancement c) { + // UNVERIFIED -- see class javadoc. + throw new UnsupportedOperationException( + "guikit: wire this to your Advancements API shape before use -- see ConditionChecker javadoc"); + } + + private static boolean checkPredicate(ServerPlayer player, Condition.PredicateCond c) { + // UNVERIFIED -- LootContext-based predicate evaluation against player. + throw new UnsupportedOperationException( + "guikit: wire this to your predicate-evaluation API shape before use -- see ConditionChecker javadoc"); + } +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenu.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenu.java new file mode 100644 index 00000000..20565475 --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenu.java @@ -0,0 +1,108 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +/** + * Fabric port of the whole chest_minecart mechanic. + * + * datapack: widget items are stamped onto a chest_minecart. Left-click moves the item OUT + * of the cart into the player's inventory; #guikit:fill re-runs to refill the empty slot; + * clear detects the item that left, the handler runs, item removed, redraw if dirty. + * A second function (internal/follow) keeps the cart teleporting onto the owning player + * every tick so it can't be walked away from or opened by someone else. + * + * Fabric: none of that exists. AbstractContainerMenu#clicked is the actual click trigger. + * We intercept it for the container's own slots (0..slots()-1), run the definition's + * onClick directly, and never call the vanilla pickup/move logic -- the item never leaves + * the slot, so there is nothing to "clear" or refill, and nothing to keep server-side state + * in sync with (no follow-teleport, no redraw-every-tick). Player-inventory slots (the + * bottom 36) keep normal vanilla behaviour so players can still manage their own items + * while a menu is open, matching what the datapack did by never touching the player's real + * inventory in the first place. + */ +public class GuikitMenu extends AbstractContainerMenu { + private static final int PLAYER_INV_SIZE = 36; + + private final SimpleContainer container; + private final GuikitMenuDefinition definition; + private final ServerPlayer serverPlayer; // null on the client + private int page = 0; + + public GuikitMenu(int syncId, Inventory playerInventory, GuikitMenuOpening opening) { + super(GuikitMenus.GUIKIT_MENU, syncId); + this.definition = GuikitMenuDefinitions.get(opening.menuId()); + if (this.definition == null) { + throw new IllegalStateException("guikit: no menu registered for " + opening.menuId() + + " (was #guikit:register equivalent -- call GuikitMenuDefinitions.register first)"); + } + this.page = opening.page(); + this.container = new SimpleContainer(definition.slots()); + this.serverPlayer = playerInventory.player instanceof ServerPlayer sp ? sp : null; + + int rows = definition.slots() / 9; + for (int row = 0; row < rows; row++) { + for (int col = 0; col < 9; col++) { + int index = row * 9 + col; + addSlot(new Slot(container, index, 8 + col * 18, 18 + row * 18)); + } + } + int invY = 18 + rows * 18 + 14; + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 9; col++) { + addSlot(new Slot(playerInventory, col + row * 9 + 9, 8 + col * 18, invY + row * 18)); + } + } + for (int col = 0; col < 9; col++) { + addSlot(new Slot(playerInventory, col, 8 + col * 18, invY + 58)); + } + + if (serverPlayer != null) { + redraw(); + } + } + + /** Was #guikit:fill: re-run the definition's draw for the current page. */ + public void redraw() { + if (serverPlayer == null) return; + definition.draw(serverPlayer, container, page); + broadcastChanges(); + } + + /** Was function guikit:widget/goto_page: set the page and redraw, nothing else touches state. */ + public void gotoPage(int newPage) { + this.page = newPage; + redraw(); + } + + @Override + public void clicked(int slotId, int button, ClickType clickType, Player player) { + boolean isContainerSlot = slotId >= 0 && slotId < definition.slots(); + if (isContainerSlot && serverPlayer != null) { + definition.onClick(serverPlayer, this, slotId, page); + return; // never call super -- the widget item never moves or leaves the slot + } + super.clicked(slotId, button, clickType, player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + // Shift-click on a widget slot must not extract it either. + return ItemStack.EMPTY; + } + + @Override + public boolean stillValid(Player player) { + return true; // no chest_minecart to lose line-of-sight to; menu stays open until closed + } + + public GuikitMenuDefinition definition() { + return definition; + } +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinition.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinition.java new file mode 100644 index 00000000..615bfb3b --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinition.java @@ -0,0 +1,28 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; + +/** + * One "menu" as the datapack defined it: a #guikit:register entry (title/size) plus the + * #guikit:fill listener (draw) plus the #guikit:probe listener (click dispatch). All three + * live together here instead of three separate data-driven tag callbacks. + */ +public interface GuikitMenuDefinition { + Component title(); + + /** Container size, e.g. 27 for a chest-sized menu (was the "container" registry's `slots`). */ + int slots(); + + /** Fill the container for the given page. Was #guikit:fill + widget/pad + widget/draw. */ + void draw(ServerPlayer player, Container container, int page); + + /** + * A container slot was left-clicked. Was #guikit:probe: one {id, fn} line per clickable + * widget, matched against the slot the click came from. The click never moves or removes + * the item -- see GuikitMenu#clicked -- so there is no re-draw-after-every-click step + * unless this handler itself calls container.setChanges() / requests one. + */ + void onClick(ServerPlayer player, GuikitMenu menu, int slotIndex, int page); +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinitions.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinitions.java new file mode 100644 index 00000000..6773a7eb --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuDefinitions.java @@ -0,0 +1,26 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.resources.ResourceLocation; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Replaces storage guikit:reg menus."ns:id" = {...}. A menu-providing mod calls + * GuikitMenuDefinitions.register(id, definition) from its own onInitialize -- the direct + * equivalent of a menu datapack adding itself to #guikit:register. No load-order tag needed: + * Fabric's onInitialize ordering + this being a plain map handles it. + */ +public final class GuikitMenuDefinitions { + private static final Map REGISTRY = new LinkedHashMap<>(); + + private GuikitMenuDefinitions() {} + + public static void register(ResourceLocation id, GuikitMenuDefinition definition) { + REGISTRY.put(id, definition); + } + + public static GuikitMenuDefinition get(ResourceLocation id) { + return REGISTRY.get(id); + } +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuOpening.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuOpening.java new file mode 100644 index 00000000..896f11ca --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenuOpening.java @@ -0,0 +1,18 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; + +/** + * What the datapack put in storage guikit:in {menu:"ns:id"} before function guikit:api/open. + * Sent server -> client so the correct GuikitMenuDefinition can be looked up on both sides. + */ +public record GuikitMenuOpening(ResourceLocation menuId, int page) { + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + ResourceLocation.STREAM_CODEC, GuikitMenuOpening::menuId, + ByteBufCodecs.VAR_INT, GuikitMenuOpening::page, + GuikitMenuOpening::new + ); +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenus.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenus.java new file mode 100644 index 00000000..f1b9050c --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/GuikitMenus.java @@ -0,0 +1,37 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.inventory.MenuType; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; +import net.runtoolkit.guikit.Guikit; + +/** + * Replaces the datapack's storage-based registry (guikit:reg menus."ns:id" = {...}). + * In the datapack a menu was a data entry read at fill/probe time; here it is a real + * MenuType, opened with player.openMenu(...) -- no chest_minecart entity involved. + * + * UNVERIFIED: ExtendedScreenHandlerType's exact constructor signature (factory + + * StreamCodec vs. factory + PacketCodec) has moved between Fabric API releases. + * Check net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType for the + * 0.136.x/26.x signature before this compiles -- this file is unbuilt/untested. + */ +public final class GuikitMenus { + private GuikitMenus() {} + + public static final ResourceLocation MENU_ID = + ResourceLocation.fromNamespaceAndPath(Guikit.MOD_ID, "menu"); + + // ExtendedScreenHandlerType lets the server pass an opening payload (which menu + // definition, which page) the way the datapack passed storage guikit:in {menu:"ns:id"}. + public static MenuType GUIKIT_MENU; + + public static void register() { + GUIKIT_MENU = new ExtendedScreenHandlerType<>( + (syncId, inventory, opening) -> new GuikitMenu(syncId, inventory, opening), + GuikitMenuOpening.STREAM_CODEC + ); + Registry.register(BuiltInRegistries.MENU, MENU_ID, GUIKIT_MENU); + } +} diff --git a/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/Payment.java b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/Payment.java new file mode 100644 index 00000000..3b39f9ab --- /dev/null +++ b/mods/guikit-fabric/src/main/java/net/runtoolkit/guikit/menu/Payment.java @@ -0,0 +1,45 @@ +package net.runtoolkit.guikit.menu; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; + +/** + * Java port of widget/pay_score, widget/pay_item, widget/pay_xp. Each returns true = paid, + * false = not enough (nothing taken), same contract as the datapack functions. + */ +public final class Payment { + private Payment() {} + + /** UNVERIFIED -- see ConditionChecker javadoc, same Scoreboard-API caveat applies here. */ + public static boolean payScore(ServerPlayer player, String objective, int amount) { + throw new UnsupportedOperationException( + "guikit: wire this to your Scoreboard API shape before use"); + } + + public static boolean payItem(ServerPlayer player, ResourceLocation item, int count) { + int have = 0; + for (ItemStack stack : player.getInventory().items) { + if (!stack.isEmpty() && stack.getItem().builtInRegistryHolder().key().location().equals(item)) { + have += stack.getCount(); + } + } + if (have < count) return false; + + int remaining = count; + for (ItemStack stack : player.getInventory().items) { + if (remaining <= 0) break; + if (stack.isEmpty() || !stack.getItem().builtInRegistryHolder().key().location().equals(item)) continue; + int take = Math.min(remaining, stack.getCount()); + stack.shrink(take); + remaining -= take; + } + return true; + } + + public static boolean payXp(ServerPlayer player, int amountLevels) { + if (player.experienceLevel < amountLevels) return false; + player.giveExperienceLevels(-amountLevels); + return true; + } +} diff --git a/mods/guikit-fabric/src/main/resources/fabric.mod.json b/mods/guikit-fabric/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..5e75a36c --- /dev/null +++ b/mods/guikit-fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,18 @@ +{ + "schemaVersion": 1, + "id": "guikit", + "version": "${version}", + "name": "guikit", + "description": "Server-authoritative container-menu GUI framework -- Fabric port of the guikit datapack.", + "authors": ["runtoolkit"], + "license": "MIT", + "environment": "*", + "entrypoints": { + "main": ["net.runtoolkit.guikit.Guikit"] + }, + "depends": { + "fabricloader": ">=0.17", + "fabric-api": "*", + "minecraft": "~26.3" + } +} From 39ee62b824cbc39802baf464ba30615e44dd449c Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:13:24 +0300 Subject: [PATCH 2/7] Update build.gradle --- mods/guikit-fabric/build.gradle | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle index e9532a42..39db3a6a 100644 --- a/mods/guikit-fabric/build.gradle +++ b/mods/guikit-fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.15.0' + id 'fabric-loom' version '1.15.5' id 'maven-publish' } @@ -41,15 +41,4 @@ tasks.register('printModInfo') { } } -tasks.register('checkLicenses') { - group = 'guikit' - description = 'Fails the build if NOTICE.md or a bundled third-party license is missing.' - doLast { - def notice = file("${projectDir}/NOTICE.md") - if (!notice.exists()) { - throw new GradleException("NOTICE.md is missing — third-party attribution (macroEngine / StringLib / PlayerAction) must ship with every build.") - } - } -} - build.dependsOn checkLicenses From f539c69109afd6838dee8757f1dd09c2729501dc Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:16:54 +0300 Subject: [PATCH 3/7] Add files via upload --- mods/guikit-fabric/gradle.properties | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 mods/guikit-fabric/gradle.properties diff --git a/mods/guikit-fabric/gradle.properties b/mods/guikit-fabric/gradle.properties new file mode 100644 index 00000000..f8ce47f3 --- /dev/null +++ b/mods/guikit-fabric/gradle.properties @@ -0,0 +1,9 @@ +# NOTE: fabric_version below is the last version documented for 26.1 in the +# skill reference. It is UNVERIFIED for 26.3 specifically -- check +# https://fabricmc.net/develop/ before the first real build. +minecraft_version=26.3 +loader_version=0.17.0 +fabric_version=0.136.1+26.1 +mod_version=0.1.0 +maven_group=net.runtoolkit +archives_base_name=guikit From ee1217c354f42669926a7d8632ab60f38c161f3e Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:19:38 +0300 Subject: [PATCH 4/7] Fix syntax for fabric-api dependency and checkLicenses --- mods/guikit-fabric/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle index 39db3a6a..c22c1f51 100644 --- a/mods/guikit-fabric/build.gradle +++ b/mods/guikit-fabric/build.gradle @@ -14,7 +14,7 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc:fabric-api:fabric-api:${project.fabric_version}" } processResources { @@ -41,4 +41,4 @@ tasks.register('printModInfo') { } } -build.dependsOn checkLicenses +build.dependsOn tasks.named('checkLicenses') From e408ab88b75347014d7220b0b61155ad181079a1 Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:22:28 +0300 Subject: [PATCH 5/7] Remove printModInfo task from build.gradle Removed custom task 'printModInfo' and adjusted build settings. --- mods/guikit-fabric/build.gradle | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle index c22c1f51..f41b8af1 100644 --- a/mods/guikit-fabric/build.gradle +++ b/mods/guikit-fabric/build.gradle @@ -30,15 +30,3 @@ java { targetCompatibility = JavaVersion.VERSION_25 toolchain.languageVersion = JavaLanguageVersion.of(25) } - -// ---- Custom tasks ---- - -tasks.register('printModInfo') { - group = 'guikit' - description = 'Prints mod id, version and target Minecraft version.' - doLast { - println "mod=${project.name} version=${project.mod_version} minecraft=${project.minecraft_version}" - } -} - -build.dependsOn tasks.named('checkLicenses') From f1d5bd600f5d72943613462a8472562a40461b03 Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:25:37 +0300 Subject: [PATCH 6/7] Update Gradle build file for Fabric mod --- mods/guikit-fabric/build.gradle | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle index f41b8af1..bad01472 100644 --- a/mods/guikit-fabric/build.gradle +++ b/mods/guikit-fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.15.5' + id 'net.fabricmc.fabric-loom' version '1.15.5' id 'maven-publish' } @@ -7,26 +7,40 @@ version = project.mod_version group = project.maven_group repositories { + // Loom zaten Minecraft + Fabric depolarını ekliyor. + // Sadece ekstra mod bağımlılıkları için ekle. mavenCentral() } dependencies { + // Minecraft minecraft "com.mojang:minecraft:${project.minecraft_version}" + + // Official Mojang mappings (26.x için varsayılan ve önerilen) mappings loom.officialMojangMappings() - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc:fabric-api:fabric-api:${project.fabric_version}" + + // Fabric Loader + implementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API (doğru koordinatlar) + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" } processResources { - inputs.property "version", project.version + def version = project.version + inputs.property "version", version + filesMatching("fabric.mod.json") { - expand "version": project.version + expand "version": version } } +tasks.withType(JavaCompile).configureEach { + it.options.release = 25 +} + java { withSourcesJar() sourceCompatibility = JavaVersion.VERSION_25 targetCompatibility = JavaVersion.VERSION_25 - toolchain.languageVersion = JavaLanguageVersion.of(25) } From 51f2670b6bf9b06078b230058ccdea6d05ddc1dd Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Sun, 20 Sep 2026 19:40:16 +0300 Subject: [PATCH 7/7] Add files via upload --- mods/guikit-fabric/build.gradle | 36 +++++++++++++++++++++------- mods/guikit-fabric/gradle.properties | 14 +++++++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/mods/guikit-fabric/build.gradle b/mods/guikit-fabric/build.gradle index bad01472..7dca84bc 100644 --- a/mods/guikit-fabric/build.gradle +++ b/mods/guikit-fabric/build.gradle @@ -1,28 +1,28 @@ plugins { - id 'net.fabricmc.fabric-loom' version '1.15.5' + id 'net.fabricmc.fabric-loom' version '1.18.2' id 'maven-publish' } version = project.mod_version group = project.maven_group +base { + archivesName = project.archives_base_name +} + repositories { - // Loom zaten Minecraft + Fabric depolarını ekliyor. - // Sadece ekstra mod bağımlılıkları için ekle. - mavenCentral() + // Loom automatically adds the essential Fabric + Minecraft repositories. + // Only add extra repositories here if you depend on other mods. } dependencies { - // Minecraft + // Minecraft (26.3 is unobfuscated — do NOT declare mappings) minecraft "com.mojang:minecraft:${project.minecraft_version}" - // Official Mojang mappings (26.x için varsayılan ve önerilen) - mappings loom.officialMojangMappings() - // Fabric Loader implementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API (doğru koordinatlar) + // Fabric API implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" } @@ -44,3 +44,21 @@ java { sourceCompatibility = JavaVersion.VERSION_25 targetCompatibility = JavaVersion.VERSION_25 } + +jar { + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}" } + } +} + +// configure the maven publication +publishing { + publications { + create("mavenJava", MavenPublication) { + from components.java + } + } + repositories { + // Add repositories to publish to here. + } +} diff --git a/mods/guikit-fabric/gradle.properties b/mods/guikit-fabric/gradle.properties index f8ce47f3..4014ce36 100644 --- a/mods/guikit-fabric/gradle.properties +++ b/mods/guikit-fabric/gradle.properties @@ -1,9 +1,13 @@ -# NOTE: fabric_version below is the last version documented for 26.1 in the -# skill reference. It is UNVERIFIED for 26.3 specifically -- check -# https://fabricmc.net/develop/ before the first real build. +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx2G +org.gradle.parallel=true + +# Fabric Properties - check https://fabricmc.net/develop for latest minecraft_version=26.3 -loader_version=0.17.0 -fabric_version=0.136.1+26.1 +loader_version=0.19.5 +fabric_version=0.161.0+26.3 + +# Mod Properties mod_version=0.1.0 maven_group=net.runtoolkit archives_base_name=guikit