Follow Up: Player and World Manipulation

There are two areas which our Dojoers explored at this past event which I wanted to highlight. The first has to do with the code which determines what is dropped when we break our custom block. Normally it looks like this:

/**
* This method determines what is dropped when the block is broken
*/
@Override
public int idDropped(int par1, Random random, int zero) {
	if(random.nextBoolean()){        //get a random boolean (flip a coin)
		return Item.appleRed.itemID;
	} else {
		return this.blockID;
	}
}

This “flips a coin” and determines whether our custom block will drop itself or a delicious red apple. But what if we want to drop one of three items? Our boolean is only either “true” or “false”. We’ll need to use another operator: modulus.

The modulus operator in Java looks like ‘%’ and is a fancy way to deal with remainders when dividing. Let’s update the code and then I’ll walk you through it.

/**
* This method determines what is dropped when the block is broken
*/
@Override
public int idDropped(int par1, Random random, int zero) {
	int randomInt = random.nextInt();
	if((randomInt % 3) == 0){        //if our number divided by 3 goes evenly
		return Item.appleRed.itemID;
	} else if((randomInt % 3) == 1){        //if our number divided by 3 leaves a remainder of 1
		return Block.dirt.blockID;	//Drop a block of dirt!	
	} else {					//here for simplicity we just catch all other scenarios
		return this.blockID;			//but we could also say (random.nextInt() % 3) == 2 
	}						//for when our number divided by 3 leaves a remainder of 2
}

You’ll notice the code: if((random.nextInt() % 3) == 0) which in English reads: if we divide a random integer by 3 and the remainder is 0, do this. Similarly, the next check says: if we divide our random integer by 3 and the remainder is 1, do this instead. Our last else block will catch every other scenario, which in this case is only then we divide our random integer by 3 and we get a remainder of 2. We take a shortcut here and simply write else. Now we will drop one of three items instead of our original two.

The second cool piece of code a dojoer discovered is how to make explosions when we click on our block. The normal click code is below:

/**
  * This method determines what will happen if you right click the block while it's placed.
  */
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityplayer, int par6, float par7, float par8, float par9) {
    
    //First we check to make sure the player doesn't have any items equipped so we know they're not trying to place a block
    if(entityplayer.getCurrentEquippedItem() == null){	
	    if(entityplayer.isSneaking()){	//Do something different if a player is sneaking
		    if(world.isRaining()){
			    world.getWorldInfo().setRaining(false);
		    } else {
			    world.getWorldInfo().setRaining(true);
		    }
	    } else {	//We do this if the player isn't sneaking
		    if(world.isDaytime()){
			    world.getWorldInfo().setWorldTime(18000);
		    } else {
			    world.getWorldInfo().setWorldTime(6000);
		    }
	    }
	    return true;
    } else {
	    return false;
    }
}

This normally toggles if it’s raining if you click while sneaking or toggles if it’s day/night if you’re not sneaking. By poking around the World object our dojoer found the method he wanted to use: createExplosion. You too can poke around the world object by creating a new line under “if(entityplayer.getCurrentEquippedItem() == null){“, typing “world.” (without quotes) and then hitting ctrl+spacebar. This will show you all the methods available to the World object. You can also hold crtl while clicking on the World object to take you directly to the class which will show you it’s variables, methods, and the code inside each method. Hit alt+left arrow to go back.

Now, when you select createExplosion, you’ll see some default parameters are created like this:

world.createExplosion(par1Entity, par2, par4, par6, par8, par9);

Because Forge decompiles Minecraft in order to help mod it, sometimes the names of method parameters can be tricky to understand. And even when we DO understand them it can also be tricky to decide if we should create new variables or use existing ones for the method. One great way to try and understand how this method works is to Google it. Remember, there are many other modders in your same shoes trying to understand the code and multiple communities with experienced members who are happy to help. When I searched for “minecraft forge world.createExplosion”, I found the following bit of code:

par3World.createExplosion((Entity) null, x, y, z, 3F, true);

This gives me a bit of understanding about what each of these parameters does. I know the first is an Entity object(perhaps who “causes” the explosion for death messages), the next three are probably coordinates, the next is a floating point number (which is can include fractions of integers like 12.2 or -144.0927) which I estimate to be the strength of the explosion, and finally a boolean which (according to the page I read) controls whether the explosion happens client side or server side (I am currently unaware of the implications of this).

So getting back to our method, if we switch it up to this:

/**
  * This method determines what will happen if you right click the block while it's placed.
  */
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityplayer, int par6, float par7, float par8, float par9) {
    
    //First we check to make sure the player doesn't have any items equipped so we know they're not trying to place a block
    if(entityplayer.getCurrentEquippedItem() == null){	
	    world.createExplosion(entityplayer, x, y, z, 10.0F, true); //boom
	    return true;
    } else {
	    return false;
    }
}

We’ll make the block explode with a force of 10 (not sure how big this is). This will explode right where it is since we are using the same quordinates we get of where the block is when it’s clicked from “onBlockActivated”. A quick note about the float we passed in as 10.0F. Sometimes Java is able to realize when we type a number in what kind of number we’re saying it should be (whether an integer or float), as it does in turning our x, y, and z integers into doubles (a double is very similar to a float). But sometimes Java needs a bit of help. Here in this method we help Java out by putting an ‘F’ after the number to say, “Yes, this is a float variable”.

Time for some homework:
– Make our block drop one of FIVE items instead of 3. Bonus: break 25 blocks, record what is dropped each time, and post your results in a comment to this post!
– Play around with creating an explosion. Make it really big or really small. Turn the block into a cannon by creating the explosion 10 units in front of you. Play around with the boolean parameter. Do you notice any difference when it’s true or false? Bonus: Try to crash the game. See what it would take for the explosion to literally crash the world and take note of what happens. Be sure to post anything interesting you come across as a comment below!