Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <canvas id="gc"></canvas>
<center>
  <h1 id="text">Generating world</h1>
</center>

<textarea rows="50" cols="100" id="command">Please close and open the CMD line again</textarea>
              
            
!

CSS

              
                #gc {
  border: 2px solid black;
  visibility: hidden;
}
#text {
  visibility: visible;
  font-family: "Arial";
  font-size: 150px;
}

body, html {
  margin: 0;
  padding: 0;
  height: 100%;
}

#command {
  visibility: hidden;
  position: absolute;
  top: 0;
  left: 0;
  width: 600px;
  height: 250px;
}
              
            
!

JS

              
                /*
pollFunc(function() {

  var movedBlocks = [];
  for (var i = 0; i < world.length; i++) {
    if (world[i].id == 5) {
      movedBlocks.push(world[i]);
      setBlock(world[i].x, world[i].y, 1, true);

      if (getBlock(world[i].x+1, world[i].y)[0].id == 8) {
        for (var j = 0; j < world.length; j++) {
          if (c.distance(world[i].x, world[i].y, world[j].x, world[j].y) < 10) {
            if (c.random(0, 1) == 1) {
              setBlock(world[j].x, world[j].y, 7, false);
            }
          }
        }
      }
    }
  }

  for (var i = 0; i < movedBlocks.length; i++) {
    setBlock(movedBlocks[i].x+1, movedBlocks[i].y, 5, false);
  }

}, 1000*40, 1000);
*/


var c = new GameCanvas('gc');
c.setsize(window.innerWidth, window.innerHeight);
c.hideScrollBar();
document.getElementById('gc').style.visibility = "visible";
document.getElementById('text').style.visibility = "hidden"; 
document.getElementById('text').style.fontSize = "1px";

var width = c.width;
var height = c.height;
var keys = [100];
var mouse = {x: 0, y: 0, right: false};
var scroll = "";
var centerX = width/2;
var centerY = height/2;
var tick = 0;
var isIpad = navigator.userAgent.match(/iPad/i) != null;

var world = [];
var worldInfo = {width: 500,
                 height: 40};
var blockSize = 50;
var screenMiddle = {x: width/2,
                    y: height/2};

var player = {x: 0,
              y: 3,
              width: 1,
              height: 2,
              velo: 0,
              img: 0};
var gravity = 0.01;

var camera = {x: 0,
              y: 0};

var inv = [];
for (var i = 0; i < 9; i++) {
  inv.push({id: 0, amount: 0, wall: false});
}

var invSel = 1;
var invScrollKey = true;
var placeKey = true;

var idInfo = [100];
idInfo[1] = {id: 1, name: "Air", color: "lightblue", image: "http://0.tqn.com/d/desktoppub/1/S/b/k/3/swatch-lightcyan.png"};
idInfo[2] = {id: 2, name: "Grass", color: "rgb(101, 64, 23)", image: "https://aaserver.net/images/grass.png"};
idInfo[3] = {id: 3, name: "Dirt", color: "rgb(101, 64, 23)", image: "https://aaserver.net/images/dirt.png"};
idInfo[4] = {id: 4, name: "Log", color: "rgb(72, 40, 9)", image: "https://aaserver.net/images/tree.png"};
idInfo[5] = {id: 5, name: "Wood", color: "rgb(221, 178, 140)", image: "https://aaserver.net/images/wood.jpg" /*"http://orig07.deviantart.net/d03e/f/2008/148/c/3/wood_floor_by_gnrbishop.jpg"*/};
idInfo[6] = {id: 6, name: "Work table", color: "rgb(187, 161, 80)", image: "https://aaserver.net/images/workbench.png"};
idInfo[7] = {id: 7, name: "Ice", color: "rgb(218, 220, 240)", image: "https://aaserver.net/images/snow.jpg"/*"http://bgfons.com/upload/snow_texture1556.jpg"*/};
idInfo[8] = {id: 8, name: "Cobble", color: "rgb(154, 154, 154)", image: "https://aaserver.net/images/cobble.png"};
idInfo[9] = {id: 9, name: "Stone block", color: "rgb(78, 78, 78)", image: "https://aaserver.net/images/stone_brick.png"};
idInfo[10] = {id: 10, name: "Leaves", color: "rgb(36, 152, 15)", image: "https://aaserver.net/images/leaves.png"};
idInfo[11] = {id: 11, name: "CMD line", color: "rgb(36, 152, 15)", image: "http://static.planetminecraft.com/files/resource_media/screenshot/1252/dYBGH_4521120_lrg.jpg"};
idInfo[12] = {id: 12, name: "PickBreaker", color: "rgb(87, 87, 87)", image: "https://aaserver.net/images/bedrock.jpg"/*"https://ih1.redbubble.net/image.258051353.4077/flat,800x800,070,f.u4.jpg"*/};

for (var i = 1; i < idInfo.length; i++) {
  if (idInfo[i].id != i) {
    alert("The game has crashed!\nError in idInfo array. Id's don't match!");
  }
}

var stars = [];
for (var i = 0; i < 300; i++) {
  stars.push({x: c.random(0, width),
              y: c.random(0, height),
              size: c.random(1, 5),
              blinkSpeed: c.random(0.03, 0.1)});
}

var crafting = false;
var craftKey = true;
var craftScroll = 1;
var craftMode = 1;
var craftingList = [];
craftingList.push({in: [2], out: {block: 2, wall: true}});
craftingList.push({in: [3], out: {block: 3, wall: true}});
craftingList.push({in: [4], out: {block: 4, wall: true}});
craftingList.push({in: [5], out: {block: 5, wall: true}});
craftingList.push({in: [6], out: {block: 6, wall: true}});
craftingList.push({in: [7], out: {block: 7, wall: true}});
craftingList.push({in: [8], out: {block: 8, wall: true}});
craftingList.push({in: [9], out: {block: 9, wall: true}});
craftingList.push({in: [10], out: {block: 10, wall: true}});
craftingList.push({in: [4], out: {block: 4, wall: false}});
craftingList.push({in: [10], out: {block: 10, wall: false}});

craftingList.push({in: [4], out: {block: 5, wall: false}});
craftingList.push({in: [3, 3], out: {block: 8, wall: false}});
craftingList.push({in: [8, 8], out: {block: 9, wall: false}});

var cmd = false;
var CmdPrompt = false;
var command = "";
var thisCMDBlock = {x: 0, y: 0};

var menu = true;

if (!generateWorld(worldInfo.width, worldInfo.height, blockSize, 3)) {
  alert("Cannot generate world!\nTry to reload the page!");
}
else {
  for (var i = -worldInfo.width/2+20; i < worldInfo.width/2-20; i++) {
    if (c.random(0, 10) == 1)
      tree(i, 2);
  }
  for (var i = -worldInfo.width/2+100; i < worldInfo.width/2-100; i++) {
    if (c.random(0, 40) == 1)
      mountain(i, 3);
  }
  pickUp(6, false);
  /*pickUp(11, false);
  for (var i = 0; i < 900; i++)
  pickUp(7, false);*/
  
  if (!localStorage.world) {
    localStorage.world = JSON.stringify(world);
  }
  
  if (!localStorage.inv) {
    localStorage.inv = JSON.stringify(inv);
  }
}

document.addEventListener('contextmenu', event => event.preventDefault());
loop();
function loop() {
  // drawVoid();
  c.rect(0, 0, width, height, "lightblue");
  drawWorld();
  drawPlayer();
  // drawCoordSys();
  inventory();
  craftingF();
  cmdF();
  
  if (tick % 400 == 0 && tick != 0 && !menu) {
    console.log("Saving...");
    localStorage.world = JSON.stringify(world);
    localStorage.inv = JSON.stringify(inv);
    console.log("World saved!");
  }
  
  if (inv[invSel-1].id == 0 && isIpad) {
    if (mouse.x < width/2 && mouse.click) {
      keys[37] = true;
    }
    else if (mouse.x > width/2 && mouse.click) {
      keys[39] = true;
    }
    else {
      keys = [100];
    }
  }
  
  if (menu)
    menuF();
  
  if (isIpad) {
    if (mouse.click && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id == 1 && inv[invSel-1].amount >= 1 && !crafting && !menu && mouse.y < height-100) {
    if (placeKey) {
      setBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5, inv[invSel-1].id, false);
      inv[invSel-1].amount--;
      placeKey = false;
    }
  }
  else if (!mouse.click) {
    placeKey = true;
  }
    
    if (mouse.click && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id != 1 && !crafting && !menu && inv[invSel-1].id != 0 && mouse.y < height-100) {
    if (placeKey) {
      pickUp(getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id, getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].wall);
      setBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5, 1, false);
      placeKey = false;
    }
  }
  else if (!mouse.click) {
    placeKey = true;
  }
  }
  
  tick++;
  requestAnimationFrame(loop);
}

function menuF() {
  c.rect(width/2-300, 175, 600, height-175-100, "lightgray");
  c.picture(width/2-125/2, 150/2-125/2, "https://aaserver.net/images/diamond.png", 125, 125);
  c.text(width/2-125/2-80, 150/2+125/2-20, 120, "B", "black");
  c.text(width/2+125/2, 150/2+125/2-20, 120, "M", "black");
  c.text(width/2+125/2+100, 150/2+125/2-20, 60, "s", "black");
  c.text(width/2-125/2-30, 150, 40, "BlockMines", "gray");
  
  c.rect(width/2-125+10, 260, 250, 100, "darkblue");
  c.rect(width/2-125, 250, 250, 100, "blue");
  
  c.rect(width/2-125+10, 250+100+20+10, 250, 100, "darkblue");
  c.rect(width/2-125, 250+100+20, 250, 100, "blue");
  
  c.ctx.textAlign = "center";
  c.text(width/2, 325, 60, "START", "darkblue");
  c.text(width/2, 325+120, 60, "RESET", "darkblue");
  c.ctx.textAlign = "left";
  
  if (mouse.x > width/2-125 && mouse.x < width/2-125+250 && mouse.y > 250 && mouse.y < 250+100 && mouse.click) {
    invSel = 5;
    menu = false;
    world = JSON.parse(localStorage.world);
    inv = JSON.parse(localStorage.inv);
  }
  
  if (mouse.x > width/2-125 && mouse.x < width/2-125+250 && mouse.y > 250+120 && mouse.y < 250+120+100 && mouse.click) {
    if (confirm("Are you sure you want to delete the world?")) {
      localStorage.removeItem("world");
      localStorage.removeItem("inv");
      menu = false;
      invSel = 5;
    }
    else {
      mouse.x = 0;
      mouse.y = 0;
      mouse.click = false;
    }
  }
}

function drawVoid() {
  c.rect(0, 0, width, height, "black");
  var i;
  var ii = stars.length;
  
  for (i = 0; i < ii; i++) {
    if (stars[i].size >= 5 || stars[i].size <= 1)
      stars[i].blinkSpeed = -stars[i].blinkSpeed;
    
    stars[i].size += stars[i].blinkSpeed;
    if (stars[i].size <= 0) {
      stars[i].size = 1;
    }
    c.circle(stars[i].x, stars[i].y, stars[i].size, "rgba(255, 255, 255, 0.6)");
  }
}

function drawWorld() {
  var i;
  
  var wh = worldInfo.height;
  var d;
  var b;
  
  d = wh*worldInfo.width/2+Math.floor(camera.x)*wh-wh*Math.floor(width/2/blockSize)-wh;
  b = wh*worldInfo.width/2-Math.floor(camera.x)*wh-wh*Math.floor(width/2/blockSize)-wh*3;
  
  var ii = world.length-b;
  
  for (i = d; i < ii; i++) {
    var thisBlock = world[i];
    if (!thisBlock) {
      continue;
    }
    
    var thisX = thisBlock.x*blockSize-(blockSize/2)-camera.x*blockSize;
    var thisY = thisBlock.y*blockSize-(blockSize/2)-camera.y*blockSize;

    const z = 94;
    var p = point(thisX+blockSize, thisY, z);
    var p2 = point(thisX+blockSize, thisY+blockSize, z);
    var p3 = point(thisX, thisY, z);
    var p4 = point(thisX, thisY+blockSize, z);
    
    if (thisBlock.id != 1) {
      const baseColor = idInfo[thisBlock.id].color;
      const rgb = baseColor.split("(")[1].split(")")[0].split(",");
      
      // c.ctx.fillStyle = idInfo[thisBlock.id].color;
      
      if (!thisBlock.wall) {
        //Up
        let b = getBlock(thisBlock.x, thisBlock.y - 1);
        if (!b || b[0].id == 1 || b[0].wall) {
          c.ctx.fillStyle = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;

          c.ctx.beginPath();
          c.ctx.moveTo(thisX+centerX, thisY+centerY);
          c.ctx.lineTo(p3.x, p3.y);
          c.ctx.lineTo(p.x, p.y);
          c.ctx.lineTo(thisX+centerX+blockSize, thisY+centerY);
          c.ctx.lineTo(thisX+centerX, thisY+centerY);
          c.ctx.fill();
        }

        //Down
        b = getBlock(thisBlock.x, thisBlock.y + 1);
        if (!b || b[0].id == 1 || b[0].wall) {
          c.ctx.fillStyle = `rgb(${Math.floor(rgb[0] * 0.5)}, ${Math.floor(rgb[1] * 0.5)}, ${Math.floor(rgb[2] * 0.5)})`;

          c.ctx.beginPath();
          c.ctx.moveTo(thisX+centerX, thisY+centerY+blockSize);
          c.ctx.lineTo(p4.x, p4.y);
          c.ctx.lineTo(p2.x, p2.y);
          c.ctx.lineTo(thisX+centerX+blockSize, thisY+centerY+blockSize);
          c.ctx.lineTo(thisX+centerX, thisY+centerY+blockSize);
          c.ctx.fill();
        }

        //Left
        b = getBlock(thisBlock.x + 1, thisBlock.y);
        if (!b || b[0].id == 1 || b[0].wall) {
          c.ctx.fillStyle = `rgb(${Math.floor(rgb[0] * 0.75)}, ${Math.floor(rgb[1] * 0.75)}, ${Math.floor(rgb[2] * 0.75)})`;

          c.ctx.beginPath();
          c.ctx.moveTo(thisX+blockSize+centerX, thisY+centerY);
          c.ctx.lineTo(p.x, p.y);
          c.ctx.lineTo(p2.x, p2.y);
          c.ctx.lineTo(thisX+centerX+blockSize, thisY+centerY+blockSize);
          c.ctx.lineTo(thisX+centerX+blockSize, thisY+centerY);
          c.ctx.fill();
        }

        //Right
        b = getBlock(thisBlock.x - 1, thisBlock.y);
        if (!b || b[0].id == 1 || b[0].wall) {
          c.ctx.fillStyle = `rgb(${Math.floor(rgb[0] * 0.9)}, ${Math.floor(rgb[1] * 0.9)}, ${Math.floor(rgb[2] * 0.9)})`;

          c.ctx.beginPath();
          c.ctx.moveTo(thisX+centerX, thisY+centerY);
          c.ctx.lineTo(p3.x, p3.y);
          c.ctx.lineTo(p4.x, p4.y);
          c.ctx.lineTo(thisX+centerX, thisY+centerY+blockSize);
          c.ctx.lineTo(thisX+centerX, thisY+centerY);
          c.ctx.fill();
        }
      }
      
      // Back
      if (thisBlock.wall) {
        c.picture(p3.x, p3.y, idInfo[thisBlock.id].image, p2.x - p3.x + 1, p2.y - p.y + 1);
        
        c.ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
        c.ctx.beginPath();
        c.ctx.moveTo(p.x + 1, p.y);
        c.ctx.lineTo(p2.x + 1, p2.y + 1);
        c.ctx.lineTo(p4.x, p4.y + 1);
        c.ctx.lineTo(p3.x, p3.y);
        c.ctx.lineTo(p.x + 1, p.y);
        c.ctx.fill();
      }
    }
    else {
      let roofId;
      for (let j = 1; j < 10; j++) {
        const block = getBlock(thisBlock.x, thisBlock.y - j);
        if (block && !block[0].wall && (block[0].id == 2 || block[0].id == 3 || block[0].id == 7 || block[0].id == 8)) {
          roofId = block[0].id == 2 ? 3 : block[0].id;
          break;
        }
      }
      
      if (roofId) {
        // c.ctx.fillStyle = idInfo[roofId].color;
        // c.ctx.beginPath();
        // c.ctx.moveTo(p.x + 1, p.y);
        // c.ctx.lineTo(p2.x + 1, p2.y + 1);
        // c.ctx.lineTo(p4.x, p4.y + 1);
        // c.ctx.lineTo(p3.x, p3.y);
        // c.ctx.lineTo(p.x + 1, p.y);
        // c.ctx.fill();
        
        c.picture(p3.x, p3.y, idInfo[roofId].image, p2.x - p3.x + 1, p2.y - p.y + 1);
        
        c.ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
        c.ctx.beginPath();
        c.ctx.moveTo(p.x + 1, p.y);
        c.ctx.lineTo(p2.x + 1, p2.y + 1);
        c.ctx.lineTo(p4.x, p4.y + 1);
        c.ctx.lineTo(p3.x, p3.y);
        c.ctx.lineTo(p.x + 1, p.y);
        c.ctx.fill();
      }
    }
  }
  
  var ii = world.length-b;
  
  for (i = d; i < ii; i++) {
    var thisBlock = world[i];
    
    if (thisBlock && thisBlock.id != 1 && !thisBlock.wall) {
      //c.rect(screenMiddle.x+thisBlock.x*blockSize-(blockSize/2)-camera.x*blockSize, screenMiddle.y+thisBlock.y*blockSize-(blockSize/2)-camera.y*blockSize, blockSize+1, blockSize+1, idInfo[thisBlock.id].color);

      var thisX = screenMiddle.x+thisBlock.x*blockSize-(blockSize/2)-camera.x*blockSize;
      var thisY = screenMiddle.y+thisBlock.y*blockSize-(blockSize/2)-camera.y*blockSize;

      c.rect(thisX, thisY, blockSize+1, blockSize+1, idInfo[thisBlock.id].color);
      c.picture(thisX, thisY, idInfo[thisBlock.id].image, blockSize+1, blockSize+1);
      if (thisBlock.wall) {
        c.rect(thisX, thisY, blockSize, blockSize, "rgba(0, 0, 0, 0.3)");
      }
    }
  }
}

function drawPlayer() {
  //c.circle(screenMiddle.x+player.x*blockSize-blockSize/2-camera.x*blockSize, screenMiddle.y+player.y*blockSize-blockSize/2-camera.y*blockSize, player.width*blockSize/2, "red");
  
  if (player.img == 0)
    c.picture(screenMiddle.x+player.x*blockSize-blockSize/2-camera.x*blockSize-blockSize/2, screenMiddle.y+player.y*blockSize-blockSize/2-camera.y*blockSize-player.height*blockSize, "https://aaserver.net/images/me1.png", player.width*blockSize, player.height*blockSize);
  else if (player.img == 1)
    c.picture(screenMiddle.x+player.x*blockSize-blockSize/2-camera.x*blockSize-blockSize/2, screenMiddle.y+player.y*blockSize-blockSize/2-camera.y*blockSize-player.height*blockSize, "https://aaserver.net/images/me2.png", player.width*blockSize, player.height*blockSize);
  else if (player.img == 2)
    c.picture(screenMiddle.x+player.x*blockSize-blockSize/2-camera.x*blockSize-blockSize/2, screenMiddle.y+player.y*blockSize-blockSize/2-camera.y*blockSize-player.height*blockSize, "https://aaserver.net/images/me3.png", player.width*blockSize, player.height*blockSize);
  
  if (keys[37] && !menu)
    player.x -= 0.1;
  if (keys[39] && !menu)
    player.x += 0.1;
  
  if (keys[37] && !menu)
    player.img = 1;
  else if (keys[39] && !menu)
    player.img = 2;
  else
    player.img = 0;
  
  if (player.x > camera.x)
    camera.x += 0.09;
  if (player.x < camera.x)
    camera.x -= 0.09;  
  
  if (player.y > camera.y)
    camera.y += player.velo;
  if (player.y < camera.y)
    camera.y -= player.velo;
  
  player.y += player.velo;
  player.velo += 0.01;
  
  if (getBlock(player.x, player.y)[0].id != 1 && getBlock(player.x, player.y)[0].wall == false) {
    player.velo = 0;
    if (keys[38] && !menu && !crafting) {
      player.velo -= 0.2;
    }
  }
  
  if (getBlock(player.x-0.5, player.y-0.5)[0].id != 1 && keys[37] && getBlock(player.x-0.5, player.y-0.5)[0].wall == false) {
    player.x += 0.1;
    
    if (getBlock(player.x, player.y)[0].id != 1 && getBlock(player.x, player.y)[0].wall == false && isIpad) {
      player.velo -= 0.2;
    }
  }
  if (getBlock(player.x+0.5, player.y-0.5)[0].id != 1 && keys[39] && getBlock(player.x+0.5, player.y-0.5)[0].wall == false) {
    player.x -= 0.1;
    
    if (getBlock(player.x, player.y)[0].id != 1 && getBlock(player.x, player.y)[0].wall == false && isIpad) {
      player.velo -= 0.2;
    }
  }
  /*if (getBlock(player.x, player.y-0.5)[0].id != 1 && keys[32]) {
    player.y -= player.velo;
  }*/
}

function inventory() {
  c.rect(width/2-25-4*55-5, height-80, (25+4*55)*2+10, 60, "lightgray");
  for (var i = 0; i < 5; i++) {
    c.rect(width/2-25-i*55, height-75, 50, 50, "gray");
    
    if (mouse.x > width/2-25-i*55 && mouse.x < width/2-25-i*55+50 && mouse.y > height-75 && mouse.y < height-75+50 && mouse.click) {
      invSel = 5-i;
    }
  }
  for (var i = 1; i < 5; i++) {
    c.rect(width/2-25+i*55, height-75, 50, 50, "gray");
    
    if (mouse.x > width/2-25+i*55 && mouse.x < width/2-25+i*55+50 && mouse.y > height-75 && mouse.y < height-75+50 && mouse.click) {
      invSel = 5+i;
    }
  }
  
  c.rect(width/2-25-4*55-5+(invSel-1)*55, height-80, 60, 60, "black");
  
  for (var i = 0; i < inv.length; i++) {
    if (inv[i].id != 0) {
      c.picture(width/2-25-4*55+i*55, height-75, idInfo[inv[i].id].image, 50, 50);
      c.rect(width/2-25-4*55+i*55, height-75, 50, 50, inv[i].wall ? "rgba(0, 0, 0, 0.3)" : "rgba(0, 0, 0, 0)");
      
      c.text(width/2-25-4*55+i*55+5, height-53, 20, inv[i].amount, "white");
    }
    
    if (inv[i].amount <= 0)
      inv[i].id = 0;
  }
  
  
  for (var i = 0; i < 9; i++) {
    if (keys[49+i] && !menu)
      invSel = 1+i;
  }
  
  var b = getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5);
  if (mouse.click && b && b[0].id == 1 && inv[invSel-1].amount >= 1 && !crafting && !menu && !cmd) {
    if (placeKey) {
      setBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5, inv[invSel-1].id, inv[invSel-1].wall);
      inv[invSel-1].amount--;
      placeKey = false;
    }
  }
  else if (!mouse.click) {
    placeKey = true;
  }
  
  if (mouse.right && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5) && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id != 1 /*&& getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id != 6*/ && !crafting && !menu && !cmd && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id != 12) {
    if (placeKey) {
      pickUp(getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id, getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].wall);
      setBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5, 1, false);
      placeKey = false;
    }
  }
  else if (!mouse.click) {
    placeKey = true;
  }
}

function cmdF() {
  if (mouse.click && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x, (mouse.y-screenMiddle.y)/blockSize+camera.y) && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x, (mouse.y-screenMiddle.y)/blockSize+camera.y)[0].id == 11) {
    cmd = true;
    thisCMDBlock = {x: (mouse.x-screenMiddle.x)/blockSize+camera.x, y: (mouse.y-screenMiddle.y)/blockSize+camera.y};
  } 
  
  if (cmd) {
    c.rect(width/2-300, 100, 600, height-100-100, "lightgray");
    c.rect(width/2+300-30-10+5, 110+5, 30, 30, "darkred");
    c.rect(width/2+300-30-10, 110, 30, 30, "red");
    
    if ((mouse.x > width/2+300-30-10 && mouse.x < width/2+300-30-10+30 && mouse.y > 110 && mouse.y < 140 && mouse.click) || keys[27]) {
      cmd = false;
      document.getElementById('command').style.visibility = "hidden";
      document.getElementById('command').value = getBlock(thisCMDBlock.x, thisCMDBlock.y)[0].cmd ? getBlock(thisCMDBlock.x, thisCMDBlock.y)[0].cmd : "";
    }
    
    if (CmdPrompt) {
      document.getElementById('command').style.visibility = "visible";
      document.getElementById('command').style.left = width/2-300 + "px";
      document.getElementById('command').style.top = 150 + "px";
      CmdPrompt = false;
    }
    
    command = document.getElementById('command').value;
    
    c.rect(width/2-75+10, 430+10, 150, 75, "darkblue");
    c.rect(width/2-75, 430, 150, 75, "blue");
    c.ctx.textAlign = "center";
    c.text(width/2, 490, 50, "RUN", "darkblue");
    c.ctx.textAlign = "left";
    
    if (mouse.x > width/2-75 && mouse.x < width/2+75 && mouse.y > 430 && mouse.y < 430+75 && mouse.click) {
      try {
        eval(command);
      }
      catch(e) {
        alert(e);
      }
      world[getBlock(thisCMDBlock.x, thisCMDBlock.y)[1]].cmd = command;
      cmd = false;
      document.getElementById('command').style.visibility = "hidden";
    }
  }
  else {
    CmdPrompt = true;
  }
}

function craftingF() {
  if (mouse.click && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5) && getBlock((mouse.x-screenMiddle.x)/blockSize+camera.x+0.5, (mouse.y-screenMiddle.y)/blockSize+camera.y+0.5)[0].id == 6) {
    crafting = true;
  }
  
  if (crafting) {
    c.rect(width/2-300, 100, 600, height-100-100, "lightgray");
    c.rect(width/2+300-30-10+5, 110+5, 30, 30, "darkred");
    c.rect(width/2+300-30-10, 110, 30, 30, "red");
    
    c.rect(width/2-295+5, 105+5, 250, 40, "darkblue");
    c.rect(width/2-295, 105, 250, 40, "blue");
    
    c.rect(width/2-295+5+260, 105+5, 250, 40, "darkblue");
    c.rect(width/2-295+260, 105, 250, 40, "blue");
    
    c.ctx.textAlign = "center";
    c.text(width/2-295+250/2, 135, 30, "Walls", "darkblue");
    c.text(width/2-295+260+250/2, 135, 30, "Others", "darkblue");
    c.ctx.textAlign = "left";
    
    if (mouse.x > width/2-295 && mouse.x < width/2-295+250 && mouse.y > 105 && mouse.y < 105+40 && mouse.click) {
      craftMode = 1;
    }
    
    if (mouse.x > width/2-295+260 && mouse.x < width/2-295+250+260 && mouse.y > 105 && mouse.y < 105+40 && mouse.click) {
      craftMode = 2;
    }
    
    if ((mouse.x > width/2+300-30-10 && mouse.x < width/2+300-30-10+30 && mouse.y > 110 && mouse.y < 140 && mouse.click) || keys[27]) {
      crafting = false;
    }
    
    if (keys[38]) {
      craftScroll -= 5;
    }
    
    if (keys[40] && craftScroll <= 0) {
      craftScroll += 5;
    }
    
    if (craftMode == 1) {
      for (var i = 0; i < 11; i++) {
        if (150+i*65+craftScroll > 150) {
          c.rect(width/2-300+5, 150+i*65+craftScroll, 590, 60, "gray");
        }
        for (var j = 0; j < craftingList[i].in.length; j++) {
          if (150+i*65+craftScroll > 150) {
            c.picture(width/2-300+10+j*55, 150+i*65+5+craftScroll, idInfo[craftingList[i].in[j]].image, 50, 50);
          }
        }
        if (150+i*65+craftScroll > 150) {
          c.picture(width/2+300-10-50, 150+i*65+5+craftScroll, idInfo[craftingList[i].out.block].image, 50, 50);
          c.rect(width/2+300-10-50, 150+i*65+5+craftScroll, 50, 50, craftingList[i].out.wall ? "rgba(0, 0, 0, 0.3)" : "rgba(0, 0, 0, 0)");
        }

        if (mouse.x > width/2-300+5 && mouse.x < width/2+300-5 && mouse.y > 150+i*65+craftScroll && mouse.y < 150+i*65+60+craftScroll && mouse.click) {
          if (craftKey) {
            var removedItems = [];
            for (var k = 0; k < craftingList[i].in.length; k++) {
              for (var j = 0; j < inv.length; j++) {
                if (inv[j].id == craftingList[i].in[k]) {
                  inv[j].amount--;
                  removedItems.push(inv[j].id);
                }
              }
            }
            if (removedItems.equals(craftingList[i].in)) {
              pickUp(craftingList[i].out.block, craftingList[i].out.wall);
            }
            else {
              for (var j = 0; j < removedItems.length; j++) {
                pickUp(removedItems[j], false);
              }
            }

            craftKey = false;
          }
        }
        else {
          if (!mouse.click)
            craftKey = true;
        }
      }
    }
    
    if (craftMode == 2) {
      for (var i = 11; i < craftingList.length; i++) {
        if (150+(i-11)*65+craftScroll > 150)
          c.rect(width/2-300+5, 150+(i-11)*65+craftScroll, 590, 60, "gray");
        for (var j = 0; j < craftingList[i].in.length; j++) {
          if (150+(i-11)*65+craftScroll > 150) {
            c.picture(width/2-300+10+j*55, 150+(i-11)*65+5+craftScroll, idInfo[craftingList[i].in[j]].image, 50, 50);
          }
        }
        if (150+(i-11)*65+craftScroll > 150) {
          c.picture(width/2+300-10-50, 150+(i-11)*65+5+craftScroll, idInfo[craftingList[i].out.block].image, 50, 50);
          c.rect(width/2+300-10-50, 150+(i-11)*65+5+craftScroll, 50, 50, craftingList[i].out.wall ? "rgba(0, 0, 0, 0.3)" : "rgba(0, 0, 0, 0)");
        }

        if (mouse.x > width/2-300+5 && mouse.x < width/2+300-5 && mouse.y > 150+(i-11)*65+craftScroll && mouse.y < 150+(i-11)*65+60+craftScroll && mouse.click) {
          if (craftKey) {
            var removedItems = [];
            for (var k = 0; k < craftingList[i].in.length; k++) {
              for (var j = 0; j < inv.length; j++) {
                if (inv[j].id == craftingList[i].in[k]) {
                  inv[j].amount--;
                  removedItems.push(inv[j].id);
                }
              }
            }
            if (removedItems.equals(craftingList[i].in)) {
              pickUp(craftingList[i].out.block, craftingList[i].out.wall);
            }
            else {
              for (var j = 0; j < removedItems.length; j++) {
                pickUp(removedItems[j], false);
              }
            }

            craftKey = false;
          }
        }
        else {
          if (!mouse.click)
            craftKey = true;
        }
      }
    }
  }
}

function mountain(x, y) {
  var a = 0;
  var r = c.random(10, 15);
  for (var j = 0; j < r; j++) {
    for (var i = 0; i < 30-a*c.random(1, 1.5); i++) {
      setBlock(x+i+a, y-j, j == r-1 ? 2 : 3, false);
      if (r-1 == j && c.random(0, 4) == 1) {
        tree(x+i+a, y-j);
      }
    }
    a += c.random(0, 3);
  }
}

function tree(x, y) {
  var r = c.random(4, 8);
  for (var i = 0; i < r; i++) {
    setBlock(x, y-i, 4, true);
  }
  if (r > 6) {
    setBlock(x-1, y-r/2, 10, true);
    setBlock(x-2, y-r/2, 10, true);
    setBlock(x+1, y-r/2, 10, true);
    setBlock(x+2, y-r/2, 10, true);
    
    setBlock(x-1, y-r+2, 10, true);
    setBlock(x+1, y-r+2, 10, true);
  }
}
             
// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

function pickUp(id, wall) {
  for (var i = 0; i < inv.length; i++) {
    if (inv[i].id == id && inv[i].wall == wall) {
      inv[i].amount += 1;
      break;
    }
    else if (inv[i].id == 0) {
      inv[i].id = id;
      inv[i].amount++;
      inv[i].wall = wall;
      break;
    }
  }
}

function remove(id) {
  for (var i = 0; i < inv.length; i++) {
    if (inv[i].id == id) {
      inv[i].amount = 0;
      break;
    }
  }
}

function drawCoordSys() {
  c.line(0, coordOnScreen(0, 0).y, width, coordOnScreen(0, 0).y, 2, "red");
  c.line(coordOnScreen(0, 0).x, 0, coordOnScreen(0, 0).x, height, 2, "red");
}

function generateWorld(twidth, theight, blockSize, groundLevel) {
  for (var x = 0-twidth/2; x < 0+twidth/2; x++) {
    for (var y = 0-theight/2; y < 0+theight/2; y++) {
      var blockSettings = {x: x,
                           y: y,
                           wall: false};
      if (y < groundLevel)
        blockSettings.id = 1;
      else if (y == groundLevel)
        blockSettings.id = 2;
      else if (y > groundLevel && y < groundLevel+5)
        blockSettings.id = 3;
      else if (y >= groundLevel+5 && y < groundLevel+theight/2-10)
        blockSettings.id = 8;
      else if (y > groundLevel+theight/2-10 && y < groundLevel+theight/2-5)
        blockSettings.id = 7;
      else if (y > groundLevel+theight/2-6)
        blockSettings.id = 12;
      else
        blockSettings.id = 8;
      
      world.push(blockSettings);
    }
  }
  return true;
}

function getBlock(x, y) {
  x = Math.floor(x);
  y = Math.floor(y);
  
  if (x < -worldInfo.width / 2 || x > worldInfo.width / 2 || y < -worldInfo.height / 2 || y > worldInfo.height / 2) {
    return false;
  }
  
  const index = (x + worldInfo.width / 2) * worldInfo.height + y + worldInfo.height / 2;
  if (index < 0 || index >= world.length) {
    return false;
  }
  
  return [world[index], index];
}

// function getBlock(x, y) {
//   x = Math.floor(x);
//   y = Math.floor(y);
//   var i;
//   var ii = world.length;
//   for (i = 0; i < ii; i++) {
//     if (world[i].x == x && world[i].y == y) {
//       return [world[i], i];
//       break;
//     }
//   }
//   return false;
// }

function setBlock(x, y, id, wall) {
  world[getBlock(x, y)[1]].id = id;
  world[getBlock(x, y)[1]].wall = wall;
}

function coordOnScreen(x, y) {
  return {x: screenMiddle.x+x*blockSize-(blockSize/2)-camera.x*blockSize,
          y: screenMiddle.y+y*blockSize-(blockSize/2)-camera.y*blockSize};
}

function point(x, y, z) {;
  return {x: x*(map(z, 0, 100, 0, 100)/100)+centerX, y: y*(map(z, 0, 100, 0, 100)/100)+centerY};
}
  
function map( x,  in_min,  in_max,  out_min,  out_max){
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*24*60*60*1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i <ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

function pollFunc(fn, timeout, interval) {
    var startTime = (new Date()).getTime();
    interval = interval || 1000,
    canPoll = true;

    (function p() {
        canPoll = ((new Date).getTime() - startTime ) <= timeout;
        if (!fn() && canPoll)  { // ensures the function exucutes
            setTimeout(p, interval);
        }
    })();
}

document.addEventListener("keydown", function(e) {
  keys[e.keyCode] = true;
});

document.addEventListener("keyup", function(e) {
  keys[e.keyCode] = false;
});

document.addEventListener("mousemove", function(e) {
  mouse.x = e.clientX;
  mouse.y = e.clientY;
});

document.addEventListener("mousedown", function(e) {
  if (e.button == 0)
    mouse.click = true;
  else if (e.button == 2)
    mouse.right = true;
});

document.addEventListener("mouseup", function(e) {
  mouse.click = false;
  mouse.right = false;
});

document.addEventListener("touchstart", function(e) {
  mouse.x = e.changedTouches[0].pageX;
  mouse.y = e.changedTouches[0].pageY;
  mouse.click = true;
});

document.addEventListener("touchmove", function(e) {
  mouse.x = e.changedTouches[0].pageX;
  mouse.y = e.changedTouches[0].pageY;
  e.preventDefault();
});

document.addEventListener("touchend", function(e) {
  mouse.click = false;
  mouse.right = false;
});

var lastScrollTop = 0;
// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
document.addEventListener("scroll", function(){
   var st = window.pageYOffset || document.documentElement.scrollTop;
   if (st > lastScrollTop){
       scroll = "down";
   } else {
      scroll = "up";
   }
   lastScrollTop = st;
}, false);

window.onerror = function(e) {
  if (e == "Uncaught TypeError: Cannot set property 'id' of undefined")
    alert("The game has crashed!\nCannot place block outside of world!");
  else if (e == "Uncaught TypeError: Cannot read property 'id' of undefined")
    alert("The game has crashed!\nCannot remove block/move outside of the world!");
  else
    alert("The game has crashed!\nUnknown error: " + e);
}
              
            
!
999px

Console