Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 4xDMG/7787a984f4735d812b642d776e9d5913 to your computer and use it in GitHub Desktop.
Save 4xDMG/7787a984f4735d812b642d776e9d5913 to your computer and use it in GitHub Desktop.
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