@nxg-org/mineflayer-util-plugin 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +674 -0
  2. package/lib/WorldFunctions.d.ts +10 -0
  3. package/lib/WorldFunctions.js +18 -0
  4. package/lib/calcs/aabb.d.ts +36 -0
  5. package/lib/calcs/aabb.js +194 -0
  6. package/lib/commonSense.d.ts +22 -0
  7. package/lib/commonSense.js +220 -0
  8. package/lib/customImplementations/inventory.d.ts +10 -0
  9. package/lib/customImplementations/inventory.js +95 -0
  10. package/lib/entityFunctions.d.ts +36 -0
  11. package/lib/entityFunctions.js +78 -0
  12. package/lib/filterFunctions.d.ts +23 -0
  13. package/lib/filterFunctions.js +45 -0
  14. package/lib/index.d.ts +27 -0
  15. package/lib/index.js +7 -0
  16. package/lib/inventoryFunctions.d.ts +45 -0
  17. package/lib/inventoryFunctions.js +208 -0
  18. package/lib/mathUtil.d.ts +23 -0
  19. package/lib/mathUtil.js +49 -0
  20. package/lib/movementFunctions.d.ts +43 -0
  21. package/lib/movementFunctions.js +109 -0
  22. package/lib/predictiveFunctions.d.ts +25 -0
  23. package/lib/predictiveFunctions.js +172 -0
  24. package/lib/utilFunctions.d.ts +50 -0
  25. package/lib/utilFunctions.js +140 -0
  26. package/lib/worldRelated/predictiveWorld.d.ts +41 -0
  27. package/lib/worldRelated/predictiveWorld.js +108 -0
  28. package/lib/worldRelated/raycastIterator.d.ts +45 -0
  29. package/lib/worldRelated/raycastIterator.js +114 -0
  30. package/package.json +33 -0
  31. package/src/WorldFunctions.ts +19 -0
  32. package/src/calcs/aabb.ts +218 -0
  33. package/src/commonSense.ts +189 -0
  34. package/src/customImplementations/inventory.ts +90 -0
  35. package/src/entityFunctions.ts +71 -0
  36. package/src/filterFunctions.ts +54 -0
  37. package/src/index.ts +29 -0
  38. package/src/inventoryFunctions.ts +187 -0
  39. package/src/mathUtil.ts +56 -0
  40. package/src/movementFunctions.ts +116 -0
  41. package/src/predictiveFunctions.ts +187 -0
  42. package/src/utilFunctions.ts +152 -0
  43. package/src/worldRelated/predictiveWorld.ts +109 -0
  44. package/src/worldRelated/raycastIterator.ts +136 -0
  45. package/tsconfig.json +17 -0
@@ -0,0 +1,71 @@
1
+ import type { Bot } from "mineflayer";
2
+ import type { Entity } from "prismarine-entity";
3
+ import type { Vec3 } from "vec3";
4
+ import { AABB } from "./calcs/aabb";
5
+
6
+ export class EntityFunctions {
7
+ healthSlot: number = 7;
8
+ constructor(public bot: Bot) {
9
+ this.bot.on("spawn", async () => {
10
+ // await this.bot.util.sleep(1000)
11
+ // const slot = this.bot.entity.metadata.slice(5).findIndex((data) => Number(data) === 20);
12
+ // if (slot > 0) {
13
+ // this.healthSlot = slot + 5;
14
+ // }
15
+ this.healthSlot = Number(this.bot.version.split(".")[1]) <= 16 ? 7 : 9;
16
+ });
17
+ }
18
+
19
+ /**
20
+ * TODO: Version specific right now. Generalize. Unknown method.
21
+ *
22
+ * Checks if main hand is activated.
23
+ * @returns boolean
24
+ */
25
+ isMainHandActive(entity?: Entity): boolean {
26
+ return ((entity ?? this.bot.entity).metadata[6] as any) === 1; //as any & (1 | 0)) === (1 | 0);
27
+ }
28
+
29
+ /**
30
+ * TODO: Version specific right now. Generalize. Unknown method.
31
+ *
32
+ * Checks if offhand is activated.
33
+ * @returns boolean
34
+ */
35
+ isOffHandActive(entity?: Entity): boolean {
36
+ return ((entity ?? this.bot.entity).metadata[6] as any) === 1; //& (1 | 2)) === (1 | 2);
37
+ }
38
+
39
+ /**
40
+ * TODO: Version specific right now. Generalize. Unknown method.
41
+ * @param metadata metadata from Prismarine-Entity Entity.
42
+ * @returns
43
+ */
44
+ getHealth(entity?: Entity): number {
45
+ entity = entity ?? this.bot.entity;
46
+ let metadata = entity.metadata;
47
+ //console.log(entity.metadata, this.healthSlot, this.bot.entity.health)
48
+ let healthSlot = this.healthSlot; //metadata[this.healthSlot] ? this.healthSlot : metadata.findIndex((met) => Number(met) > 1 && Number(met) <= 20);
49
+ // return Number(metadata[healthSlot]) + (Number(metadata[healthSlot + 4]) ?? 0);
50
+
51
+ let health = Number(metadata[healthSlot]);
52
+ if (!health || health === 0) health = entity === this.bot.entity ? this.bot.entity.health ?? 0 : 0;
53
+ if (health === 0) console.log(this.healthSlot, entity.metadata);
54
+ // console.log(health + (Number(metadata[this.healthSlot + 4]) ?? 0))
55
+ return health + (Number(metadata[this.healthSlot + 4]) ?? 0);
56
+ }
57
+
58
+ getDistanceToEntity(entity: Entity): number {
59
+ return this.getDistanceBetweenEntities(this.bot.entity, entity);
60
+ }
61
+
62
+ getDistanceBetweenEntities(first: Entity, second: Entity): number {
63
+ return first.position.distanceTo(second.position);
64
+ }
65
+
66
+ getEntityAABB(entity: { position: Vec3; height: number; width?: number }): AABB {
67
+ const w = entity.width ?? entity.height / 2;
68
+ const { x, y, z } = entity.position;
69
+ return new AABB(-w, 0, -w, w, entity.height, w).offset(x, y, z);
70
+ }
71
+ }
@@ -0,0 +1,54 @@
1
+ import type { Entity } from "prismarine-entity";
2
+ import type { Bot } from "mineflayer";
3
+ import type { Vec3 } from "vec3";
4
+
5
+ /**
6
+ * TODO: Inherit other bot names. May need to communciate to a server for this one. Or perhaps reference this once?
7
+ */
8
+ export class FilterFunctions {
9
+ public specificNames: string[] = [];
10
+ public botNames: string[] = [];
11
+ constructor(private bot: Bot) {}
12
+
13
+ addBotName(name: string): void {
14
+ this.botNames.push(name);
15
+ }
16
+
17
+ getNearestEntity(func: (entity: Entity, ...args: any[]) => boolean, ...args: any[]): Entity | null {
18
+ return this.bot.nearestEntity((entity: Entity) => func(entity, ...args));
19
+ }
20
+
21
+ static getNearestEntity(bot: Bot, func: (entity: Entity, ...args: any[]) => boolean, ...args: any[]): Entity | null {
22
+ return bot.nearestEntity((entity: Entity) => func(entity, ...args));
23
+ }
24
+
25
+ allButOtherBotsFilter(): Entity | null {
26
+ return this.getNearestEntity((e: Entity) => e.type === "player" && (!this.botNames?.includes(e.username ?? "") ?? true));
27
+ }
28
+
29
+ static allButOtherBotsFilter(bot: Bot, ...names: string[]): Entity | null {
30
+ return FilterFunctions.getNearestEntity(bot, (e: Entity) => e.type === "player" && !names.includes(e.username ?? ""));
31
+ }
32
+
33
+ specificNamesFilter(): Entity | null {
34
+ return this.getNearestEntity((e: Entity) => e.type === "player" && (this.specificNames?.includes(e.username ?? "") ?? true));
35
+ }
36
+
37
+ static specificNamesFilter(bot: Bot, ...names: string[]): Entity | null {
38
+ return FilterFunctions.getNearestEntity(bot, (e: Entity) => e.type === "player" && names.includes(e.username ?? ""));
39
+ }
40
+
41
+ nearestCrystalFilter(): Entity | null {
42
+ return this.getNearestEntity((e: Entity) => e.name === "ender_crystal");
43
+ }
44
+
45
+ static nearestCrystalFilter(bot: Bot): Entity | null {
46
+ return FilterFunctions.getNearestEntity(bot, (e: Entity) => e.name === "ender_crystal");
47
+ }
48
+
49
+ entityAtPosition(position: Vec3) {
50
+ return this.getNearestEntity((entity: Entity) => entity.position.offset(-0.5, -1, -0.5).equals(position));
51
+ }
52
+
53
+ static entityAtPosition(bot: Bot, position: Vec3) {}
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ import type { Bot } from "mineflayer";
2
+ import { UtilFunctions } from "./utilFunctions";
3
+ import { PredictiveWorld } from "./worldRelated/predictiveWorld";
4
+
5
+ declare module "mineflayer" {
6
+ type PrioGroups = "inventory" | "movement";
7
+ interface Bot {
8
+ util: UtilFunctions,
9
+ }
10
+
11
+ interface BotEvents {
12
+ startedEquippingMainHand: () => void;
13
+ startedEquippingOffHand: () => void;
14
+ stoppedEquippingMainHand: () => void;
15
+ stoppedEquippingOffHand: () => void;
16
+ startedEquippingOtherSlot: () => void;
17
+ stoppedEquippingOtherSlot: () => void;
18
+ }
19
+ }
20
+
21
+ declare module "prismarine-entity" {
22
+ interface Entity {
23
+ attributes: { [index: string]: {value: number, modifiers: any[] }},
24
+ }
25
+ }
26
+
27
+ export default function inject(bot: Bot) {
28
+ bot.util = new UtilFunctions(bot);
29
+ }
@@ -0,0 +1,187 @@
1
+ import { Bot, EquipmentDestination } from "mineflayer";
2
+ import { Item } from "prismarine-item";
3
+ import { promisify } from "util";
4
+ import { BuiltInPriorityOptions } from "./utilFunctions";
5
+ const sleep = promisify(setTimeout);
6
+
7
+ /**
8
+ * Error codes:
9
+ *
10
+ * 0 = completed successfully.
11
+ *
12
+ * 1 = Item is already equipped.
13
+ *
14
+ * 2 = Item could not be found.
15
+ *
16
+ * 3 = We are currently equipping an item.
17
+ */
18
+ export class InventoryFunctions {
19
+ private _equippingMainHand: boolean = false;
20
+ private _equippingOffHand: boolean = false;
21
+ private _equippingOtherSlot: boolean = false;
22
+ public usingMainHand: boolean = false;
23
+ public usingOffHand: boolean = false;
24
+
25
+ constructor(public bot: Bot) {}
26
+
27
+ public set equippingOtherSlot(value: boolean) {
28
+ if (this._equippingOtherSlot === value) return;
29
+ if (value) this.bot.emit("startedEquippingOtherSlot");
30
+ else this.bot.emit("stoppedEquippingOtherSlot");
31
+ this._equippingOtherSlot = value;
32
+ }
33
+
34
+ public get equippingOtherSlot(): boolean {
35
+ return this._equippingOtherSlot;
36
+ }
37
+
38
+ public set equippingMainHand(value: boolean) {
39
+ if (this._equippingMainHand === value) return;
40
+ if (value) this.bot.emit("startedEquippingMainHand");
41
+ else this.bot.emit("stoppedEquippingMainHand");
42
+ this._equippingMainHand = value;
43
+ }
44
+
45
+ public get equippingMainHand(): boolean {
46
+ return this._equippingMainHand;
47
+ }
48
+
49
+ public set equippingOffHand(value: boolean) {
50
+ if (this._equippingOffHand === value) return;
51
+ if (value) this.bot.emit("startedEquippingOffHand");
52
+ else this.bot.emit("stoppedEquippingOffHand");
53
+ this._equippingOffHand = value;
54
+ }
55
+
56
+ public get equippingOffHand(): boolean {
57
+ return this._equippingOffHand;
58
+ }
59
+
60
+ getAllItems(): Item[] {
61
+ return [
62
+ ...this.bot.inventory.items(),
63
+ ...["hand", "head", "torso", "legs", "feet", "off-hand"].map(
64
+ (name) => this.bot.inventory.slots[this.bot.getEquipmentDestSlot(name)]
65
+ ),
66
+ ].filter((e) => !!e);
67
+ }
68
+
69
+ getAllItemsExceptCurrent(current: EquipmentDestination): Item[] {
70
+ return [
71
+ ...this.bot.inventory.items(),
72
+ ...["hand", "head", "torso", "legs", "feet", "off-hand"]
73
+ .filter((name) => name !== current)
74
+ .map((name) => this.bot.inventory.slots[this.bot.getEquipmentDestSlot(name)]),
75
+ ].filter((e) => !!e);
76
+ }
77
+
78
+ getHandWithItem(offhand?: boolean): Item | null {
79
+ return this.bot.inventory.slots[this.bot.getEquipmentDestSlot(this.getHand(offhand))];
80
+ }
81
+
82
+ getHand(offhand: boolean = false): "hand" | "off-hand" {
83
+ return offhand ? "off-hand" : "hand";
84
+ }
85
+
86
+ findItemByID(itemId: number, metadata?: number): Item | null {
87
+ const potentialMatches = this.getAllItems().filter((item) => item.type === itemId);
88
+ if (metadata) return potentialMatches.find((item) => item.metadata === metadata) ?? null;
89
+ return potentialMatches[0] ?? null;
90
+ }
91
+
92
+ findItem(name: string, metadata?: number) {
93
+ //[...this.getAllItems(), this.bot.inventory.selectedItem!]
94
+ const potentialMatches = this.getAllItems().filter((item) => item?.name.includes(name));
95
+ if (metadata) return potentialMatches.find((item) => item.metadata === metadata) ?? null;
96
+ return potentialMatches[0] ?? null;
97
+ }
98
+
99
+ //alias.
100
+ has(name: string, metadata?: number) {
101
+ return !!this.findItem(name, metadata);
102
+ }
103
+
104
+ async equipItemRaw(item: Item, dest: EquipmentDestination): Promise<boolean> {
105
+ if (this.bot.inventory.slots[this.bot.getEquipmentDestSlot(dest)] === item) return true;
106
+ await this.bot.equip(item, dest);
107
+ return false;
108
+ }
109
+
110
+ async equipItem(name: string, dest: EquipmentDestination, options: BuiltInPriorityOptions): Promise<number> {
111
+ if (this.bot.inventory.slots[this.bot.getEquipmentDestSlot(dest)]?.name.includes(name)) return 1;
112
+ const item = this.getAllItemsExceptCurrent(dest).find((item) => item?.name.includes(name));
113
+ if (!!item) {
114
+ await this.bot.util.builtInsPriority(options, this.bot.equip, item, dest);
115
+ return 0;
116
+ }
117
+ return 2;
118
+ }
119
+
120
+ async equipMainHand(name: string, options: BuiltInPriorityOptions = { group: "inventory", priority: 1 }): Promise<number> {
121
+ while (this._equippingMainHand) {
122
+ await sleep(0);
123
+ }
124
+ return await this.equipMainHandNoWait(name, options);
125
+ }
126
+
127
+ async equipOffHand(name: string, options: BuiltInPriorityOptions = { group: "inventory", priority: 1 }): Promise<number> {
128
+ while (this._equippingOffHand) {
129
+ await sleep(0);
130
+ }
131
+ return await this.equipOffHandNoWait(name, options);
132
+ }
133
+
134
+ async equipSlot(
135
+ name: string,
136
+ destination: EquipmentDestination,
137
+ options: BuiltInPriorityOptions = { group: "inventory", priority: 1 }
138
+ ): Promise<number> {
139
+ while (this._equippingOtherSlot) {
140
+ await sleep(0);
141
+ }
142
+ return await this.equipSlotNoWait(name, destination, options);
143
+ }
144
+
145
+ async equipMainHandNoWait(name: string, options: BuiltInPriorityOptions): Promise<number> {
146
+ if (this._equippingMainHand) return 3;
147
+ this._equippingMainHand = true;
148
+ const result = await this.equipItem(name, "hand", options);
149
+ this._equippingMainHand = false;
150
+ return result;
151
+ }
152
+
153
+ async equipOffHandNoWait(name: string, options: BuiltInPriorityOptions): Promise<number> {
154
+ if (this._equippingOffHand) return 3;
155
+ this.equippingOffHand = true;
156
+ const result = await this.equipItem(name, "off-hand", options);
157
+ this.equippingOffHand = false;
158
+ return result;
159
+ }
160
+
161
+ async equipSlotNoWait(name: string, dest: EquipmentDestination, options: BuiltInPriorityOptions) {
162
+ if (this._equippingOtherSlot) return 3;
163
+ this.equippingOtherSlot = true;
164
+ const result = await this.equipItem(name, dest, options);
165
+ this.equippingOtherSlot = false;
166
+ return result;
167
+ }
168
+
169
+ async customEquip(item: Item, destination: EquipmentDestination, retries: number = 1) {
170
+ for (let i = 0; i < retries; i++) {
171
+ try {
172
+ await this.bot.equip(item, destination);
173
+ return true;
174
+ } catch (error) {
175
+ if (this.bot.inventory.selectedItem) {
176
+ const slot = this.bot.inventory.firstEmptyInventorySlot(false) || -999;
177
+ try {
178
+ await this.bot.clickWindow(slot, 0, 0);
179
+ } catch (error) {
180
+ return false;
181
+ }
182
+ }
183
+ }
184
+ }
185
+ return false;
186
+ }
187
+ }
@@ -0,0 +1,56 @@
1
+ import { Bot } from "mineflayer";
2
+ import { Vec3 } from "vec3";
3
+
4
+ const PI = Math.PI;
5
+ const PI_2 = Math.PI * 2;
6
+ const TO_RAD = PI / 180;
7
+ const TO_DEG = 1 / TO_RAD;
8
+ const FROM_NOTCH_BYTE = 360 / 256;
9
+ // From wiki.vg: Velocity is believed to be in units of 1/8000 of a block per server tick (50ms)
10
+ const FROM_NOTCH_VEL = 1 / 8000;
11
+
12
+ export class MathFunctions {
13
+ constructor() {}
14
+
15
+ toNotchianYaw = (yaw: number) => this.toDegrees(PI - yaw);
16
+ toNotchianPitch = (pitch: number) => this.toDegrees(-pitch);
17
+ fromNotchianYawByte = (yaw: number) => this.fromNotchianYaw(yaw * FROM_NOTCH_BYTE);
18
+ fromNotchianPitchByte = (pitch: number) => this.fromNotchianPitch(pitch * FROM_NOTCH_BYTE);
19
+
20
+ euclideanMod(numerator: number, denominator: number) {
21
+ const result = numerator % denominator;
22
+ return result < 0 ? result + denominator : result;
23
+ }
24
+
25
+ toRadians(degrees: number) {
26
+ return TO_RAD * degrees;
27
+ }
28
+
29
+ toDegrees(radians: number) {
30
+ return TO_DEG * radians;
31
+ }
32
+
33
+ fromNotchianYaw(yaw: number) {
34
+ return this.euclideanMod(PI - this.toRadians(yaw), PI_2);
35
+ }
36
+
37
+ fromNotchianPitch(pitch: number) {
38
+ return this.euclideanMod(this.toRadians(-pitch) + PI, PI_2) - PI;
39
+ }
40
+
41
+ fromNotchVelocity(vel: Vec3) {
42
+ return new Vec3(vel.x * FROM_NOTCH_VEL, vel.y * FROM_NOTCH_VEL, vel.z * FROM_NOTCH_VEL);
43
+ }
44
+
45
+ pointToYawAndPitch(bot: Bot, point: Vec3) {
46
+ const delta = point.minus(bot.entity.position.offset(0, bot.entity.height, 0));
47
+ return this.dirToYawAndPitch(delta);
48
+ }
49
+
50
+ dirToYawAndPitch(dir: Vec3) {
51
+ const yaw = Math.atan2(-dir.x, -dir.z);
52
+ const groundDistance = Math.sqrt(dir.x * dir.x + dir.z * dir.z);
53
+ const pitch = Math.atan2(dir.y, groundDistance);
54
+ return { yaw: yaw, pitch: pitch };
55
+ }
56
+ }
@@ -0,0 +1,116 @@
1
+ import type { Bot } from "mineflayer";
2
+ import type { Entity } from "prismarine-entity";
3
+ import type { Vec3 } from "vec3";
4
+ import { goals } from "mineflayer-pathfinder";
5
+
6
+ const { GoalCompositeAll, GoalInvert, GoalFollow } = goals;
7
+
8
+ export class MovementFunctions {
9
+ goalArray = new GoalCompositeAll();
10
+ lastYaw: number = 0;
11
+ lastPitch: number = 0;
12
+ constructor(public bot: Bot) {}
13
+
14
+ /**
15
+ * Fuckin' mineflayer-pathfinder still doesn't have typings.
16
+ * Pain in my goddamn ass.
17
+ * @returns have the goal changed
18
+ */
19
+ addGoal(goal: any): boolean {
20
+ if (this.goalArray.goals.find((inGoal) => inGoal === goal)) return false;
21
+ this.goalArray.push(goal);
22
+ return true;
23
+ }
24
+
25
+ /**
26
+ * Sets current goal and clears all others.
27
+ * @param goal any type of mineflayer-pathfinder goal.
28
+ * @returns have the goal changed
29
+ */
30
+ setOnlyGoal(goal: any, dynamic: boolean = false): boolean {
31
+ const goalArr = [goal];
32
+ if (this.goalArray.goals === goalArr) return false;
33
+ this.goalArray.goals = goalArr;
34
+ this.bot.pathfinder.setGoal(this.goalArray, dynamic);
35
+ return true;
36
+ }
37
+
38
+ /**
39
+ * Reset all goals inside the goal array to none.
40
+ * @returns have the goals changed
41
+ */
42
+ stop(): boolean {
43
+ if (this.goalArray.goals.length === 0) return false;
44
+ this.goalArray.goals = [];
45
+ this.bot.pathfinder.setGoal(null);
46
+ return true;
47
+ }
48
+
49
+ /**
50
+ * Retreat from current entity.
51
+ * @param entity Prismarine-Entity Entity
52
+ * @returns have the goals changed.
53
+ */
54
+ retreatFromEntity(entity: Entity, distance: number, dynamic: boolean = true): boolean {
55
+ const oldGoals = this.goalArray.goals.length;
56
+ this.goalArray.goals = this.goalArray.goals.filter(
57
+ (goal: any) => goal.goal?.entity?.id === entity.id && goal.goal?.rangeSq === distance * distance
58
+ );
59
+ if (oldGoals !== this.goalArray.goals.length || this.goalArray.goals.length === 0) {
60
+ this.goalArray.push(new GoalFollow(entity!, distance));
61
+ this.goalArray.push(new GoalInvert(new GoalFollow(entity!, distance - 1)));
62
+ this.bot.pathfinder.setGoal(this.goalArray, dynamic);
63
+ return true;
64
+ }
65
+ return false;
66
+ }
67
+
68
+ /**
69
+ * Follow entity with a specific range. Will not approach past a certain distance either.
70
+ * @param entity Prismarine-Entity Entity
71
+ * @returns have the goals changed
72
+ */
73
+ followEntityWithRespectRange(entity: Entity, followDistance: number, invertDistance?: number): boolean {
74
+ const oldGoals = this.goalArray.goals.length;
75
+ this.goalArray.goals = (this.goalArray.goals as any[]).filter((goal) => {
76
+ return goal.entity?.id === entity.id && goal.rangeSq === followDistance * followDistance;
77
+ });
78
+
79
+ if (oldGoals !== this.goalArray.goals.length || !this.bot.pathfinder.isMoving() || this.goalArray.goals.length === 0) {
80
+ if (this.goalArray.goals.length > 0) {
81
+ this.goalArray.goals = [];
82
+ }
83
+ this.goalArray.push(new GoalFollow(entity, followDistance));
84
+ this.goalArray.push(new GoalInvert(new GoalFollow(entity, invertDistance ?? followDistance - 0.5)));
85
+ this.bot.pathfinder.setGoal(this.goalArray, true);
86
+ return true;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ forceLook(yaw: number, pitch: number, update: boolean = false) {
93
+ const notchianYawAndPitch = { yaw: this.bot.util.math.toNotchianYaw(yaw), pitch: this.bot.util.math.toNotchianPitch(pitch) };
94
+ this.bot._client.write("look", { ...notchianYawAndPitch, onGround: false });
95
+ if (update) {
96
+ // this.bot.entity.yaw = yaw;
97
+ // this.bot.entity.pitch = pitch
98
+ this.bot.look(yaw, pitch, true);
99
+ }
100
+ }
101
+
102
+ forceLookAt(pos: Vec3, update: boolean = false, trueForce: boolean = false) {
103
+ const { yaw, pitch } = this.bot.util.math.pointToYawAndPitch(this.bot, pos);
104
+ const nyp = { yaw: this.bot.util.math.toNotchianYaw(yaw), pitch: this.bot.util.math.toNotchianPitch(pitch) };
105
+ if (nyp.yaw !== this.lastYaw || nyp.pitch !== this.lastPitch || trueForce) {
106
+ this.bot._client.write("look", { ...nyp, onGround: false });
107
+ if (update) {
108
+ // this.bot.entity.yaw = yaw;
109
+ // this.bot.entity.pitch = pitch
110
+ this.bot.lookAt(pos, true);
111
+ }
112
+ }
113
+ }
114
+
115
+ lazyTeleport(endPos: Vec3) {}
116
+ }