@nxg-org/mineflayer-physics-util 1.5.5 → 1.5.7
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/dist/physics/engines/entityPhysics.js +17 -23
- package/dist/physics/engines/optimizedPhysics.d.ts +79 -0
- package/dist/physics/engines/optimizedPhysics.js +742 -0
- package/dist/physics/states/entityState.d.ts +2 -0
- package/dist/physics/states/entityState.js +11 -0
- package/dist/physics/states/playerState.d.ts +1 -0
- package/dist/physics/states/playerState.js +2 -1
- package/package.json +2 -2
- package/tests/actualBot.ts +29 -8
|
@@ -294,10 +294,7 @@ class EntityPhysics {
|
|
|
294
294
|
if (dz !== oldVelZ)
|
|
295
295
|
vel.z = 0;
|
|
296
296
|
if (dy !== oldVelY) {
|
|
297
|
-
if (entity.collisionBehavior.blockEffects &&
|
|
298
|
-
blockAtFeet &&
|
|
299
|
-
blockAtFeet.type === this.slimeBlockId &&
|
|
300
|
-
!entity.state.control.sneak) {
|
|
297
|
+
if (entity.collisionBehavior.blockEffects && blockAtFeet && blockAtFeet.type === this.slimeBlockId && !entity.state.control.sneak) {
|
|
301
298
|
vel.y = -vel.y;
|
|
302
299
|
}
|
|
303
300
|
else {
|
|
@@ -329,9 +326,7 @@ class EntityPhysics {
|
|
|
329
326
|
else if (block.type === this.bubblecolumnId) {
|
|
330
327
|
const down = !block.metadata;
|
|
331
328
|
const aboveBlock = world.getBlock(cursor.offset(0, 1, 0));
|
|
332
|
-
const bubbleDrag = aboveBlock && aboveBlock.type === 0 /* air */
|
|
333
|
-
? physicsSettings_1.PhysicsSettings.bubbleColumnSurfaceDrag
|
|
334
|
-
: physicsSettings_1.PhysicsSettings.bubbleColumnDrag;
|
|
329
|
+
const bubbleDrag = aboveBlock && aboveBlock.type === 0 /* air */ ? physicsSettings_1.PhysicsSettings.bubbleColumnSurfaceDrag : physicsSettings_1.PhysicsSettings.bubbleColumnDrag;
|
|
335
330
|
if (down) {
|
|
336
331
|
vel.y = Math.max(bubbleDrag.maxDown, vel.y - bubbleDrag.down);
|
|
337
332
|
}
|
|
@@ -592,6 +587,7 @@ class EntityPhysics {
|
|
|
592
587
|
vel.x *= inertia;
|
|
593
588
|
vel.z *= inertia;
|
|
594
589
|
}
|
|
590
|
+
// this is player-only.
|
|
595
591
|
else if (entity.state.elytraFlying) {
|
|
596
592
|
const { pitch, sinPitch, cosPitch, lookDir } = (0, physicsUtils_1.getLookingVector)(entity.state);
|
|
597
593
|
const horizontalSpeed = Math.sqrt(vel.x * vel.x + vel.z * vel.z);
|
|
@@ -600,20 +596,20 @@ class EntityPhysics {
|
|
|
600
596
|
// cosPitch is in [0, 1], so cosPitch > 0.0 is just to protect against
|
|
601
597
|
// divide by zero errors
|
|
602
598
|
if (vel.y < 0.0 && cosPitch > 0.0) {
|
|
603
|
-
const movingDownSpeedModifier = vel.y *
|
|
604
|
-
vel.x += lookDir.x * movingDownSpeedModifier / cosPitch;
|
|
599
|
+
const movingDownSpeedModifier = vel.y * -0.1 * cosPitchSquared;
|
|
600
|
+
vel.x += (lookDir.x * movingDownSpeedModifier) / cosPitch;
|
|
605
601
|
vel.y += movingDownSpeedModifier;
|
|
606
|
-
vel.z += lookDir.z * movingDownSpeedModifier / cosPitch;
|
|
602
|
+
vel.z += (lookDir.z * movingDownSpeedModifier) / cosPitch;
|
|
607
603
|
}
|
|
608
604
|
if (pitch < 0.0 && cosPitch > 0.0) {
|
|
609
|
-
const lookDownSpeedModifier = horizontalSpeed *
|
|
610
|
-
vel.x += -lookDir.x * lookDownSpeedModifier / cosPitch;
|
|
605
|
+
const lookDownSpeedModifier = horizontalSpeed * -sinPitch * 0.04;
|
|
606
|
+
vel.x += (-lookDir.x * lookDownSpeedModifier) / cosPitch;
|
|
611
607
|
vel.y += lookDownSpeedModifier * 3.2;
|
|
612
|
-
vel.z += -lookDir.z * lookDownSpeedModifier / cosPitch;
|
|
608
|
+
vel.z += (-lookDir.z * lookDownSpeedModifier) / cosPitch;
|
|
613
609
|
}
|
|
614
610
|
if (cosPitch > 0.0) {
|
|
615
|
-
vel.x += (lookDir.x / cosPitch * horizontalSpeed - vel.x) * 0.1;
|
|
616
|
-
vel.z += (lookDir.z / cosPitch * horizontalSpeed - vel.z) * 0.1;
|
|
611
|
+
vel.x += ((lookDir.x / cosPitch) * horizontalSpeed - vel.x) * 0.1;
|
|
612
|
+
vel.z += ((lookDir.z / cosPitch) * horizontalSpeed - vel.z) * 0.1;
|
|
617
613
|
}
|
|
618
614
|
vel.x *= 0.99;
|
|
619
615
|
vel.y *= 0.98;
|
|
@@ -686,12 +682,11 @@ class EntityPhysics {
|
|
|
686
682
|
if (entity.state.jumpTicks > 0)
|
|
687
683
|
entity.state.jumpTicks--;
|
|
688
684
|
if (entity.state.isInWater || entity.state.isInLava) {
|
|
689
|
-
vel.y +=
|
|
685
|
+
vel.y += 0.04;
|
|
690
686
|
}
|
|
691
687
|
else if (entity.state.onGround && entity.state.jumpTicks === 0) {
|
|
692
688
|
const blockBelow = world.getBlock(entity.position.floored().offset(0, -0.5, 0));
|
|
693
|
-
vel.y =
|
|
694
|
-
Math.fround(0.42) * (blockBelow && blockBelow.type === this.honeyblockId ? physicsSettings_1.PhysicsSettings.honeyblockJumpSpeed : 1);
|
|
689
|
+
vel.y = Math.fround(0.42) * (blockBelow && blockBelow.type === this.honeyblockId ? physicsSettings_1.PhysicsSettings.honeyblockJumpSpeed : 1);
|
|
695
690
|
if (entity.state.jumpBoost > 0) {
|
|
696
691
|
vel.y += 0.1 * entity.state.jumpBoost;
|
|
697
692
|
}
|
|
@@ -707,10 +702,8 @@ class EntityPhysics {
|
|
|
707
702
|
entity.state.jumpTicks = 0; // reset autojump cooldown
|
|
708
703
|
}
|
|
709
704
|
entity.state.jumpQueued = false;
|
|
710
|
-
strafe =
|
|
711
|
-
|
|
712
|
-
forward =
|
|
713
|
-
(entity.state.control.forward - entity.state.control.back) * 0.98;
|
|
705
|
+
strafe = (entity.state.control.left - entity.state.control.right) * 0.98;
|
|
706
|
+
forward = (entity.state.control.forward - entity.state.control.back) * 0.98;
|
|
714
707
|
if (entity.state.control.sneak) {
|
|
715
708
|
strafe *= physicsSettings_1.PhysicsSettings.sneakSpeed;
|
|
716
709
|
forward *= physicsSettings_1.PhysicsSettings.sneakSpeed;
|
|
@@ -722,7 +715,8 @@ class EntityPhysics {
|
|
|
722
715
|
entity.state.control.sprint = false;
|
|
723
716
|
}
|
|
724
717
|
}
|
|
725
|
-
entity.state.elytraFlying =
|
|
718
|
+
entity.state.elytraFlying =
|
|
719
|
+
entity.state.elytraFlying && entity.state.elytraEquipped && !entity.state.onGround && !entity.state.levitation;
|
|
726
720
|
if (entity.state.fireworkRocketDuration > 0) {
|
|
727
721
|
if (!entity.state.elytraFlying) {
|
|
728
722
|
entity.state.fireworkRocketDuration = 0;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { AABB } from "@nxg-org/mineflayer-util-plugin";
|
|
2
|
+
import md from "minecraft-data";
|
|
3
|
+
import { Block } from "prismarine-block";
|
|
4
|
+
import { Effect } from "prismarine-entity";
|
|
5
|
+
import { Vec3 } from "vec3";
|
|
6
|
+
import { CheapEffects, CheapEnchantments, makeSupportFeature } from "../../util/physicsUtils";
|
|
7
|
+
import { EPhysicsCtx } from "../settings/entityPhysicsCtx";
|
|
8
|
+
import { EntityState } from "../states/entityState";
|
|
9
|
+
import { IPhysics } from "./IPhysics";
|
|
10
|
+
/**
|
|
11
|
+
* Looking at this code, it's too specified towards players.
|
|
12
|
+
*
|
|
13
|
+
* I will eventually split this code into PlayerState and bot.entityState, where bot.entityState contains fewer controls.
|
|
14
|
+
*/
|
|
15
|
+
export declare class EntityPhysics implements IPhysics {
|
|
16
|
+
data: md.IndexedData;
|
|
17
|
+
movementSpeedAttribute: any;
|
|
18
|
+
supportFeature: ReturnType<typeof makeSupportFeature>;
|
|
19
|
+
blockSlipperiness: {
|
|
20
|
+
[name: string]: number;
|
|
21
|
+
};
|
|
22
|
+
protected slimeBlockId: number;
|
|
23
|
+
protected soulsandId: number;
|
|
24
|
+
protected honeyblockId: number;
|
|
25
|
+
protected webId: number;
|
|
26
|
+
protected waterId: number;
|
|
27
|
+
protected lavaId: number;
|
|
28
|
+
protected ladderId: number;
|
|
29
|
+
protected vineId: number;
|
|
30
|
+
protected bubblecolumnId: number;
|
|
31
|
+
protected waterLike: Set<number>;
|
|
32
|
+
readonly statusEffectNames: {
|
|
33
|
+
[type in CheapEffects]: string;
|
|
34
|
+
};
|
|
35
|
+
readonly enchantmentNames: {
|
|
36
|
+
[type in CheapEnchantments]: string;
|
|
37
|
+
};
|
|
38
|
+
constructor(mcData: md.IndexedData);
|
|
39
|
+
getEntityBB(entity: EPhysicsCtx, pos: {
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
z: number;
|
|
43
|
+
}): AABB;
|
|
44
|
+
setPositionToBB(entity: EPhysicsCtx, bb: AABB, pos: {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
z: number;
|
|
48
|
+
}): void;
|
|
49
|
+
shouldMoveEntity(entity: EPhysicsCtx): boolean;
|
|
50
|
+
getUnderlyingBlockBBs(queryBB: AABB, world: any): AABB[];
|
|
51
|
+
getSurroundingBBs(queryBB: AABB, world: any): AABB[];
|
|
52
|
+
adjustPositionHeight(entity: EPhysicsCtx, pos: Vec3, world: any): void;
|
|
53
|
+
moveEntity(entity: EPhysicsCtx, dx: number, dy: number, dz: number, world: any): void;
|
|
54
|
+
applyHeading(entity: EPhysicsCtx, strafe: number, forward: number, multiplier: number): void;
|
|
55
|
+
getEffectLevel(wantedEffect: CheapEffects, effects: Effect[]): number;
|
|
56
|
+
getEnchantmentLevel(wantedEnchantment: CheapEnchantments, enchantments: any[]): any;
|
|
57
|
+
isOnLadder(pos: {
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
z: number;
|
|
61
|
+
}, world: any): any;
|
|
62
|
+
doesNotCollide(entity: EPhysicsCtx, pos: {
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
z: number;
|
|
66
|
+
}, world: any): boolean;
|
|
67
|
+
isMaterialInBB(queryBB: AABB, type: number, world: any): boolean;
|
|
68
|
+
getWaterInBB(bb: AABB, world: any): any[];
|
|
69
|
+
getLiquidHeightPcent(block: Block): number;
|
|
70
|
+
getRenderedDepth(block: Block): number;
|
|
71
|
+
getFlow(block: Block, world: any): Vec3;
|
|
72
|
+
isInWaterApplyCurrent(bb: AABB, vel: {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
z: number;
|
|
76
|
+
}, world: any): boolean;
|
|
77
|
+
moveEntityWithHeading(entity: EPhysicsCtx, strafe: number, forward: number, world: any): void;
|
|
78
|
+
simulate(entity: EPhysicsCtx, world: any): EntityState;
|
|
79
|
+
}
|
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.EntityPhysics = void 0;
|
|
27
|
+
const mineflayer_util_plugin_1 = require("@nxg-org/mineflayer-util-plugin");
|
|
28
|
+
const vec3_1 = require("vec3");
|
|
29
|
+
const physicsUtils_1 = require("../../util/physicsUtils");
|
|
30
|
+
const attributes = __importStar(require("../info/attributes"));
|
|
31
|
+
const math = __importStar(require("../info/math"));
|
|
32
|
+
const physicsSettings_1 = require("../settings/physicsSettings");
|
|
33
|
+
/**
|
|
34
|
+
* Looking at this code, it's too specified towards players.
|
|
35
|
+
*
|
|
36
|
+
* I will eventually split this code into PlayerState and bot.entityState, where bot.entityState contains fewer controls.
|
|
37
|
+
*/
|
|
38
|
+
class EntityPhysics {
|
|
39
|
+
constructor(mcData) {
|
|
40
|
+
this.data = mcData;
|
|
41
|
+
const blocksByName = mcData.blocksByName;
|
|
42
|
+
this.supportFeature = (0, physicsUtils_1.makeSupportFeature)(mcData);
|
|
43
|
+
this.movementSpeedAttribute = this.data.attributesByName.movementSpeed.resource;
|
|
44
|
+
this.blockSlipperiness = {};
|
|
45
|
+
this.slimeBlockId = blocksByName.slime_block ? blocksByName.slime_block.id : blocksByName.slime.id;
|
|
46
|
+
this.blockSlipperiness[this.slimeBlockId] = 0.8;
|
|
47
|
+
this.blockSlipperiness[blocksByName.ice.id] = 0.98;
|
|
48
|
+
this.blockSlipperiness[blocksByName.packed_ice.id] = 0.98;
|
|
49
|
+
// 1.9+
|
|
50
|
+
if (blocksByName.frosted_ice)
|
|
51
|
+
this.blockSlipperiness[blocksByName.frosted_ice.id] = 0.98;
|
|
52
|
+
// 1.13+
|
|
53
|
+
if (blocksByName.blue_ice)
|
|
54
|
+
this.blockSlipperiness[blocksByName.blue_ice.id] = 0.989;
|
|
55
|
+
this.soulsandId = blocksByName.soul_sand.id;
|
|
56
|
+
this.honeyblockId = blocksByName.honey_block ? blocksByName.honey_block.id : -1; // 1.15+
|
|
57
|
+
this.webId = blocksByName.cobweb ? blocksByName.cobweb.id : blocksByName.web.id;
|
|
58
|
+
this.waterId = blocksByName.water.id;
|
|
59
|
+
this.lavaId = blocksByName.lava.id;
|
|
60
|
+
this.ladderId = blocksByName.ladder.id;
|
|
61
|
+
this.vineId = blocksByName.vine.id;
|
|
62
|
+
this.waterLike = new Set();
|
|
63
|
+
if (blocksByName.seagrass)
|
|
64
|
+
this.waterLike.add(blocksByName.seagrass.id); // 1.13+
|
|
65
|
+
if (blocksByName.tall_seagrass)
|
|
66
|
+
this.waterLike.add(blocksByName.tall_seagrass.id); // 1.13+
|
|
67
|
+
if (blocksByName.kelp)
|
|
68
|
+
this.waterLike.add(blocksByName.kelp.id); // 1.13+
|
|
69
|
+
this.bubblecolumnId = blocksByName.bubble_column ? blocksByName.bubble_column.id : -1; // 1.13+
|
|
70
|
+
if (blocksByName.bubble_column)
|
|
71
|
+
this.waterLike.add(this.bubblecolumnId);
|
|
72
|
+
this.statusEffectNames = {}; // mmm, speed.
|
|
73
|
+
this.enchantmentNames = {}; //mmm, double speed.
|
|
74
|
+
let ind = 0;
|
|
75
|
+
const tmp = (0, physicsUtils_1.getStatusEffectNamesForVersion)(this.supportFeature);
|
|
76
|
+
for (const key in tmp) {
|
|
77
|
+
this.statusEffectNames[ind] = tmp[key];
|
|
78
|
+
ind++;
|
|
79
|
+
}
|
|
80
|
+
Object.freeze(this.statusEffectNames);
|
|
81
|
+
ind = 0;
|
|
82
|
+
const tmp1 = (0, physicsUtils_1.getEnchantmentNamesForVersion)(this.supportFeature);
|
|
83
|
+
for (const key in tmp1) {
|
|
84
|
+
this.enchantmentNames[ind] = tmp1[key];
|
|
85
|
+
}
|
|
86
|
+
Object.freeze(this.enchantmentNames);
|
|
87
|
+
}
|
|
88
|
+
getEntityBB(entity, pos) {
|
|
89
|
+
const w = entity.getHalfWidth();
|
|
90
|
+
return new mineflayer_util_plugin_1.AABB(-w, 0, -w, w, entity.height, w).translate(pos.x, pos.y, pos.z);
|
|
91
|
+
}
|
|
92
|
+
setPositionToBB(entity, bb, pos) {
|
|
93
|
+
const halfWidth = entity.getHalfWidth();
|
|
94
|
+
pos.x = bb.minX + halfWidth;
|
|
95
|
+
pos.y = bb.minY;
|
|
96
|
+
pos.z = bb.minZ + halfWidth;
|
|
97
|
+
}
|
|
98
|
+
shouldMoveEntity(entity) {
|
|
99
|
+
return !((entity.state.isCollidedHorizontally || entity.state.isCollidedVertically) &&
|
|
100
|
+
!entity.collisionBehavior.affectedAfterCollision);
|
|
101
|
+
}
|
|
102
|
+
getUnderlyingBlockBBs(queryBB, world /*prismarine-world*/) {
|
|
103
|
+
const surroundingBBs = [];
|
|
104
|
+
const cursor = new vec3_1.Vec3(0, Math.floor(queryBB.minY) - 0.251, 0);
|
|
105
|
+
for (cursor.z = Math.floor(queryBB.minZ); cursor.z <= Math.floor(queryBB.maxZ); cursor.z++) {
|
|
106
|
+
for (cursor.x = Math.floor(queryBB.minX); cursor.x <= Math.floor(queryBB.maxX); cursor.x++) {
|
|
107
|
+
const block = world.getBlock(cursor);
|
|
108
|
+
if (block) {
|
|
109
|
+
const blockPos = block.position;
|
|
110
|
+
for (const shape of block.shapes) {
|
|
111
|
+
const blockBB = new mineflayer_util_plugin_1.AABB(shape[0], shape[1], shape[2], shape[3], shape[4], shape[5]);
|
|
112
|
+
blockBB.translate(blockPos.x, blockPos.y, blockPos.z);
|
|
113
|
+
surroundingBBs.push(blockBB);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return surroundingBBs;
|
|
119
|
+
}
|
|
120
|
+
getSurroundingBBs(queryBB, world /*prismarine-world*/) {
|
|
121
|
+
const surroundingBBs = [];
|
|
122
|
+
const cursor = new vec3_1.Vec3(0, 0, 0);
|
|
123
|
+
for (cursor.y = Math.floor(queryBB.minY) - 1; cursor.y <= Math.floor(queryBB.maxY); cursor.y++) {
|
|
124
|
+
for (cursor.z = Math.floor(queryBB.minZ); cursor.z <= Math.floor(queryBB.maxZ); cursor.z++) {
|
|
125
|
+
for (cursor.x = Math.floor(queryBB.minX); cursor.x <= Math.floor(queryBB.maxX); cursor.x++) {
|
|
126
|
+
const block = world.getBlock(cursor);
|
|
127
|
+
if (block) {
|
|
128
|
+
const blockPos = block.position;
|
|
129
|
+
for (const shape of block.shapes) {
|
|
130
|
+
const blockBB = new mineflayer_util_plugin_1.AABB(shape[0], shape[1], shape[2], shape[3], shape[4], shape[5]);
|
|
131
|
+
blockBB.translate(blockPos.x, blockPos.y, blockPos.z);
|
|
132
|
+
surroundingBBs.push(blockBB);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return surroundingBBs;
|
|
139
|
+
}
|
|
140
|
+
adjustPositionHeight(entity, pos, world /*prismarine-world*/) {
|
|
141
|
+
const playerBB = this.getEntityBB(entity, pos);
|
|
142
|
+
const queryBB = playerBB.clone().extend(0, -1, 0);
|
|
143
|
+
const surroundingBBs = this.getSurroundingBBs(queryBB, world);
|
|
144
|
+
let dy = -1;
|
|
145
|
+
for (const blockBB of surroundingBBs) {
|
|
146
|
+
dy = blockBB.computeOffsetY(playerBB, dy);
|
|
147
|
+
}
|
|
148
|
+
pos.y += dy;
|
|
149
|
+
}
|
|
150
|
+
moveEntity(entity, dx, dy, dz, world /*prismarine-world*/) {
|
|
151
|
+
var _a;
|
|
152
|
+
if (!this.shouldMoveEntity(entity)) {
|
|
153
|
+
entity.velocity.set(0, 0, 0);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const vel = entity.velocity;
|
|
157
|
+
const pos = entity.position;
|
|
158
|
+
if (entity.state.isInWeb && !((_a = entity.entityType) === null || _a === void 0 ? void 0 : _a.name.includes("arrow"))) {
|
|
159
|
+
dx *= 0.25;
|
|
160
|
+
dy *= 0.05;
|
|
161
|
+
dz *= 0.25;
|
|
162
|
+
vel.x = 0;
|
|
163
|
+
vel.y = 0;
|
|
164
|
+
vel.z = 0;
|
|
165
|
+
entity.state.isInWeb = false;
|
|
166
|
+
}
|
|
167
|
+
const oldOldVelX = dx;
|
|
168
|
+
let oldVelX = dx;
|
|
169
|
+
const oldVelY = dy;
|
|
170
|
+
let oldVelZ = dz;
|
|
171
|
+
const oldOldVelZ = dz;
|
|
172
|
+
if (entity.useControls && entity.state.control.sneak && entity.state.onGround) {
|
|
173
|
+
const step = 0.05;
|
|
174
|
+
// In the 3 loops bellow, y offset should be -1, but that doesnt reproduce vanilla behavior.
|
|
175
|
+
for (; dx !== 0 && this.getSurroundingBBs(this.getEntityBB(entity, pos).translate(dx, 0, 0), world).length === 0; oldVelX = dx) {
|
|
176
|
+
if (dx < step && dx >= -step)
|
|
177
|
+
dx = 0;
|
|
178
|
+
else if (dx > 0)
|
|
179
|
+
dx -= step;
|
|
180
|
+
else
|
|
181
|
+
dx += step;
|
|
182
|
+
}
|
|
183
|
+
for (; dz !== 0 && this.getSurroundingBBs(this.getEntityBB(entity, pos).translate(0, 0, dz), world).length === 0; oldVelZ = dz) {
|
|
184
|
+
if (dz < step && dz >= -step)
|
|
185
|
+
dz = 0;
|
|
186
|
+
else if (dz > 0)
|
|
187
|
+
dz -= step;
|
|
188
|
+
else
|
|
189
|
+
dz += step;
|
|
190
|
+
}
|
|
191
|
+
while (dx !== 0 && dz !== 0 && this.getSurroundingBBs(this.getEntityBB(entity, pos).translate(dx, 0, dz), world).length === 0) {
|
|
192
|
+
if (dx < step && dx >= -step)
|
|
193
|
+
dx = 0;
|
|
194
|
+
else if (dx > 0)
|
|
195
|
+
dx -= step;
|
|
196
|
+
else
|
|
197
|
+
dx += step;
|
|
198
|
+
if (dz < step && dz >= -step)
|
|
199
|
+
dz = 0;
|
|
200
|
+
else if (dz > 0)
|
|
201
|
+
dz -= step;
|
|
202
|
+
else
|
|
203
|
+
dz += step;
|
|
204
|
+
oldVelX = dx;
|
|
205
|
+
oldVelZ = dz;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
let playerBB = this.getEntityBB(entity, pos);
|
|
209
|
+
const queryBB = playerBB.clone().extend(dx, dy, dz);
|
|
210
|
+
const surroundingBBs = this.getSurroundingBBs(queryBB, world);
|
|
211
|
+
const oldBB = playerBB.clone();
|
|
212
|
+
for (const blockBB of surroundingBBs) {
|
|
213
|
+
dy = blockBB.computeOffsetY(playerBB, dy);
|
|
214
|
+
}
|
|
215
|
+
playerBB.translate(0, dy, 0);
|
|
216
|
+
for (const blockBB of surroundingBBs) {
|
|
217
|
+
dx = blockBB.computeOffsetX(playerBB, dx);
|
|
218
|
+
}
|
|
219
|
+
playerBB.translate(dx, 0, 0);
|
|
220
|
+
for (const blockBB of surroundingBBs) {
|
|
221
|
+
dz = blockBB.computeOffsetZ(playerBB, dz);
|
|
222
|
+
}
|
|
223
|
+
playerBB.translate(0, 0, dz);
|
|
224
|
+
// Step on block if height < stepHeight
|
|
225
|
+
if (entity.stepHeight > 0 && (entity.state.onGround || (dy !== oldVelY && oldVelY < 0)) && (dx !== oldVelX || dz !== oldVelZ)) {
|
|
226
|
+
const oldVelXCol = dx;
|
|
227
|
+
const oldVelYCol = dy;
|
|
228
|
+
const oldVelZCol = dz;
|
|
229
|
+
const oldBBCol = playerBB.clone();
|
|
230
|
+
dy = entity.stepHeight;
|
|
231
|
+
const queryBB = oldBB.clone().extend(oldVelX, dy, oldVelZ);
|
|
232
|
+
const surroundingBBs = this.getSurroundingBBs(queryBB, world);
|
|
233
|
+
const BB1 = oldBB.clone();
|
|
234
|
+
const BB2 = oldBB.clone();
|
|
235
|
+
const BB_XZ = BB1.clone().extend(dx, 0, dz);
|
|
236
|
+
let dy1 = dy;
|
|
237
|
+
let dy2 = dy;
|
|
238
|
+
for (const blockBB of surroundingBBs) {
|
|
239
|
+
dy1 = blockBB.computeOffsetY(BB_XZ, dy1);
|
|
240
|
+
dy2 = blockBB.computeOffsetY(BB2, dy2);
|
|
241
|
+
}
|
|
242
|
+
BB1.translate(0, dy1, 0);
|
|
243
|
+
BB2.translate(0, dy2, 0);
|
|
244
|
+
let dx1 = oldVelX;
|
|
245
|
+
let dx2 = oldVelX;
|
|
246
|
+
for (const blockBB of surroundingBBs) {
|
|
247
|
+
dx1 = blockBB.computeOffsetX(BB1, dx1);
|
|
248
|
+
dx2 = blockBB.computeOffsetX(BB2, dx2);
|
|
249
|
+
}
|
|
250
|
+
BB1.translate(dx1, 0, 0);
|
|
251
|
+
BB2.translate(dx2, 0, 0);
|
|
252
|
+
let dz1 = oldVelZ;
|
|
253
|
+
let dz2 = oldVelZ;
|
|
254
|
+
for (const blockBB of surroundingBBs) {
|
|
255
|
+
dz1 = blockBB.computeOffsetZ(BB1, dz1);
|
|
256
|
+
dz2 = blockBB.computeOffsetZ(BB2, dz2);
|
|
257
|
+
}
|
|
258
|
+
BB1.translate(0, 0, dz1);
|
|
259
|
+
BB2.translate(0, 0, dz2);
|
|
260
|
+
const norm1 = dx1 * dx1 + dz1 * dz1;
|
|
261
|
+
const norm2 = dx2 * dx2 + dz2 * dz2;
|
|
262
|
+
if (norm1 > norm2) {
|
|
263
|
+
dx = dx1;
|
|
264
|
+
dy = -dy1;
|
|
265
|
+
dz = dz1;
|
|
266
|
+
playerBB = BB1;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
dx = dx2;
|
|
270
|
+
dy = -dy2;
|
|
271
|
+
dz = dz2;
|
|
272
|
+
playerBB = BB2;
|
|
273
|
+
}
|
|
274
|
+
for (const blockBB of surroundingBBs) {
|
|
275
|
+
dy = blockBB.computeOffsetY(playerBB, dy);
|
|
276
|
+
}
|
|
277
|
+
playerBB.translate(0, dy, 0);
|
|
278
|
+
if (oldVelXCol * oldVelXCol + oldVelZCol * oldVelZCol >= dx * dx + dz * dz) {
|
|
279
|
+
dx = oldVelXCol;
|
|
280
|
+
dy = oldVelYCol;
|
|
281
|
+
dz = oldVelZCol;
|
|
282
|
+
playerBB = oldBBCol;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Update flags
|
|
286
|
+
this.setPositionToBB(entity, playerBB, pos);
|
|
287
|
+
entity.state.sneakCollision = dx !== oldOldVelX || dz !== oldOldVelZ;
|
|
288
|
+
entity.state.isCollidedHorizontally = dx !== oldVelX || dz !== oldVelZ;
|
|
289
|
+
entity.state.isCollidedVertically = dy !== oldVelY;
|
|
290
|
+
entity.state.onGround = entity.state.isCollidedVertically && oldVelY < 0;
|
|
291
|
+
const blockAtFeet = world.getBlock(pos.offset(0, -0.2, 0));
|
|
292
|
+
if (dx !== oldVelX)
|
|
293
|
+
vel.x = 0;
|
|
294
|
+
if (dz !== oldVelZ)
|
|
295
|
+
vel.z = 0;
|
|
296
|
+
if (dy !== oldVelY) {
|
|
297
|
+
if (entity.collisionBehavior.blockEffects &&
|
|
298
|
+
blockAtFeet &&
|
|
299
|
+
blockAtFeet.type === this.slimeBlockId &&
|
|
300
|
+
!entity.state.control.sneak) {
|
|
301
|
+
vel.y = -vel.y;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
vel.y = 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Finally, apply block collisions (web, soulsand...)
|
|
308
|
+
playerBB.contract(0.001, 0.001, 0.001);
|
|
309
|
+
const cursor = new vec3_1.Vec3(0, 0, 0);
|
|
310
|
+
for (cursor.y = Math.floor(playerBB.minY); cursor.y <= Math.floor(playerBB.maxY); cursor.y++) {
|
|
311
|
+
for (cursor.z = Math.floor(playerBB.minZ); cursor.z <= Math.floor(playerBB.maxZ); cursor.z++) {
|
|
312
|
+
for (cursor.x = Math.floor(playerBB.minX); cursor.x <= Math.floor(playerBB.maxX); cursor.x++) {
|
|
313
|
+
const block = world.getBlock(cursor);
|
|
314
|
+
if (block) {
|
|
315
|
+
if (entity.collisionBehavior.blockEffects && this.supportFeature("velocityBlocksOnCollision")) {
|
|
316
|
+
if (block.type === this.soulsandId) {
|
|
317
|
+
vel.x *= physicsSettings_1.PhysicsSettings.soulsandSpeed;
|
|
318
|
+
vel.z *= physicsSettings_1.PhysicsSettings.soulsandSpeed;
|
|
319
|
+
}
|
|
320
|
+
else if (block.type === this.honeyblockId) {
|
|
321
|
+
vel.x *= physicsSettings_1.PhysicsSettings.honeyblockSpeed;
|
|
322
|
+
vel.z *= physicsSettings_1.PhysicsSettings.honeyblockSpeed;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (block.type === this.webId) {
|
|
326
|
+
entity.state.isInWeb = true;
|
|
327
|
+
}
|
|
328
|
+
// no blockEffects check here, apparently all entities are affected by this.
|
|
329
|
+
else if (block.type === this.bubblecolumnId) {
|
|
330
|
+
const down = !block.metadata;
|
|
331
|
+
const aboveBlock = world.getBlock(cursor.offset(0, 1, 0));
|
|
332
|
+
const bubbleDrag = aboveBlock && aboveBlock.type === 0 /* air */
|
|
333
|
+
? physicsSettings_1.PhysicsSettings.bubbleColumnSurfaceDrag
|
|
334
|
+
: physicsSettings_1.PhysicsSettings.bubbleColumnDrag;
|
|
335
|
+
if (down) {
|
|
336
|
+
vel.y = Math.max(bubbleDrag.maxDown, vel.y - bubbleDrag.down);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
vel.y = Math.min(bubbleDrag.maxUp, vel.y + bubbleDrag.up);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (entity.collisionBehavior.blockEffects && this.supportFeature("velocityBlocksOnTop")) {
|
|
347
|
+
const blockBelow = world.getBlock(entity.position.floored().offset(0, -0.5, 0));
|
|
348
|
+
if (blockBelow) {
|
|
349
|
+
if (blockBelow.type === this.soulsandId) {
|
|
350
|
+
vel.x *= physicsSettings_1.PhysicsSettings.soulsandSpeed;
|
|
351
|
+
vel.z *= physicsSettings_1.PhysicsSettings.soulsandSpeed;
|
|
352
|
+
}
|
|
353
|
+
else if (blockBelow.type === this.honeyblockId) {
|
|
354
|
+
vel.x *= physicsSettings_1.PhysicsSettings.honeyblockSpeed;
|
|
355
|
+
vel.z *= physicsSettings_1.PhysicsSettings.honeyblockSpeed;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
applyHeading(entity, strafe, forward, multiplier) {
|
|
361
|
+
if (!this.shouldMoveEntity(entity)) {
|
|
362
|
+
entity.velocity.set(0, 0, 0);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
let speed = Math.sqrt(strafe * strafe + forward * forward);
|
|
366
|
+
if (speed < 0.01)
|
|
367
|
+
return;
|
|
368
|
+
speed = multiplier / Math.max(speed, 1);
|
|
369
|
+
strafe *= speed;
|
|
370
|
+
forward *= speed;
|
|
371
|
+
const yaw = Math.PI - entity.state.yaw;
|
|
372
|
+
const sin = Math.sin(yaw);
|
|
373
|
+
const cos = Math.cos(yaw);
|
|
374
|
+
const vel = entity.velocity;
|
|
375
|
+
vel.x += strafe * cos - forward * sin;
|
|
376
|
+
vel.z += forward * cos + strafe * sin;
|
|
377
|
+
}
|
|
378
|
+
getEffectLevel(wantedEffect, effects) {
|
|
379
|
+
const effectDescriptor = this.data.effectsByName[this.statusEffectNames[wantedEffect]];
|
|
380
|
+
if (!effectDescriptor) {
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
383
|
+
const effectInfo = effects[effectDescriptor.id];
|
|
384
|
+
if (!effectInfo) {
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
return effectInfo.amplifier + 1;
|
|
388
|
+
}
|
|
389
|
+
getEnchantmentLevel(wantedEnchantment, enchantments) {
|
|
390
|
+
const enchantmentName = this.enchantmentNames[wantedEnchantment];
|
|
391
|
+
const enchantmentDescriptor = this.data.enchantmentsByName[enchantmentName];
|
|
392
|
+
if (!enchantmentDescriptor) {
|
|
393
|
+
return 0;
|
|
394
|
+
}
|
|
395
|
+
for (const enchInfo of enchantments) {
|
|
396
|
+
if (typeof enchInfo.id === "string") {
|
|
397
|
+
if (enchInfo.id.includes(enchantmentName)) {
|
|
398
|
+
return enchInfo.lvl;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else if (enchInfo.id === enchantmentDescriptor.id) {
|
|
402
|
+
return enchInfo.lvl;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
isOnLadder(pos, world /*prismarine-world*/) {
|
|
408
|
+
const block = world.getBlock(pos);
|
|
409
|
+
return block && (block.type === this.ladderId || block.type === this.vineId);
|
|
410
|
+
}
|
|
411
|
+
doesNotCollide(entity, pos, world /*prismarine-world*/) {
|
|
412
|
+
const pBB = this.getEntityBB(entity, pos);
|
|
413
|
+
return !this.getSurroundingBBs(pBB, world).some((x) => pBB.intersects(x)) && this.getWaterInBB(pBB, world).length === 0;
|
|
414
|
+
}
|
|
415
|
+
isMaterialInBB(queryBB, type, world /*prismarine-world*/) {
|
|
416
|
+
const cursor = new vec3_1.Vec3(0, 0, 0);
|
|
417
|
+
for (cursor.y = Math.floor(queryBB.minY); cursor.y <= Math.floor(queryBB.maxY); cursor.y++) {
|
|
418
|
+
for (cursor.z = Math.floor(queryBB.minZ); cursor.z <= Math.floor(queryBB.maxZ); cursor.z++) {
|
|
419
|
+
for (cursor.x = Math.floor(queryBB.minX); cursor.x <= Math.floor(queryBB.maxX); cursor.x++) {
|
|
420
|
+
const block = world.getBlock(cursor);
|
|
421
|
+
if (block && block.type === type)
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
getWaterInBB(bb, world /*prismarine-world*/) {
|
|
429
|
+
const waterBlocks = [];
|
|
430
|
+
const cursor = new vec3_1.Vec3(0, 0, 0);
|
|
431
|
+
for (cursor.y = Math.floor(bb.minY); cursor.y <= Math.floor(bb.maxY); cursor.y++) {
|
|
432
|
+
for (cursor.z = Math.floor(bb.minZ); cursor.z <= Math.floor(bb.maxZ); cursor.z++) {
|
|
433
|
+
for (cursor.x = Math.floor(bb.minX); cursor.x <= Math.floor(bb.maxX); cursor.x++) {
|
|
434
|
+
const block = world.getBlock(cursor);
|
|
435
|
+
if (block && (block.type === this.waterId || this.waterLike.has(block.type) || block.getProperties().waterlogged)) {
|
|
436
|
+
const waterLevel = cursor.y + 1 - this.getLiquidHeightPcent(block);
|
|
437
|
+
if (Math.ceil(bb.maxY) >= waterLevel)
|
|
438
|
+
waterBlocks.push(block);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return waterBlocks;
|
|
444
|
+
}
|
|
445
|
+
getLiquidHeightPcent(block) {
|
|
446
|
+
return (this.getRenderedDepth(block) + 1) / 9;
|
|
447
|
+
}
|
|
448
|
+
getRenderedDepth(block) {
|
|
449
|
+
if (!block)
|
|
450
|
+
return -1;
|
|
451
|
+
if (this.waterLike.has(block.type))
|
|
452
|
+
return 0;
|
|
453
|
+
if (block.getProperties().waterlogged)
|
|
454
|
+
return 0;
|
|
455
|
+
if (block.type !== this.waterId)
|
|
456
|
+
return -1;
|
|
457
|
+
const meta = block.metadata;
|
|
458
|
+
return meta >= 8 ? 0 : meta;
|
|
459
|
+
}
|
|
460
|
+
getFlow(block, world /*prismarine-world*/) {
|
|
461
|
+
const curlevel = this.getRenderedDepth(block);
|
|
462
|
+
const flow = new vec3_1.Vec3(0, 0, 0);
|
|
463
|
+
for (const [dx, dz] of [
|
|
464
|
+
[0, 1],
|
|
465
|
+
[-1, 0],
|
|
466
|
+
[0, -1],
|
|
467
|
+
[1, 0],
|
|
468
|
+
]) {
|
|
469
|
+
const adjBlock = world.getBlock(block.position.offset(dx, 0, dz));
|
|
470
|
+
const adjLevel = this.getRenderedDepth(adjBlock);
|
|
471
|
+
if (adjLevel < 0) {
|
|
472
|
+
if (adjBlock && adjBlock.boundingBox !== "empty") {
|
|
473
|
+
const adjLevel = this.getRenderedDepth(world.getBlock(block.position.offset(dx, -1, dz)));
|
|
474
|
+
if (adjLevel >= 0) {
|
|
475
|
+
const f = adjLevel - (curlevel - 8);
|
|
476
|
+
flow.x += dx * f;
|
|
477
|
+
flow.z += dz * f;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
const f = adjLevel - curlevel;
|
|
483
|
+
flow.x += dx * f;
|
|
484
|
+
flow.z += dz * f;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (block.metadata >= 8) {
|
|
488
|
+
for (const [dx, dz] of [
|
|
489
|
+
[0, 1],
|
|
490
|
+
[-1, 0],
|
|
491
|
+
[0, -1],
|
|
492
|
+
[1, 0],
|
|
493
|
+
]) {
|
|
494
|
+
const adjBlock = world.getBlock(block.position.offset(dx, 0, dz));
|
|
495
|
+
const adjUpBlock = world.getBlock(block.position.offset(dx, 1, dz));
|
|
496
|
+
if ((adjBlock && adjBlock.boundingBox !== "empty") || (adjUpBlock && adjUpBlock.boundingBox !== "empty")) {
|
|
497
|
+
flow.normalize().translate(0, -6, 0);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return flow.normalize();
|
|
502
|
+
}
|
|
503
|
+
isInWaterApplyCurrent(bb, vel, world /*prismarine-world*/) {
|
|
504
|
+
const acceleration = new vec3_1.Vec3(0, 0, 0);
|
|
505
|
+
const waterBlocks = this.getWaterInBB(bb, world);
|
|
506
|
+
const isInWater = waterBlocks.length > 0;
|
|
507
|
+
for (const block of waterBlocks) {
|
|
508
|
+
const flow = this.getFlow(block, world);
|
|
509
|
+
acceleration.add(flow);
|
|
510
|
+
}
|
|
511
|
+
const len = acceleration.norm();
|
|
512
|
+
if (len > 0) {
|
|
513
|
+
vel.x += (acceleration.x / len) * 0.014;
|
|
514
|
+
vel.y += (acceleration.y / len) * 0.014;
|
|
515
|
+
vel.z += (acceleration.z / len) * 0.014;
|
|
516
|
+
}
|
|
517
|
+
return isInWater;
|
|
518
|
+
}
|
|
519
|
+
moveEntityWithHeading(entity, strafe, forward, world /*prismarine-world*/) {
|
|
520
|
+
if (!this.shouldMoveEntity(entity)) {
|
|
521
|
+
entity.velocity.set(0, 0, 0);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const vel = entity.velocity;
|
|
525
|
+
const pos = entity.position;
|
|
526
|
+
const gravityMultiplier = vel.y <= 0 && entity.state.slowFalling > 0 ? physicsSettings_1.PhysicsSettings.slowFalling : 1;
|
|
527
|
+
// Unsure how to handle this w/ other entities.
|
|
528
|
+
if (!entity.state.isInWater && !entity.state.isInLava) {
|
|
529
|
+
let acceleration = entity.airborneAccel;
|
|
530
|
+
let inertia = entity.airborneInertia;
|
|
531
|
+
const blockUnder = world.getBlock(pos.offset(0, -1, 0));
|
|
532
|
+
if (entity.state.onGround && blockUnder) {
|
|
533
|
+
let playerSpeedAttribute;
|
|
534
|
+
if (entity.state.attributes && entity.state.attributes[this.movementSpeedAttribute]) {
|
|
535
|
+
// Use server-side player attributes
|
|
536
|
+
playerSpeedAttribute = entity.state.attributes[this.movementSpeedAttribute];
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
// Create an attribute if the player does not have it
|
|
540
|
+
//TODO: Generalize to all entities.
|
|
541
|
+
playerSpeedAttribute = attributes.createAttributeValue(physicsSettings_1.PhysicsSettings.playerSpeed);
|
|
542
|
+
}
|
|
543
|
+
// Client-side sprinting (don't rely on server-side sprinting)
|
|
544
|
+
// setSprinting in LivingEntity.java
|
|
545
|
+
//TODO: Generalize to all entities.
|
|
546
|
+
playerSpeedAttribute = attributes.deleteAttributeModifier(playerSpeedAttribute, physicsSettings_1.PhysicsSettings.sprintingUUID); // always delete sprinting (if it exists)
|
|
547
|
+
if (entity.state.control.sprint) {
|
|
548
|
+
if (!attributes.checkAttributeModifier(playerSpeedAttribute, physicsSettings_1.PhysicsSettings.sprintingUUID)) {
|
|
549
|
+
playerSpeedAttribute = attributes.addAttributeModifier(playerSpeedAttribute, {
|
|
550
|
+
uuid: physicsSettings_1.PhysicsSettings.sprintingUUID,
|
|
551
|
+
amount: physicsSettings_1.PhysicsSettings.sprintSpeed,
|
|
552
|
+
operation: 2,
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
// Calculate what the speed is (0.1 if no modification)
|
|
557
|
+
const attributeSpeed = attributes.getAttributeValue(playerSpeedAttribute);
|
|
558
|
+
inertia = (this.blockSlipperiness[blockUnder.type] || physicsSettings_1.PhysicsSettings.defaultSlipperiness) * 0.91;
|
|
559
|
+
acceleration = attributeSpeed * (0.1627714 / (inertia * inertia * inertia));
|
|
560
|
+
if (acceleration < 0)
|
|
561
|
+
acceleration = 0; // acceleration should not be negative
|
|
562
|
+
}
|
|
563
|
+
this.applyHeading(entity, strafe, forward, acceleration);
|
|
564
|
+
if (entity.collisionBehavior.blockEffects && this.isOnLadder(pos, world)) {
|
|
565
|
+
vel.x = math.clamp(-physicsSettings_1.PhysicsSettings.ladderMaxSpeed, vel.x, physicsSettings_1.PhysicsSettings.ladderMaxSpeed);
|
|
566
|
+
vel.z = math.clamp(-physicsSettings_1.PhysicsSettings.ladderMaxSpeed, vel.z, physicsSettings_1.PhysicsSettings.ladderMaxSpeed);
|
|
567
|
+
vel.y = Math.max(vel.y, entity.state.control.sneak ? 0 : -physicsSettings_1.PhysicsSettings.ladderMaxSpeed);
|
|
568
|
+
}
|
|
569
|
+
this.moveEntity(entity, vel.x, vel.y, vel.z, world);
|
|
570
|
+
if (entity.collisionBehavior.blockEffects &&
|
|
571
|
+
this.isOnLadder(pos, world) &&
|
|
572
|
+
(entity.state.isCollidedHorizontally || (this.supportFeature("climbUsingJump") && entity.state.control.jump))) {
|
|
573
|
+
vel.y = physicsSettings_1.PhysicsSettings.ladderClimbSpeed; // climb ladder
|
|
574
|
+
}
|
|
575
|
+
// Not adding an additional function call. No point.
|
|
576
|
+
if (entity.gravityThenDrag) {
|
|
577
|
+
// Apply gravity, then air drag.
|
|
578
|
+
if (entity.state.levitation > 0)
|
|
579
|
+
vel.y += (0.05 * entity.state.levitation - vel.y) * 0.2;
|
|
580
|
+
else
|
|
581
|
+
vel.y -= entity.gravity * gravityMultiplier;
|
|
582
|
+
vel.y *= entity.airdrag;
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
// Apply airdrag, then gravity.
|
|
586
|
+
vel.y *= entity.airdrag;
|
|
587
|
+
if (entity.state.levitation > 0)
|
|
588
|
+
vel.y += (0.05 * entity.state.levitation - vel.y) * 0.2;
|
|
589
|
+
else
|
|
590
|
+
vel.y -= entity.gravity * gravityMultiplier;
|
|
591
|
+
}
|
|
592
|
+
vel.x *= inertia;
|
|
593
|
+
vel.z *= inertia;
|
|
594
|
+
}
|
|
595
|
+
else if (entity.state.elytraFlying) {
|
|
596
|
+
const { pitch, sinPitch, cosPitch, lookDir } = (0, physicsUtils_1.getLookingVector)(entity.state);
|
|
597
|
+
const horizontalSpeed = Math.sqrt(vel.x * vel.x + vel.z * vel.z);
|
|
598
|
+
const cosPitchSquared = cosPitch * cosPitch;
|
|
599
|
+
vel.y += entity.gravity * gravityMultiplier * (-1.0 + cosPitchSquared * 0.75);
|
|
600
|
+
// cosPitch is in [0, 1], so cosPitch > 0.0 is just to protect against
|
|
601
|
+
// divide by zero errors
|
|
602
|
+
if (vel.y < 0.0 && cosPitch > 0.0) {
|
|
603
|
+
const movingDownSpeedModifier = vel.y * (-0.1) * cosPitchSquared;
|
|
604
|
+
vel.x += lookDir.x * movingDownSpeedModifier / cosPitch;
|
|
605
|
+
vel.y += movingDownSpeedModifier;
|
|
606
|
+
vel.z += lookDir.z * movingDownSpeedModifier / cosPitch;
|
|
607
|
+
}
|
|
608
|
+
if (pitch < 0.0 && cosPitch > 0.0) {
|
|
609
|
+
const lookDownSpeedModifier = horizontalSpeed * (-sinPitch) * 0.04;
|
|
610
|
+
vel.x += -lookDir.x * lookDownSpeedModifier / cosPitch;
|
|
611
|
+
vel.y += lookDownSpeedModifier * 3.2;
|
|
612
|
+
vel.z += -lookDir.z * lookDownSpeedModifier / cosPitch;
|
|
613
|
+
}
|
|
614
|
+
if (cosPitch > 0.0) {
|
|
615
|
+
vel.x += (lookDir.x / cosPitch * horizontalSpeed - vel.x) * 0.1;
|
|
616
|
+
vel.z += (lookDir.z / cosPitch * horizontalSpeed - vel.z) * 0.1;
|
|
617
|
+
}
|
|
618
|
+
vel.x *= 0.99;
|
|
619
|
+
vel.y *= 0.98;
|
|
620
|
+
vel.z *= 0.99;
|
|
621
|
+
this.moveEntity(entity, world, vel.x, vel.y, vel.z);
|
|
622
|
+
if (entity.state.onGround) {
|
|
623
|
+
entity.state.elytraFlying = false;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
// Water / Lava movement
|
|
628
|
+
const lastY = pos.y;
|
|
629
|
+
let acceleration = entity.liquidAccel;
|
|
630
|
+
const inertia = entity.state.isInWater ? entity.waterInertia : entity.lavaInertia;
|
|
631
|
+
let horizontalInertia = inertia;
|
|
632
|
+
if (entity.state.isInWater) {
|
|
633
|
+
let strider = Math.min(entity.state.depthStrider, 3);
|
|
634
|
+
if (!entity.state.onGround) {
|
|
635
|
+
strider *= 0.5;
|
|
636
|
+
}
|
|
637
|
+
if (strider > 0) {
|
|
638
|
+
horizontalInertia += ((0.546 - horizontalInertia) * strider) / 3;
|
|
639
|
+
acceleration += ((0.7 - acceleration) * strider) / 3;
|
|
640
|
+
}
|
|
641
|
+
if (entity.state.dolphinsGrace > 0)
|
|
642
|
+
horizontalInertia = 0.96;
|
|
643
|
+
}
|
|
644
|
+
this.applyHeading(entity, strafe, forward, acceleration);
|
|
645
|
+
this.moveEntity(entity, vel.x, vel.y, vel.z, world);
|
|
646
|
+
if (entity.gravityThenDrag) {
|
|
647
|
+
vel.y -= (entity.state.isInWater ? entity.waterGravity : entity.lavaGravity) * gravityMultiplier;
|
|
648
|
+
vel.y *= inertia;
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
vel.y *= inertia;
|
|
652
|
+
vel.y -= (entity.state.isInWater ? entity.waterGravity : entity.lavaGravity) * gravityMultiplier;
|
|
653
|
+
}
|
|
654
|
+
vel.x *= horizontalInertia;
|
|
655
|
+
vel.z *= horizontalInertia;
|
|
656
|
+
if (entity.state.isCollidedHorizontally &&
|
|
657
|
+
this.doesNotCollide(entity, pos.offset(vel.x, vel.y + 0.6 - pos.y + lastY, vel.z), world)) {
|
|
658
|
+
vel.y = physicsSettings_1.PhysicsSettings.outOfLiquidImpulse; // jump out of liquid
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
simulate(entity, world /*prismarine-world*/) {
|
|
663
|
+
if (!this.shouldMoveEntity(entity)) {
|
|
664
|
+
entity.velocity.set(0, 0, 0);
|
|
665
|
+
return entity.state;
|
|
666
|
+
}
|
|
667
|
+
const vel = entity.velocity;
|
|
668
|
+
const pos = entity.position;
|
|
669
|
+
const waterBB = this.getEntityBB(entity, pos).contract(0.001, 0.401, 0.001);
|
|
670
|
+
const lavaBB = this.getEntityBB(entity, pos).contract(0.1, 0.4, 0.1);
|
|
671
|
+
// assume that if we shouldn't move entity, isInWater and isInLava are already properly set.
|
|
672
|
+
entity.state.isInWater = this.isInWaterApplyCurrent(waterBB, vel, world);
|
|
673
|
+
entity.state.isInLava = this.isMaterialInBB(lavaBB, this.lavaId, world);
|
|
674
|
+
// Reset velocity component if it falls under the threshold
|
|
675
|
+
if (Math.abs(vel.x) < physicsSettings_1.PhysicsSettings.negligeableVelocity)
|
|
676
|
+
vel.x = 0;
|
|
677
|
+
if (Math.abs(vel.y) < physicsSettings_1.PhysicsSettings.negligeableVelocity)
|
|
678
|
+
vel.y = 0;
|
|
679
|
+
if (Math.abs(vel.z) < physicsSettings_1.PhysicsSettings.negligeableVelocity)
|
|
680
|
+
vel.z = 0;
|
|
681
|
+
let strafe = 0;
|
|
682
|
+
let forward = 0;
|
|
683
|
+
// Handle inputs
|
|
684
|
+
if (entity.useControls) {
|
|
685
|
+
if (entity.state.control.jump || entity.state.jumpQueued) {
|
|
686
|
+
if (entity.state.jumpTicks > 0)
|
|
687
|
+
entity.state.jumpTicks--;
|
|
688
|
+
if (entity.state.isInWater || entity.state.isInLava) {
|
|
689
|
+
vel.y += 0.04; // according to prismarine-physics
|
|
690
|
+
}
|
|
691
|
+
else if (entity.state.onGround && entity.state.jumpTicks === 0) {
|
|
692
|
+
const blockBelow = world.getBlock(entity.position.floored().offset(0, -0.5, 0));
|
|
693
|
+
vel.y =
|
|
694
|
+
Math.fround(0.42) * (blockBelow && blockBelow.type === this.honeyblockId ? physicsSettings_1.PhysicsSettings.honeyblockJumpSpeed : 1);
|
|
695
|
+
if (entity.state.jumpBoost > 0) {
|
|
696
|
+
vel.y += 0.1 * entity.state.jumpBoost;
|
|
697
|
+
}
|
|
698
|
+
if (entity.state.control.sprint) {
|
|
699
|
+
const yaw = Math.PI - entity.state.yaw;
|
|
700
|
+
vel.x -= Math.sin(yaw) * 0.2;
|
|
701
|
+
vel.z += Math.cos(yaw) * 0.2;
|
|
702
|
+
}
|
|
703
|
+
entity.state.jumpTicks = physicsSettings_1.PhysicsSettings.autojumpCooldown;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
entity.state.jumpTicks = 0; // reset autojump cooldown
|
|
708
|
+
}
|
|
709
|
+
entity.state.jumpQueued = false;
|
|
710
|
+
strafe =
|
|
711
|
+
(entity.state.control.left - entity.state.control.right) * 0.98;
|
|
712
|
+
forward =
|
|
713
|
+
(entity.state.control.forward - entity.state.control.back) * 0.98;
|
|
714
|
+
if (entity.state.control.sneak) {
|
|
715
|
+
strafe *= physicsSettings_1.PhysicsSettings.sneakSpeed;
|
|
716
|
+
forward *= physicsSettings_1.PhysicsSettings.sneakSpeed;
|
|
717
|
+
entity.state.control.sprint = false;
|
|
718
|
+
}
|
|
719
|
+
if (entity.state.isUsingItem) {
|
|
720
|
+
strafe *= physicsSettings_1.PhysicsSettings.usingItemSpeed;
|
|
721
|
+
forward *= physicsSettings_1.PhysicsSettings.usingItemSpeed;
|
|
722
|
+
entity.state.control.sprint = false;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
entity.state.elytraFlying = entity.state.elytraFlying && entity.state.elytraEquipped && !entity.state.onGround && !entity.state.levitation;
|
|
726
|
+
if (entity.state.fireworkRocketDuration > 0) {
|
|
727
|
+
if (!entity.state.elytraFlying) {
|
|
728
|
+
entity.state.fireworkRocketDuration = 0;
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
const { lookDir } = (0, physicsUtils_1.getLookingVector)(entity.state);
|
|
732
|
+
vel.x += lookDir.x * 0.1 + (lookDir.x * 1.5 - vel.x) * 0.5;
|
|
733
|
+
vel.y += lookDir.y * 0.1 + (lookDir.y * 1.5 - vel.y) * 0.5;
|
|
734
|
+
vel.z += lookDir.z * 0.1 + (lookDir.z * 1.5 - vel.z) * 0.5;
|
|
735
|
+
--entity.state.fireworkRocketDuration;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
this.moveEntityWithHeading(entity, strafe, forward, world);
|
|
739
|
+
return entity.state;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
exports.EntityPhysics = EntityPhysics;
|
|
@@ -96,6 +96,8 @@ export declare class EntityState implements EntityStateBuilder {
|
|
|
96
96
|
* @returns AABB
|
|
97
97
|
*/
|
|
98
98
|
getAABB(): AABB;
|
|
99
|
+
lookAt(vec3: Vec3): void;
|
|
100
|
+
look(yaw: number, pitch: number): void;
|
|
99
101
|
getUnderlyingBlockBBs(world: any): AABB[];
|
|
100
102
|
getSurroundingBBs(world: any): AABB[];
|
|
101
103
|
}
|
|
@@ -258,6 +258,17 @@ class EntityState {
|
|
|
258
258
|
const w = this.halfWidth;
|
|
259
259
|
return new mineflayer_util_plugin_1.AABB(this.pos.x - w, this.pos.y, this.pos.z - w, this.pos.x + w, this.pos.y + this.height, this.pos.z + w);
|
|
260
260
|
}
|
|
261
|
+
lookAt(vec3) {
|
|
262
|
+
const dx = vec3.x - this.pos.x;
|
|
263
|
+
const dy = vec3.y - this.pos.y;
|
|
264
|
+
const dz = vec3.z - this.pos.z;
|
|
265
|
+
this.yaw = Math.atan2(dz, dx) * 180 / Math.PI - 90;
|
|
266
|
+
this.pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)) * 180 / Math.PI;
|
|
267
|
+
}
|
|
268
|
+
look(yaw, pitch) {
|
|
269
|
+
this.yaw = yaw;
|
|
270
|
+
this.pitch = pitch;
|
|
271
|
+
}
|
|
261
272
|
getUnderlyingBlockBBs(world /*prismarine-world*/) {
|
|
262
273
|
const queryBB = this.getAABB();
|
|
263
274
|
return this.ctx.getUnderlyingBlockBBs(queryBB, world);
|
|
@@ -72,7 +72,8 @@ exports.EntityDimensions = EntityDimensions;
|
|
|
72
72
|
class PlayerState {
|
|
73
73
|
constructor(ctx, bot, control) {
|
|
74
74
|
var _a, _b, _c, _d, _e;
|
|
75
|
-
this.height = 1.
|
|
75
|
+
this.height = 1.8;
|
|
76
|
+
this.eyeHeight = 1.62;
|
|
76
77
|
this.halfWidth = 0.3;
|
|
77
78
|
this.supportFeature = (0, physicsUtils_1.makeSupportFeature)(ctx.data);
|
|
78
79
|
this.ctx = ctx;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxg-org/mineflayer-physics-util",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.7",
|
|
4
4
|
"description": "Provides functionality for more accurate entity and projectile tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mineflayer",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"expect": "^29.5.0",
|
|
28
|
-
"mineflayer": "^4.
|
|
28
|
+
"mineflayer": "^4.18.0",
|
|
29
29
|
"mineflayer-pathfinder": "^2.4.4",
|
|
30
30
|
"prismarine-entity": "^2.4.0",
|
|
31
31
|
"typescript": "^4.5.5"
|
package/tests/actualBot.ts
CHANGED
|
@@ -11,12 +11,22 @@ const bot: Bot = createBot({
|
|
|
11
11
|
username: "testingbot"
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
bot.once('spawn', () => {
|
|
14
|
+
bot.once('spawn', async () => {
|
|
15
15
|
bot.loadPlugin(loader)
|
|
16
16
|
bot.loadPlugin(pathfinder)
|
|
17
|
+
await bot.waitForTicks(20)
|
|
18
|
+
bot.chat('rocky1928')
|
|
17
19
|
})
|
|
18
20
|
|
|
19
21
|
|
|
22
|
+
const rl = require('readline').createInterface({
|
|
23
|
+
input: process.stdin,
|
|
24
|
+
output: process.stdout
|
|
25
|
+
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
rl.on('line', (line: any) => bot.chat(line))
|
|
29
|
+
|
|
20
30
|
bot.on("chat", (user, message) => {
|
|
21
31
|
const [cmd, ...args] = message.split(' ')
|
|
22
32
|
const author = bot.nearestEntity(e=>e.username===user);
|
|
@@ -28,14 +38,24 @@ bot.on("chat", (user, message) => {
|
|
|
28
38
|
bot.physics = new Physics(bot.registry, bot.world);
|
|
29
39
|
break;
|
|
30
40
|
case "new":
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
const val = new EntityPhysics(bot.registry)
|
|
42
|
+
const oldSim = (bot.physics as any).simulatePlayer;
|
|
43
|
+
|
|
44
|
+
(EntityState.prototype as any).apply = function (bot: Bot) {
|
|
45
|
+
this.applyToBot(bot);
|
|
46
|
+
};
|
|
47
|
+
(bot.physics as any).simulatePlayer = (...args: any[]) => {
|
|
48
|
+
// bot.jumpTicks = 0
|
|
49
|
+
const ctx = EPhysicsCtx.FROM_BOT(val, bot)
|
|
50
|
+
ctx.state.jumpTicks = 0; // allow immediate jumping
|
|
51
|
+
// ctx.state.control.set('sneak', true)
|
|
52
|
+
return val.simulate(ctx, bot.world);
|
|
53
|
+
return oldSim(...args);
|
|
54
|
+
};
|
|
38
55
|
break;
|
|
56
|
+
case "jump":
|
|
57
|
+
bot.setControlState('jump', true)
|
|
58
|
+
break
|
|
39
59
|
case "come":
|
|
40
60
|
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
41
61
|
const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3);
|
|
@@ -48,6 +68,7 @@ bot.on("chat", (user, message) => {
|
|
|
48
68
|
break;
|
|
49
69
|
case "stop":
|
|
50
70
|
bot.pathfinder.stop();
|
|
71
|
+
bot.clearControlStates();
|
|
51
72
|
bot.chat('Stopped!')
|
|
52
73
|
break;
|
|
53
74
|
|