goose
goose

Reputation: 2660

Minecraft Fabric Mod doesn't animate custom compass

I'm trying to build a minecraft mod that provides a compass that points towards the nearest diamond ore block. I've gotten relatively far, I can see in the logs of my mod that the direction to the nearest diamond ore is being logged. However the diamond compass doesn't animate.

I don't understand why my code isn't animating the compass.

Is there something wrong with my approach? What's stopping the animation from working?

FerndaleMod.java

package com.ferndale;

import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroups;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;

public class FerndaleMod implements ModInitializer {
    public static final String MOD_ID = "ferndale";

    // Register the Diamond Compass item
    public static final Item DIAMOND_COMPASS = new Item(new Item.Settings());

    @Override
    public void onInitialize() {
        System.out.println("[🔧 DEBUG] Ferndale Mod Loaded!");

        // Register the Diamond Compass in the game
        Registry.register(Registries.ITEM, new Identifier(MOD_ID, "diamond_compass"), DIAMOND_COMPASS);

        // Add to the Tools & Utilities Creative Tab
        ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS).register(entries -> {
            entries.add(new ItemStack(DIAMOND_COMPASS));
        });
    }
}

DiamondCompassItem.java

package com.ferndale;

import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.CompassItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public class DiamondCompassItem extends CompassItem {
    public DiamondCompassItem(Settings settings) {
        super(settings);
    }

    public static void setLodestonePos(ItemStack stack, BlockPos pos) {
        NbtCompound nbt = stack.getOrCreateNbt();
        nbt.putInt("LodestoneX", pos.getX());
        nbt.putInt("LodestoneY", pos.getY());
        nbt.putInt("LodestoneZ", pos.getZ());
    }

    @Override
    public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context) {
        if (stack.hasNbt() && stack.getNbt() != null) {
            NbtCompound nbt = stack.getNbt();
            if (nbt.contains("LodestoneX") && nbt.contains("LodestoneY") && nbt.contains("LodestoneZ")) {
                tooltip.add(Text.of("Pointing to: " +
                        nbt.getInt("LodestoneX") + ", " +
                        nbt.getInt("LodestoneY") + ", " +
                        nbt.getInt("LodestoneZ")));
            } else {
                tooltip.add(Text.of("Not pointing to anything."));
            }
        }
        super.appendTooltip(stack, world, tooltip, context);
    }
}

ModItems.java

package com.ferndale;

import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.minecraft.item.CompassItem;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;

public class ModItems {
    public static final Item DIAMOND_COMPASS = registerItem("diamond_compass",
            new CompassItem(new FabricItemSettings().maxCount(1)));

    private static Item registerItem(String name, Item item) {
        return Registry.register(Registries.ITEM, new Identifier("ferndale", name), item);
    }

    public static void registerModItems() {
        System.out.println("Registering Mod Items for Ferndale...");
    }
}

DiamondCompassTracker.java

package com.ferndale;

import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

public class DiamondCompassTracker {
    public static float calculateAngle(ItemStack stack, World world, PlayerEntity player) {
        BlockPos nearestDiamond = findNearestDiamond(player, world);
        if (nearestDiamond == null) {
            return 0.0f;
        }

        return getCompassAngle(player, nearestDiamond);
    }

    private static BlockPos findNearestDiamond(PlayerEntity player, World world) {
        BlockPos playerPos = player.getBlockPos();
        BlockPos nearestDiamond = null;
        double nearestDistance = Double.MAX_VALUE;

        int radius = 50;  // Search range
        for (int x = -radius; x <= radius; x++) {
            for (int y = -radius; y <= radius; y++) {
                for (int z = -radius; z <= radius; z++) {
                    BlockPos pos = playerPos.add(x, y, z);
                    if (world.getBlockState(pos).isOf(Blocks.DIAMOND_ORE)) {
                        double distance = playerPos.getSquaredDistance(pos);
                        if (distance < nearestDistance) {
                            nearestDiamond = pos;
                            nearestDistance = distance;
                        }
                    }
                }
            }
        }
        return nearestDiamond;
    }

    private static float getCompassAngle(PlayerEntity player, BlockPos target) {
        Vec3d playerPos = player.getPos();
        Vec3d targetPos = new Vec3d(target.getX(), target.getY(), target.getZ());
        double angle = Math.atan2(targetPos.getZ() - playerPos.getZ(), targetPos.getX() - playerPos.getX());

        // Normalize angle to be between 0.0 and 1.0 (used by Minecraft's model system)
        return (float) ((angle / (2 * Math.PI) + 1) % 1);
    }
}

CompassUtils.java

package com.ferndale;

import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;

public class CompassUtils {
    public static float getAngle(ItemStack stack, World world, ClientPlayerEntity player) {
        if (!stack.hasNbt()) {
            return 0.0F;
        }

        NbtCompound nbt = stack.getNbt();
        if (nbt == null) {
            return 0.0F;
        }

        if (!nbt.contains("LodestoneX") || !nbt.contains("LodestoneY") || !nbt.contains("LodestoneZ")) {
            return 0.0F;
        }

        double lodestoneX = nbt.getInt("LodestoneX") + 0.5;
        double lodestoneZ = nbt.getInt("LodestoneZ") + 0.5;
        double dx = lodestoneX - player.getX();
        double dz = lodestoneZ - player.getZ();
        float angle = (float) (MathHelper.atan2(dz, dx) * (180.0 / Math.PI)) - player.getYaw();

        return MathHelper.wrapDegrees(angle / 360.0F);
    }
}

FerndaleClientMod.java

package com.ferndale;

import com.ferndale.FerndaleMod;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.item.ModelPredicateProviderRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public class FerndaleClientMod implements ClientModInitializer {
    @Override
    public void onInitializeClient() {
        System.out.println("[🔧 DEBUG] Registering Model Predicate for Diamond Compass");

        ModelPredicateProviderRegistry.register(FerndaleMod.DIAMOND_COMPASS, new Identifier("angle"),
                (stack, world, entity, seed) -> {
                    if (world == null || entity == null) {
                        return 0.0f;
                    }
                    if (entity instanceof PlayerEntity player) {
                        float angle = DiamondCompassTracker.calculateAngle(stack, world, player);
                        System.out.println("[🔧 DEBUG] Compass Angle: " + angle);
                        return angle;
                    }
                    return 0.0f;
                });
    }
}

fabric_mod.json

{
    "schemaVersion": 1,
    "id": "ferndale",
    "version": "1.0.0",
    "name": "Ferndale",
    "description": "A mod that adds a Diamond Compass to track diamonds.",
    "authors": [""],
    "contact": {
        "homepage": "https://example.com",
        "sources": ""
    },
    "license": "MIT",
    "environment": "*",
    "entrypoints": {
        "main": ["com.ferndale.FerndaleMod"],
        "client": ["com.ferndale.FerndaleClientMod"]
    },
    "depends": {
        "fabricloader": ">=0.14.21",
        "fabric": "*",
        "minecraft": "1.20.1"
    }
}

resource: diamond_compass.json

{
  "parent": "item/handheld",
  "textures": {
    "layer0": "minecraft:item/compass"
  },
  "overrides": [
    {
      "predicate": { "angle": 0 },
      "model": "minecraft:item/compass"
    }
  ]
}

Upvotes: -1

Views: 58

Answers (0)

Related Questions