@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,25 @@
1
+ import type { Bot } from "mineflayer";
2
+ import type { Entity } from "prismarine-entity";
3
+ import { Vec3 } from "vec3";
4
+ import { Overwrites, PredictiveWorld } from "./worldRelated/predictiveWorld";
5
+ export declare const ARMOR_THOUGHNESS_KEY = "generic.armorToughness";
6
+ export declare class PredictiveFunctions {
7
+ private bot;
8
+ private damageMultiplier;
9
+ private armorToughnessKey;
10
+ private armorProtectionKey;
11
+ private resistanceIndex;
12
+ world: PredictiveWorld;
13
+ constructor(bot: Bot);
14
+ getDamageWithEffects(damage: number, effects: {
15
+ [id: string]: {
16
+ id: number;
17
+ amplifier: number;
18
+ duration: number;
19
+ };
20
+ }): number;
21
+ placeBlocks(blocks: Overwrites): void;
22
+ removePredictedBlocks(positions: Vec3[], force?: boolean): void;
23
+ selfExplosionDamage(sourcePos: Vec3, power: number, rawDamages?: boolean): number;
24
+ getExplosionDamage(targetEntity: Entity, sourcePos: Vec3, power: number, rawDamages?: boolean): number;
25
+ }
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PredictiveFunctions = exports.ARMOR_THOUGHNESS_KEY = void 0;
7
+ const minecraft_data_1 = __importDefault(require("minecraft-data"));
8
+ const vec3_1 = require("vec3");
9
+ const predictiveWorld_1 = require("./worldRelated/predictiveWorld");
10
+ const armorPieces = ["head", "torso", "legs", "feet"];
11
+ // https://minecraft.fandom.com/wiki/Explosion
12
+ // Use bot.world, there's no typing yet.
13
+ function calcExposure(playerPos, explosionPos, world) {
14
+ const dx = 1 / (0.6 * 2 + 1);
15
+ const dy = 1 / (1.8 * 2 + 1);
16
+ const dz = 1 / (0.6 * 2 + 1);
17
+ const d3 = (1 - Math.floor(1 / dx) * dx) / 2;
18
+ const d4 = (1 - Math.floor(1 / dz) * dz) / 2;
19
+ let sampled = 0;
20
+ let exposed = 0;
21
+ const pos = new vec3_1.Vec3(0, 0, 0);
22
+ for (pos.y = playerPos.y; pos.y <= playerPos.y + 1.8; pos.y += 1.8 * dy) {
23
+ for (pos.x = playerPos.x - 0.3 + d3; pos.x <= playerPos.x + 0.3; pos.x += 0.6 * dx) {
24
+ for (pos.z = playerPos.z - 0.3 + d4; pos.z <= playerPos.z + 0.3; pos.z += 0.6 * dz) {
25
+ const dir = pos.minus(explosionPos);
26
+ const range = dir.norm();
27
+ if (world.raycast(explosionPos, dir.normalize(), range) === null) {
28
+ exposed++;
29
+ }
30
+ sampled++;
31
+ }
32
+ }
33
+ }
34
+ return exposed / sampled;
35
+ }
36
+ // https://minecraft.fandom.com/wiki/Armor#Damage_protection
37
+ function getDamageAfterAbsorb(damages, armorValue, toughness) {
38
+ const var3 = 2 + toughness / 4;
39
+ const var4 = Math.min(Math.max(armorValue - damages / var3, armorValue * 0.2), 20);
40
+ return damages * (1 - var4 / 25);
41
+ }
42
+ // https://minecraft.fandom.com/wiki/Attribute#Operations
43
+ function getAttributeValue(prop) {
44
+ let X = prop.value;
45
+ for (const mod of prop.modifiers) {
46
+ if (mod.operation !== 0)
47
+ continue;
48
+ X += mod.amount;
49
+ }
50
+ let Y = X;
51
+ for (const mod of prop.modifiers) {
52
+ if (mod.operation !== 1)
53
+ continue;
54
+ Y += X * mod.amount;
55
+ }
56
+ for (const mod of prop.modifiers) {
57
+ if (mod.operation !== 2)
58
+ continue;
59
+ Y += Y * mod.amount;
60
+ }
61
+ return Y;
62
+ }
63
+ function getDamageWithEnchantments(damage, equipment) {
64
+ const enchantments = equipment.some((e) => !!e)
65
+ ? equipment
66
+ .map((armor) => {
67
+ var _a;
68
+ return (_a = armor === null || armor === void 0 ? void 0 : armor.enchants.map((enchant) => {
69
+ switch (enchant === null || enchant === void 0 ? void 0 : enchant.name) {
70
+ case "protection":
71
+ return enchant.lvl;
72
+ case "blast_protection":
73
+ return enchant.lvl * 2;
74
+ default:
75
+ return 0;
76
+ }
77
+ }).reduce((b, a) => b + a, 0)) !== null && _a !== void 0 ? _a : [0];
78
+ })
79
+ .reduce((b, a) => b + a, 0)
80
+ : 0;
81
+ return damage * (1 - Math.min(enchantments, 20) / 25);
82
+ }
83
+ const DIFFICULTY_VALUES = {
84
+ peaceful: 0,
85
+ easy: 1,
86
+ normal: 2,
87
+ hard: 3,
88
+ };
89
+ exports.ARMOR_THOUGHNESS_KEY = "generic.armorToughness";
90
+ const AIR_BLOCK = { type: 0 };
91
+ class PredictiveFunctions {
92
+ constructor(bot) {
93
+ this.bot = bot;
94
+ this.damageMultiplier = 7; // for 1.12+ 8 for 1.8 TODO check when the change occur (likely 1.9)
95
+ this.resistanceIndex = "11";
96
+ if (require('minecraft-data')(bot.version).isNewerOrEqualTo("1.16")) {
97
+ this.armorToughnessKey = "generic.armorToughness";
98
+ this.armorProtectionKey = "generic.armor";
99
+ }
100
+ else {
101
+ this.armorToughnessKey = "generic.armorToughness";
102
+ this.armorProtectionKey = "generic.armor";
103
+ }
104
+ const effects = (0, minecraft_data_1.default)(bot.version).effects;
105
+ for (const effectId in effects) {
106
+ const effect = effects[effectId];
107
+ if (effect.name.includes("resistance")) {
108
+ this.resistanceIndex = effectId;
109
+ break;
110
+ }
111
+ }
112
+ this.world = new predictiveWorld_1.PredictiveWorld(bot);
113
+ }
114
+ //There's a mistyping in mineflayer. Effect[] is not accurate. You cannot map over it.
115
+ getDamageWithEffects(damage, effects) {
116
+ var _a, _b;
117
+ const resistanceLevel = (_b = (_a = effects === null || effects === void 0 ? void 0 : effects[this.resistanceIndex]) === null || _a === void 0 ? void 0 : _a.amplifier) !== null && _b !== void 0 ? _b : 0;
118
+ return damage * (1 - resistanceLevel / 5);
119
+ }
120
+ placeBlocks(blocks) {
121
+ this.world.setBlocks(blocks);
122
+ }
123
+ removePredictedBlocks(positions, force = false) {
124
+ this.world.removeBlocks(positions, force);
125
+ }
126
+ selfExplosionDamage(sourcePos, power, rawDamages = false) {
127
+ const distance = this.bot.entity.position.distanceTo(sourcePos);
128
+ const radius = 2 * power;
129
+ if (distance >= radius)
130
+ return 0;
131
+ const exposure = calcExposure(this.bot.entity.position, sourcePos, this.world);
132
+ const impact = (1 - distance / radius) * exposure;
133
+ let damages = Math.floor((impact * impact + impact) * this.damageMultiplier * power + 1);
134
+ // The following modifiers are constant for the input bot.entity and doesnt depend
135
+ // on the source position, so if the goal is to compare between positions they can be
136
+ // ignored to save computations
137
+ if (!rawDamages && this.bot.entity.attributes[this.armorProtectionKey]) {
138
+ const armor = getAttributeValue(this.bot.entity.attributes[this.armorProtectionKey]);
139
+ const armorToughness = getAttributeValue(this.bot.entity.attributes[this.armorToughnessKey]);
140
+ damages = getDamageAfterAbsorb(damages, armor, armorToughness);
141
+ const equipment = armorPieces.map((piece) => this.bot.inventory.slots[this.bot.getEquipmentDestSlot(piece)]);
142
+ damages = getDamageWithEnchantments(damages, equipment);
143
+ damages = this.getDamageWithEffects(damages, this.bot.entity.effects);
144
+ damages *= DIFFICULTY_VALUES[this.bot.game.difficulty] * 0.5;
145
+ }
146
+ return Math.floor(damages);
147
+ }
148
+ getExplosionDamage(targetEntity, sourcePos, power, rawDamages = false) {
149
+ const distance = targetEntity.position.distanceTo(sourcePos);
150
+ const radius = 2 * power;
151
+ if (distance >= radius)
152
+ return 0;
153
+ const exposure = calcExposure(targetEntity.position, sourcePos, this.world);
154
+ const impact = (1 - distance / radius) * exposure;
155
+ let damages = Math.floor((impact * impact + impact) * this.damageMultiplier * power + 1);
156
+ // The following modifiers are constant for the input targetEntity and doesnt depend
157
+ // on the source position, so if the goal is to compare between positions they can be
158
+ // ignored to save computations
159
+ if (!rawDamages && targetEntity.attributes[this.armorProtectionKey]) {
160
+ const armor = getAttributeValue(targetEntity.attributes[this.armorProtectionKey]);
161
+ const armorToughness = getAttributeValue(targetEntity.attributes[this.armorToughnessKey]);
162
+ damages = getDamageAfterAbsorb(damages, armor, armorToughness);
163
+ damages = getDamageWithEnchantments(damages, targetEntity.equipment);
164
+ damages = this.getDamageWithEffects(damages, targetEntity.effects);
165
+ if (targetEntity.type === "player") {
166
+ damages *= DIFFICULTY_VALUES[this.bot.game.difficulty] * 0.5;
167
+ }
168
+ }
169
+ return Math.floor(damages);
170
+ }
171
+ }
172
+ exports.PredictiveFunctions = PredictiveFunctions;
@@ -0,0 +1,50 @@
1
+ /// <reference types="node" />
2
+ import type { Bot, PrioGroups } from "mineflayer";
3
+ import { EntityFunctions } from "./entityFunctions";
4
+ import { FilterFunctions } from "./filterFunctions";
5
+ import { InventoryFunctions } from "./inventoryFunctions";
6
+ import { MovementFunctions } from "./movementFunctions";
7
+ import { PredictiveFunctions } from "./predictiveFunctions";
8
+ import { MathFunctions } from "./mathUtil";
9
+ import { CommonSense } from "./commonSense";
10
+ import { WorldFunctions } from "./WorldFunctions";
11
+ export declare type BuiltInPriorityOptions = {
12
+ group: PrioGroups;
13
+ priority: number;
14
+ returnIfRunning?: boolean;
15
+ errCancel?: boolean;
16
+ };
17
+ export declare type CustomPriorityOptions = {
18
+ priority: number;
19
+ group?: PrioGroups;
20
+ returnIfRunning?: boolean;
21
+ errCancel?: boolean;
22
+ };
23
+ export declare class UtilFunctions {
24
+ bot: Bot;
25
+ inv: InventoryFunctions;
26
+ move: MovementFunctions;
27
+ entity: EntityFunctions;
28
+ predict: PredictiveFunctions;
29
+ filters: FilterFunctions;
30
+ math: MathFunctions;
31
+ commonSense: CommonSense;
32
+ world: WorldFunctions;
33
+ private builtInsPriorityStore;
34
+ private customPriorityStore;
35
+ private builtInCurrentExecuting;
36
+ private customCurrentExecuting;
37
+ constructor(bot: Bot);
38
+ sleep: typeof import("timers/promises").setTimeout;
39
+ isBuiltInsEmpty(name?: string): boolean;
40
+ isCustomEmpty(name?: string): boolean;
41
+ /**
42
+ *
43
+ * @param object \{priority, errCancel} => priority of function (highest order first), throw error if already running a function.
44
+ * @param func any custom function.
45
+ * @param args the arguments of passed in function.
46
+ * @returns Error if errCancel and already executing, otherwise result of function.
47
+ */
48
+ customPriority<K extends (...args: any) => any>({ priority, group, returnIfRunning, errCancel }: CustomPriorityOptions, func: K, ...args: Parameters<K>): number | Promise<ReturnType<K> | Error>;
49
+ builtInsPriority<K extends (...args: any) => any>({ group, priority, returnIfRunning, errCancel }: BuiltInPriorityOptions, func: K, ...args: Parameters<K>): number | Promise<ReturnType<K> | Error>;
50
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UtilFunctions = void 0;
13
+ const entityFunctions_1 = require("./entityFunctions");
14
+ const filterFunctions_1 = require("./filterFunctions");
15
+ const inventoryFunctions_1 = require("./inventoryFunctions");
16
+ const movementFunctions_1 = require("./movementFunctions");
17
+ const util_1 = require("util");
18
+ const predictiveFunctions_1 = require("./predictiveFunctions");
19
+ const mathUtil_1 = require("./mathUtil");
20
+ const commonSense_1 = require("./commonSense");
21
+ const WorldFunctions_1 = require("./WorldFunctions");
22
+ class UtilFunctions {
23
+ constructor(bot) {
24
+ this.bot = bot;
25
+ this.sleep = (0, util_1.promisify)(setTimeout);
26
+ this.inv = new inventoryFunctions_1.InventoryFunctions(bot);
27
+ this.move = new movementFunctions_1.MovementFunctions(bot);
28
+ this.entity = new entityFunctions_1.EntityFunctions(bot);
29
+ this.predict = new predictiveFunctions_1.PredictiveFunctions(bot);
30
+ this.filters = new filterFunctions_1.FilterFunctions(bot);
31
+ this.commonSense = new commonSense_1.CommonSense(bot);
32
+ this.world = new WorldFunctions_1.WorldFunctions(bot);
33
+ this.math = new mathUtil_1.MathFunctions();
34
+ this.builtInsPriorityStore = {};
35
+ this.customPriorityStore = {};
36
+ this.builtInCurrentExecuting = {};
37
+ this.customCurrentExecuting = {};
38
+ }
39
+ isBuiltInsEmpty(name) {
40
+ var _a;
41
+ if (name) {
42
+ return !((_a = this.builtInsPriorityStore[name]) === null || _a === void 0 ? void 0 : _a.length) || !this.builtInCurrentExecuting[name];
43
+ }
44
+ else {
45
+ return !Object.values(this.builtInsPriorityStore).length || !Object.values(this.builtInCurrentExecuting).length;
46
+ }
47
+ }
48
+ isCustomEmpty(name) {
49
+ var _a;
50
+ if (name) {
51
+ return !((_a = this.customPriorityStore[name]) === null || _a === void 0 ? void 0 : _a.length) && !this.customCurrentExecuting[name];
52
+ }
53
+ else {
54
+ return !Object.values(this.customPriorityStore).length && !Object.values(this.customCurrentExecuting).length;
55
+ }
56
+ }
57
+ /**
58
+ *
59
+ * @param object \{priority, errCancel} => priority of function (highest order first), throw error if already running a function.
60
+ * @param func any custom function.
61
+ * @param args the arguments of passed in function.
62
+ * @returns Error if errCancel and already executing, otherwise result of function.
63
+ */
64
+ customPriority({ priority, group, returnIfRunning, errCancel }, func, ...args) {
65
+ var _a, _b;
66
+ var _c;
67
+ const name = (_a = group !== null && group !== void 0 ? group : func.name) !== null && _a !== void 0 ? _a : "anonymous";
68
+ const actionQueue = ((_b = (_c = this.customPriorityStore)[name]) !== null && _b !== void 0 ? _b : (_c[name] = []));
69
+ // console.log("custom", group ?? func.name ?? "anonymous", actionQueue, this.isCustomEmpty(name))
70
+ if (errCancel && actionQueue.length > 1)
71
+ throw "already executing";
72
+ if (returnIfRunning && !this.isCustomEmpty(name))
73
+ return 1;
74
+ // console.log("running.")
75
+ return new Promise((res, rej) => __awaiter(this, void 0, void 0, function* () {
76
+ var _d, _e;
77
+ const currentlyExecuting = actionQueue.shift();
78
+ if (currentlyExecuting)
79
+ this.customCurrentExecuting[(_d = group !== null && group !== void 0 ? group : currentlyExecuting[1].name) !== null && _d !== void 0 ? _d : "anonymous"] = currentlyExecuting;
80
+ const index = actionQueue.findIndex(([prio]) => priority > prio);
81
+ actionQueue.splice(index === -1 ? actionQueue.length : index, 0, [
82
+ priority,
83
+ () => __awaiter(this, void 0, void 0, function* () {
84
+ var _f;
85
+ try {
86
+ res(yield func(...args));
87
+ }
88
+ catch (e) {
89
+ rej(e);
90
+ }
91
+ actionQueue.shift();
92
+ yield ((_f = actionQueue[0]) === null || _f === void 0 ? void 0 : _f[1]());
93
+ }),
94
+ ]);
95
+ if (currentlyExecuting) {
96
+ actionQueue.unshift(currentlyExecuting);
97
+ this.customCurrentExecuting[(_e = group !== null && group !== void 0 ? group : currentlyExecuting[1].name) !== null && _e !== void 0 ? _e : "anonymous"] = undefined;
98
+ }
99
+ else
100
+ yield actionQueue[0][1]();
101
+ }));
102
+ }
103
+ builtInsPriority({ group, priority, returnIfRunning, errCancel }, func, ...args) {
104
+ var _a;
105
+ var _b;
106
+ const actionQueue = ((_a = (_b = this.builtInsPriorityStore)[group]) !== null && _a !== void 0 ? _a : (_b[group] = []));
107
+ // console.log("builtin", group, actionQueue)
108
+ if (errCancel && !this.isBuiltInsEmpty(group))
109
+ throw "already executing";
110
+ if (returnIfRunning && !this.isBuiltInsEmpty(group))
111
+ return 1;
112
+ return new Promise((res, rej) => __awaiter(this, void 0, void 0, function* () {
113
+ const currentlyExecuting = actionQueue.shift();
114
+ if (currentlyExecuting)
115
+ this.customCurrentExecuting[group] = currentlyExecuting;
116
+ const index = actionQueue.findIndex(([prio]) => priority > prio);
117
+ actionQueue.splice(index === -1 ? actionQueue.length : index, 0, [
118
+ priority,
119
+ () => __awaiter(this, void 0, void 0, function* () {
120
+ var _c;
121
+ try {
122
+ res(yield func.bind(this.bot)(...args));
123
+ }
124
+ catch (e) {
125
+ rej(e);
126
+ }
127
+ actionQueue.shift();
128
+ yield ((_c = actionQueue[0]) === null || _c === void 0 ? void 0 : _c[1]());
129
+ }),
130
+ ]);
131
+ if (currentlyExecuting) {
132
+ actionQueue.unshift(currentlyExecuting);
133
+ this.builtInCurrentExecuting[group] = undefined;
134
+ }
135
+ else
136
+ yield actionQueue[0][1]();
137
+ }));
138
+ }
139
+ }
140
+ exports.UtilFunctions = UtilFunctions;
@@ -0,0 +1,41 @@
1
+ import type { Bot } from "mineflayer";
2
+ import type { Block } from "prismarine-block";
3
+ import { Vec3 } from "vec3";
4
+ export declare type Overwrites = {
5
+ [coord: string]: Block | null;
6
+ };
7
+ /**
8
+ * A class dedicated to predictive logic.
9
+ *
10
+ * Currently, this class can predict explosion damages of crystals using a custom world.
11
+ */
12
+ export declare class PredictiveWorld {
13
+ bot: Bot;
14
+ private blocks;
15
+ constructor(bot: Bot);
16
+ raycast(from: Vec3, direction: Vec3, range: number, matcher?: ((block: Block) => boolean) | null): Block | null;
17
+ /**
18
+ * this works
19
+ * @param {Block} block
20
+ */
21
+ setBlock(pos: Vec3, block: Block): void;
22
+ /**
23
+ * @param {Overwrites} blocks Blocks indexed by position.toString()
24
+ */
25
+ setBlocks(blocks: Overwrites): void;
26
+ /**
27
+ * @param {Vec3} pos
28
+ * @returns {Block} Block at position.
29
+ */
30
+ getBlock(pos: Vec3): Block | null;
31
+ removeBlock(pos: Vec3, force: boolean): void;
32
+ removeBlocks(positions: Vec3[], force: boolean): void;
33
+ /**
34
+ * @param playerPos Position of effected entity.
35
+ * @param explosionPos Position of explosion origin.
36
+ * @param block bot.block
37
+ * @returns List of affected blocks that potentially protect the entity.
38
+ */
39
+ getExplosionAffectedBlocks(playerPos: Vec3, explosionPos: Vec3): Overwrites;
40
+ loadExplosionAffectedBlocks(playerPos: Vec3, explosionPos: Vec3): void;
41
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PredictiveWorld = void 0;
4
+ const vec3_1 = require("vec3");
5
+ const raycastIterator_1 = require("./raycastIterator");
6
+ /**
7
+ * A class dedicated to predictive logic.
8
+ *
9
+ * Currently, this class can predict explosion damages of crystals using a custom world.
10
+ */
11
+ class PredictiveWorld {
12
+ constructor(bot) {
13
+ this.bot = bot;
14
+ this.blocks = {};
15
+ }
16
+ raycast(from, direction, range, matcher = null) {
17
+ const iter = new raycastIterator_1.RaycastIterator(from, direction, range);
18
+ let pos = iter.next();
19
+ while (pos) {
20
+ const position = new vec3_1.Vec3(pos.x, pos.y, pos.z);
21
+ const block = this.getBlock(position);
22
+ if (block && (!matcher || matcher(block))) {
23
+ const intersect = iter.intersect(block.shapes, position);
24
+ if (intersect) {
25
+ //@ts-expect-error 2
26
+ block.face = intersect.face;
27
+ //@ts-expect-error
28
+ block.intersect = intersect.pos;
29
+ return block;
30
+ }
31
+ }
32
+ pos = iter.next();
33
+ }
34
+ return null;
35
+ }
36
+ /**
37
+ * this works
38
+ * @param {Block} block
39
+ */
40
+ setBlock(pos, block) {
41
+ var _a;
42
+ var _b, _c;
43
+ (_a = (_b = this.blocks)[_c = pos.toString()]) !== null && _a !== void 0 ? _a : (_b[_c] = block);
44
+ }
45
+ /**
46
+ * @param {Overwrites} blocks Blocks indexed by position.toString()
47
+ */
48
+ setBlocks(blocks) {
49
+ for (const index in blocks)
50
+ this.blocks[index] = blocks[index];
51
+ }
52
+ /**
53
+ * @param {Vec3} pos
54
+ * @returns {Block} Block at position.
55
+ */
56
+ getBlock(pos) {
57
+ const pblock = this.blocks[pos.toString()];
58
+ if (pblock !== undefined && pblock !== null)
59
+ return pblock;
60
+ return this.bot.blockAt(pos);
61
+ }
62
+ removeBlock(pos, force) {
63
+ if (force) {
64
+ delete this.blocks[pos.toString()];
65
+ }
66
+ else {
67
+ const realBlock = this.bot.blockAt(pos);
68
+ if (realBlock)
69
+ this.blocks[pos.toString()] = realBlock;
70
+ else
71
+ delete this.blocks[pos.toString()];
72
+ }
73
+ }
74
+ removeBlocks(positions, force) {
75
+ positions.forEach((pos) => this.removeBlock(pos, force));
76
+ }
77
+ /**
78
+ * @param playerPos Position of effected entity.
79
+ * @param explosionPos Position of explosion origin.
80
+ * @param block bot.block
81
+ * @returns List of affected blocks that potentially protect the entity.
82
+ */
83
+ getExplosionAffectedBlocks(playerPos, explosionPos) {
84
+ let blocks = {};
85
+ const dx = 1 / (0.6 * 2 + 1);
86
+ const dy = 1 / (1.8 * 2 + 1);
87
+ const dz = 1 / (0.6 * 2 + 1);
88
+ const d3 = (1 - Math.floor(1 / dx) * dx) / 2;
89
+ const d4 = (1 - Math.floor(1 / dz) * dz) / 2;
90
+ const pos = new vec3_1.Vec3(0, 0, 0);
91
+ for (pos.y = playerPos.y; pos.y <= playerPos.y + 1.8; pos.y += 1.8 * dy) {
92
+ for (pos.x = playerPos.x - 0.3 + d3; pos.x <= playerPos.x + 0.3; pos.x += 0.6 * dx) {
93
+ for (pos.z = playerPos.z - 0.3 + d4; pos.z <= playerPos.z + 0.3; pos.z += 0.6 * dz) {
94
+ const dir = pos.minus(explosionPos);
95
+ const range = dir.norm();
96
+ const potentialBlock = this.raycast(explosionPos, dir.normalize(), range);
97
+ if (potentialBlock !== null)
98
+ blocks[potentialBlock.position.toString()] = potentialBlock;
99
+ }
100
+ }
101
+ }
102
+ return blocks;
103
+ }
104
+ loadExplosionAffectedBlocks(playerPos, explosionPos) {
105
+ this.setBlocks(this.getExplosionAffectedBlocks(playerPos, explosionPos));
106
+ }
107
+ }
108
+ exports.PredictiveWorld = PredictiveWorld;
@@ -0,0 +1,45 @@
1
+ import { Vec3 } from "vec3";
2
+ export declare enum BlockFace {
3
+ UNKNOWN = -999,
4
+ BOTTOM = 0,
5
+ TOP = 1,
6
+ NORTH = 2,
7
+ SOUTH = 3,
8
+ WEST = 4,
9
+ EAST = 5
10
+ }
11
+ export declare class RaycastIterator {
12
+ block: {
13
+ x: number;
14
+ y: number;
15
+ z: number;
16
+ face: number;
17
+ };
18
+ blockVec: Vec3;
19
+ pos: Vec3;
20
+ dir: Vec3;
21
+ invDirX: number;
22
+ invDirY: number;
23
+ invDirZ: number;
24
+ stepX: number;
25
+ stepY: number;
26
+ stepZ: number;
27
+ tDeltaX: number;
28
+ tDeltaY: number;
29
+ tDeltaZ: number;
30
+ tMaxX: number;
31
+ tMaxY: number;
32
+ tMaxZ: number;
33
+ maxDistance: number;
34
+ constructor(pos: Vec3, dir: Vec3, maxDistance: number);
35
+ intersect(shapes: [x0: BlockFace, y0: BlockFace, z0: BlockFace, x1: BlockFace, y1: BlockFace, z1: BlockFace][], offset: Vec3): {
36
+ pos: Vec3;
37
+ face: BlockFace;
38
+ } | null;
39
+ next(): {
40
+ x: number;
41
+ y: number;
42
+ z: number;
43
+ face: number;
44
+ } | null;
45
+ }