mc-beta-server/server/AABB.ts
Holly 63333a04aa Implement AABB collision and add EntityItem properly.
The items are fully functional apart from picking them up, they are commented out in the MPClient breakBlock function if you want to play with them.
2023-11-09 16:30:40 +00:00

97 lines
No EOL
3.4 KiB
TypeScript

import { FunkyArray } from "../funkyArray";
import Vec3 from "./Vec3";
// Based on this MDN article:
// https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection
export default class AABB {
private static readonly aabbPool:FunkyArray<string, AABB> = new FunkyArray<string, AABB>();
public readonly aabbPoolString:string;
public readonly pooled:boolean;
public initMin:Vec3;
public initMax:Vec3;
public min:Vec3;
public max:Vec3;
public constructor(minXOrMin:Vec3 | number, minYOrMax:Vec3 | number, minZ?:number, maxX?:number, maxY?:number, maxZ?:number, pooled:boolean = false) {
if (minXOrMin instanceof Vec3 && minYOrMax instanceof Vec3) {
this.min = minXOrMin;
this.max = minYOrMax;
} else if (typeof(minXOrMin) === "number" && typeof(minYOrMax) === "number" && typeof(minZ) === "number" && typeof(maxX) === "number" && typeof(maxY) === "number" && typeof(maxZ) === "number") {
this.min = new Vec3(minXOrMin, minYOrMax, minZ);
this.max = new Vec3(maxX, maxY, maxZ);
} else {
throw new Error("Invalid input parameters: AABB must be supplied with either two Vec3 with the min and max bounds or the raw bounds.");
}
this.initMin = new Vec3(this.min);
this.initMax = new Vec3(this.max);
this.pooled = pooled;
this.aabbPoolString = AABB.createAABBPoolString(this.min.x, this.min.y, this.min.z, this.max.x, this.max.y, this.max.z);
if (!AABB.aabbPool.has(this.aabbPoolString)) {
AABB.aabbPool.set(this.aabbPoolString, this);
}
console.log(this);
}
public static createAABBPoolString(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number) {
return `m${minX}c${minY}a${minZ}a${maxX}b${maxY}b${maxZ}`;
}
public static getAABB(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number) {
const aabbPoolString = this.createAABBPoolString(minX, minY, minZ, maxX, maxY, maxZ);
if (AABB.aabbPool.has(aabbPoolString)) {
const aabb = AABB.aabbPool.get(aabbPoolString);
if (aabb === undefined) {
throw new Error(`Pooled AABB was ${typeof(aabb)}! This should be impossible.`);
}
return aabb;
}
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
}
public static intersects(a:AABB, b:AABB) {
return a.min.x <= b.max.x && a.max.x >= b.min.x && a.min.y <= b.max.y && a.max.y >= b.min.y && a.min.z <= b.max.z && a.max.z >= b.min.z;
}
public intersects(aabb:AABB) {
return this.min.x <= aabb.max.x && this.max.x >= aabb.min.x && this.min.y <= aabb.max.y && this.max.y >= aabb.min.y && this.min.z <= aabb.max.z && this.max.z >= aabb.min.z;
}
public static intersectionY(a: AABB, b: AABB) {
const minY = Math.max(a.min.y, b.min.y);
const maxY = Math.min(a.max.y, b.max.y);
return minY <= maxY ? maxY - minY : 0;
}
public intersectionY(aabb: AABB) {
const minY = Math.max(this.min.y, aabb.min.y);
const maxY = Math.min(this.max.y, aabb.max.y);
return minY <= maxY ? maxY - minY : 0;
}
public move(xOrVec3:Vec3 | number, y?:number, z?:number) {
if (this.pooled) {
throw new Error(`Attempted to move a pooled AABB. This is not allowed!`);
}
this.min.set(this.initMin);
this.max.set(this.initMax);
if (xOrVec3 instanceof Vec3) {
this.min.add(xOrVec3);
this.max.add(xOrVec3);
} else if (typeof(xOrVec3) === "number" && typeof(y) === "number" && typeof(z) === "number") {
this.min.add(xOrVec3, y, z);
this.max.add(xOrVec3, y, z);
}
}
}