UNPKG

@magikcraft/mct1

Version:

Minecraft for Type 1 Diabetes

612 lines (588 loc) 19.6 kB
import { Vector3, Direction } from '@magikcraft/mct1/vector3' import * as util from 'utils' interface iRegion { vectorA: Vector3 vectorB: Vector3 world: string name: string constructor(vectorA: Vector3, vectorB: Vector3, name?: string) toArray(): Array<number[]> toString(): string xArray(): Array<number> yArray(): Array<number> zArray(): Array<number> contains(sampleVector): boolean getSmallestPoint(): Vector3 getLargestPoint(): Vector3 getCenterPoint(): Vector3 getSize(): Vector3 randomPoint(): Vector3 randomPoints(amount: number): Array<Vector3> closestPoint(location: Vector3): Vector3 distToClosestPoint(location: Vector3): number AreOverlaping(regionA: iRegion, regionB): Boolean Alter( region: Region, amount: number, direction?: Direction | Array<Direction> ): Region Expand( region: Region, amount?: number, direction?: Direction | Array<Direction> ): Region Contract( region: Region, amount?: number, direction?: Direction | Array<Direction> ): Region } /** * Region * @constructor * @param {Vector3} vectorA - First Vector * @param {Vector3} vectorB - Second Vector * @param {string} [name] - Optional Name/ID * * Creates and instance of a region */ export class Region { vectorA: Vector3 = new Vector3(0, 0, 0, '') vectorB: Vector3 = new Vector3(0, 0, 0, '') world: string = '' name: string = '' constructor(vectorA, vectorB, world = '', name = '') { this.vectorA = vectorA || Vector3.zero this.vectorB = vectorB || Vector3.zero this.world = world this.name = name } /** * ToArray * @return {Array} - Array Region Object * * Will create an array from the region object * >> array -> [ [0,0,0], [0,0,0] ]; */ toArray(): Array<any> { return [this.vectorA.toArray(), this.vectorB.toArray()] } /** * FromArray * @param {Array} array - Given Array * * Will return a region object based on the array */ FromArray(array: Array<number | string>): Region { var region = new Region( new Vector3(array[0][0], array[0][1], array[0][2]), new Vector3(array[1][0], array[1][1], array[1][2]) ) if (array[0][4]) { // World in vectorA exists region.vectorA.world = array[0][4] } if (array[0][4]) { // World in vectorA exists region.vectorB.world = array[1][4] } return region } /** * toString * @return {string} - String version of region * * Will return a string version of the region */ toString(): string { if (this.world == '' && this.name == '') { // Only vectors given return ( '[' + this.vectorA.toString() + ',' + this.vectorB.toString() + ']' ) } else if (this.name == '' && this.world != '') { // No ID given return ( '[' + this.vectorA.toString() + ',' + this.vectorB.toString() + ', ' + this.world + ']' ) } else if (this.name != '' && this.world == '') { // All args where given return ( '[' + this.vectorA.toString() + ',' + this.vectorB.toString() + ', (Name)' + this.world + ']' ) } else { return ( '[' + this.vectorA.toString() + ',' + this.vectorB.toString() + ', ' + this.world + ', ' + this.name + ']' ) } } /** * xArray * @returns {Array} - X real space array * * Returns an array with all points that the array * exists in on the x axis * >> [ 201, 202, 203... ] */ xArray(): Array<number> { var smallestBounds = this.getSmallestPoint() var regionSize = this.getSize() var returnable: Array<number> = [] for (var i = 0; i < regionSize.x; i++) { returnable.push(smallestBounds.x + i) } return returnable } /** * yArray * @returns {Array} - Y real space array * * Returns an array with all points that the array * exists in on the y axis * >> [ 201, 202, 203... ] */ yArray(): Array<number> { var smallestBounds = this.getSmallestPoint() var regionSize = this.getSize() var returnable: Array<number> = [] for (var i = 0; i < (regionSize.y || 1); i++) { returnable.push(smallestBounds.y + i) } return returnable } /** * xArray * @returns {Array} - X real space array * * Returns an array with all points that the array * exists in on the x axis * >> [ 201, 202, 203... ] */ zArray(): Array<number> { var smallestBounds = this.getSmallestPoint() var regionSize = this.getSize() var returnable: Array<number> = [] for (var i = 0; i < (regionSize.z || 1); i++) { returnable.push(smallestBounds.z + i) } return returnable } /** * xLength * @returns {number} - The length of the region in the x axis * * Will calculate the length of the the x axis of the region */ xLength(): number { return Math.abs(this.vectorA.x - this.vectorB.x) } /** * yLength * @returns {number} - The length of the region in the y axis * * Will calculate the length of the the y axis of the region */ yLength(): number { return Math.abs(this.vectorA.y - this.vectorB.y) } /** * zLength * @returns {number} - The length of the region in the z axis * * Will calculate the length of the the z axis of the region */ zLength(): number { return Math.abs(this.vectorA.z - this.vectorB.z) } /** * contains * @param {Vector3} sampleVector - Point to compare against the region * @returns {boolean} - True of False if the point is in the region * * Sample the region to see if the vector is in the region */ contains(sampleVector: Vector3): boolean { if (this.world == sampleVector.world) { if ( (sampleVector.x || 0) < Math.min(this.vectorA.x, this.vectorB.x) ) { return false } else if ( (sampleVector.x || 0) > Math.max(this.vectorA.x, this.vectorB.x) ) { return false } else if ( (sampleVector.y || 0) < Math.min(this.vectorA.y, this.vectorB.y) ) { return false } else if ( (sampleVector.y || 0) > Math.max(this.vectorA.y, this.vectorB.y) ) { return false } else if ( (sampleVector.z || 0) < Math.min(this.vectorA.z, this.vectorB.z) ) { return false } else if ( (sampleVector.z || 0) > Math.max(this.vectorA.z, this.vectorB.z) ) { return false } else { return true } } else { return false } } /** * getSmallestPoint * @return {Vector3} - Smallest Point * * This will get the smallest component point of the region * >> [[26,43,78], [12,42,25]] => [12,42,25] */ getSmallestPoint(): Vector3 { return new Vector3( Math.min(this.vectorA.x, this.vectorB.x), Math.min(this.vectorA.y, this.vectorB.y), Math.min(this.vectorA.z, this.vectorB.z), this.world ) } /** * getLargestPoint * @return {Vector3} - Largest Point * * This will get the largest component point of the region * >> [[26,43,78], [12,42,25]] => [26,43,78] */ getLargestPoint(): Vector3 { return new Vector3( Math.max(this.vectorA.x, this.vectorB.x), Math.max(this.vectorA.y, this.vectorB.y), Math.max(this.vectorA.z, this.vectorB.z), this.world ) } /** * getCenterPoint * @return {Vector3} - Center point of the region * * Returns the center point of the region as a vector3 */ getCenterPoint(): Vector3 { var smallestPoint = this.getSmallestPoint() var size = this.getSize() return new Vector3( smallestPoint.x + size.x / 2, smallestPoint.y + size.y / 2, smallestPoint.z + size.z / 2, this.world ) } /** * getWorld * @param {boolean} [worldObj] - Optional bool to export world name */ getWorld(worldObj?: boolean): string | any { this._unifyWorldNames() worldObj = worldObj || false if (worldObj) { return util.world(this.world) } else { return this.world } } /** * getSize * @return {Vector3} - Size as vector * * Will return the size of the region as a vector */ getSize() { return new Vector3( Math.abs(this.vectorA.x - this.vectorB.x), Math.abs(this.vectorA.y - this.vectorB.y), Math.abs(this.vectorA.z - this.vectorB.z), this.world ) } /** * randomPoint * @return {Vector3} - Point in region space * * Will get a random point inside the region */ randomPoint() { var regionSize = this.getSize() // << Returns Vector3 var smallestPoint = this.getSmallestPoint() var vec = new Vector3( Math.round(smallestPoint.x + Math.random() * (regionSize.x || 0)), Math.round(smallestPoint.y + Math.random() * (regionSize.y || 0)), Math.round(smallestPoint.z + Math.random() * (regionSize.z || 0)), this.world ) return vec } /** * randomPoints * @param {number} [amount] - Number of coords to return * @return {Array} - Points in region space (Vector3 Array) * * Will create an array of Vector3 points within the region */ randomPoints(amount): Array<Vector3> { amount = amount || 1 if (amount == 0) { return [this.randomPoint()] } else { var coords: Array<Vector3> = [] for (var i = 0; i < amount; i++) { coords.push(this.randomPoint()) } return coords } } /** * closestPoint * @param {Vector3} location - Given location as vector3 * @return {Vector3} - Closest point in region to location * * Will return the closest position to the location * within the region. * * Location: [24,18,36] * Region: [[62,632,2], [23,63,10]] * >> Closest Point: [24,63,10] */ closestPoint(location: Vector3): Vector3 { // Test to see if the location is in the region first // Less computation for the engine to do if (this.contains(location)) { // The location is in the region return location } else { // Get all of the closet points in panes var locationArray = location.toArray() var greatestBounds = this.getLargestPoint().toArray // << Vector3 Returns var smallestBounds = this.getSmallestPoint().toArray // << Vector3 Returns var arrayPositions: Array<number[]> = [] for (var a = 0; a < 3; a++) { // Check through all axis's // If the location is greater than the greatest bounds if (location[a] > greatestBounds[a]) { arrayPositions.push([greatestBounds[a]]) // If the location is smaller than the smallest bounds } else if (location[a] < smallestBounds[a]) { arrayPositions.push([smallestBounds[a]]) // The location must be within the bounds. } else { // Depending on the iteration, get the appropiate axis's array switch (a) { case 0: arrayPositions.push(this.xArray()) break case 1: arrayPositions.push(this.yArray()) break case 2: arrayPositions.push(this.zArray()) break default: break } } } // Test for the closest point var closestPoint: Vector3 = new Vector3( Infinity, Infinity, Infinity, this.world ) var closestDist: number = Infinity for (var x = 0; x < arrayPositions[0].length; x++) { for (var y = 0; y < arrayPositions[1].length; y++) { for (var z = 0; z < arrayPositions[2].length; z++) { // If the distance between the two points is the least // so far, replace the closest point var testPoint = new Vector3( arrayPositions[0][x], arrayPositions[1][y], arrayPositions[2][z], this.world ) var testDist = Vector3.Distance(testPoint, location) if (testDist < closestDist) { closestDist = testDist closestPoint = testPoint } } } } return closestPoint } } /** * distToClosestPoint * @param {Vector3} location - Given location as vector3 * @return {number} - Distance to point * * Will return the distance to the closest point in the region * Refer to closestPoint */ distToClosestPoint(location: Vector3): number { return Vector3.Distance(this.closestPoint(location), location) } /** * AreOverlaping * @param {Region} regionA - First Region * @param {Region} regionB - Second Region * @return {boolean} - True if the regions overlap * * Will return true if the regions overlap */ AreOverlaping(regionA: Region, regionB): Boolean { var centerB = regionB.getCenterPoint() var queryPoint = regionA.closestPoint(centerB) return regionB.isIn(queryPoint) ? true : false } Alter(region: Region, amount: number, direction?: any): Region { if (!direction) { // Change in all directions var smallestVector: Vector3 = region.getSmallestPoint() var largestVector: Vector3 = region.getLargestPoint() var alterVector: Vector3 = new Vector3( 1 * amount, 1 * amount, 1 * amount ) var vectorA = Vector3.Minus(smallestVector, alterVector) var vectorB = Vector3.Add(largestVector, alterVector) return new Region(vectorA, vectorB) } else if (!direction[0]) { // Not array, but direction given var smallestVector: Vector3 = region.getSmallestPoint() var largestVector: Vector3 = region.getLargestPoint() if (direction == Direction.UP) { smallestVector.y = Math.max( 0, Math.min(largestVector.y + amount, 128) ) } else if (direction == Direction.EAST) { largestVector.x += amount return new Region(smallestVector, largestVector) } else if (direction == Direction.NORTH) { largestVector.z += amount return new Region(smallestVector, largestVector) } else if (direction == Direction.DOWN) { smallestVector.y = Math.max( 0, Math.min(smallestVector.y - amount, 128) ) return new Region(smallestVector, largestVector) } else if (direction == Direction.SOUTH) { smallestVector.x -= amount return new Region(smallestVector, largestVector) } else if (direction == Direction.WEST) { smallestVector.z -= amount return new Region(smallestVector, largestVector) } else { return this.Alter(region, amount) } } else { // Has to be array // Do the operation[0], // If last, return, else remove [0] and try again var _region = this.Alter( region, amount, direction[direction.length - 1] ) if (direction.length == 1) { return _region } else { return this.Alter(_region, amount, direction.pop()) } } return region } Expand( region: Region, amount?: number, direction?: Direction | Array<Direction> ): Region { amount = Math.abs(amount || 1) return this.Alter(region, amount, direction) } Contract( region: Region, amount?: number, direction?: Direction | Array<Direction> ): Region { amount = -Math.abs(amount || 1) return this.Alter(region, amount, direction) } /** * _unifyWorldNames * * Fixes and unifies the names for regions * Criticaly important */ private _unifyWorldNames() { if (this.world == '') { var worldA = this.vectorA.world || '' var worldB = this.vectorA.world || '' if (worldA == '' && worldB == '') { // No world is given in the regions // Just give it a null world this.vectorA.world = '' this.vectorB.world = '' this.world = '' } else if (worldA == '') { // World B as the given world // Assign the region and vectorA worlds to vectorB's world this.vectorA.world = worldB this.world = worldB return worldB } else if (worldB == '') { // World A as the given world // Assign the region and vectorB worlds to vectorA's world this.vectorB.world = worldA this.world = worldA return worldA } else if (worldB == worldA) { // Both worlds have the same name // Assign the region world to the two vectors one's this.world = worldA } } else { this.vectorA.world = this.world this.vectorB.world = this.world } } }