Code viewer for World: Minecraft Builder

// Cloned by Enhanced on 5 Jun 2018 from World "Cloned Enhanced Minecraft world" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 1 Jun 2018 from World "Enhanced Minecraft world" by Nathan Bonnard 
// Please leave this clone trail here.
 


// Cloned by Nathan Bonnard on 31 May 2018 from World "Minecraft with cursor + better camera" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 30 May 2018 from World "Minecraft with cursor" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 29 May 2018 from World "MineCraft" by Starter user 
// Please leave this clone trail here.
 



// ==== Starter World ===============================================================================================
// (c) Ancient Brain Ltd. All rights reserved.
// This code is only for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// This code may not be copied, re-published or used on any other website.
// To include a run of this code on another website, see the "Embed code" links provided on the Ancient Brain site.
// ==================================================================================================================




// "MineCraft" World 
// user adds blocks 


// --- not using nextStep() loop for actions, only for rendering: ------------------------ 
// all actions are taken whenever user hits keys and not any other time
// however, still need to use nextStep() loop for render update

 
// ====================================================================================================================
// =Added  cursor to choose where to place blocks, controls adapt to camera postion, the blocks to place can be chosen=
// =from the info box, buttons draw shapes                                                                            =
// ====================================================================================================================
 
 
 
 

// ===================================================================================================================
// === Start of tweaker's box ======================================================================================== 
// ===================================================================================================================

// The easiest things to modify are in this box.
// You should be able to change things in this box without being a JavaScript programmer.
// Go ahead and change some of these. What's the worst that could happen?



// These 3 have default values, so this section is optional:

AB.clockTick       = 100;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 1000000;    

	// Length of run: Maximum length of run in steps. Default 1000.

AB.screenshotStep  = 50;   
  
	// Take screenshot on this step. (All resources should have finished loading.) Default 50.
AB.drawRunControls = false;
threeworld.drawCameraControls = false;

 
 
 const FILE_ARRAY = [
		"/uploads/mathias/dirt.jpg",
		"/uploads/mathias/stone.png",
		"/uploads/mathias/wood.png",
		"/uploads/mathias/glass.png",
		"/uploads/mathias/grass.jpg",
		"/uploads/mathias/meat.jpg"
		];
		
 const SOUND_BLOCK = '/uploads/starter/chamber.mp3' ;
 const SOUND_DEL   = '/uploads/starter/chamber.mp3'


 const SKYCOLOR 	= 0xFFFFFF;			 	// a number, not a string 
 const CURSORCOLOR  = "red";
 
const objectsize = 300 ;

const MAXPOS                = 4000 ;                                 
const startRadiusConst	 	= MAXPOS * 0.5 ;		// distance from centre to start the camera at
const maxRadiusConst 		= MAXPOS * 5 ;		// maximum distance from camera we will render things  

const shortDistance = 2; //used for checking if two vectors are close to be the same

//--- change threeworld defaults: -------------------------------

threehandler.MAXCAMERAPOS = MAXPOS * 10 ;			// allow camera go far away 


// ===================================================================================================================
// === End of tweaker's box ==========================================================================================
// ===================================================================================================================


// You will need to be some sort of JavaScript programmer to change things below the tweaker's box.


function randomfloatAtoB ( A, B )			 
{
 return ( A + ( Math.random() * (B-A) ) );
}

function randomintAtoB ( A, B )			 
{
 return  ( Math.round ( randomfloatAtoB ( A, B ) ) );
}
  




function World() { 


function createCursor() 
{
    //create cursor
    
    //create shape and material for the edges
    var edgeshape = new THREE.CylinderGeometry(10,10,objectsize,32);
    var material = new THREE.MeshBasicMaterial( {color: CURSORCOLOR} );
    
    
    //create edges
    var edge1 = new THREE.Mesh( edgeshape, material );
    var edge2 = new THREE.Mesh( edgeshape, material );
    var edge3 = new THREE.Mesh( edgeshape, material );
    var edge4 = new THREE.Mesh( edgeshape, material );
    var edge5 = new THREE.Mesh( edgeshape, material );
    var edge6 = new THREE.Mesh( edgeshape, material );
    var edge7 = new THREE.Mesh( edgeshape, material );
    var edge8 = new THREE.Mesh( edgeshape, material );
    var edge9 = new THREE.Mesh( edgeshape, material );
    var edge10 = new THREE.Mesh( edgeshape, material );
    var edge11= new THREE.Mesh( edgeshape, material );
    var edge12= new THREE.Mesh( edgeshape, material );
    
    
    //place edges correctly
    edge1.position.set(-objectsize/2,0,-objectsize/2);
    
    edge2.position.set(-objectsize/2,0,+objectsize/2);
    
    edge3.position.set(+objectsize/2,0,+objectsize/2);
    
    edge4.position.set(+objectsize/2,0,-objectsize/2);
    
    edge5.position.set(objectsize/2,objectsize/2,0);
    edge5.rotation.x = Math.PI / 2;
    
    edge6.position.set(-objectsize/2,objectsize/2,0);
    edge6.rotation.x = Math.PI / 2;
    
    edge7.position.set(objectsize/2,-objectsize/2,0);
    edge7.rotation.x = Math.PI / 2;
    
    edge8.position.set(-objectsize/2,-objectsize/2,0);
    edge8.rotation.x = Math.PI / 2;
    
    edge9.position.set(0,-objectsize/2,objectsize/2);
    edge9.rotation.z = Math.PI / 2;
    
    edge10.position.set(0,-objectsize/2,-objectsize/2);
    edge10.rotation.z = Math.PI / 2;
    
    edge11.position.set(0,+objectsize/2,objectsize/2);
    edge11.rotation.z = Math.PI / 2;
    
    edge12.position.set(0,+objectsize/2,-objectsize/2);
    edge12.rotation.z = Math.PI / 2;
    
    //add all edges to a group, 
    var cursor = new THREE.Group();

    cursor.add(edge1);
    cursor.add(edge2);
    cursor.add(edge3);
    cursor.add(edge4);
    cursor.add(edge5);
    cursor.add(edge6);
    cursor.add(edge7);
    cursor.add(edge8);
    cursor.add(edge9);
    cursor.add(edge10);
    cursor.add(edge11);
    cursor.add(edge12);
    
    //you can now manipulate the cursor as a unique object
    return cursor;
}


var x, y, z;        // current location 

var cursor = createCursor();

var textureArray;

var blockArray = [];


    // Inputs to instantiate Box
 
var leftInput;
var rightInput;
var forwardInput;
var backwardInput;
var topInput;
var bottonInput;

var currentTexture;

function init()		 
{
     if(FILE_ARRAY.length > 0)
    {
        currentTexture = 0;
    }
   
    leftInput       =   65;
    rightInput      =   68;
    forwardInput    =   87;
    backwardInput   =   83;
    topInput        =   82;
    bottomInput     =   70;
    
    
    cursor.position.set(0,0,0);
    threeworld.scene.add(cursor);
    
	textureArray = [FILE_ARRAY.length];
    for (let i = 0; i < FILE_ARRAY.length; i++)
    {
        textureArray[i] = new THREE.ImageUtils.loadTexture( FILE_ARRAY[i] );
    }
   
    
	for ( let i = 0; i < textureArray.length; i++ )    // for all textures 
	{ 
        textureArray[i].minFilter = THREE.LinearFilter;
	}
	threeworld.camera.lookAt(cursor.position);
}


//=============================================================================
//Useful functions
//=============================================================================

function getBlockIndexAt(position)
{
    let index = 0;
    for (let block of blockArray)
    {
        if ( block.position.distanceTo(position) < shortDistance )
        {
            return index;
        }
        index++;
    }
    
    return -1;
}

function placeBlockAt(pos)
{
    //create block at cursor position
    var shape  = new THREE.BoxGeometry( objectsize, objectsize, objectsize );
    var block  = new THREE.Mesh( shape );
    
    block.position.x = pos.x;     
    block.position.y = pos.y;
    block.position.z = pos.z;
    
    threeworld.scene.add(block);
    paintThis ( block );
    
    // sound effect credit:
    // http://soundbible.com/1399-Chambering-A-Round.html
    var audioBlock = new Audio( SOUND_BLOCK );
    audioBlock.play();
    
    blockArray.push(block)
}

function deleteBlockAt(position)
{
        let toDeleteIndex = getBlockIndexAt(position);
        
        if ( toDeleteIndex > -1 )
        {
            threeworld.scene.remove(blockArray[toDeleteIndex]);
            blockArray.splice(toDeleteIndex, 1);
            var audioDelete = new Audio( SOUND_DEL );
            audioDelete.play();
        }
        
}

function isOccupied(position)
{
    for (let block of blockArray)
    {
        if ( block.position.distanceTo(position) < shortDistance )
        {
            return true;
        }
    }
    
    return false;
}

function paintThis( object )        // paint objects with random textures 
{
        object.material =  new THREE.MeshBasicMaterial ( { transparent: true, opacity:1 , map:textureArray[currentTexture]  } ); 
}


function drawPyramid()
{
    var startPosition = new THREE.Vector3(cursor.position.x, cursor.position.y, cursor.position.z);
    
    for (let j = 0 ; j<4 ; j++)
    {
        for(let i=-j ; i <= j ; i++)
        {
            for(let k = -j ; k <= j ; k++)
            {
                var where = new THREE.Vector3(startPosition.x + i*objectsize , startPosition.y - j*objectsize, startPosition.z + k*objectsize);
                if ( !isOccupied(where) ) placeBlockAt(where);
            }
            
        }
    }
}


function drawCube()
{
    var startPosition = new THREE.Vector3(cursor.position.x, cursor.position.y, cursor.position.z);
    var cubePosition = new THREE.Vector3(cursor.position.x - objectsize , cursor.position.y - objectsize , cursor.position.z - objectsize );
    
    for(var i = 0 ; i<3 ; i++)
    {
        for(var j = 0 ; j<3 ; j++)
        {
            for(var k = 0 ; k<3 ; k++)
            {
               
                var where = new THREE.Vector3(cubePosition.x + i*objectsize , cubePosition.y + j*objectsize, cubePosition.z + k*objectsize);
                if ( !isOccupied(where) ) placeBlockAt(where);
                
            }
        }
    }
    
    cursor.position.set(startPosition.x, startPosition.y + objectsize , startPosition.z);
}

function onChangeSelectTexture()
{
    var selectBox = document.getElementById("textureSelector");
    var selectedValue = selectBox.options[selectBox.selectedIndex].value;
    currentTexture = selectedValue;
    let s4 = "<p>Selected block : <img src=\""+ FILE_ARRAY[currentTexture]+"\" height=\"60\" width=\"60\"></p>";
    $("#user_span6").html( s4 );
    
    document.getElementById("p1").click();
}


// the main key handling function:

function handleKeyDown (e)
{
 
  if ( e.keyCode == leftInput ) { cursor.position.x +=  - objectsize ; 	e.preventDefault(); }   // left
  if ( e.keyCode == rightInput ) { cursor.position.x +=  + objectsize ; 	e.preventDefault(); }   // right
 
  if ( e.keyCode == forwardInput ) { cursor.position.z +=  - objectsize ; 	e.preventDefault(); }   // forward
  if ( e.keyCode == backwardInput ) { cursor.position.z +=  + objectsize ; 	e.preventDefault(); }   // back 
  
  if ( e.keyCode == bottomInput ) { cursor.position.y +=  - objectsize ; 	e.preventDefault(); }   
  if ( e.keyCode == topInput ) { cursor.position.y +=  + objectsize ;     e.preventDefault(); }
  
  if ( e.keyCode == 13 )  // Enter key pressed
  { 

      if( !isOccupied( cursor.position )) //if no block at cursor
      {
        
        placeBlockAt(cursor.position);
    
      }
      
    e.preventDefault();
      
  }
    
  if ( e.keyCode == 46 ) { //delete button pressed
      
    if (isOccupied(cursor.position)) 
    {
        deleteBlockAt(cursor.position);
    }
    e.preventDefault();
  }
}

	this.endCondition = false;

 

this.newRun = function() 
{
	threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 

	var s = "<p id='p1'>   Use WASD, r (up) and f(down) to move the cursor. </p>";
 	$("#user_span2").html( s );
 	var s1 = "<p>   Press Enter to place a block, Del to delete one. </p>";
 	$("#user_span3").html( s1 );
 	var s2 = "<p>   Use the dropdown menu to change the kind of block you want to use </p>";
 	$("#user_span4").html( s2 );
 	var s3 = "<p><select id=\"textureSelector\" name=\"texture\" >";
    for(let i = 0; i < FILE_ARRAY.length; i++)
    {
        s3 += "<option value=\"" + i + "\" style=\"background-image:url(" + FILE_ARRAY[i]+ ") \"> Block </option>";
    }
    s3 += "</select>";
 	$("#user_span5").html( s3 );
 	
 	var s6 = "<p>Selected block : <img src=\""+ FILE_ARRAY[0]+"\" height=\"60\" width=\"60\"></p>"
 	$("#user_span6").html( s6 );
 	
 	var s7 = "<p><button id='pyramidButton'>Draw Pyramid</button> <button id='cubeButton'>Draw Cube</button></p>"
 	$("#user_span7").html( s7 );
 	
 	
 	init();
	   
	// set up the main key handler:
	document.addEventListener( 'keydown', handleKeyDown);
	document.getElementById("textureSelector").addEventListener("change", onChangeSelectTexture);
	document.getElementById("pyramidButton").addEventListener("click", drawPyramid);
	document.getElementById("cubeButton").addEventListener("click", drawCube);

};


 

this.nextStep = function()
{
    if((threeworld.camera.rotation.y >= -Math.PI / 4 && threeworld.camera.rotation.y <= Math.PI / 4) &&
    (threeworld.camera.rotation.x >= -Math.PI / 2 && threeworld.camera.rotation.x <= 0) &&
    (threeworld.camera.rotation.z >= -Math.PI / 4 && threeworld.camera.rotation.z <= Math.PI / 4))
    {
        leftInput       =   65;
        rightInput      =   68;
        forwardInput    =   87;
        backwardInput   =   83;
    }
    
    else if((threeworld.camera.rotation.y >= -Math.PI / 4 && threeworld.camera.rotation.y <= Math.PI / 4) &&
    (threeworld.camera.rotation.x >= -Math.PI && threeworld.camera.rotation.x <= -Math.PI / 2) &&
    (threeworld.camera.rotation.z >= 3 * Math.PI / 4 || threeworld.camera.rotation.z <= -3 * Math.PI / 4))
    {
        leftInput       =   68;
        rightInput      =   65;
        forwardInput    =   83;
        backwardInput   =   87;
    }
    
    else if((threeworld.camera.rotation.y >= 0 && threeworld.camera.rotation.y <= Math.PI / 2) &&
    (threeworld.camera.rotation.x >= -Math.PI && threeworld.camera.rotation.x <= 0) &&
    (threeworld.camera.rotation.z >= 0 && threeworld.camera.rotation.z <= Math.PI))
    {
        leftInput       =   87;
        rightInput      =   83;
        forwardInput    =   68;
        backwardInput   =   65;
    }
    
    else if((threeworld.camera.rotation.y >= -Math.PI / 2 && threeworld.camera.rotation.y <= 0) &&
    (threeworld.camera.rotation.x >= -Math.PI && threeworld.camera.rotation.x <= 0) &&
    (threeworld.camera.rotation.z >= - Math.PI && threeworld.camera.rotation.z <= 0))
    {
        leftInput       =   83;
        rightInput      =   87;
        forwardInput    =   65;
        backwardInput   =   68;
    }
};


this.endRun = function(){};



}