implement block placing and destroying
This commit is contained in:
@@ -22,15 +22,15 @@ window.World = class {
|
||||
return y < 0 || y > World.TOTAL_HEIGHT ? null : chunk.getSection(y >> 4);
|
||||
}
|
||||
|
||||
getCollisionBoxes(aabb) {
|
||||
getCollisionBoxes(region) {
|
||||
let boundingBoxList = [];
|
||||
|
||||
let minX = MathHelper.floor_double(aabb.minX);
|
||||
let maxX = MathHelper.floor_double(aabb.maxX + 1.0);
|
||||
let minY = MathHelper.floor_double(aabb.minY);
|
||||
let maxY = MathHelper.floor_double(aabb.maxY + 1.0);
|
||||
let minZ = MathHelper.floor_double(aabb.minZ);
|
||||
let maxZ = MathHelper.floor_double(aabb.maxZ + 1.0);
|
||||
let minX = MathHelper.floor_double(region.minX);
|
||||
let maxX = MathHelper.floor_double(region.maxX + 1.0);
|
||||
let minY = MathHelper.floor_double(region.minY);
|
||||
let maxY = MathHelper.floor_double(region.maxY + 1.0);
|
||||
let minZ = MathHelper.floor_double(region.minZ);
|
||||
let maxZ = MathHelper.floor_double(region.maxZ + 1.0);
|
||||
|
||||
for (let x = minX; x < maxX; x++) {
|
||||
for (let y = minY; y < maxY; y++) {
|
||||
@@ -64,16 +64,15 @@ window.World = class {
|
||||
return chunkSection == null ? 0 : chunkSection.getBlockAt(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
getChunkAt(x, z) {
|
||||
let zArray = this.chunks[x];
|
||||
if (typeof zArray === 'undefined') {
|
||||
zArray = this.chunks[x] = [];
|
||||
}
|
||||
getChunkSectionAt(chunkX, layerY, chunkZ) {
|
||||
return this.getChunkAt(chunkX, chunkZ).getSection(layerY);
|
||||
}
|
||||
|
||||
let chunk = zArray[z];
|
||||
getChunkAt(x, z) {
|
||||
let index = x + (z << 16);
|
||||
let chunk = this.chunks[index];
|
||||
if (typeof chunk === 'undefined') {
|
||||
chunk = new Chunk(this, x, z);
|
||||
this.chunks[x][z] = chunk;
|
||||
this.chunks[index] = chunk = new Chunk(this, x, z);
|
||||
this.group.add(chunk.group);
|
||||
}
|
||||
return chunk;
|
||||
@@ -99,10 +98,123 @@ window.World = class {
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
for (let y = minY; y <= maxY; y++) {
|
||||
for (let z = minZ; z <= maxZ; z++) {
|
||||
this.getChunkAt(x, y, z).queueForRebuild();
|
||||
this.getChunkSectionAt(x, y, z).queueForRebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rayTraceBlocks(from, to) {
|
||||
let toX = MathHelper.floor_double(to.x);
|
||||
let toY = MathHelper.floor_double(to.y);
|
||||
let toZ = MathHelper.floor_double(to.z);
|
||||
|
||||
let x = MathHelper.floor_double(from.x);
|
||||
let y = MathHelper.floor_double(from.y);
|
||||
let z = MathHelper.floor_double(from.z);
|
||||
|
||||
let blockId = this.getBlockAt(x, y, z);
|
||||
let block = Block.getById(blockId);
|
||||
let hit = block == null ? null : block.collisionRayTrace(x, y, z, from, to);
|
||||
|
||||
if (hit != null) {
|
||||
return hit;
|
||||
}
|
||||
|
||||
let lastHit = null;
|
||||
|
||||
let counter = 200;
|
||||
while (counter-- >= 0) {
|
||||
if (x === toX && y === toY && z === toZ) {
|
||||
return lastHit;
|
||||
}
|
||||
|
||||
let hitX = true;
|
||||
let hitY = true;
|
||||
let hitZ = true;
|
||||
|
||||
let nearestX1 = 999.0;
|
||||
let nearestY1 = 999.0;
|
||||
let nearestZ1 = 999.0;
|
||||
|
||||
if (toX > x) {
|
||||
nearestX1 = x + 1.0;
|
||||
} else if (toX < x) {
|
||||
nearestX1 = x;
|
||||
} else {
|
||||
hitX = false;
|
||||
}
|
||||
|
||||
if (toY > y) {
|
||||
nearestY1 = y + 1.0;
|
||||
} else if (toY < y) {
|
||||
nearestY1 = y;
|
||||
} else {
|
||||
hitY = false;
|
||||
}
|
||||
|
||||
if (toZ > z) {
|
||||
nearestZ1 = z + 1.0;
|
||||
} else if (toZ < z) {
|
||||
nearestZ1 = z;
|
||||
} else {
|
||||
hitZ = false;
|
||||
}
|
||||
|
||||
let nearestX = 999.0;
|
||||
let nearestY = 999.0;
|
||||
let nearestZ = 999.0;
|
||||
|
||||
let diffX = to.x - from.x;
|
||||
let diffY = to.y - from.y;
|
||||
let diffZ = to.z - from.z;
|
||||
|
||||
if (hitX) {
|
||||
nearestX = (nearestX1 - from.x) / diffX;
|
||||
}
|
||||
if (hitY) {
|
||||
nearestY = (nearestY1 - from.y) / diffY;
|
||||
}
|
||||
if (hitZ) {
|
||||
nearestZ = (nearestZ1 - from.z) / diffZ;
|
||||
}
|
||||
|
||||
if (nearestX === -0.0) {
|
||||
nearestX = -1.0E-4;
|
||||
}
|
||||
if (nearestY === -0.0) {
|
||||
nearestY = -1.0E-4;
|
||||
}
|
||||
if (nearestZ === -0.0) {
|
||||
nearestZ = -1.0E-4;
|
||||
}
|
||||
|
||||
let face;
|
||||
if (nearestX < nearestY && nearestX < nearestZ) {
|
||||
face = toX > x ? EnumBlockFace.WEST : EnumBlockFace.EAST;
|
||||
from = new Vector3(nearestX1, from.y + diffY * nearestX, from.z + diffZ * nearestX);
|
||||
} else if (nearestY < nearestZ) {
|
||||
face = toY > y ? EnumBlockFace.BOTTOM : EnumBlockFace.TOP;
|
||||
from = new Vector3(from.x + diffX * nearestY, nearestY1, from.z + diffZ * nearestY);
|
||||
} else {
|
||||
face = toZ > z ? EnumBlockFace.NORTH : EnumBlockFace.SOUTH;
|
||||
from = new Vector3(from.x + diffX * nearestZ, from.y + diffY * nearestZ, nearestZ1);
|
||||
}
|
||||
|
||||
x = MathHelper.floor_double(from.x) - (face === EnumBlockFace.EAST ? 1 : 0);
|
||||
y = MathHelper.floor_double(from.y) - (face === EnumBlockFace.TOP ? 1 : 0);
|
||||
z = MathHelper.floor_double(from.z) - (face === EnumBlockFace.SOUTH ? 1 : 0);
|
||||
|
||||
let blockId = this.getBlockAt(x, y, z);
|
||||
let block = Block.getById(blockId);
|
||||
let hit = block == null ? null : block.collisionRayTrace(x, y, z, from, to);
|
||||
if (hit != null) {
|
||||
return hit;
|
||||
}
|
||||
}
|
||||
|
||||
return lastHit;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -51,6 +51,117 @@ window.Block = class {
|
||||
return this.boundingBox;
|
||||
}
|
||||
|
||||
collisionRayTrace(x, y, z, start, end) {
|
||||
start = start.addVector(-x, -y, -z);
|
||||
end = end.addVector(-x, -y, -z);
|
||||
|
||||
let vec3 = start.getIntermediateWithXValue(end, this.boundingBox.minX);
|
||||
let vec31 = start.getIntermediateWithXValue(end, this.boundingBox.maxX);
|
||||
let vec32 = start.getIntermediateWithYValue(end, this.boundingBox.minY);
|
||||
let vec33 = start.getIntermediateWithYValue(end, this.boundingBox.maxY);
|
||||
let vec34 = start.getIntermediateWithZValue(end, this.boundingBox.minZ);
|
||||
let vec35 = start.getIntermediateWithZValue(end, this.boundingBox.maxZ);
|
||||
|
||||
if (!this.isVecInsideYZBounds(vec3)) {
|
||||
vec3 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInsideYZBounds(vec31)) {
|
||||
vec31 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInsideXZBounds(vec32)) {
|
||||
vec32 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInsideXZBounds(vec33)) {
|
||||
vec33 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInsideXYBounds(vec34)) {
|
||||
vec34 = null;
|
||||
}
|
||||
|
||||
if (!this.isVecInsideXYBounds(vec35)) {
|
||||
vec35 = null;
|
||||
}
|
||||
|
||||
let vec36 = null;
|
||||
if (vec3 != null && (vec36 == null || start.squareDistanceTo(vec3) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec3;
|
||||
}
|
||||
if (vec31 != null && (vec36 == null || start.squareDistanceTo(vec31) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec31;
|
||||
}
|
||||
if (vec32 != null && (vec36 == null || start.squareDistanceTo(vec32) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec32;
|
||||
}
|
||||
if (vec33 != null && (vec36 == null || start.squareDistanceTo(vec33) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec33;
|
||||
}
|
||||
if (vec34 != null && (vec36 == null || start.squareDistanceTo(vec34) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec34;
|
||||
}
|
||||
if (vec35 != null && (vec36 == null || start.squareDistanceTo(vec35) < start.squareDistanceTo(vec36))) {
|
||||
vec36 = vec35;
|
||||
}
|
||||
|
||||
if (vec36 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let face = null;
|
||||
if (vec36 === vec3) {
|
||||
face = EnumBlockFace.WEST;
|
||||
}
|
||||
if (vec36 === vec31) {
|
||||
face = EnumBlockFace.EAST;
|
||||
}
|
||||
if (vec36 === vec32) {
|
||||
face = EnumBlockFace.BOTTOM;
|
||||
}
|
||||
if (vec36 === vec33) {
|
||||
face = EnumBlockFace.TOP;
|
||||
}
|
||||
if (vec36 === vec34) {
|
||||
face = EnumBlockFace.NORTH;
|
||||
}
|
||||
if (vec36 === vec35) {
|
||||
face = EnumBlockFace.SOUTH;
|
||||
}
|
||||
return new MovingObjectPosition(vec36.addVector(x, y, z), face, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a vector is within the Y and Z bounds of the block.
|
||||
*/
|
||||
isVecInsideYZBounds(point) {
|
||||
return point == null ? false : point.y >= this.boundingBox.minY
|
||||
&& point.y <= this.boundingBox.maxY
|
||||
&& point.z >= this.boundingBox.minZ
|
||||
&& point.z <= this.boundingBox.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a vector is within the X and Z bounds of the block.
|
||||
*/
|
||||
isVecInsideXZBounds(point) {
|
||||
return point == null ? false : point.x >= this.boundingBox.minX
|
||||
&& point.x <= this.boundingBox.maxX
|
||||
&& point.z >= this.boundingBox.minZ
|
||||
&& point.z <= this.boundingBox.maxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a vector is within the X and Y bounds of the block.
|
||||
*/
|
||||
isVecInsideXYBounds(point) {
|
||||
return point == null ? false : point.x >= this.boundingBox.minX
|
||||
&& point.x <= this.boundingBox.maxX
|
||||
&& point.y >= this.boundingBox.minY
|
||||
&& point.y <= this.boundingBox.maxY;
|
||||
}
|
||||
|
||||
static getById(typeId) {
|
||||
return Block.blocks[typeId];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user