@nxg-org/mineflayer-physics-util 1.8.13 → 1.8.15
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.
- package/.vscode/settings.json +4 -4
- package/README.md +1 -1
- package/dist/physics/engines/botcraft.js +21 -7
- package/dist/physics/states/playerState.js +1 -1
- package/dist/simulators/baseSimulator.d.ts +1 -1
- package/eslint.config.mjs +17 -17
- package/package.json +46 -46
- package/tests/actualBot.ts +198 -198
- package/tests/fakeWorld.test.ts +354 -354
- package/tests/predictBot.ts +73 -73
- package/tests/util/testUtils.ts +67 -67
package/.vscode/settings.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"print.colourScheme": "GitHub",
|
|
3
|
-
"ecl.launchConfiguration": "not found",
|
|
4
|
-
"ecl.targetCluster": {}
|
|
1
|
+
{
|
|
2
|
+
"print.colourScheme": "GitHub",
|
|
3
|
+
"ecl.launchConfiguration": "not found",
|
|
4
|
+
"ecl.targetCluster": {}
|
|
5
5
|
}
|
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
# mineflayer-physics-utils
|
|
1
|
+
# mineflayer-physics-utils
|
|
@@ -223,13 +223,14 @@ class BotcraftPhysics {
|
|
|
223
223
|
physicsTick(ctx, world) {
|
|
224
224
|
// Check for rocket boosting if currently in elytra flying mode
|
|
225
225
|
const entity = ctx.state;
|
|
226
|
-
if (ctx.state.elytraFlying) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
226
|
+
// if (ctx.state.elytraFlying) {
|
|
227
|
+
// // TODO: entity check for fireworks
|
|
228
|
+
// // TODO: check if firework is attached to player
|
|
229
|
+
// if (false) {
|
|
230
|
+
// // player->speed += player->front_vector * 0.1 + (player->front_vector * 1.5 - player->speed) * 0.5;
|
|
231
|
+
// }
|
|
232
|
+
// }
|
|
233
|
+
// for now, only check if this is a player.
|
|
233
234
|
const playerFlag = ctx.entityType.type === "player";
|
|
234
235
|
this.fluidPhysics(ctx, world, true);
|
|
235
236
|
this.fluidPhysics(ctx, world, false);
|
|
@@ -940,8 +941,21 @@ class BotcraftPhysics {
|
|
|
940
941
|
if (player.onGround) {
|
|
941
942
|
player.fallFlying = false;
|
|
942
943
|
}
|
|
944
|
+
// Potentially not the correct place for this logic, but it is easier to implement here for now. This is the firework boost from elytra flying.
|
|
945
|
+
if (player.fireworkRocketDuration > 0) {
|
|
946
|
+
const { lookDir } = (0, physicsUtils_1.getLookingVector)(player);
|
|
947
|
+
player.vel.x += lookDir.x * 0.1 + (lookDir.x * 1.5 - player.vel.x) * 0.5;
|
|
948
|
+
player.vel.y += lookDir.y * 0.1 + (lookDir.y * 1.5 - player.vel.y) * 0.5;
|
|
949
|
+
player.vel.z += lookDir.z * 0.1 + (lookDir.z * 1.5 - player.vel.z) * 0.5;
|
|
950
|
+
--player.fireworkRocketDuration;
|
|
951
|
+
}
|
|
952
|
+
// we're on ground or in air, not flying.
|
|
943
953
|
}
|
|
944
954
|
else {
|
|
955
|
+
// clear firework boost if on ground or in air without flying, otherwise it can cause issues with movement.
|
|
956
|
+
if (player.fireworkRocketDuration > 0) {
|
|
957
|
+
player.fireworkRocketDuration = 0;
|
|
958
|
+
}
|
|
945
959
|
const blockBelow = world.getBlock(this.getBlockBelowAffectingMovement(player, world));
|
|
946
960
|
// deviation. using our stores slipperiness values.
|
|
947
961
|
const friction = blockBelow
|
|
@@ -13,7 +13,7 @@ export declare class BaseSimulator<State extends IEntityState = IEntityState> {
|
|
|
13
13
|
predictGenerator(simCtx: EPhysicsCtx<State>, world: any, ticks?: number, controls?: ControlStateHandler): Generator<IEntityState, EPhysicsCtx<State>, unknown>;
|
|
14
14
|
predictForward(target: Entity, world: any, ticks?: number, controls?: ControlStateHandler): EntityState;
|
|
15
15
|
predictForwardRaw(simCtx: EPhysicsCtx<State>, world: any, ticks?: number, controls?: ControlStateHandler): State;
|
|
16
|
-
simulateUntil(goal: SimulationGoal
|
|
16
|
+
simulateUntil(goal: SimulationGoal<State>, onGoalReach: OnGoalReachFunction<State>, controller: Controller<State>, simCtx: EPhysicsCtx<State>, world: any, ticks?: number): State;
|
|
17
17
|
static getReached<State extends IEntityState = IEntityState>(...path: Vec3[]): SimulationGoal<State>;
|
|
18
18
|
static getCleanupPosition<State extends IEntityState = IEntityState>(...path: Vec3[]): OnGoalReachFunction<State>;
|
|
19
19
|
static buildFullController<State extends IEntityState = IEntityState>(...controllers: Controller<State>[]): Controller<State>;
|
package/eslint.config.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { defineConfig } from "eslint/config";
|
|
2
|
-
import globals from "globals";
|
|
3
|
-
import js from "@eslint/js";
|
|
4
|
-
import tseslint from "typescript-eslint";
|
|
5
|
-
|
|
6
|
-
export default defineConfig([
|
|
7
|
-
{
|
|
8
|
-
files: ["**/*.{ts,tsx}"], // Only check TypeScript files
|
|
9
|
-
languageOptions: { globals: globals.browser }
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
files: ["**/*.{ts,tsx}"], // Only check TypeScript files
|
|
13
|
-
plugins: { js },
|
|
14
|
-
extends: ["js/recommended"]
|
|
15
|
-
},
|
|
16
|
-
tseslint.configs.recommended,
|
|
17
|
-
]);
|
|
1
|
+
import { defineConfig } from "eslint/config";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import js from "@eslint/js";
|
|
4
|
+
import tseslint from "typescript-eslint";
|
|
5
|
+
|
|
6
|
+
export default defineConfig([
|
|
7
|
+
{
|
|
8
|
+
files: ["**/*.{ts,tsx}"], // Only check TypeScript files
|
|
9
|
+
languageOptions: { globals: globals.browser }
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
files: ["**/*.{ts,tsx}"], // Only check TypeScript files
|
|
13
|
+
plugins: { js },
|
|
14
|
+
extends: ["js/recommended"]
|
|
15
|
+
},
|
|
16
|
+
tseslint.configs.recommended,
|
|
17
|
+
]);
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nxg-org/mineflayer-physics-util",
|
|
3
|
-
"version": "1.8.
|
|
4
|
-
"description": "Provides functionality for more accurate entity and projectile tracking.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"mineflayer",
|
|
7
|
-
"mineflayer-plugin",
|
|
8
|
-
"mineflayer-tracker"
|
|
9
|
-
],
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/nxg-org/mineflayer-physics-utils.git"
|
|
13
|
-
},
|
|
14
|
-
"license": "GPL-3.0",
|
|
15
|
-
"author": "generel_schwerz",
|
|
16
|
-
"main": "dist/index.js",
|
|
17
|
-
"types": "dist/index.d.ts",
|
|
18
|
-
"scripts": {
|
|
19
|
-
"lint": "eslint . --ext .ts,.tsx",
|
|
20
|
-
"build": "npx tsc",
|
|
21
|
-
"prepublishOnly": "npm run build",
|
|
22
|
-
"test": "mocha --require ts-node/register --recursive tests/**/*.test.ts"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@nxg-org/mineflayer-util-plugin": "^1.8.2"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@eslint/js": "^9.23.0",
|
|
29
|
-
"@types/mocha": "^10.0.10",
|
|
30
|
-
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
|
31
|
-
"@typescript-eslint/parser": "^8.27.0",
|
|
32
|
-
"eslint": "^9.23.0",
|
|
33
|
-
"expect": "^29.7.0",
|
|
34
|
-
"globals": "^16.0.0",
|
|
35
|
-
"minecraft-data": "^3.83.1",
|
|
36
|
-
"mineflayer": "^4.26.0",
|
|
37
|
-
"mineflayer-pathfinder": "^2.4.4",
|
|
38
|
-
"mocha": "^11.1.0",
|
|
39
|
-
"prismarine-entity": "^2.4.0",
|
|
40
|
-
"prismarine-registry": "^1.11.0",
|
|
41
|
-
"ts-node": "^10.9.2",
|
|
42
|
-
"typescript": "^5.8.2",
|
|
43
|
-
"typescript-eslint": "^8.27.0"
|
|
44
|
-
},
|
|
45
|
-
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@nxg-org/mineflayer-physics-util",
|
|
3
|
+
"version": "1.8.15",
|
|
4
|
+
"description": "Provides functionality for more accurate entity and projectile tracking.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mineflayer",
|
|
7
|
+
"mineflayer-plugin",
|
|
8
|
+
"mineflayer-tracker"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/nxg-org/mineflayer-physics-utils.git"
|
|
13
|
+
},
|
|
14
|
+
"license": "GPL-3.0",
|
|
15
|
+
"author": "generel_schwerz",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
20
|
+
"build": "npx tsc",
|
|
21
|
+
"prepublishOnly": "npm run build",
|
|
22
|
+
"test": "mocha --require ts-node/register --recursive tests/**/*.test.ts"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@nxg-org/mineflayer-util-plugin": "^1.8.2"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@eslint/js": "^9.23.0",
|
|
29
|
+
"@types/mocha": "^10.0.10",
|
|
30
|
+
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
|
31
|
+
"@typescript-eslint/parser": "^8.27.0",
|
|
32
|
+
"eslint": "^9.23.0",
|
|
33
|
+
"expect": "^29.7.0",
|
|
34
|
+
"globals": "^16.0.0",
|
|
35
|
+
"minecraft-data": "^3.83.1",
|
|
36
|
+
"mineflayer": "^4.26.0",
|
|
37
|
+
"mineflayer-pathfinder": "^2.4.4",
|
|
38
|
+
"mocha": "^11.1.0",
|
|
39
|
+
"prismarine-entity": "^2.4.0",
|
|
40
|
+
"prismarine-registry": "^1.11.0",
|
|
41
|
+
"ts-node": "^10.9.2",
|
|
42
|
+
"typescript": "^5.8.2",
|
|
43
|
+
"typescript-eslint": "^8.27.0"
|
|
44
|
+
},
|
|
45
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
46
|
+
}
|
package/tests/actualBot.ts
CHANGED
|
@@ -1,198 +1,198 @@
|
|
|
1
|
-
import { pathfinder, goals } from "mineflayer-pathfinder";
|
|
2
|
-
import { Bot, createBot } from "mineflayer";
|
|
3
|
-
const physicsInject = require("mineflayer/lib/plugins/physics");
|
|
4
|
-
import loader, { BotcraftPhysics, EntityPhysics, EntityState, EPhysicsCtx } from "../src/index";
|
|
5
|
-
import { PlayerState } from "../src/physics/states";
|
|
6
|
-
|
|
7
|
-
const { Physics } = require("prismarine-physics");
|
|
8
|
-
|
|
9
|
-
const rl = require("readline").createInterface({
|
|
10
|
-
input: process.stdin,
|
|
11
|
-
output: process.stdout,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
let bot1: Bot;
|
|
15
|
-
function buildBot() {
|
|
16
|
-
console.log("hey!");
|
|
17
|
-
|
|
18
|
-
const bot = createBot({
|
|
19
|
-
host: process.argv[2] || 'localhost',
|
|
20
|
-
port: Number(process.argv[3]),
|
|
21
|
-
username: "testingbot",
|
|
22
|
-
version: process.argv[4],
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
bot.on('login', () => {
|
|
26
|
-
bot.chat("Hello! I am a testing bot!");
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
bot.once("spawn", async () => {
|
|
30
|
-
bot.loadPlugin(loader);
|
|
31
|
-
bot.loadPlugin(pathfinder);
|
|
32
|
-
await bot.waitForTicks(20);
|
|
33
|
-
(bot as any).physics.yawSpeed = 50;
|
|
34
|
-
(bot as any).physics.pitchSpeed = 50;
|
|
35
|
-
setupNewPhysics(bot);
|
|
36
|
-
// setupNewPhysics(bot);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
bot.on('entityMoved', (entity => {
|
|
40
|
-
// if (entity !== bot.entity)
|
|
41
|
-
// console.log(entity.attributes)
|
|
42
|
-
}))
|
|
43
|
-
|
|
44
|
-
let wasOnGround = false;
|
|
45
|
-
const printNextPos = false;
|
|
46
|
-
|
|
47
|
-
bot.on("move", (pos) => {
|
|
48
|
-
// console.log(pos);
|
|
49
|
-
if (bot.entity.onGround && !wasOnGround) {
|
|
50
|
-
// bot.chat("Hit the ground! " + bot.entity.position.toString());
|
|
51
|
-
}
|
|
52
|
-
wasOnGround = bot.entity.onGround;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// print whenever another player hits the ground
|
|
56
|
-
const lastPositions: Record<string, boolean> = {};
|
|
57
|
-
bot.on("entityMoved", (entity) => {
|
|
58
|
-
if (entity.username && entity.username !== bot.username) {
|
|
59
|
-
// check by seeing is y value is an integer
|
|
60
|
-
if (Math.floor(entity.position.y) === entity.position.y && !lastPositions[entity.username]) {
|
|
61
|
-
// check if in liquid
|
|
62
|
-
const block = bot.blockAt(entity.position);
|
|
63
|
-
if (block && (block.type === bot.registry.blocksByName.water.id || block.type === bot.registry.blocksByName.lava.id)) return;
|
|
64
|
-
|
|
65
|
-
bot.chat(`${entity.username} hit the ground! ${entity.position.toString()}`);
|
|
66
|
-
lastPositions[entity.username] = true;
|
|
67
|
-
} else if (Math.floor(entity.position.y) !== entity.position.y) {
|
|
68
|
-
lastPositions[entity.username] = false;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
let usingNew = false;
|
|
74
|
-
let oldSimulate: any = null;
|
|
75
|
-
let state: PlayerState | null = null;
|
|
76
|
-
|
|
77
|
-
function setupNewPhysics(bot: Bot) {
|
|
78
|
-
if (usingNew) return;
|
|
79
|
-
usingNew = true;
|
|
80
|
-
oldSimulate = (bot.physics as any).simulatePlayer;
|
|
81
|
-
|
|
82
|
-
const val = new BotcraftPhysics(bot.registry);
|
|
83
|
-
|
|
84
|
-
(EntityState.prototype as any).apply = function (this: EntityState, bot: Bot) {
|
|
85
|
-
console.log(this.control, this.isUsingItem);
|
|
86
|
-
this.applyToBot(bot);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const ctx = EPhysicsCtx.FROM_BOT(val, bot);
|
|
90
|
-
state = ctx.state as PlayerState;
|
|
91
|
-
|
|
92
|
-
// EntityPhysics.prototype.simulate = function (ctx, world) {
|
|
93
|
-
// bot.physics.simulatePlayer(ctx.state, world);
|
|
94
|
-
// }
|
|
95
|
-
|
|
96
|
-
(bot.physics as any).autojumpCooldown = 0;
|
|
97
|
-
// (bot.physics).jumpTicks = 0;
|
|
98
|
-
|
|
99
|
-
(bot.physics as any).simulatePlayer = (...args: any[]) => {
|
|
100
|
-
state!.update(bot);
|
|
101
|
-
ctx.state.jumpTicks = 0; // allow immediate jumping
|
|
102
|
-
return val.simulate(ctx, bot.world);
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
bot.on("chat", async (user, message) => {
|
|
107
|
-
const [cmd, ...args] = message.split(" ");
|
|
108
|
-
const author = bot.nearestEntity((e) => e.username === user);
|
|
109
|
-
|
|
110
|
-
switch (cmd) {
|
|
111
|
-
case "using":
|
|
112
|
-
bot.chat(`Using new physics: ${usingNew}`);
|
|
113
|
-
break;
|
|
114
|
-
case "lookatme":
|
|
115
|
-
if (!author) return bot.chat("I can't see you!");
|
|
116
|
-
bot.lookAt(author.position.offset(0, author.height, 0));
|
|
117
|
-
break;
|
|
118
|
-
case "status":
|
|
119
|
-
const str0 = `pos: ${bot.entity.position.toString()}, vel: ${bot.entity.velocity.toString()}, yaw: ${bot.entity.yaw}, pitch: ${bot.entity.pitch}`;
|
|
120
|
-
bot.chat(str0);
|
|
121
|
-
|
|
122
|
-
const str = `onGround: ${bot.entity.onGround}, hCol: ${(bot.entity as any).isCollidedHorizontally}, vCol: ${
|
|
123
|
-
(bot.entity as any).isCollidedVertically
|
|
124
|
-
}, inWater: ${(bot.entity as any).isInWater}, inLava: ${(bot.entity as any).isInLava}`;
|
|
125
|
-
bot.chat(str);
|
|
126
|
-
|
|
127
|
-
if (state != null) {
|
|
128
|
-
const str1 = `crouching: ${state.crouching}, sprinting: ${state.sprinting}`;
|
|
129
|
-
bot.chat(str1);
|
|
130
|
-
}
|
|
131
|
-
break;
|
|
132
|
-
case "use":
|
|
133
|
-
if (bot.usingHeldItem) bot.deactivateItem();
|
|
134
|
-
else bot.activateItem();
|
|
135
|
-
break;
|
|
136
|
-
case "useoff":
|
|
137
|
-
bot.deactivateItem();
|
|
138
|
-
bot.activateItem(true);
|
|
139
|
-
break;
|
|
140
|
-
case "control":
|
|
141
|
-
if (args[0] === "clear") return bot.clearControlStates();
|
|
142
|
-
if (args.length === 1) return bot.setControlState(args[0] as any, !bot.getControlState(args[0] as any));
|
|
143
|
-
bot.setControlState(args[0] as any, args[1] === "true");
|
|
144
|
-
break;
|
|
145
|
-
case "sim":
|
|
146
|
-
// turn all but the mentioned ones off
|
|
147
|
-
const [time, ...controls] = args;
|
|
148
|
-
bot.clearControlStates();
|
|
149
|
-
for (const control of controls) {
|
|
150
|
-
bot.setControlState(control as any, true);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
for (let i = 0; i <= Number(time); i++) {
|
|
154
|
-
console.log(bot.entity.position, bot.entity.velocity, i);
|
|
155
|
-
await bot.waitForTicks(1);
|
|
156
|
-
}
|
|
157
|
-
bot.clearControlStates();
|
|
158
|
-
|
|
159
|
-
break;
|
|
160
|
-
case "reset":
|
|
161
|
-
usingNew = false;
|
|
162
|
-
bot.quit();
|
|
163
|
-
await new Promise((res) => setTimeout(res, 3000));
|
|
164
|
-
bot1 = buildBot();
|
|
165
|
-
|
|
166
|
-
break;
|
|
167
|
-
case "new":
|
|
168
|
-
setupNewPhysics(bot);
|
|
169
|
-
bot.chat("Switched to new physics!");
|
|
170
|
-
break;
|
|
171
|
-
case "jump":
|
|
172
|
-
bot.setControlState("jump", true);
|
|
173
|
-
break;
|
|
174
|
-
case "come":
|
|
175
|
-
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
176
|
-
const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3);
|
|
177
|
-
bot.pathfinder.setGoal(goal0);
|
|
178
|
-
break;
|
|
179
|
-
case "goto":
|
|
180
|
-
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
181
|
-
const goal1 = new goals.GoalNear(Number(args[0]), Number(args[1]), Number(args[2]), 3);
|
|
182
|
-
bot.pathfinder.setGoal(goal1);
|
|
183
|
-
break;
|
|
184
|
-
case "stop":
|
|
185
|
-
bot.deactivateItem();
|
|
186
|
-
bot.pathfinder.stop();
|
|
187
|
-
bot.clearControlStates();
|
|
188
|
-
bot.chat("Stopped!");
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
rl.on("line", (line: any) => bot.chat(line));
|
|
194
|
-
|
|
195
|
-
return bot;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
bot1 = buildBot();
|
|
1
|
+
import { pathfinder, goals } from "mineflayer-pathfinder";
|
|
2
|
+
import { Bot, createBot } from "mineflayer";
|
|
3
|
+
const physicsInject = require("mineflayer/lib/plugins/physics");
|
|
4
|
+
import loader, { BotcraftPhysics, EntityPhysics, EntityState, EPhysicsCtx } from "../src/index";
|
|
5
|
+
import { PlayerState } from "../src/physics/states";
|
|
6
|
+
|
|
7
|
+
const { Physics } = require("prismarine-physics");
|
|
8
|
+
|
|
9
|
+
const rl = require("readline").createInterface({
|
|
10
|
+
input: process.stdin,
|
|
11
|
+
output: process.stdout,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
let bot1: Bot;
|
|
15
|
+
function buildBot() {
|
|
16
|
+
console.log("hey!");
|
|
17
|
+
|
|
18
|
+
const bot = createBot({
|
|
19
|
+
host: process.argv[2] || 'localhost',
|
|
20
|
+
port: Number(process.argv[3]),
|
|
21
|
+
username: "testingbot",
|
|
22
|
+
version: process.argv[4],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
bot.on('login', () => {
|
|
26
|
+
bot.chat("Hello! I am a testing bot!");
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
bot.once("spawn", async () => {
|
|
30
|
+
bot.loadPlugin(loader);
|
|
31
|
+
bot.loadPlugin(pathfinder);
|
|
32
|
+
await bot.waitForTicks(20);
|
|
33
|
+
(bot as any).physics.yawSpeed = 50;
|
|
34
|
+
(bot as any).physics.pitchSpeed = 50;
|
|
35
|
+
setupNewPhysics(bot);
|
|
36
|
+
// setupNewPhysics(bot);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
bot.on('entityMoved', (entity => {
|
|
40
|
+
// if (entity !== bot.entity)
|
|
41
|
+
// console.log(entity.attributes)
|
|
42
|
+
}))
|
|
43
|
+
|
|
44
|
+
let wasOnGround = false;
|
|
45
|
+
const printNextPos = false;
|
|
46
|
+
|
|
47
|
+
bot.on("move", (pos) => {
|
|
48
|
+
// console.log(pos);
|
|
49
|
+
if (bot.entity.onGround && !wasOnGround) {
|
|
50
|
+
// bot.chat("Hit the ground! " + bot.entity.position.toString());
|
|
51
|
+
}
|
|
52
|
+
wasOnGround = bot.entity.onGround;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// print whenever another player hits the ground
|
|
56
|
+
const lastPositions: Record<string, boolean> = {};
|
|
57
|
+
bot.on("entityMoved", (entity) => {
|
|
58
|
+
if (entity.username && entity.username !== bot.username) {
|
|
59
|
+
// check by seeing is y value is an integer
|
|
60
|
+
if (Math.floor(entity.position.y) === entity.position.y && !lastPositions[entity.username]) {
|
|
61
|
+
// check if in liquid
|
|
62
|
+
const block = bot.blockAt(entity.position);
|
|
63
|
+
if (block && (block.type === bot.registry.blocksByName.water.id || block.type === bot.registry.blocksByName.lava.id)) return;
|
|
64
|
+
|
|
65
|
+
bot.chat(`${entity.username} hit the ground! ${entity.position.toString()}`);
|
|
66
|
+
lastPositions[entity.username] = true;
|
|
67
|
+
} else if (Math.floor(entity.position.y) !== entity.position.y) {
|
|
68
|
+
lastPositions[entity.username] = false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
let usingNew = false;
|
|
74
|
+
let oldSimulate: any = null;
|
|
75
|
+
let state: PlayerState | null = null;
|
|
76
|
+
|
|
77
|
+
function setupNewPhysics(bot: Bot) {
|
|
78
|
+
if (usingNew) return;
|
|
79
|
+
usingNew = true;
|
|
80
|
+
oldSimulate = (bot.physics as any).simulatePlayer;
|
|
81
|
+
|
|
82
|
+
const val = new BotcraftPhysics(bot.registry);
|
|
83
|
+
|
|
84
|
+
(EntityState.prototype as any).apply = function (this: EntityState, bot: Bot) {
|
|
85
|
+
console.log(this.control, this.isUsingItem);
|
|
86
|
+
this.applyToBot(bot);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const ctx = EPhysicsCtx.FROM_BOT(val, bot);
|
|
90
|
+
state = ctx.state as PlayerState;
|
|
91
|
+
|
|
92
|
+
// EntityPhysics.prototype.simulate = function (ctx, world) {
|
|
93
|
+
// bot.physics.simulatePlayer(ctx.state, world);
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
(bot.physics as any).autojumpCooldown = 0;
|
|
97
|
+
// (bot.physics).jumpTicks = 0;
|
|
98
|
+
|
|
99
|
+
(bot.physics as any).simulatePlayer = (...args: any[]) => {
|
|
100
|
+
state!.update(bot);
|
|
101
|
+
ctx.state.jumpTicks = 0; // allow immediate jumping
|
|
102
|
+
return val.simulate(ctx, bot.world);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
bot.on("chat", async (user, message) => {
|
|
107
|
+
const [cmd, ...args] = message.split(" ");
|
|
108
|
+
const author = bot.nearestEntity((e) => e.username === user);
|
|
109
|
+
|
|
110
|
+
switch (cmd) {
|
|
111
|
+
case "using":
|
|
112
|
+
bot.chat(`Using new physics: ${usingNew}`);
|
|
113
|
+
break;
|
|
114
|
+
case "lookatme":
|
|
115
|
+
if (!author) return bot.chat("I can't see you!");
|
|
116
|
+
bot.lookAt(author.position.offset(0, author.height, 0));
|
|
117
|
+
break;
|
|
118
|
+
case "status":
|
|
119
|
+
const str0 = `pos: ${bot.entity.position.toString()}, vel: ${bot.entity.velocity.toString()}, yaw: ${bot.entity.yaw}, pitch: ${bot.entity.pitch}`;
|
|
120
|
+
bot.chat(str0);
|
|
121
|
+
|
|
122
|
+
const str = `onGround: ${bot.entity.onGround}, hCol: ${(bot.entity as any).isCollidedHorizontally}, vCol: ${
|
|
123
|
+
(bot.entity as any).isCollidedVertically
|
|
124
|
+
}, inWater: ${(bot.entity as any).isInWater}, inLava: ${(bot.entity as any).isInLava}`;
|
|
125
|
+
bot.chat(str);
|
|
126
|
+
|
|
127
|
+
if (state != null) {
|
|
128
|
+
const str1 = `crouching: ${state.crouching}, sprinting: ${state.sprinting}`;
|
|
129
|
+
bot.chat(str1);
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
case "use":
|
|
133
|
+
if (bot.usingHeldItem) bot.deactivateItem();
|
|
134
|
+
else bot.activateItem();
|
|
135
|
+
break;
|
|
136
|
+
case "useoff":
|
|
137
|
+
bot.deactivateItem();
|
|
138
|
+
bot.activateItem(true);
|
|
139
|
+
break;
|
|
140
|
+
case "control":
|
|
141
|
+
if (args[0] === "clear") return bot.clearControlStates();
|
|
142
|
+
if (args.length === 1) return bot.setControlState(args[0] as any, !bot.getControlState(args[0] as any));
|
|
143
|
+
bot.setControlState(args[0] as any, args[1] === "true");
|
|
144
|
+
break;
|
|
145
|
+
case "sim":
|
|
146
|
+
// turn all but the mentioned ones off
|
|
147
|
+
const [time, ...controls] = args;
|
|
148
|
+
bot.clearControlStates();
|
|
149
|
+
for (const control of controls) {
|
|
150
|
+
bot.setControlState(control as any, true);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (let i = 0; i <= Number(time); i++) {
|
|
154
|
+
console.log(bot.entity.position, bot.entity.velocity, i);
|
|
155
|
+
await bot.waitForTicks(1);
|
|
156
|
+
}
|
|
157
|
+
bot.clearControlStates();
|
|
158
|
+
|
|
159
|
+
break;
|
|
160
|
+
case "reset":
|
|
161
|
+
usingNew = false;
|
|
162
|
+
bot.quit();
|
|
163
|
+
await new Promise((res) => setTimeout(res, 3000));
|
|
164
|
+
bot1 = buildBot();
|
|
165
|
+
|
|
166
|
+
break;
|
|
167
|
+
case "new":
|
|
168
|
+
setupNewPhysics(bot);
|
|
169
|
+
bot.chat("Switched to new physics!");
|
|
170
|
+
break;
|
|
171
|
+
case "jump":
|
|
172
|
+
bot.setControlState("jump", true);
|
|
173
|
+
break;
|
|
174
|
+
case "come":
|
|
175
|
+
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
176
|
+
const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3);
|
|
177
|
+
bot.pathfinder.setGoal(goal0);
|
|
178
|
+
break;
|
|
179
|
+
case "goto":
|
|
180
|
+
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
181
|
+
const goal1 = new goals.GoalNear(Number(args[0]), Number(args[1]), Number(args[2]), 3);
|
|
182
|
+
bot.pathfinder.setGoal(goal1);
|
|
183
|
+
break;
|
|
184
|
+
case "stop":
|
|
185
|
+
bot.deactivateItem();
|
|
186
|
+
bot.pathfinder.stop();
|
|
187
|
+
bot.clearControlStates();
|
|
188
|
+
bot.chat("Stopped!");
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
rl.on("line", (line: any) => bot.chat(line));
|
|
194
|
+
|
|
195
|
+
return bot;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
bot1 = buildBot();
|