@nxg-org/mineflayer-physics-util 1.7.8 → 1.7.10
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/botcraft.d.ts +4 -1
- package/dist/physics/engines/botcraft.js +136 -75
- package/dist/physics/engines/entityPhysics.js +1 -0
- package/dist/physics/states/playerState.js +1 -0
- package/package.json +1 -1
- package/tests/actualBot.ts +165 -123
- package/tests/fakeWorld.test.ts +79 -21
|
@@ -112,7 +112,10 @@ export declare class BotcraftPhysics implements IPhysics {
|
|
|
112
112
|
movePlayer(ctx: EPhysicsCtx, world: World): void;
|
|
113
113
|
applyMovement(ctx: EPhysicsCtx, world: World): void;
|
|
114
114
|
checkInsideBlocks(player: PlayerState, world: World): void;
|
|
115
|
-
collideBoundingBox(world: World, bb: AABB, movement: Vec3): Vec3;
|
|
115
|
+
collideBoundingBox(world: World, bb: AABB, movement: Vec3, colliders?: AABB[]): Vec3;
|
|
116
|
+
private collideWithShapes;
|
|
117
|
+
shapeCollide(axis: number, bb: AABB, colliders: AABB[], movement: number): number;
|
|
118
|
+
private voxelShapeCollide;
|
|
116
119
|
collideOneAxis(movedAABB: AABB, movement: Vec3, axis: number, colliders: AABB[]): void;
|
|
117
120
|
applyInputs(inputStrength: number, player: PlayerState): void;
|
|
118
121
|
isInClimbable(player: PlayerState, world: World): boolean;
|
|
@@ -212,12 +212,9 @@ class BotcraftPhysics {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
const playerFlag = ctx.entityType.type === "player";
|
|
215
|
-
// if world is currently loaded at player position
|
|
216
|
-
if (playerFlag) {
|
|
217
|
-
// TODO: check if spectator mode
|
|
218
|
-
}
|
|
219
215
|
this.fluidPhysics(ctx, world, true);
|
|
220
216
|
this.fluidPhysics(ctx, world, false);
|
|
217
|
+
// updateSwimming moved into AiStep.
|
|
221
218
|
// separation into a new function
|
|
222
219
|
// originally: https://github.com/adepierre/Botcraft/blob/6c572071b0237c27a85211a246ce10565ef4d80f/botcraft/src/Game/Physics/PhysicsManager.cpp#L325
|
|
223
220
|
if (playerFlag) {
|
|
@@ -697,12 +694,14 @@ class BotcraftPhysics {
|
|
|
697
694
|
blockJumpFactor = 0.4;
|
|
698
695
|
}
|
|
699
696
|
if (this.verLessThan("1.20.5")) {
|
|
700
|
-
player.vel.y = 0.42 * blockJumpFactor + jumpBoost;
|
|
697
|
+
player.vel.y = Math.fround(0.42) * blockJumpFactor + jumpBoost;
|
|
701
698
|
if (player.sprinting) {
|
|
702
|
-
const yawRad = player.yaw; // should already be in yaw.
|
|
699
|
+
const yawRad = Math.PI - player.yaw; // should already be in yaw. MINEFLAYER SPECIFC CHANGE, MATH.PI -
|
|
703
700
|
// potential inconsistency here. This may not be accurate.
|
|
704
|
-
|
|
705
|
-
|
|
701
|
+
const offsetX = Math.fround(Math.sin(yawRad)) * 0.2;
|
|
702
|
+
const offsetZ = Math.fround(Math.cos(yawRad)) * 0.2;
|
|
703
|
+
player.vel.x -= offsetX;
|
|
704
|
+
player.vel.z += offsetZ;
|
|
706
705
|
}
|
|
707
706
|
}
|
|
708
707
|
else {
|
|
@@ -711,7 +710,7 @@ class BotcraftPhysics {
|
|
|
711
710
|
if (jumpPower > 1e-5) {
|
|
712
711
|
player.vel.y = jumpPower;
|
|
713
712
|
if (player.sprinting) {
|
|
714
|
-
const yawRad = player.yaw; // should already be in yaw.
|
|
713
|
+
const yawRad = Math.PI - player.yaw; // should already be in yaw. MINEFLAYER SPECIFC CHANGE, MATH.PI -
|
|
715
714
|
player.vel.x -= Math.sin(yawRad) * 0.2;
|
|
716
715
|
player.vel.z += Math.cos(yawRad) * 0.2;
|
|
717
716
|
}
|
|
@@ -893,7 +892,18 @@ class BotcraftPhysics {
|
|
|
893
892
|
const inertia = player.onGround ? friction * ctx.airborneInertia : ctx.airborneInertia;
|
|
894
893
|
// deviation, adding additional logic for changing attribute values.
|
|
895
894
|
const movementSpeedAttr = this.getMovementSpeedAttribute(ctx);
|
|
896
|
-
|
|
895
|
+
let inputStrength;
|
|
896
|
+
if (player.onGround) {
|
|
897
|
+
inputStrength = movementSpeedAttr * (0.21600002 / (friction * friction * friction));
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
inputStrength = 0.02;
|
|
901
|
+
// DEVIATION: taken from p-physics, fixes motion!
|
|
902
|
+
if (player.control.sprint) {
|
|
903
|
+
const airSprintFactor = ctx.airborneAccel * 0.3;
|
|
904
|
+
inputStrength += airSprintFactor;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
897
907
|
this.applyInputs(inputStrength, player);
|
|
898
908
|
if (player.onClimbable) {
|
|
899
909
|
// LivingEntity::handleOnClimbable
|
|
@@ -941,9 +951,9 @@ class BotcraftPhysics {
|
|
|
941
951
|
player.stuckSpeedMultiplier.set(0, 0, 0);
|
|
942
952
|
player.vel.set(0, 0, 0);
|
|
943
953
|
}
|
|
944
|
-
let
|
|
954
|
+
let maxUpStep = ctx.stepHeight;
|
|
945
955
|
if (!this.verLessThan("1.20.5")) {
|
|
946
|
-
|
|
956
|
+
maxUpStep = player.attributes[this.stepHeightAttribute].value;
|
|
947
957
|
}
|
|
948
958
|
// const playerAABB = player.getBB();
|
|
949
959
|
if (!player.flying && movement.y <= 0.0 && player.control.sneak && player.onGround) {
|
|
@@ -955,58 +965,48 @@ class BotcraftPhysics {
|
|
|
955
965
|
bb.expand(-1e-7, -1e-7, -1e-7);
|
|
956
966
|
return bb;
|
|
957
967
|
};
|
|
958
|
-
while (movement.x != 0.0 && this.worldIsFree(world, prepare(movement.x, -
|
|
968
|
+
while (movement.x != 0.0 && this.worldIsFree(world, prepare(movement.x, -maxUpStep, 0), false)) {
|
|
959
969
|
movement.x = movement.x < step && movement.x >= -step ? 0.0 : movement.x > 0.0 ? movement.x - step : movement.x + step;
|
|
960
970
|
}
|
|
961
|
-
while (movement.z != 0.0 && this.worldIsFree(world, prepare(0, -
|
|
971
|
+
while (movement.z != 0.0 && this.worldIsFree(world, prepare(0, -maxUpStep, movement.z), false)) {
|
|
962
972
|
movement.z = movement.z < step && movement.z >= -step ? 0.0 : movement.z > 0.0 ? movement.z - step : movement.z + step;
|
|
963
973
|
}
|
|
964
|
-
while ((movement.x != 0.0 && movement.z != 0.0 && prepare(movement.x, -
|
|
974
|
+
while ((movement.x != 0.0 && movement.z != 0.0 && prepare(movement.x, -maxUpStep, movement.z), false)) {
|
|
965
975
|
movement.x = movement.x < step && movement.x >= -step ? 0.0 : movement.x > 0.0 ? movement.x - step : movement.x + step;
|
|
966
976
|
movement.z = movement.z < step && movement.z >= -step ? 0.0 : movement.z > 0.0 ? movement.z - step : movement.z + step;
|
|
967
977
|
}
|
|
968
978
|
}
|
|
969
979
|
const movementBeforeCollisions = movement.clone();
|
|
970
|
-
{
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
if (
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
// stepUpBB.translate(horizontalMovement.x * 0.5, 0, horizontalMovement.z * 0.5);
|
|
987
|
-
// stepUpBB.expand(horizontalMovement.x, 0, horizontalMovement.z);
|
|
988
|
-
// stepUpBB.translate(0, maxStepUp, 0);
|
|
989
|
-
// const movementStepUpOnly = this.collideBoundingBox(world, stepUpBB, horizontalMovement);
|
|
990
|
-
const movementStepUpOnly = this.collideBoundingBox(world, player.getBB(), new vec3_1.Vec3(0, maxStepUp, 0));
|
|
991
|
-
if (movementStepUpOnly.y < maxStepUp) {
|
|
992
|
-
const check = this.collideBoundingBox(world, player.getBB().translateVec(movementStepUpOnly), horizontalMovement).plus(movementStepUpOnly);
|
|
993
|
-
if (check.x * check.x + check.z * check.z >
|
|
994
|
-
movementWithStepUp.x * movementWithStepUp.x + movementWithStepUp.z * movementWithStepUp.z) {
|
|
995
|
-
movementWithStepUp = check;
|
|
980
|
+
{ // Entity::collide
|
|
981
|
+
const playerAABB = player.getBB();
|
|
982
|
+
const hDist = (vec) => Math.sqrt(vec.x * vec.x + vec.z * vec.z);
|
|
983
|
+
// const entityCollisions = world.getEntityCollisions(player, playerAABB.expand(movement));
|
|
984
|
+
let newMovement = Math.pow(movement.norm(), 2) === 0 ? movement : this.collideBoundingBox(world, playerAABB, movement);
|
|
985
|
+
const collisionX = Math.abs(movement.x - newMovement.x) > 1e-7;
|
|
986
|
+
const collisionY = Math.abs(movement.y - newMovement.y) > 1e-7;
|
|
987
|
+
const collisionZ = Math.abs(movement.z - newMovement.z) > 1e-7;
|
|
988
|
+
const onGround = player.onGround || (collisionY && movement.y < 0);
|
|
989
|
+
if (maxUpStep > 0 && onGround && (collisionX || collisionZ)) {
|
|
990
|
+
let stepUpMovement = this.collideBoundingBox(world, playerAABB, new vec3_1.Vec3(movement.x, maxUpStep, movement.z));
|
|
991
|
+
const stepOnlyMovement = this.collideBoundingBox(world, playerAABB.expandTowardsCoords(movement.x, 0, movement.z), new vec3_1.Vec3(0, maxUpStep, 0));
|
|
992
|
+
if (stepOnlyMovement.y < maxUpStep) {
|
|
993
|
+
const adjustedStepUp = this.collideBoundingBox(world, playerAABB.translateVec(stepOnlyMovement), new vec3_1.Vec3(movement.x, 0, movement.z)).add(stepOnlyMovement);
|
|
994
|
+
if (hDist(adjustedStepUp) > hDist(stepUpMovement)) {
|
|
995
|
+
stepUpMovement = adjustedStepUp;
|
|
996
996
|
}
|
|
997
997
|
}
|
|
998
|
-
if (
|
|
999
|
-
|
|
1000
|
-
movement = movementWithStepUp.plus(this.collideBoundingBox(world, player.getBB().translateVec(movementWithStepUp), new vec3_1.Vec3(0.0, -movementWithStepUp.y + movementBeforeCollisions.y, 0.0)));
|
|
998
|
+
if (hDist(stepUpMovement) > hDist(newMovement)) {
|
|
999
|
+
newMovement = stepUpMovement.add(this.collideBoundingBox(world, playerAABB.translateVec(stepUpMovement), new vec3_1.Vec3(0, -stepUpMovement.y + movement.y, 0)));
|
|
1001
1000
|
}
|
|
1002
1001
|
}
|
|
1002
|
+
movement = newMovement;
|
|
1003
1003
|
}
|
|
1004
1004
|
if (Math.pow(movement.norm(), 2) > 1e-7) {
|
|
1005
1005
|
player.pos.add(movement);
|
|
1006
1006
|
}
|
|
1007
|
-
const collisionX = movement.x
|
|
1008
|
-
const collisionY = movement.y
|
|
1009
|
-
const collisionZ = movement.z
|
|
1007
|
+
const collisionX = Math.abs(movement.x - movementBeforeCollisions.x) > 1e-7;
|
|
1008
|
+
const collisionY = Math.abs(movement.y - movementBeforeCollisions.y) > 1e-7;
|
|
1009
|
+
const collisionZ = Math.abs(movement.z - movementBeforeCollisions.z) > 1e-7;
|
|
1010
1010
|
player.isCollidedHorizontally = collisionX || collisionZ;
|
|
1011
1011
|
player.isCollidedVertically = collisionY;
|
|
1012
1012
|
// TODO: add minor horizontal collision check
|
|
@@ -1135,27 +1135,99 @@ class BotcraftPhysics {
|
|
|
1135
1135
|
}
|
|
1136
1136
|
}
|
|
1137
1137
|
}
|
|
1138
|
-
collideBoundingBox(world, bb, movement) {
|
|
1139
|
-
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
const
|
|
1138
|
+
collideBoundingBox(world, bb, movement, colliders = []) {
|
|
1139
|
+
const queryBB = bb.clone().expandTowards(movement);
|
|
1140
|
+
const combinedColliders = [...colliders];
|
|
1141
|
+
const blockCollisions = this.getSurroundingBBs(queryBB, world);
|
|
1142
|
+
for (const block of blockCollisions) {
|
|
1143
|
+
combinedColliders.push(block);
|
|
1144
|
+
}
|
|
1145
|
+
return this.collideWithShapes(movement, bb, combinedColliders);
|
|
1146
|
+
}
|
|
1147
|
+
collideWithShapes(movement, bb, colliders = []) {
|
|
1143
1148
|
if (colliders.length === 0) {
|
|
1144
1149
|
return movement;
|
|
1145
1150
|
}
|
|
1146
|
-
let
|
|
1147
|
-
let
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1151
|
+
let dx = movement.x;
|
|
1152
|
+
let dy = movement.y;
|
|
1153
|
+
let dz = movement.z;
|
|
1154
|
+
if (dy !== 0.0) {
|
|
1155
|
+
dy = this.shapeCollide(1, bb, colliders, dy);
|
|
1156
|
+
if (dy !== 0.0) {
|
|
1157
|
+
bb = bb.translate(0, dy, 0);
|
|
1158
|
+
}
|
|
1153
1159
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
this.
|
|
1160
|
+
const prioritizeZ = Math.abs(dx) < Math.abs(dz);
|
|
1161
|
+
if (prioritizeZ && dz !== 0.0) {
|
|
1162
|
+
dz = this.shapeCollide(2, bb, colliders, dz);
|
|
1163
|
+
if (dz !== 0.0) {
|
|
1164
|
+
bb = bb.translate(0, 0, dz);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (dx !== 0.0) {
|
|
1168
|
+
dx = this.shapeCollide(0, bb, colliders, dx);
|
|
1169
|
+
if (!prioritizeZ && dx !== 0.0) {
|
|
1170
|
+
bb = bb.translate(dx, 0, 0);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
if (!prioritizeZ && dz !== 0.0) {
|
|
1174
|
+
dz = this.shapeCollide(2, bb, colliders, dz);
|
|
1175
|
+
}
|
|
1176
|
+
return new vec3_1.Vec3(dx, dy, dz);
|
|
1177
|
+
}
|
|
1178
|
+
shapeCollide(axis, bb, colliders, movement) {
|
|
1179
|
+
if (Math.abs(movement) < 1e-7) {
|
|
1180
|
+
return 0.0;
|
|
1181
|
+
}
|
|
1182
|
+
movement = this.voxelShapeCollide(axis, bb, movement, colliders);
|
|
1183
|
+
return movement;
|
|
1184
|
+
}
|
|
1185
|
+
voxelShapeCollide(axis, bb, movement, colliders) {
|
|
1186
|
+
if (Math.abs(movement) < 1e-7) {
|
|
1187
|
+
return 0.0;
|
|
1188
|
+
}
|
|
1189
|
+
const [minBB, maxBB] = bb.minAndMaxArrays();
|
|
1190
|
+
const maxAxis = axis === 0 ? bb.maxX : axis === 1 ? bb.maxY : bb.maxZ;
|
|
1191
|
+
const minAxis = axis === 0 ? bb.minX : axis === 1 ? bb.minY : bb.minZ;
|
|
1192
|
+
const offAxis1 = (axis + 1) % 3;
|
|
1193
|
+
const offAxis2 = (axis + 2) % 3;
|
|
1194
|
+
if (movement > 0.0) {
|
|
1195
|
+
for (const collider of colliders) {
|
|
1196
|
+
const colliderMin = axis === 0 ? collider.minX : axis === 1 ? collider.minY : collider.minZ;
|
|
1197
|
+
// verify that the other axis are colliding.
|
|
1198
|
+
const [minPt, maxPt] = collider.minAndMaxArrays();
|
|
1199
|
+
if (maxBB[offAxis1] - 1e-7 <= minPt[offAxis1] || minBB[offAxis1] + 1e-7 >= maxPt[offAxis1] ||
|
|
1200
|
+
maxBB[offAxis2] - 1e-7 <= minPt[offAxis2] || minBB[offAxis2] + 1e-7 >= maxPt[offAxis2]) {
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
if (colliderMin >= maxAxis) {
|
|
1204
|
+
const distance = colliderMin - maxAxis;
|
|
1205
|
+
if (distance >= -1e-7) {
|
|
1206
|
+
movement = Math.min(movement, distance);
|
|
1207
|
+
}
|
|
1208
|
+
// return movement;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
else if (movement < 0.0) {
|
|
1213
|
+
for (const collider of colliders) {
|
|
1214
|
+
// verify that the other axis are colliding.
|
|
1215
|
+
const [minPt, maxPt] = collider.minAndMaxArrays();
|
|
1216
|
+
if (maxBB[offAxis1] - 1e-7 <= minPt[offAxis1] || minBB[offAxis1] + 1e-7 >= maxPt[offAxis1] ||
|
|
1217
|
+
maxBB[offAxis2] - 1e-7 <= minPt[offAxis2] || minBB[offAxis2] + 1e-7 >= maxPt[offAxis2]) {
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
const colliderMax = axis === 0 ? collider.maxX : axis === 1 ? collider.maxY : collider.maxZ;
|
|
1221
|
+
if (colliderMax <= minAxis) {
|
|
1222
|
+
const distance = colliderMax - minAxis;
|
|
1223
|
+
if (distance <= 1e-7) {
|
|
1224
|
+
movement = Math.max(movement, distance);
|
|
1225
|
+
}
|
|
1226
|
+
// return movement;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1157
1229
|
}
|
|
1158
|
-
return
|
|
1230
|
+
return movement;
|
|
1159
1231
|
}
|
|
1160
1232
|
collideOneAxis(movedAABB, movement, axis, colliders) {
|
|
1161
1233
|
const minAABB = movedAABB.minPoint().toArray();
|
|
@@ -1172,17 +1244,6 @@ class BotcraftPhysics {
|
|
|
1172
1244
|
const maxCollider = collider.maxPoint().toArray();
|
|
1173
1245
|
const cond1 = movementLst[thisAxis] > 0.0 && maxAABB[thisAxis] - 1e-7 <= minCollider[thisAxis];
|
|
1174
1246
|
const cond2 = movementLst[thisAxis] < 0.0 && minAABB[thisAxis] + 1e-7 >= maxCollider[thisAxis];
|
|
1175
|
-
// if (collider.minY === 5 && thisAxis === 2) {
|
|
1176
|
-
// console.log("collider", collider);
|
|
1177
|
-
// console.log("movement", movement);
|
|
1178
|
-
// console.log("movedAABB", movedAABB);
|
|
1179
|
-
// console.log("movementLst", movementLst);
|
|
1180
|
-
// console.log(minCollider, maxCollider);
|
|
1181
|
-
// console.log(minAABB, maxAABB);
|
|
1182
|
-
// console.log("axis", thisAxis);
|
|
1183
|
-
// console.log(movementLst[thisAxis], maxAABB[thisAxis] - 1e-7, minCollider[thisAxis], cond1);
|
|
1184
|
-
// console.log(movementLst[thisAxis], minAABB[thisAxis] + 1e-7, maxCollider[thisAxis], cond2);
|
|
1185
|
-
// }
|
|
1186
1247
|
if (maxAABB[axis1] - 1e-7 > minCollider[axis1] &&
|
|
1187
1248
|
minAABB[axis1] + 1e-7 < maxCollider[axis1] &&
|
|
1188
1249
|
maxAABB[axis2] - 1e-7 > minCollider[axis2] &&
|
|
@@ -1211,7 +1272,7 @@ class BotcraftPhysics {
|
|
|
1211
1272
|
if (sqrNorm > 1) {
|
|
1212
1273
|
inputVector.normalize();
|
|
1213
1274
|
}
|
|
1214
|
-
inputVector.scale(inputStrength
|
|
1275
|
+
inputVector.scale(inputStrength);
|
|
1215
1276
|
const yaw = Math.PI - player.yaw;
|
|
1216
1277
|
const sinYaw = Math.sin(yaw);
|
|
1217
1278
|
const cosYaw = Math.cos(yaw);
|
|
@@ -432,6 +432,7 @@ class PlayerState {
|
|
|
432
432
|
const dz = vec3.z - this.pos.z;
|
|
433
433
|
this.yaw = Math.atan2(dz, dx) * 180 / Math.PI - 90;
|
|
434
434
|
this.pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)) * 180 / Math.PI;
|
|
435
|
+
console.log(this.yaw, this.pitch);
|
|
435
436
|
}
|
|
436
437
|
look(yaw, pitch) {
|
|
437
438
|
this.yaw = yaw;
|
package/package.json
CHANGED
package/tests/actualBot.ts
CHANGED
|
@@ -1,141 +1,183 @@
|
|
|
1
1
|
import { pathfinder, goals } from "mineflayer-pathfinder";
|
|
2
2
|
import { Bot, createBot } from "mineflayer";
|
|
3
|
-
const physicsInject = require("mineflayer/lib/plugins/physics")
|
|
3
|
+
const physicsInject = require("mineflayer/lib/plugins/physics");
|
|
4
4
|
import loader, { BotcraftPhysics, EntityPhysics, EntityState, EPhysicsCtx } from "../src/index";
|
|
5
5
|
import { PlayerState } from "../src/physics/states";
|
|
6
6
|
|
|
7
7
|
const { Physics } = require("prismarine-physics");
|
|
8
8
|
|
|
9
|
-
const bot: Bot = createBot({
|
|
10
|
-
host: process.argv[2],
|
|
11
|
-
port: Number(process.argv[3]),
|
|
12
|
-
username: "testingbot",
|
|
13
|
-
version: process.argv[4],
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
bot.once("spawn", async () => {
|
|
17
|
-
bot.loadPlugin(loader);
|
|
18
|
-
bot.loadPlugin(pathfinder);
|
|
19
|
-
await bot.waitForTicks(20);
|
|
20
|
-
(bot as any).physics.yawSpeed = 50;
|
|
21
|
-
(bot as any).physics.pitchSpeed = 50;
|
|
22
|
-
// setupNewPhysics(bot);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
9
|
const rl = require("readline").createInterface({
|
|
26
10
|
input: process.stdin,
|
|
27
11
|
output: process.stdout,
|
|
28
12
|
});
|
|
29
13
|
|
|
30
|
-
rl.on("line", (line: any) => bot.chat(line));
|
|
31
14
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
bot
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
let bot1: Bot;
|
|
16
|
+
function buildBot() {
|
|
17
|
+
console.log('hey!')
|
|
18
|
+
|
|
19
|
+
const bot = createBot({
|
|
20
|
+
host: process.argv[2],
|
|
21
|
+
port: Number(process.argv[3]),
|
|
22
|
+
username: "testingbot",
|
|
23
|
+
version: process.argv[4],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
bot.once("spawn", async () => {
|
|
27
|
+
bot.loadPlugin(loader);
|
|
28
|
+
bot.loadPlugin(pathfinder);
|
|
29
|
+
await bot.waitForTicks(20);
|
|
30
|
+
(bot as any).physics.yawSpeed = 50;
|
|
31
|
+
(bot as any).physics.pitchSpeed = 50;
|
|
32
|
+
// setupNewPhysics(bot);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
let wasOnGround = false;
|
|
36
|
+
let printNextPos = false;
|
|
37
|
+
|
|
38
|
+
bot.on("move", (pos) => {
|
|
39
|
+
// console.log(pos);
|
|
40
|
+
if (bot.entity.onGround && !wasOnGround) {
|
|
41
|
+
// bot.chat("Hit the ground! " + bot.entity.position.toString());
|
|
42
|
+
}
|
|
43
|
+
wasOnGround = bot.entity.onGround;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// print whenever another player hits the ground
|
|
47
|
+
let lastPositions: Record<string, boolean> = {};
|
|
48
|
+
bot.on("entityMoved", (entity) => {
|
|
49
|
+
if (entity.username && entity.username !== bot.username) {
|
|
50
|
+
// check by seeing is y value is an integer
|
|
51
|
+
if (Math.floor(entity.position.y) === entity.position.y && !lastPositions[entity.username]) {
|
|
52
|
+
// check if in liquid
|
|
53
|
+
const block = bot.blockAt(entity.position);
|
|
54
|
+
if (block && (block.type === bot.registry.blocksByName.water.id || block.type === bot.registry.blocksByName.lava.id)) return;
|
|
55
|
+
|
|
56
|
+
bot.chat(`${entity.username} hit the ground! ${entity.position.toString()}`);
|
|
57
|
+
lastPositions[entity.username] = true;
|
|
58
|
+
} else if (Math.floor(entity.position.y) !== entity.position.y) {
|
|
59
|
+
lastPositions[entity.username] = false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
let usingNew = false;
|
|
65
|
+
let oldSimulate: any = null;
|
|
66
|
+
|
|
67
|
+
function setupNewPhysics(bot: Bot) {
|
|
68
|
+
if (usingNew) return;
|
|
69
|
+
usingNew = true;
|
|
70
|
+
oldSimulate = (bot.physics as any).simulatePlayer;
|
|
71
|
+
|
|
72
|
+
const val = new BotcraftPhysics(bot.registry);
|
|
73
|
+
|
|
74
|
+
(EntityState.prototype as any).apply = function (this: EntityState, bot: Bot) {
|
|
75
|
+
// console.log(this.control, this.isUsingItem);
|
|
76
|
+
this.applyToBot(bot);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const ctx = EPhysicsCtx.FROM_BOT(val, bot);
|
|
80
|
+
const state = ctx.state as PlayerState;
|
|
81
|
+
|
|
82
|
+
// EntityPhysics.prototype.simulate = function (ctx, world) {
|
|
83
|
+
// bot.physics.simulatePlayer(ctx.state, world);
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
(bot.physics as any).autojumpCooldown = 0;
|
|
87
|
+
// (bot.physics).jumpTicks = 0;
|
|
88
|
+
|
|
89
|
+
(bot.physics as any).simulatePlayer = (...args: any[]) => {
|
|
90
|
+
state.update(bot);
|
|
91
|
+
ctx.state.jumpTicks = 0; // allow immediate jumping
|
|
92
|
+
return val.simulate(ctx, bot.world);
|
|
93
|
+
};
|
|
39
94
|
}
|
|
40
|
-
wasOnGround = bot.entity.onGround;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// print whenever another player hits the ground
|
|
44
|
-
let lastPositions: Record<string, boolean> = {};
|
|
45
|
-
bot.on("entityMoved", (entity) => {
|
|
46
|
-
if (entity.username && entity.username !== bot.username) {
|
|
47
|
-
// check by seeing is y value is an integer
|
|
48
|
-
if (Math.floor(entity.position.y) === entity.position.y && !lastPositions[entity.username]) {
|
|
49
|
-
|
|
50
|
-
// check if in liquid
|
|
51
|
-
const block = bot.blockAt(entity.position);
|
|
52
|
-
if (block && (block.type === bot.registry.blocksByName.water.id || block.type === bot.registry.blocksByName.lava.id)) return;
|
|
53
|
-
|
|
54
|
-
bot.chat(`${entity.username} hit the ground! ${entity.position.toString()}`);
|
|
55
|
-
lastPositions[entity.username] = true;
|
|
56
|
-
} else if (Math.floor(entity.position.y) !== entity.position.y) {
|
|
57
|
-
lastPositions[entity.username] = false;
|
|
58
|
-
}}
|
|
59
|
-
});
|
|
60
95
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
bot.on("chat", async (user, message) => {
|
|
97
|
+
const [cmd, ...args] = message.split(" ");
|
|
98
|
+
const author = bot.nearestEntity((e) => e.username === user);
|
|
99
|
+
|
|
100
|
+
switch (cmd) {
|
|
101
|
+
case "using":
|
|
102
|
+
bot.chat(`Using new physics: ${usingNew}`);
|
|
103
|
+
break;
|
|
104
|
+
case "lookatme":
|
|
105
|
+
if (!author) return bot.chat("I can't see you!");
|
|
106
|
+
bot.lookAt(author.position.offset(0, author.height, 0));
|
|
107
|
+
break;
|
|
108
|
+
case "status":
|
|
109
|
+
const str = `onGround: ${bot.entity.onGround}, hCol:${(bot.entity as any).isCollidedHorizontally}, vCol:${
|
|
110
|
+
(bot.entity as any).isCollidedVertically
|
|
111
|
+
}, inWater:${(bot.entity as any).isInWater}, inLava:${(bot.entity as any).isInLava}`;
|
|
112
|
+
bot.chat(str);
|
|
113
|
+
break;
|
|
114
|
+
case "use":
|
|
115
|
+
if (bot.usingHeldItem) bot.deactivateItem();
|
|
116
|
+
else bot.activateItem();
|
|
117
|
+
break;
|
|
118
|
+
case "useoff":
|
|
119
|
+
bot.deactivateItem();
|
|
120
|
+
bot.activateItem(true);
|
|
121
|
+
break;
|
|
122
|
+
case "control":
|
|
123
|
+
if (args[0] === "clear") return bot.clearControlStates();
|
|
124
|
+
if (args.length === 1) return bot.setControlState(args[0] as any, !bot.getControlState(args[0] as any));
|
|
125
|
+
bot.setControlState(args[0] as any, args[1] === "true");
|
|
126
|
+
break;
|
|
127
|
+
case "sim":
|
|
128
|
+
// turn all but the mentioned ones off
|
|
129
|
+
const [time, ...controls] = args;
|
|
130
|
+
bot.clearControlStates();
|
|
131
|
+
for (const control of controls) {
|
|
132
|
+
bot.setControlState(control as any, true);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (let i = 0; i <= Number(time); i++) {
|
|
136
|
+
console.log(bot.entity.position, bot.entity.velocity, i);
|
|
137
|
+
await bot.waitForTicks(1);
|
|
138
|
+
}
|
|
139
|
+
bot.clearControlStates();
|
|
140
|
+
|
|
141
|
+
break;
|
|
142
|
+
case "reset":
|
|
143
|
+
usingNew = false;
|
|
144
|
+
bot.quit();
|
|
145
|
+
await new Promise((res) => setTimeout(res, 3000));
|
|
146
|
+
bot1 = buildBot();
|
|
147
|
+
|
|
148
|
+
break;
|
|
149
|
+
case "new":
|
|
150
|
+
setupNewPhysics(bot);
|
|
151
|
+
bot.chat("Switched to new physics!");
|
|
152
|
+
break;
|
|
153
|
+
case "jump":
|
|
154
|
+
bot.setControlState("jump", true);
|
|
155
|
+
break;
|
|
156
|
+
case "come":
|
|
157
|
+
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
158
|
+
const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3);
|
|
159
|
+
bot.pathfinder.setGoal(goal0);
|
|
160
|
+
break;
|
|
161
|
+
case "goto":
|
|
162
|
+
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
163
|
+
const goal1 = new goals.GoalNear(Number(args[0]), Number(args[1]), Number(args[2]), 3);
|
|
164
|
+
bot.pathfinder.setGoal(goal1);
|
|
165
|
+
break;
|
|
166
|
+
case "stop":
|
|
167
|
+
bot.deactivateItem();
|
|
168
|
+
bot.pathfinder.stop();
|
|
169
|
+
bot.clearControlStates();
|
|
170
|
+
bot.chat("Stopped!");
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
rl.on("line", (line: any) => bot.chat(line));
|
|
177
|
+
|
|
178
|
+
return bot;
|
|
179
|
+
}
|
|
71
180
|
|
|
72
|
-
// EntityPhysics.prototype.simulate = function (ctx, world) {
|
|
73
|
-
// bot.physics.simulatePlayer(ctx.state, world);
|
|
74
|
-
// }
|
|
75
181
|
|
|
76
|
-
(bot.physics as any).autojumpCooldown = 0;
|
|
77
|
-
// (bot.physics).jumpTicks = 0;
|
|
78
182
|
|
|
79
|
-
|
|
80
|
-
state.update(bot);
|
|
81
|
-
ctx.state.jumpTicks = 0; // allow immediate jumping
|
|
82
|
-
return val.simulate(ctx, bot.world);
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
bot.on("chat", (user, message) => {
|
|
87
|
-
const [cmd, ...args] = message.split(" ");
|
|
88
|
-
const author = bot.nearestEntity((e) => e.username === user);
|
|
89
|
-
|
|
90
|
-
switch (cmd) {
|
|
91
|
-
case "lookatme":
|
|
92
|
-
if (!author) return bot.chat("I can't see you!");
|
|
93
|
-
bot.lookAt(author.position.offset(0, author.height, 0));
|
|
94
|
-
break;
|
|
95
|
-
case "status":
|
|
96
|
-
const str = `onGround: ${bot.entity.onGround}, hCol:${(bot.entity as any).isCollidedHorizontally}, vCol:${(bot.entity as any).isCollidedVertically}, inWater:${(bot.entity as any).isInWater}, inLava:${(bot.entity as any).isInLava}`;
|
|
97
|
-
bot.chat(str);
|
|
98
|
-
break
|
|
99
|
-
case "use":
|
|
100
|
-
if (bot.usingHeldItem) bot.deactivateItem();
|
|
101
|
-
else bot.activateItem();
|
|
102
|
-
break;
|
|
103
|
-
case "useoff":
|
|
104
|
-
bot.deactivateItem()
|
|
105
|
-
bot.activateItem(true)
|
|
106
|
-
break
|
|
107
|
-
case "control":
|
|
108
|
-
|
|
109
|
-
if (args[0] === "clear") return bot.clearControlStates();
|
|
110
|
-
if (args.length !== 2) return bot.chat("Invalid control command!");
|
|
111
|
-
bot.setControlState(args[0] as any, args[1] === "true");
|
|
112
|
-
break;
|
|
113
|
-
case "original":
|
|
114
|
-
bot.loadPlugin(physicsInject);
|
|
115
|
-
bot.chat("Switched to original physics!");
|
|
116
|
-
break;
|
|
117
|
-
case "new":
|
|
118
|
-
setupNewPhysics(bot);
|
|
119
|
-
bot.chat("Switched to new physics!");
|
|
120
|
-
break;
|
|
121
|
-
case "jump":
|
|
122
|
-
bot.setControlState("jump", true);
|
|
123
|
-
break;
|
|
124
|
-
case "come":
|
|
125
|
-
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
126
|
-
const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3);
|
|
127
|
-
bot.pathfinder.setGoal(goal0);
|
|
128
|
-
break;
|
|
129
|
-
case "goto":
|
|
130
|
-
if (!author) return bot.chat(`Cannot see ${user}!`);
|
|
131
|
-
const goal1 = new goals.GoalNear(Number(args[0]), Number(args[1]), Number(args[2]), 3);
|
|
132
|
-
bot.pathfinder.setGoal(goal1);
|
|
133
|
-
break;
|
|
134
|
-
case "stop":
|
|
135
|
-
bot.deactivateItem();
|
|
136
|
-
bot.pathfinder.stop();
|
|
137
|
-
bot.clearControlStates();
|
|
138
|
-
bot.chat("Stopped!");
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
});
|
|
183
|
+
bot1 = buildBot();
|
package/tests/fakeWorld.test.ts
CHANGED
|
@@ -13,10 +13,11 @@ import { Bot, ControlState } from "mineflayer";
|
|
|
13
13
|
|
|
14
14
|
const version = "1.12.2";
|
|
15
15
|
const mcData = md(version);
|
|
16
|
+
const Engine = BotcraftPhysics;
|
|
16
17
|
const Block = block(version) as typeof PBlock;
|
|
17
18
|
|
|
18
|
-
const groundLevel =
|
|
19
|
-
const floatingOffset =
|
|
19
|
+
const groundLevel = 67;
|
|
20
|
+
const floatingOffset = 100 - groundLevel;
|
|
20
21
|
const control: { [key: string]: boolean } = {};
|
|
21
22
|
|
|
22
23
|
class FakeWorld {
|
|
@@ -47,12 +48,13 @@ class FakeWorld {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
function createFakePlayer(pos: Vec3,
|
|
51
|
+
function createFakePlayer(pos: Vec3, tmpGroundLevel: number = groundLevel) {
|
|
52
|
+
const onGround = pos.y === tmpGroundLevel
|
|
51
53
|
return {
|
|
52
54
|
entity: {
|
|
53
55
|
position: pos,
|
|
54
|
-
velocity: new Vec3(0, -0.08, 0),
|
|
55
|
-
onGround:
|
|
56
|
+
velocity: new Vec3(0, onGround ? -0.08 : 0, 0),
|
|
57
|
+
onGround: onGround,
|
|
56
58
|
isInWater: false,
|
|
57
59
|
isInLava: false,
|
|
58
60
|
isInWeb: false,
|
|
@@ -94,7 +96,7 @@ describe("Physics Simulation Tests", () => {
|
|
|
94
96
|
const setupEntity = (yOffset: number) => {
|
|
95
97
|
fakePlayer = createFakePlayer(new Vec3(0, groundLevel + yOffset, 0), groundLevel);
|
|
96
98
|
fakePlayer.entity = applyMdToNewEntity(EPhysicsCtx, playerType, fakePlayer.entity);
|
|
97
|
-
physics = new
|
|
99
|
+
physics = new Engine(mcData);
|
|
98
100
|
playerCtx = EPhysicsCtx.FROM_BOT(physics, fakePlayer);
|
|
99
101
|
playerState = playerCtx.state as PlayerState;
|
|
100
102
|
playerState.control = ControlStateHandler.DEFAULT();
|
|
@@ -110,7 +112,7 @@ describe("Physics Simulation Tests", () => {
|
|
|
110
112
|
playerState.vel.y = 0;
|
|
111
113
|
playerCtx.gravity = 0;
|
|
112
114
|
|
|
113
|
-
for (let i = 0; i <
|
|
115
|
+
for (let i = 0; i < 2; i++) {
|
|
114
116
|
// playerState.update(fakePlayer);
|
|
115
117
|
physics.simulate(playerCtx, fakeWorld);
|
|
116
118
|
playerState.apply(fakePlayer);
|
|
@@ -127,6 +129,7 @@ describe("Physics Simulation Tests", () => {
|
|
|
127
129
|
for (let i = 0; i < 10; i++) {
|
|
128
130
|
physics.simulate(playerCtx, fakeWorld);
|
|
129
131
|
playerState.apply(fakePlayer);
|
|
132
|
+
// console.log(fakePlayer.entity.position, playerState.pos, playerState.vel, playerState.age)
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
if (playerState.control.forward) {
|
|
@@ -136,10 +139,10 @@ describe("Physics Simulation Tests", () => {
|
|
|
136
139
|
}
|
|
137
140
|
});
|
|
138
141
|
|
|
139
|
-
it("
|
|
142
|
+
it("sprint-jumping", () => {
|
|
140
143
|
setupEntity(0);
|
|
141
144
|
playerState.control.forward = true;
|
|
142
|
-
|
|
145
|
+
playerState.control.sprint = true;
|
|
143
146
|
|
|
144
147
|
for (let i = 0; i < 4; i++) {
|
|
145
148
|
physics.simulate(playerCtx, fakeWorld);
|
|
@@ -156,37 +159,39 @@ describe("Physics Simulation Tests", () => {
|
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
expect(fakePlayer.entity.position.y).toEqual(groundLevel);
|
|
159
|
-
expect(fakePlayer.entity.position.z).toEqual(-
|
|
162
|
+
expect(fakePlayer.entity.position.z).toEqual(-4.085029471928113);
|
|
160
163
|
});
|
|
161
164
|
|
|
162
|
-
it("
|
|
165
|
+
it("walk_fallspeed", () => {
|
|
163
166
|
setupEntity(floatingOffset);
|
|
164
167
|
playerState.control.forward = true;
|
|
165
168
|
|
|
166
169
|
while (!fakePlayer.entity.onGround && playerState.age < 100) {
|
|
167
170
|
physics.simulate(playerCtx, fakeWorld);
|
|
171
|
+
// console.log(fakePlayer.entity.position, playerState.pos, playerState.vel, playerState.age)
|
|
168
172
|
playerState.apply(fakePlayer);
|
|
169
173
|
}
|
|
170
174
|
|
|
175
|
+
expect(fakePlayer.entity.position.z).toEqual(-5.082680598494437);
|
|
171
176
|
expect(fakePlayer.entity.position.y).toEqual(groundLevel);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const landingPos = playerState.pos.clone();
|
|
177
|
+
});
|
|
175
178
|
|
|
179
|
+
it ("sprint_fallspeed", () => {
|
|
176
180
|
setupEntity(floatingOffset);
|
|
177
181
|
playerState.control.forward = true;
|
|
178
182
|
playerState.control.sprint = true;
|
|
179
183
|
|
|
184
|
+
// console.log(playerState.vel)
|
|
180
185
|
while (!fakePlayer.entity.onGround && playerState.age < 100) {
|
|
181
186
|
physics.simulate(playerCtx, fakeWorld);
|
|
182
187
|
playerState.apply(fakePlayer);
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
console.log(fakePlayer.entity.position, landingPos, playerState.pos)
|
|
190
|
+
// console.log(fakePlayer.entity.position, landingPos, playerState.pos, playerState.control)
|
|
186
191
|
|
|
192
|
+
expect(fakePlayer.entity.position.z).toEqual(-7.624010798740387);
|
|
187
193
|
expect(fakePlayer.entity.position.y).toEqual(groundLevel);
|
|
188
|
-
|
|
189
|
-
});
|
|
194
|
+
})
|
|
190
195
|
|
|
191
196
|
it("should restore position after gravity toggle", () => {
|
|
192
197
|
setupEntity(floatingOffset);
|
|
@@ -219,7 +224,7 @@ describe("Physics Simulation Tests", () => {
|
|
|
219
224
|
playerState.apply(fakePlayer);
|
|
220
225
|
}
|
|
221
226
|
|
|
222
|
-
expect(fakePlayer.entity.position.y).toEqual(
|
|
227
|
+
expect(fakePlayer.entity.position.y).toEqual(groundLevel + 1.001335979112147);
|
|
223
228
|
|
|
224
229
|
for (let i = 0; i < 9; i++) {
|
|
225
230
|
physics.simulate(playerCtx, fakeWorld);
|
|
@@ -229,18 +234,71 @@ describe("Physics Simulation Tests", () => {
|
|
|
229
234
|
expect(fakePlayer.entity.position.y).toEqual(groundLevel);
|
|
230
235
|
});
|
|
231
236
|
|
|
232
|
-
it("
|
|
237
|
+
it("hCol-z", () => {
|
|
233
238
|
setupEntity(0);
|
|
234
|
-
|
|
239
|
+
const blockPos = new Vec3(0, groundLevel + 1, -2);
|
|
240
|
+
fakeWorld.setOverrideBlock(blockPos, mcData.blocksByName.dirt.id);
|
|
241
|
+
playerState.look(0, 0);
|
|
235
242
|
playerState.control.forward = true;
|
|
236
243
|
|
|
237
244
|
for (let i = 0; i < 10; i++) {
|
|
238
245
|
physics.simulate(playerCtx, fakeWorld);
|
|
239
246
|
playerState.apply(fakePlayer);
|
|
240
|
-
|
|
247
|
+
console.log(fakePlayer.entity.position, playerState.isCollidedHorizontally);
|
|
241
248
|
}
|
|
242
249
|
|
|
243
250
|
expect(playerState.pos.z).toEqual(-0.7);
|
|
244
251
|
expect(playerState.isCollidedHorizontally).toEqual(true);
|
|
245
252
|
});
|
|
253
|
+
|
|
254
|
+
it("hCol--z", () => {
|
|
255
|
+
setupEntity(0);
|
|
256
|
+
const blockPos = new Vec3(0, groundLevel + 1, 1);
|
|
257
|
+
fakeWorld.setOverrideBlock(blockPos, mcData.blocksByName.dirt.id);
|
|
258
|
+
playerState.look(-359.9999 * (Math.PI / 360), 0);
|
|
259
|
+
playerState.control.forward = true;
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < 10; i++) {
|
|
262
|
+
physics.simulate(playerCtx, fakeWorld);
|
|
263
|
+
playerState.apply(fakePlayer);
|
|
264
|
+
console.log(fakePlayer.entity.position, playerState.isCollidedHorizontally);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
expect(playerState.pos.z).toEqual(0.7);
|
|
268
|
+
expect(playerState.isCollidedHorizontally).toEqual(true);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it("hCol--x", () => {
|
|
272
|
+
setupEntity(0);
|
|
273
|
+
const blockPos = new Vec3(-2, groundLevel + 1, 0);
|
|
274
|
+
fakeWorld.setOverrideBlock(blockPos, mcData.blocksByName.dirt.id);
|
|
275
|
+
playerState.look(180 * (Math.PI / 360), 0)
|
|
276
|
+
playerState.control.forward = true;
|
|
277
|
+
|
|
278
|
+
for (let i = 0; i < 10; i++) {
|
|
279
|
+
physics.simulate(playerCtx, fakeWorld);
|
|
280
|
+
playerState.apply(fakePlayer);
|
|
281
|
+
console.log(fakePlayer.entity.position, playerState.isCollidedHorizontally);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
expect(playerState.pos.x).toEqual(-0.7);
|
|
285
|
+
expect(playerState.isCollidedHorizontally).toEqual(true);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("hCol-x", () => {
|
|
289
|
+
setupEntity(0);
|
|
290
|
+
const blockPos = new Vec3(1, groundLevel + 1, 0);
|
|
291
|
+
fakeWorld.setOverrideBlock(blockPos, mcData.blocksByName.dirt.id);
|
|
292
|
+
playerState.look(-180 * (Math.PI / 360), 0);
|
|
293
|
+
playerState.control.forward = true;
|
|
294
|
+
|
|
295
|
+
for (let i = 0; i < 10; i++) {
|
|
296
|
+
physics.simulate(playerCtx, fakeWorld);
|
|
297
|
+
playerState.apply(fakePlayer);
|
|
298
|
+
console.log(fakePlayer.entity.position, playerState.isCollidedHorizontally);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
expect(playerState.pos.x).toEqual(0.7);
|
|
302
|
+
expect(playerState.isCollidedHorizontally).toEqual(true);
|
|
303
|
+
});
|
|
246
304
|
});
|