Jump to content

3 simple ( hopefully ) questions from a beginner.


doku

Recommended Posts

Hi gents / ladies,

 

I'm trying to expand my minecraft editting capabilities from just texturing so I've started tinkering around with forge.  I've managed to get some of what I want working but I have 3 questions and would be grateful if anyone could provide answers.

 

1. How do you override the default blocks to use a custom one.  e.g blockgrass becomes doku_grass when mod is running. ( currently I'm replacing the block declaration in Block.java but would like to not modify existing code if possible )

2. How do you ( can you? ) rotate a texture index for the side of a block by say 90degrees.

3. How do you randomise a texture index for a block side.  - When I tried this it initially worked, however everytime any block in the current chunk was modified the randomisation was re-applied which obviously is crap :).

 

Thanks in advance

 

doku.

Link to comment
Share on other sites

I only just solved this problem (rotating the texture) so here is my solution.

Consider that it can be done either by using metadata or tile entities.

I had to use tile entities as to many of my blocks metdata entries were already taken and thus not free to determine diffrent sides.

 

One thing you might want to do is have a look at the thread i opened not long ago titled:

"Client appears not to be writing to NBT"

It contains all you need to know about saving the direction and rereading it when the world is loaded.

 

What you also need (and even though it is contained in that thread i will re-post it here) is a function that determines the direction, mine is overly precise as i need diffrent parts of my data triple for diffrent blocks.

 

setDirection function:

	public void setDirection(double playerHeight, float playerAngle){
	Side side = FMLCommonHandler.instance().getEffectiveSide();
	playerAngle = Math.abs(playerAngle) % 360;
	if(side == Side.CLIENT) playerHeight -= 1.62;
	if(playerHeight % 1 >= 0.5)playerHeight = (int)playerHeight+1; else playerHeight = (int)playerHeight;

	if(this.direction.equals("NotSetYet")){
		if(playerHeight+1 < yCoord){
			if(playerAngle>=  0 && playerAngle< 45){this.direction ="USE";}
			if(playerAngle>= 45 && playerAngle< 90){this.direction ="UES";}
			if(playerAngle>= 90 && playerAngle<135){this.direction ="UEN";}
			if(playerAngle>=135 && playerAngle<180){this.direction ="UNE";}
			if(playerAngle>=180 && playerAngle<225){this.direction ="UNW";}
			if(playerAngle>=225 && playerAngle<270){this.direction ="UWN";}
			if(playerAngle>=270 && playerAngle<315){this.direction ="UWS";}
			if(playerAngle>=315 && playerAngle<360){this.direction ="USW";}
		}else{
			if(playerAngle>=  0 && playerAngle< 45){this.direction ="DSE";}
			if(playerAngle>= 45 && playerAngle< 90){this.direction ="DES";}
			if(playerAngle>= 90 && playerAngle<135){this.direction ="DEN";}
			if(playerAngle>=135 && playerAngle<180){this.direction ="DNE";}
			if(playerAngle>=180 && playerAngle<225){this.direction ="DNW";}
			if(playerAngle>=225 && playerAngle<270){this.direction ="DWN";}
			if(playerAngle>=270 && playerAngle<315){this.direction ="DWS";}
			if(playerAngle>=315 && playerAngle<360){this.direction ="DSW";}
		}
	}
}

 

Next i will give an example on how to set and interpret this triple:

 

@Override
public void onBlockPlacedBy(World theWorld, int blockX, int blockY, int blockZ, EntityLiving thePlayer) {
	NosTileEntity tile;
	switch(theWorld.getBlockMetadata(blockX, blockY, blockZ)){
	case 1:	
	case 5:	
	case 6:		
	case 8:
		tile = (NosTileEntity)theWorld.getBlockTileEntity(blockX, blockY, blockZ);			
		tile.setDirection(thePlayer.posY,thePlayer.rotationYaw);break;				
	default: 
		break;
	}
}

public int getBlockTextureFromSideAndMetadataAndDirection(int side, int metadata, String direction){
	switch(metadata){
	case 1:
		switch(direction.charAt(1)){
		case 'N':{if(side == 3 || side == 4)return 1; else return 2;}
		case 'E':{if(side == 3 || side == 5)return 1; else return 2;}
		case 'S':{if(side == 3 || side == 4)return 2; else return 1;}
		case 'W':{if(side == 3 || side == 5)return 2; else return 1;}
		default :return 255;
		}
	case 5:
		if(direction.charAt(0) == 'D'){return  6;}else{return  7;}
	case 6:
		if(direction.charAt(0) == 'D'){return 13;}else{return 14;}
	case 8:
		if(direction.equals("UNE")||direction.equals("UEN")){if(side == 3 || side == 5) return 9; else  return 8;}
		if(direction.equals("UES")||direction.equals("USE")){if(side == 3 || side == 4) return 9; else  return 8;}
		if(direction.equals("USW")||direction.equals("UWS")){if(side == 2 || side == 4) return 9; else  return 8;}
		if(direction.equals("UWN")||direction.equals("UNW")){if(side == 2 || side == 5) return 9; else  return 8;}
		if(direction.equals("DNE")||direction.equals("DEN")){if(side == 3 || side == 5)return 11; else return 10;}
		if(direction.equals("DES")||direction.equals("DSE")){if(side == 3 || side == 4)return 11; else return 10;}
		if(direction.equals("DSW")||direction.equals("DWS")){if(side == 2 || side == 4)return 11; else return 10;}
		if(direction.equals("DWN")||direction.equals("DNW")){if(side == 2 || side == 5)return 11; else return 10;}
	default: return 255;
	}		
}

 

By now i assume you realized that the metadata values 1,5,6 and 8 of my block are blocks that can be rotated/place facing diffrent sides. I think this is all you should need, if you have further questions on this I'll do my best to help.

Link to comment
Share on other sites

Thanks for the quick reply.  I will have a look at implementing this.  One question though, why does it use playerAngle to determine a direction? isn't the playerAngle always changing as the player moves? or am I missunderstanding what it is? :)

 

Also do you have any ideas for the other questions from OP?  Thanks.

Link to comment
Share on other sites

isn't the playerAngle always changing as the player moves?

 

That is quite true, but you can compensate that by using the line:

 

playerAngle = Math.abs(playerAngle) % 360;

 

However if you still dislike the idea of using the angle i have a diffrent solution for you:

 

	public void setDirection(double playerX, double playerY, double playerZ){

	double diffX = xCoord - playerX +0.5, diffZ = zCoord - playerZ + 0.5;

	if(side == Side.CLIENT) playerY -= 1.62;
	if(playerY % 1 >= 0.5)playerY = (int)playerY+1; else playerY = (int)playerY;

	if((int)(playerY-1) < yCoord){
		if (Math.abs(diffX)>=Math.abs(diffZ)){
			if(diffX > 0){
				if(playerZ > zCoord) this.direction ="UWN"; else this.direction ="UWS";
			}else{
				if(playerZ > zCoord) this.direction ="UEN"; else this.direction ="UES";
			}
		}else{
			if(diffZ > 0){
				if(playerX > xCoord) this.direction ="UNE"; else this.direction ="UNW"; 
			}else{
				if(playerX > xCoord) this.direction ="USE"; else this.direction ="USW"; 
			}
		}
	}else{
		if (Math.abs(diffX)>=Math.abs(diffZ)){
			if(diffX > 0){
				if(playerZ > zCoord) this.direction ="DWN"; else this.direction ="DWS";
			}else{
				if(playerZ > zCoord) this.direction ="DEN"; else this.direction ="DES";
			}
		}else{
			if(diffZ > 0){
				if(playerX > xCoord) this.direction ="DNE"; else this.direction ="DNW"; 
			}else{
				if(playerX > xCoord) this.direction ="DSE"; else this.direction ="DSW"; 
			}
		}
	}
}

 

This should work just as good.

 

I don't know how to solve your first problem but the third one *could* ( i think) be solved by assigning the random texture index in the onBlockPlacedBy() function and saving it in a tile entity. Thus the random value would be generated just once and after that always be the same for that one block.

Link to comment
Share on other sites

Great, you are being very helpful thanks. :)

 

If you don't mind could you expand a bit on 'onBlockPlacedBy() function and saving it in a tile entity'.  I literally started with forge a couple of days ago and have little knowledge ( growing steadily ) on where and how to implement certain functions.

Link to comment
Share on other sites

If you don't mind could you expand a bit on 'onBlockPlacedBy() function and saving it in a tile entity'.

 

That can be done  ^^

 

The onBlockPlacedBy() function (as the name implies) is a function that gets called everytime the block containing it gets placed in the World.

 

@Override
public void onBlockPlacedBy(World theWorld, int blockX, int blockY, int blockZ, EntityLiving thePlayer) {
System.out.println("The Block has been placed");        
}

 

If you copy this into your block everytime the block gets placed the sentence "The Block has been placed" would be printed out into your console window.

 

To get a grasp of how tile entities work i would recommend to you the tutorial that can be found in the forge wiki as well as having look in the thread i mentioned before.

 

A very important thing to understand is that single blocks in a minecraft world aren't objects, in the sense of single instance of a class, but references to the block-class itself. That is why we need metadata to determine qualities that belong to a subgroup of the blocks you get from that class, for example another texture. But as metadata is somewhat limited we often times must use tile entities as these actually are single instances of a class and thus can save all the data you could wish for, such as a random texture index. In order for that to work properly you also need to use so called NBTTags (again the mentioned thread as well as the wiki are quite helpful here).

 

Now as the onBlockPlacedBy() function gets a World-object (which is the active world) you can access your tile entities

by using:

 

YourTileEntity tile = (YourTileEntity)theWorld.getBlockTileEntity(blockX, blockY, blockZ);

 

So here is a example on what your function could look like:

 

	@Override
public void onBlockPlacedBy(World theWorld, int blockX, int blockY, int blockZ, EntityLiving thePlayer) {
	YourTileEntity tile = (YOurTileEntity)theWorld.getBlockTileEntity(blockX, blockY, blockZ);	
	Random randomIntGen = new Random(YourMaxValue); 
                int randomInt = randomIntGem.nextInt();
                tile.setRandomIndex(randomInt);
}

 

YourTileEntity should than be able to handle the number (get it, save it, send it to the client etc.)

 

I would think for now you should have something to do ^^

Link to comment
Share on other sites

Perfect, many thanks.  I feel like a door has been opened :)

 

You're very welcome, I'm glad that for once i was the one who could help someone on this forum instead of just being the one asking all the questions as i have been until now^^.

 

edit: Come to think about it, that formulation *might* appear a bit odd, i simply wanted to say that i'm glad that I was able to give something back.

Link to comment
Share on other sites

Ok, so I've explored further and I'm not entirely sure the tile entity is appropriate.  I should of explained a bit more of what I'm trying to do : 

 

The blocks I'm trying to give random textures to are the ones that make up the world already, not a block I'm adding to the world.  For example I would like to have multiple texture indexes ( randomised ) for the top face of the grass block.  'onBlockPlacedBy' only seems to be called when actually putting a new block into the world, I need to modify blocks that already exist.  Due to the number of grass blocks I have the feeling that making them all tile entities will be an excessive cost.

Link to comment
Share on other sites

maybe in chunk generation process replace grass blocks with your own ones (and generate randomly meta)? i wouldn't try to overwrite base blocks on a code level - replacing base classes, it could only make your mod incompatible with other mods...

mnn.getNativeLang() != English

If I helped you please click on the "thank you" button.

Link to comment
Share on other sites

Something that just popped into my head that would also like to know - if my mod replaces vanilla block with a custom one ( via chunk generation for example ), what happens when the mod is unloaded? do any maps generated with the mod enabled no longer work correctly??

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.