Skip to content

Instantly share code, notes, and snippets.

@Ensamisten
Created March 7, 2026 10:24
Show Gist options
  • Select an option

  • Save Ensamisten/53456d35b1d3144e7379bc680370aa3c to your computer and use it in GitHub Desktop.

Select an option

Save Ensamisten/53456d35b1d3144e7379bc680370aa3c to your computer and use it in GitHub Desktop.
package io.github.ensamisten.client.command.brigadier;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.particle.DustParticleEffect;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class NavigationCommand {
private static final int GOLD_COLOR = 0xFFD700; // RGB hex for gold
public static BlockPos targetCoords;
public static boolean isNavigating = false;
private static long navigationStartTime;
private static int linePoints = 100;
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register(ClientCommandManager.literal("navigationstart")
.then(ClientCommandManager.argument("x", IntegerArgumentType.integer())
.then(ClientCommandManager.argument("y", IntegerArgumentType.integer())
.then(ClientCommandManager.argument("z", IntegerArgumentType.integer())
.executes((context) -> {
int x = IntegerArgumentType.getInteger(context, "x");
int y = IntegerArgumentType.getInteger(context, "y");
int z = IntegerArgumentType.getInteger(context, "z");
NavigationCommand.startNavigation(new BlockPos(x, y, z));
return 1;
})))));
dispatcher.register(ClientCommandManager.literal("navigationstop").executes((context) -> {
NavigationCommand.stopNavigation();
return 1;
}));
dispatcher.register(ClientCommandManager.literal("navigationsetpathpoints").then(ClientCommandManager.argument("points", IntegerArgumentType.integer(10, 10000)).executes((context) -> {
int points = IntegerArgumentType.getInteger(context, "points");
NavigationCommand.setLinePoints(points);
return 1;
})));
}
private static void setLinePoints(int points) {
if (points == linePoints) {
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §c❌ §f| §6Path line point count is already set to §e" + points + "§6."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_VILLAGER_NO, 2.0F, 1.0F);
} else {
linePoints = points;
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §a✔ §f| §6Number of path line points set to §e" + points + "§6."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, 2.0F, 1.0F);
}
}
private static void startNavigation(BlockPos coords) {
if (isNavigating && coords.equals(targetCoords)) {
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §c❌ §f| §4Already navigating to these coordinates."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_VILLAGER_NO, 2.0F, 1.0F);
} else {
if (isNavigating) {
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §9→ §f| §6Switching route to §e" + coords.toShortString() + "§6."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_WITCH_THROW, 2.0F, 2.0F);
} else {
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §a✔ §f| §6Navigation started to §e" + coords.toShortString() + "§6."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_VILLAGER_YES, 2.0F, 1.0F);
}
targetCoords = coords;
isNavigating = true;
navigationStartTime = System.currentTimeMillis();
}
}
public static void stopNavigation() {
if (isNavigating) {
isNavigating = false;
targetCoords = null;
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §c❌ §f| §4Navigation stopped."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.BLOCK_ANVIL_BREAK, 2.0F, 1.0F);
} else {
MinecraftClient.getInstance().player.sendMessage(Text.literal("§7[§3Navigation Assistant ➣§7]§f: §c❌ §f| §4You can't stop navigation when you're not navigating."), false);
MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_VILLAGER_NO, 2.0F, 1.0F);
}
}
// 1. Change onClientTick to be static (it only uses static fields/methods)
public static void onClientTick(MinecraftClient client) { // was: private void
if (isNavigating && client.player != null && targetCoords != null) {
Vec3d playerPos = client.player.getEntityPos(); // also: getEntityPos() doesn't exist — use getPos()
double distance = playerPos.distanceTo(Vec3d.ofCenter(targetCoords));
if (distance <= 5.0) {
showNavigationStats(client, playerPos); // was: this.showNavigationStats(...)
stopNavigation(); // was: this.stopNavigation()
} else {
List<Vec3d> path = calculatePath(playerPos, Vec3d.ofCenter(targetCoords));
renderParticlePath(client, path);
updateActionBar(client, playerPos);
}
}
}
public static List<Vec3d> calculatePath(Vec3d start, Vec3d end) {
List<Vec3d> path = new ArrayList();
Vec3d direction = end.subtract(start).normalize();
Vec3d current = start;
double totalDistance = start.distanceTo(end);
double stepSize = Math.max(0.5, totalDistance / (double)linePoints);
while(current.distanceTo(end) > stepSize) {
path.add(current);
Vec3d nextStep = current.add(direction.multiply(stepSize));
if (NavigationCommand.isBlockedAhead(nextStep)) {
nextStep = nextStep.add(0.0, 1.0, 0.0);
}
current = nextStep;
if (path.size() >= linePoints) {
break;
}
}
path.add(end);
return path;
}
private static boolean isBlockedAhead(Vec3d pos) {
MinecraftClient client = MinecraftClient.getInstance();
BlockPos blockPos = new BlockPos((int)pos.x, (int)pos.y, (int)pos.z);
return !client.world.getBlockState(blockPos).isAir();
}
public static void renderParticlePath(MinecraftClient client, List<Vec3d> path) {
Iterator var3 = path.iterator();
while(var3.hasNext()) {
Vec3d pos = (Vec3d) var3.next();
client.world.addParticleClient(new DustParticleEffect(GOLD_COLOR, 1.0F), pos.x, pos.y, pos.z, 0.0, 0.0, 0.0);
}
}
public static void updateActionBar(MinecraftClient client, Vec3d playerPos) {
double distance = playerPos.distanceTo(Vec3d.of(targetCoords));
String message = String.format("Distance to target: §2%.2f §7blocks §f| ", distance);
client.player.sendMessage(Text.literal("§7" + message + "§b" + targetCoords.getX() + ", " + targetCoords.getY() + ", " + targetCoords.getZ()), true);
}
public static void showNavigationStats(MinecraftClient client, Vec3d finalPos) {
Vec3d startPos = client.player.getEntityPos();
String stats = String.format("§7[§3Navigation Assistant ➣§7]§f: §a✔ §f| §aNavigation complete!\n");
client.player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2.0F, 1.0F);
client.player.sendMessage(Text.literal(stats), false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment