Skip to main content
Glama

goToSomeone

Navigate to a specific player in Minecraft, allowing you to maintain a set distance and optionally follow them using the MCP Server's client library.

Instructions

Navigate to another player

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
distanceNoDistance to maintain from the player (default: 3)
keepFollowingNoContinue following the player (default: false)
userNameYesUsername of the player to go to

Implementation Reference

  • The primary handler function for the 'goToSomeone' tool. It validates the input parameters (requiring 'userName'), sets defaults, and delegates the navigation logic to the 'goToPerson' helper.
    export const goToSomeone = async ( bot: Bot, params: ISkillParams, serviceParams: ISkillServiceParams, ): Promise<boolean> => { const skillName = 'goToSomeone'; const requiredParams = ['userName']; const isParamsValid = validateSkillParams( params, requiredParams, skillName, ); if (!isParamsValid) { serviceParams.cancelExecution?.(); bot.emit( 'alteraBotEndObservation', `Mistake: You didn't provide all of the required parameters ${requiredParams.join(', ')} for the ${skillName} skill.`, ); return false; } const defaultParams = { keepFollowing: true, distance: 3, }; return goToPerson(bot, { name: params.userName, distance: params.distance ?? defaultParams.distance, keepFollowing: params.keepFollowing ?? defaultParams.keepFollowing, signal: serviceParams.signal, }); };
  • Input schema definition for the 'goToSomeone' tool, specifying parameters, their types, descriptions, and required fields. Used to create the SkillDefinition.inputSchema.
    goToSomeone: { description: "Navigate to another player", params: { userName: { type: "string", description: "Username of the player to go to" }, distance: { type: "number", description: "Distance to maintain from the player (default: 3)" }, keepFollowing: { type: "boolean", description: "Continue following the player (default: false)" } }, required: ["userName"] },
  • Registration metadata for the 'goToSomeone' tool in SKILL_METADATA, which is used by loadSkills() to register the skill with its schema and dynamic executor.
    goToSomeone: { description: "Navigate to another player", params: { userName: { type: "string", description: "Username of the player to go to" }, distance: { type: "number", description: "Distance to maintain from the player (default: 3)" }, keepFollowing: { type: "boolean", description: "Continue following the player (default: false)" } }, required: ["userName"] },
  • Core helper function implementing the pathfinding logic to go to a player by name, using mineflayer-pathfinder's GoalFollow, with features like distance monitoring, following, teleport fallback, and observation emissions.
    export const goToPerson = async ( bot: Bot, params: IGoToPersonParams, ): Promise<boolean> => { const { distance: distanceParam, name, keepFollowing, signal } = params; const distance = Math.max(1, distanceParam); // Ensure distance is at least 1 const TELEPORT_TOLERANCE_THRESHOLD = 30; // in blocks, if the entity is this far away, try to teleport to them const EMIT_UPDATE_RATE = 2000; // in milliseconds - 2 seconds, how often to emit a message while following const MAX_FOLLOW_TIME = 300000; // in milliseconds - 5 minutes, how long to follow before stopping, this is an emergency time - out const PROCESS_UPDATE_FREQUENCY = 50; // how often to check if the bot is still following the entity in milliseconds, ~20 times per second const HASNT_MOVED_THRESHOLD = 10000; // in milliseconds - 3 seconds, how long to wait before assuming the entity has stopped moving const entity = findClosestPlayerByName(bot, { name }); if (!entity) { // bot.chat(`Entity ${name} not found.`); return bot.emit( 'alteraBotEndObservation', `Mistake: You couldn't find anyone with the name ${name} to go to.`, ); // return; } if (bot.pathfinder.isMoving()) { await bot.pathfinder.stop(); } await bot.waitForTicks(2); // give time for pathfinder to stop if (isSignalAborted(signal)) { return; } // define a dynamic goal to follow the entity const followGoal = new GoalFollow(entity, distance); bot.pathfinder.setGoal(followGoal, true); // The second argument true makes the goal dynamic await bot.waitForTicks(2); let curDistance = -9999; let messageCounter = 0; let followTargetPosition = new Vec3( entity.position.x, entity.position.y, entity.position.z, ); let hasntMovedCount = 0; // bot.emit('alteraBotTextObservation', `You started following ${ entity.username }`); for (let n = 0; n < MAX_FOLLOW_TIME; n += PROCESS_UPDATE_FREQUENCY) { if (followTargetPosition.equals(entity.position)) { hasntMovedCount += PROCESS_UPDATE_FREQUENCY; if (hasntMovedCount > HASNT_MOVED_THRESHOLD) { bot.emit('alteraBotTextObservation', `${name} has stopped moving.`); break; } } else { // reset hasn't moved count followTargetPosition = new Vec3( entity.position.x, entity.position.y, entity.position.z, ); // console.log(`new target position: ${ JSON.stringify(bot.followTargetPosition)}`); hasntMovedCount = 0; } if (!isBotFollowing(bot, { entity })) { break; } if (isSignalAborted(signal)) { break; } curDistance = bot.entity.position.distanceTo(entity.position); // check to see if we are too far away and cheats are enabled if (bot.cheatsAllowed === undefined) // if cheats have never been set, set them to true, assume they're enabled bot.cheatsAllowed = true; if (curDistance > TELEPORT_TOLERANCE_THRESHOLD && bot.cheatsAllowed) { console.log( ` attempting to telport to ${entity.username} because they are too far away.`, ); bot.chat(`/tp ${entity.username}`); // this assumes cheats are enabled // check to see if the we got a failure message when teleporting if cheats are not enabled await bot.waitForTicks(2); // give time for teleport to complete curDistance = bot.entity.position.distanceTo(entity.position); // check to see if we are still too far away (with a small buffer) if (curDistance > TELEPORT_TOLERANCE_THRESHOLD - 2) { console.log( ` failed to teleport to ${entity.username} because cheats are not enabled. Turning off cheats.`, ); bot.cheatsAllowed = false; } } if (curDistance <= distance && !keepFollowing) { return bot.emit( 'alteraBotEndObservation', `You finished going to ${name}.`, ); } messageCounter += PROCESS_UPDATE_FREQUENCY; if (keepFollowing && messageCounter >= EMIT_UPDATE_RATE) { bot.emit('alteraBotTextObservation', `You are still following ${name}.`); messageCounter = 0; } await new Promise((resolve) => setTimeout(resolve, PROCESS_UPDATE_FREQUENCY), ); // wait for a little bit } await bot.pathfinder.stop(); bot.pathfinder.setGoal(null); bot.waitForTicks(2); return bot.emit( 'alteraBotEndObservation', `You have stopped following ${name}.`, ); };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/leo4life2/minecraft-mcp-http'

If you have feedback or need assistance with the MCP directory API, please join our Discord server