/* Code for gravity. mass: Density (in kg/cm^3) fluid: Spread of substance saturation: Maximum mass for gravity reactions to occur */ let gravityTable = []; function gravity(event, mass, fluid, saturation) { if (event.type != 'tick') return; let cx = event.data[0]; let cy = event.data[1]; let chunks = event.canvas; let dirX = 0; let dirY = 0; let forceX = 0; let forceY = 0; let density = 0; let currBlock = chunks.getBlock(cx, cy); for (let x = -1; x < 2; x++) { let x2 = x / fluid; let x3 = x2 * x2; for (let y = -1; y < 2; y++) { let blok = chunks.getBlock(cx + x, cy + y); if (blok == -1) continue; let mass2 = gravityTable[blok]; density += mass2; if (density > saturation) break; if (blok == currBlock || mass == mass2) continue; let massDiff = (mass / mass2) - (mass2 / mass); if (Math.abs(massDiff) < 0.001) continue; let y3 = y * y; let dirDiff = (y - 1 + fluid); if (y == 0 && x == 0) dirDiff = 0; if (isNaN(dirDiff)) dirDiff = 0; if (dirDiff != 0) dirDiff /= (1 / 8 * (x3 - y3 + 8) * (x3 + y3)); if (isNaN(dirDiff)) dirDiff = 0; forceX += massDiff * x2; forceY += massDiff * dirDiff * y; } if (density > saturation) break; } dirX = (Math.abs(forceX) < .5) ? 0 : Math.sign(forceX); dirY = (Math.abs(forceY) < .5) ? 0 : Math.sign(forceY); if (density > saturation) { return; } let offBlock = chunks.getBlock(cx + dirX, cy + dirY); if (currBlock == offBlock && density <= saturation) { dirX = Math.sign(forceX); offBlock = chunks.getBlock(cx + dirX, cy + dirY); } if (currBlock == -1 || offBlock == -1 || currBlock == offBlock || offBlock == undefined || mainTiles.tiles[offBlock].attributes.saturation / 9 < mass || chunks.noTick[(cx + dirX) * chunks.height + (cy + dirY)]) return; if (!canGravity[offBlock]) return; chunks.noTick[cx * chunks.height + cy] = true; chunks.noTick[(cx + dirX) * chunks.height + (cy + dirY)] = true; chunks.setBlock(cx, cy, offBlock); chunks.setBlock(cx + dirX, cy + dirY, currBlock); let t = chunks.getBlock(cx, cy, true); let t2 = chunks.getBlock(cx + dirX, cy + dirY, true); chunks.setBlock(cx, cy, t2, true); chunks.setBlock(cx + dirX, cy + dirY, t, true); return true; } Tile.prototype.gravity = function (mass, fluid, saturation) { this.interactions.push(function (event) { gravity(event, mass, fluid, saturation) }); this.attributes.mass = mass; this.attributes.saturation = saturation; let that = this; this.hook.push(function () { gravityTable[mainTiles.tiles.findIndex((x, i) => x.id == that.id)] = that.attributes.mass; }) return this; } Tile.prototype.unGravity = function () { this.attributes.noGravity = true; return this; }