From b5d35785cd02b0d8200c38be6ba1d71d258ab4b5 Mon Sep 17 00:00:00 2001 From: GenerelSchwerz Date: Fri, 23 Feb 2024 17:15:39 -0500 Subject: [PATCH] update README --- docs/AdvancedUsage.md | 1115 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1108 insertions(+), 7 deletions(-) diff --git a/docs/AdvancedUsage.md b/docs/AdvancedUsage.md index 4eccae8..8adad92 100644 --- a/docs/AdvancedUsage.md +++ b/docs/AdvancedUsage.md @@ -12,15 +12,16 @@

Table of Contents

-- [Goal_Creation](#goal-creation) +- [Custom Goals](#custom-goals) - [Creating_a_sublcass_of_goals.GoalDynamic](#creating-a-sublcass-of-goals.goal) - [Creating_a_sublcass_of_goals.GoalDynamic](#creating-a-sublcass-of-goals.goaldynamic) -- [Move_Producers](#move-producers) - - [Creating_a_sublcass_of_move_produders.MoveProducer](#creating-a-sublcass-of-move-producers.moveproducer) -- [Move_Executors](#move-executors) - - [Creating_a_sublcass_of_move_executor.MoveExecutor](#creating-a-sublcass-of-move-executor.moveexecutor) -- [Move_Optimizer](#move-optimizer) - - [Creating_a_sublcass_of_move_optimizer.MoveOptimizer](#creating-a-sublcass-of-move-optimizer.moveoptimizer) +- [Movement Customization](#movement-customization) + - [Custom Movement Producers](#custom-movement-producers) + - [Creating_a_sublcass_of_move_produders.MoveProducer](#creating-a-sublcass-of-move-producers.moveproducer) + - [Custom Movement Executors](#custom-movement-executors) + - [Creating_a_sublcass_of_move_executor.MoveExecutor](#creating-a-sublcass-of-move-executor.moveexecutor) + - [Custom Movement_Optimizers](#move-optimizer) + - [Creating_a_sublcass_of_move_optimizer.MoveOptimizer](#creating-a-sublcass-of-move-optimizer.moveoptimizer) @@ -126,3 +127,1103 @@ class MyGoalDynamic extends GoalDynamic<'physicsTick', 'physicsTick'> { } } ``` + +

Movement Customization

+ +This pathfiner supports three levels of customization for movement: Movement Producers, Movement Executors, and Movement Optimizers. Each of these classes are designed to be extended and provide a simple interface for creating custom movement logic. + +To break down how this works, let's trace the code functionality. + +1. We provide a goal to Pathfinder + - now, pathfinder wants to create a path. +2. Pathfinder takes the current `MovementProviders` loaded in its settings and begins calculating the path based on them. + - `MovementProviders` are only used at calculation time, not execution time. They are used to determine whether or not movement is possible. +3. The initial path has been calculated! +4. The pathfinder now takes the calculated path and *optimizes* it using `MovementOptimizers` + - `MovementOptimizers` are used to optimize the path, removing unnecessary nodes and making the path more efficient. This is the step where straight-lining can be introduced, as normal A* does not provide this functionality well. *Note: see [here](#https://www.ijcai.org/Proceedings/09/Papers/303.pdf) for more information on straight-lining.* +5. The path has been optimized! +6. Provide this optimized path to the `goto` function in the pathfinder. +7. The pathfinder now takes the optimized path and begins executing it using `MovementExecutors`. + - `MovementExecutors` are used to execute the path, performing any necessary actions to reach the goal. This is where the bot actually moves and interacts with the world. + - `MovementExecutors` can provide runtime optimizations to the path itself via skipping nodes, but cannot modify the path itself. +8. **The path has been executed!** Or has it? + - In the event that some factor (such as failure to execute or knocking off course) has caused the bot to go off course, The pathfinder will recalculate the path and repeat steps 4-7. + - If the bot has gone off course due to an external event (such as a block update), the pathfinder will recalculate the path and repeat steps 4-7. + - If the bot has reached the goal, the pathfinder will finish and the bot will stop moving. + + +Providing customization to each step is important for creating a bot that can handle a wide variety of situations. For example, you may want to create a custom `MovementProvider` that can handle a specific type of block, or a custom `MovementExecutor` that can handle a specific type of movement. You may also want to create a custom `MovementOptimizer` that can optimize the path in a specific way. + +To add custom movement logic, you need to create a subclass of the appropriate class and implement the required methods. You can then provide an instance of your custom class to the pathfinder when creating a path. + +

Inserting custom classes into the pathfinder

+ +

Movement Providers

+ +Because Providers cannot do anything on their own, we do not provide a method of adding them to the pathfinder alone. Instead, they are paired with an executor during insertion. + +Inserting a Provider **must** be with its static instance. This is so lookups across the pathfinder can be done with the static instance. + +The movement Executor can be either its static instance or a new instance of the class. We recommend using its **static instance**. + +

Movement Executors

+ +

Inserting a Custom Movement Executor

+ + + + + + + +```ts +import { MovementExecutor, MovementProvider, Bot, World, MovementOptions } from 'mineflayer-pathfinder' + +class MyProvider extends MovementProvider { + // ... implementation +} + +class MyExecutor extends MovementExecutor { + // ... implementation +} + +bot.pathfinder.setExecutor(MyProvider, MyExecutor) + +// OR: + +const executor = new MyExecutor(bot, world, settings) + +bot.pathfinder.setExecutor(MyProvider, executor) + +``` + + + + +

Custom Movement Producers

+ + + + + + + + + +

Creating a sublcass of move_produders.MoveProducer

+ +To create a subclass of `move_produders.MoveProducer`, you need to implement the `provideMovements` method. This method is responsible for deciding whether or not movement is possible and, if possible, appending to the provided storage. + +

Example

+ +```ts + +import { MovementProvider, Move, goals } from 'mineflayer-pathfinder' + +class MyMoveProducer extends MovementProvider { + movementDirs = [ + new Vec3(1, 0, 0), + new Vec3(-1, 0, 0), + new Vec3(0, 0, 1), + new Vec3(0, 0, -1) + ] // often used in provideMovements to provide all directions. + + provideMovements (start: Move, storage: Move[], goal: goals.Goal, closed: Set): void { + // Decide whether or not movement is possible + // If possible, append to provided storage + } +} +``` + +

Custom Movement Executors

+ + + + + + + +

Creating a sublcass of move_executors.MoveExecutor

+ +To create a subclass of `move_executors.MoveExecutor`, you need to implement the `performInit`, `performPerTick`, and `align` methods. + +

Example

+ +```ts +import { Move, goals, MovementExecutor } from 'mineflayer-pathfinder' + +class MyMoveExecutor extends MovementExecutor { + + async align (thisMove: Move, tickCount?: number, goal?: goals.Goal, lookTarget?: Vec3): Promise { + // Perform modifications on bot BEFORE attempting the move + // This can be used to align to the center of blocks, etc. + // Align IS allowed to throw exceptions, it will revert to recovery + } + async performInit (thisMove: Move, currentIndex: number, path: Move[]): Promise { + // Perform initial setup upon movement start + } + + async performPerTick (thisMove: Move, tickCount: number, currentIndex: number, path: Move[]): Promise { + // Perform modifications on bot per-tick + // Return whether or not bot has reached the goal + } + + +} +```