Created
April 9, 2017 05:17
-
-
Save 4xDMG/7787a984f4735d812b642d776e9d5913 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var size = 0; | |
const magik = magikcraft.io; | |
function generateRandomCave() { | |
const dungeonArr = generateDungeonArr(); | |
const normalizedDungeon = normalizeMapArr([], dungeonArr, 0); | |
checkTile(normalizedDungeon); | |
if (size < 500) { | |
size = 0; | |
generateRandomCave(); | |
} | |
renderDungeon(normalizedDungeon); | |
} | |
function checkTile(dungeon, width = 50, length = 100) { | |
const x = Math.floor(Math.random()*width); | |
const y = Math.floor(Math.random()*length); | |
if (dungeon[x][y] === 'LOG') { | |
floodDungeon(dungeon, x, y); | |
} else { | |
checkTile(dungeon); | |
} | |
} | |
function floodDungeon(dungeon, x, y) { | |
size += 1; | |
if (dungeon[x][y] === 'LOG') { | |
dungeon[x][y] = 'AIR'; | |
} else { | |
return size; | |
} | |
floodDungeon(dungeon, x - 1, y); | |
floodDungeon(dungeon, x + 1, y); | |
floodDungeon(dungeon, x, y - 1); | |
floodDungeon(dungeon, x, y + 1); | |
} | |
function generateDungeonArr(width = 50, length = 100) { | |
const dungeonArr = []; | |
for (let i = 0; i < width; i++) { | |
dungeonArr.push([]); | |
for (let j = 0; j < length; j++) { | |
const tile = Math.random(); | |
if (tile < 0.45) { | |
dungeonArr[i].push('LOG'); | |
} else { | |
dungeonArr[i].push('BEDROCK'); | |
} | |
} | |
} | |
return dungeonArr; | |
} | |
function normalizeMapArr(oldMap, newMap, gen) { | |
if (gen === 20) { | |
return newMap; | |
} | |
const tempOldMap = newMap; | |
const tempNewMap = generateNewMap(newMap, gen); | |
return normalizeMapArr(tempOldMap, tempNewMap, gen+1); | |
} | |
function generateNewMap(oldMap, gen) { | |
const newMap = []; | |
oldMap.forEach((rowArr, rowIndex) => { | |
newMap.push([]); | |
const priorRow = oldMap.slice(rowIndex - 1, rowIndex); | |
const laterRow = oldMap.slice(rowIndex + 1, rowIndex + 2); | |
rowArr.forEach((tile, tileIndex) => { | |
let neighbourCount = 0; | |
const priorTile = tileIndex - 1; | |
const laterTile = tileIndex + 1; | |
/* Check if priorRow is a valid array and | |
count tiles neighbours. If the tile is | |
at the edge of the map force it to become | |
a wall. */ | |
if (Array.isArray(priorRow[0])) { | |
if (priorRow[0][priorTile] === 'BEDROCK') neighbourCount += 1; | |
if (priorRow[0][tileIndex] === 'BEDROCK') neighbourCount += 1; | |
if (priorRow[0][laterTile] === 'BEDROCK') neighbourCount += 1; | |
} else { | |
neighbourCount += 5; | |
} | |
// Check if previous tile on same row is inside array | |
if (priorTile >= 0) { | |
if (rowArr[priorTile] === 'BEDROCK') neighbourCount += 1; | |
} else { | |
neighbourCount += 5; | |
} | |
// Check if later tile on same row is inside array | |
if (laterTile < rowArr.length) { | |
if (rowArr[laterTile] === 'BEDROCK') neighbourCount += 1; | |
} else { | |
neighbourCount += 5; | |
} | |
// Check if laterRow is valid. | |
if (Array.isArray(laterRow[0])) { | |
if (laterRow[0][priorTile] === 'BEDROCK') neighbourCount += 1; | |
if (laterRow[0][tileIndex] === 'BEDROCK') neighbourCount += 1; | |
if (laterRow[0][laterTile] === 'BEDROCK') neighbourCount += 1; | |
} else { | |
neighbourCount += 5; | |
} | |
/* Determine if tile becomes a wall or floor | |
There must be 5 walls within each 9 tile | |
square for it to become a wall. */ | |
if (tile === 'BEDROCK') { | |
/* Use this rule set for the first four generations | |
to make a map without large open spaces */ | |
if (gen <= 4) { | |
if (neighbourCount >= 4 || neighbourCount <= 2) { | |
newMap[rowIndex].push('BEDROCK'); | |
} else { | |
newMap[rowIndex].push('LOG'); | |
} | |
} else { | |
/* Use this rule set to smooth out map and remove | |
isolated single walls. */ | |
if (neighbourCount >= 4) { | |
newMap[rowIndex].push('BEDROCK'); | |
} else { | |
newMap[rowIndex].push('LOG'); | |
} | |
} | |
} else if (neighbourCount >= 5) { | |
newMap[rowIndex].push('BEDROCK'); | |
} else { | |
newMap[rowIndex].push('LOG'); | |
} | |
}); | |
}); | |
return newMap; | |
} | |
// Code stolen from Matt | |
const material = org.bukkit.Material; | |
const player = magik.getSender(); | |
function renderDungeon(dungeon) { | |
const X = "X"; | |
const array = dungeon; | |
const numRows = array.length; | |
const numCols = array[0].length; | |
const height = 5; | |
for (let h = 0; h < height; h++) { | |
for (let i = 0; i < numRows; i++) { | |
for (let j = 0; j < numCols; j++) { | |
const zCoord = Math.floor(numRows / 2) - i; | |
const xCoord = Math.floor(numCols / 2) - j; | |
spawnAtPoint3d(zCoord, xCoord, h, array[i][j]); | |
} | |
} | |
} | |
} | |
function spawnAtPoint3d(zCoord, xCoord, yCoord, element) { | |
// get final location with zCoord, | |
// use final zCoord location as start location for xCoord | |
const startLocation = player.getTargetBlock(null, 100).getLocation(); | |
const zYaw = zCoord > 0 ? 0 : 180; | |
const zLocation = getFinalLocation(startLocation, zYaw, Math.abs(zCoord)); | |
const xYaw = xCoord > 0 ? 90 : -90; | |
const xLocation = getFinalLocation(zLocation, xYaw, Math.abs(xCoord)); | |
const yYaw = 0; | |
const yPitch = yCoord > 0 ? 90 : -90; | |
const yLocation = getVerticalLocation(xLocation, yYaw, Math.abs(yCoord)); | |
setBlock(yLocation, element); | |
} | |
function getVerticalLocation(startLoc, pitch, distance) { | |
const loc = startLoc; | |
loc.setPitch(-90); // straight up | |
return loc.add(loc.getDirection().setX(0).normalize().multiply(distance)); | |
} | |
function getFinalLocation(startLoc, yaw, distance) { | |
return normalizedStartLocation(startLoc, yaw).add(getDirectionToAddToStartLocation(yaw, distance)); | |
} | |
function getDirectionToAddToStartLocation(yaw, distance) { | |
const loc = player.getLocation(); | |
loc.setYaw(loc.getYaw() + yaw); | |
return loc.getDirection().setY(0).normalize().multiply(distance); | |
} | |
function normalizedStartLocation(startLoc, yaw) { | |
const loc = startLoc; | |
loc.setYaw(loc.getYaw() + yaw); | |
return loc; | |
} | |
function setBlock(location, element) { | |
location.getBlock().setType(getBlockObject(element)); | |
} | |
function getBlockObject(element) { | |
switch (element) { | |
case 'LOG': | |
return material.LOG; | |
case 'BEDROCK': | |
return material.BEDROCK; | |
case 'AIR': | |
return material.AIR; | |
} | |
} | |
function spawnObject(object, location) { | |
player.getWorld().spawn(location, object.class); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment