Reputation: 2660
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