Exposing standalone access to path planning capabilities in api
Describe your suggestion
Baritone has awesome capabilities in planning path with it's AStarPathFinder. When writing certain functions in other clients, it makes sense to want to use baritone's path planning while leaving path execution to the client (eg. KillAura bot on with baritone, so that the killaura bot can decide when to take control of the bot). It can technically be called if I use the unoptimized jar, but that wouldn't be the proper way of doing this.
Settings
Not applicable.
Context
I was writing a script for LiquidBounce, which uses baritone for it's path planning. However it only works if I am using the unoptimized jar.
The example ts script is shown as below. But it doesn't run on vanilla LiquidBounce yet.
import { BaritoneAPI } from "jvm-types/baritone/api/BaritoneAPI"
import { GoalXZ } from "jvm-types/baritone/api/pathing/goals/GoalXZ"
import { CalculationContext } from "jvm-types/baritone/pathing/movement/CalculationContext"
import { Favoring } from "jvm-types/baritone/utils/pathing/Favoring"
import { BetterBlockPos } from "jvm-types/baritone/api/utils/BetterBlockPos"
import { IPath } from "jvm-types/baritone/api/pathing/calc/IPath"
import { VisualizationManager } from "lbng-utils-typed/dist/visualization-utils"
import { PathCalculationResult$Type } from "jvm-types/baritone/api/utils/PathCalculationResult$Type"
// note: this import is not from baritone-api jar
// it is only presented in the baritone-unoptimized jar
// as the `AStarPathFinder` class is possibly obfuscated in the baritone-standalone jar
// so you will have to install the baritone-unoptimized jar to use this import
import { AStarPathFinder } from "jvm-types/baritone/pathing/calc/AStarPathFinder"
const script = registerScript.apply({
name: "astar-pathfinder-example",
version: "1.0.0",
authors: ["commandblock2"]
});
script.registerModule({
name: "baritone-api-example",
description: "Baritone example module",
category: "Client",
}, (mod) => {
mod.on("enable", () => {
BaritoneAPI.getSettings().allowSprint.value = true;
BaritoneAPI.getSettings().primaryTimeoutMS.value = Primitives.long(2000);
const baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
baritone.getCustomGoalProcess().setGoalAndPath(new GoalXZ(100, 100))
})
})
script.registerModule({
name: "astar-pathfinder-example",
description: "Direct AStarPathFinder construction example",
category: "Client",
settings: {
goalX: Setting.float({
name: "Goal X",
default: 100,
range: [-10000, 10000] // Assuming a reasonable range
}),
goalZ: Setting.float({
name: "Goal Z",
default: 100,
range: [-10000, 10000] // Assuming a reasonable range
}),
recalculateInterval: Setting.int({
name: "Recalculate Interval (ticks)",
default: 20,
range: [1, 200]
})
}
}, (mod) => {
const viz = new VisualizationManager(mod);
let previousPath: IPath | null = null;
let lastRecalculateTick = 0;
const calculatePath = () => {
const baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
// Get current player position
const playerPos = baritone.getPlayerContext().playerFeet();
const start = new BetterBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
// Create calculation context for threaded use
const context = new CalculationContext(baritone, true);
// Create favoring (empty favoring for no preferences)
const favoring = new Favoring(baritone.getPlayerContext(), previousPath as unknown as IPath, context);
// Create goal using settings
const goal = new GoalXZ(mod.settings.goalX.get(), mod.settings.goalZ.get());
// Construct AStarPathFinder directly
const pathfinder = new AStarPathFinder(
start, // realStart
start.getX(), // startX
start.getY(), // startY
start.getZ(), // startZ
goal, // goal
favoring, // favoring
context // context
);
// @ts-expect-error
UnsafeThread.run(() => {
const result = pathfinder.calculate(Primitives.long(2000), Primitives.long(5000));
// Handle result
if (result.getType() != PathCalculationResult$Type.CANCELLATION) {
const path = result.getPath().get();
console.log("Path found! Length: " + path.length());
mc.execute(() => {
viz.addVisualization({
lineData: {
positions: path.positions().map((pos) => new Vec3d(pos.x + .5, pos.y, pos.z + .5)),
},
durationTicks: 20 * 60,
});
previousPath = path;
});
// Use the path as needed - you now have direct access without execution
} else {
console.log("Path calculation failed: " + result.getType().toString());
}
});
};
mod.on("enable", () => {
viz.clearAllVisualizations();
lastRecalculateTick = 0; // Reset on enable
calculatePath(); // Initial calculation
});
mod.on("gametick", () => {
if (mc.player && mc.world && (mc.player.age - lastRecalculateTick) >= (mod.settings.recalculateInterval.get() as unknown as number)) {
calculatePath();
lastRecalculateTick = mc.player.age;
}
});
});
export { }
Final checklist
- [x] I know how to properly use check boxes
- [x] I have not used any OwO's or UwU's in this issue.
Wouldn't making AStarPathFinder unoptimized in the API cause a pretty significant performance decrease? I mean, it's literally the class that holds the calculations for pathing, so maybe this isn't such a good idea. Also, even if you create the PR, @leijurv is probably going to wait a zillion years to even consider merging it :). So if you really want the change, just edit the code and build it.
That being said, I am looking at giving Baritone some attacking functionality. I've implemented a way to move in any direction while looking in any other direction (as part of #4752) and expanded it to track entities here. I'll probably put settings for external autoaim and killaura as well as options to only target players, entities, or a mix of both with blacklists.
Before reading your comment, I was not aware of how optimization was working for baritone. I do think that it should be possible to make a api that calls the optimized internal implementation though. I do understand that it may bring extra maintenance cost on baritone, and I do indeed have a low expectation for this proposal to be actually accepted. For now, the unoptimized jar should be enough for me as I do not expect to use the AStarPathFinder in a online scenario yet. And I do appreciate that baritone does provide a jar without obfuscation, please keep it and thank you for your effort so much. And I also appreciate the work you have done in the your pr for adding more settings to the baritone. By the way, I am actually quite curious about how much faster is it for baritone if it were to be optimized?
By the way, I am actually quite curious about how much faster is it for baritone if it were to be optimized?
No idea on the specifics, but the difference is enough for it to matter. You can probably look up "JVM optimization" to get an idea of what it's doing and how it helps execution speed. Also, the standalone version is smaller than the unoptimized one since everything is obfuscated, which is also a plus I guess.
There's now a PR for this: #4838