Jump to content

Recommended Posts

Posted

Hello,

 

Could someone tell me the method to make multiblock structures (e.g. railcraft coke oven or liquid tanks).

Just want to know the basic idea behind these. And how I could make the whole thing render as one block and make it clickable as one block?

 

Would be nice if someone could link me to a source code example of any mod implementing this.

 

greets

  • 2 months later...
Posted

Just throwing a wild guess here but perhaps it's just a block which onUpdate() checks to see if it's a part of a structure(by checking the blocks around it). and if it is, then create a new TileEntityXXX and let all the parts of the struct setTileEntity to that.

 

OnBlockActiviated -> if this.TileEntity != null -> open GUI etc.

 

The railcraft mod warns you that you should NOT use the block as a part of regular construction due to the fact that it will slow down the server with all it's constant checks to see if is a whole coke oven.

 

I have no idea how it is actually done inn RC, but I guess it's something along those lines :)

  Quote

If you guys dont get it.. then well ya.. try harder...

Posted

a simple way to do it is in the block class

 

public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
{
    if(par1World.getBlockId(par2, par3, par4) == YourMod.YourBlock.blockID && par1World.getBlockId(par2, par3, par4 + 1) == YourMod.YourBlock.blockID)
    {
    	par1World.setBlock(par2, par3, par4, YourMod.YourMultiBlockPart.blockID);
    	par1World.setBlock(par2, par3, par4 + 1, YourMod.YourMultiBlockPart.blockID);
    	
    }
}

 

then

 

in your other block class put the open gui things in there or you could use the same one by doing this

 

first declare an integer that equals 0 then

public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
{
    if(par1World.getBlockId(par2, par3, par4) == YourMod.YourBlock.blockID && par1World.getBlockId(par2, par3, par4 + 1) == YourMod.YourBlock.blockID)
    {

      multiblock = 1;
    	
    }

    else
    {
       multiblock = 0;
    }
}

 

then in your on block activated class add this

 

@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int i, float f, float g, float t){
TileEntity tile_entity = world.getBlockTileEntity(x, y, z);
if(tile_entity == null || player.isSneaking() || this.multiblock == 0){
return false;
}

if(this.multiblock == 1)
{
player.openGui(yourMod.instance, 0, world, x, y, z);

return true;
}
}

Posted

I can tell you how I'm doing this in my upcoming stargates mod. The basic idea is that the onBlockAdded method of the component block searches the area around it looking for a particular pattern of blocks. When that pattern is found, the component blocks are flagged as having been merged into a structure. Also, one of the component blocks is picked to be the "master" block having a TileEntity holding the state of the structure as a whole. When any of the component blocks is right-clicked, the click is forwarded to the master block, which opens the GUI.

 

Unmerging is handled by the breakBlock method of the component blocks, which clears the merge flag on all the other merged blocks of the structure.

 

As for rendering the merged structure, I'm doing that using a TileEntitySpecialRenderer on the master block, and the normal block renderers of the component blocks don't render anything when they're merged. But you could also have the component blocks render themselves in two different ways for the merged and unmerged states, or replace the component blocks with different block types when they merge.

 

From what was said about Railcraft above, it sounds like it's using a somewhat inefficient method to detect merging. It shouldn't be necessary to continually check for merging, only when a potential component block is placed or removed, or possibly when a neighbour of such a block changes state.

Posted
  On 2/1/2013 at 8:46 AM, gcewing said:

I can tell you how I'm doing this in my upcoming stargates mod. The basic idea is that the onBlockAdded method of the component block searches the area around it looking for a particular pattern of blocks. When that pattern is found, the component blocks are flagged as having been merged into a structure. Also, one of the component blocks is picked to be the "master" block having a TileEntity holding the state of the structure as a whole. When any of the component blocks is right-clicked, the click is forwarded to the master block, which opens the GUI.

 

Unmerging is handled by the breakBlock method of the component blocks, which clears the merge flag on all the other merged blocks of the structure.

 

As for rendering the merged structure, I'm doing that using a TileEntitySpecialRenderer on the master block, and the normal block renderers of the component blocks don't render anything when they're merged. But you could also have the component blocks render themselves in two different ways for the merged and unmerged states, or replace the component blocks with different block types when they merge.

 

From what was said about Railcraft above, it sounds like it's using a somewhat inefficient method to detect merging. It shouldn't be necessary to continually check for merging, only when a potential component block is placed or removed, or possibly when a neighbour of such a block changes state.

 

Could you maybe explain a little more how your mod checks for the pattern? I want to make my mod recognize an entire house and give it a health and it sounds like your approach might be able to help me with that.

Posted
  On 2/1/2013 at 8:46 AM, gcewing said:

I can tell you how I'm doing this in my upcoming stargates mod. The basic idea is that the onBlockAdded method of the component block searches the area around it looking for a particular pattern of blocks. When that pattern is found, the component blocks are flagged as having been merged into a structure. Also, one of the component blocks is picked to be the "master" block having a TileEntity holding the state of the structure as a whole. When any of the component blocks is right-clicked, the click is forwarded to the master block, which opens the GUI.

 

Unmerging is handled by the breakBlock method of the component blocks, which clears the merge flag on all the other merged blocks of the structure.

 

As for rendering the merged structure, I'm doing that using a TileEntitySpecialRenderer on the master block, and the normal block renderers of the component blocks don't render anything when they're merged. But you could also have the component blocks render themselves in two different ways for the merged and unmerged states, or replace the component blocks with different block types when they merge.

 

From what was said about Railcraft above, it sounds like it's using a somewhat inefficient method to detect merging. It shouldn't be necessary to continually check for merging, only when a potential component block is placed or removed, or possibly when a neighbour of such a block changes state.

 

If you could show us exactly what you did, that would be great.

Posted

Here's some of the code I've been working with

 

	@Override
public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) {
	if (isValidCombination(par2, par3, par4, par1World)) {
		if (par1World.getBlockTileEntity(par2, par3, par4) != null) {
			System.out.println("This is the master block");
			TileEntityFurnace tile = (TileEntityFurnace) par1World.getBlockTileEntity(par2, par3, par4);
			par5EntityPlayer.displayGUIFurnace(tile);
			return true;
		}
	}

	return false;
}

 

public void onBlockAdded(World world, int x, int y, int z) {
	if (isValidCombination(x, y, z, world)) {
		super.onBlockAdded(world, x, y, z);
		System.out.println("this is a valid combination");
	}
}

 

For some reason, this code creates three seperate TileEntities when the last block is placed. Can anyone see why this is occuring?

Posted
  On 2/3/2013 at 12:59 AM, insane_gravy said:

Here's some of the code I've been working with

 

	@Override
public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) {
	if (isValidCombination(par2, par3, par4, par1World)) {
		if (par1World.getBlockTileEntity(par2, par3, par4) != null) {
			System.out.println("This is the master block");
			TileEntityFurnace tile = (TileEntityFurnace) par1World.getBlockTileEntity(par2, par3, par4);
			par5EntityPlayer.displayGUIFurnace(tile);
			return true;
		}
	}

	return false;
}

 

public void onBlockAdded(World world, int x, int y, int z) {
	if (isValidCombination(x, y, z, world)) {
		super.onBlockAdded(world, x, y, z);
		System.out.println("this is a valid combination");
	}
}

 

For some reason, this code creates three seperate TileEntities when the last block is placed. Can anyone see why this is occuring?

 

how are you detecting if it's valid?

Posted

This is the code that checks for valid combinations

 

private boolean isValidCombination(int x, int y, int z, World world) {
	if (getNextX(x, y, z, world) && getNextZ(x, y, z, world)) {
		return getTopRightDiag(x, y, z, world);
	}

	if (getNextX(x, y, z, world) && getPrevZ(x, y, z, world)) {
		return getTopLeftDiag(x, y, z, world);
	}

	if (getPrevX(x, y, z, world) && getNextZ(x, y, z, world)) {
		return getBottomRightDiag(x, y, z, world);
	}

	if (getPrevX(x, y, z, world) && getPrevZ(x, y, z, world)) {
		return getBottomLeftDiag(x, y, z, world);
	}

	return false;
}

 

private boolean getNextX(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getPrevX(int x, int y, int z, World world) {
	return world.getBlockId(x - 1, y, z) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getNextZ(int x, int y, int z, World world) {
	return world.getBlockId(x, y, z + 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getPrevZ(int x, int y, int z, World world) {
	return world.getBlockId(x, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getTopLeftDiag(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getTopRightDiag(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z + 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getBottomLeftDiag(int x, int y, int z, World world) {
	return world.getBlockId(x - 1, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getBottomRightDiag(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z + 1) == modHerbcraft.BlockOvenBrick.blockID;
}

 

It's just a boolean check.

Posted

change

private boolean getBottomRightDiag(int x, int y, int z, World world) {
        	  return world.getBlockId(x + 1, y, z + 1) == CodeLyoko.SuperCalc.blockID;
        	 }

to

private boolean getBottomRightDiag(int x, int y, int z, World world) {
        	  return world.getBlockId(x - 1, y, z + 1) == CodeLyoko.SuperCalc.blockID;
        	 }

but I'm not sure about why it makes 4 different tile entities.

 

EDIT: I figured out why. when you right click each of the blocks to open it, it checks if they're valid and then makes them they're own tile entity.

Posted

Interesting. The TileEntity should only be called once, and that's when the last block is placed.

 

I added a println statement at several points, and it's clear from console feedback that the method calls occur for all blocks when a new one is placed in close proximity to existing ones. The method calls should only happen once. What do I need to change to stop this from happening?

Posted

I figured out why!!! In the onActivated method, it checks of it's valid and if so opens the gui. You need to set a variable when the block is placed and is valid and check the variable in the onActivated method

Posted

I previously had a boolean field which would be set to "true" if the block being placed was the master block (ie: it would only be true if it was the last block in the combination). The same problem was still present even with this field present. Additionally, the GUI can only open if a TileEntity exists at the location, so it's creating TileEntities multiple times for some reason.

 

Try this version of the boolean check. It has more console statements and should show the method calls occuring more than once.

 

private boolean isValidCombination(int x, int y, int z, World world) {
	System.out.println("checking for valid combinations");
	if (getNextX(x, y, z, world) && getNextZ(x, y, z, world)) {
		return getTopRightDiag(x, y, z, world);
	}

	if (getNextX(x, y, z, world) && getPrevZ(x, y, z, world)) {
		return getTopLeftDiag(x, y, z, world);
	}

	if (getPrevX(x, y, z, world) && getNextZ(x, y, z, world)) {
		return getBottomRightDiag(x, y, z, world);
	}

	if (getPrevX(x, y, z, world) && getPrevZ(x, y, z, world)) {
		return getBottomLeftDiag(x, y, z, world);
	}

	System.out.println("no combinations found");
	return false;
}

private boolean getNextX(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getPrevX(int x, int y, int z, World world) {
	return world.getBlockId(x - 1, y, z) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getNextZ(int x, int y, int z, World world) {
	return world.getBlockId(x, y, z + 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getPrevZ(int x, int y, int z, World world) {
	return world.getBlockId(x, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getTopLeftDiag(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getTopRightDiag(int x, int y, int z, World world) {
	return world.getBlockId(x + 1, y, z + 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getBottomLeftDiag(int x, int y, int z, World world) {
	return world.getBlockId(x - 1, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

private boolean getBottomRightDiag(int x, int y, int z, World world) {
	return world.getBlockId(x - 1, y, z - 1) == modHerbcraft.BlockOvenBrick.blockID;
}

Posted

How is it creating a TileEntity by default? It should only create a TileEntity if a block is added and it detects a valid combination. I tried removing removing references to the superclass, but that doesn't fix it.

  • 2 weeks later...

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hi everyone, I'm currently developing a Forge 1.21 mod for Minecraft and I want to display a custom HUD overlay for a minigame. My goal: When the game starts, all players should see an item/block icon (from the base game, not a custom texture) plus its name/text in the HUD – similar to how the bossbar overlay works. The HUD should appear centered above the hotbar (or at a similar prominent spot), and update dynamically (icon and name change as the target item changes). What I've tried: I looked at many online tutorials and several GitHub repos (e.g. SeasonHUD, MiniHUD), but most of them use NeoForge or Forge versions <1.20 that provide the IGuiOverlay API (e.g. implements IGuiOverlay, RegisterGuiOverlaysEvent). In Forge 1.21, it seems that neither IGuiOverlay nor RegisterGuiOverlaysEvent exist anymore – at least, I can't import them and they are missing from the docs and code completion. I tried using RenderLevelStageEvent as a workaround but it is probably not intended for custom HUDs. I am not using NeoForge, and switching the project to NeoForge is currently not an option for me. I tried to look at the original minecraft source code to see how elements like hearts, hotbar etc are drawn on the screen but I am too new to Minecraft modding to understand. What I'm looking for: What is the correct way to add a custom HUD element (icon + text) in Forge 1.21, given that the previous overlay API is missing? Is there a new recommended event, callback, or method in Forge 1.21 for custom HUD overlays, or is everyone just using a workaround? Is there a minimal open-source example repo for Forge 1.21 that demonstrates a working HUD overlay without relying on NeoForge or deprecated Forge APIs? My ideal solution: Centered HUD element with an in-game item/block icon (from the base game's assets, e.g. a diamond or any ItemStack / Item) and its name as text, with a transparent background rectangle. It should be visible to the players when the mini game is running. Easy to update the item (e.g. static variable or other method), so it can change dynamically during the game. Any help, code snippets, or up-to-date references would be really appreciated! If this is simply not possible right now in Forge 1.21, it would also help to know that for sure. Thank you very much in advance!
    • The simple answer is there is not an easy way. You would need to know how to program in Java, as well as at least some familiarity with how Forge works so you could port the differences. You would also need the sourcecode for the original mod, and permission from the author to modify it, if they did not use some sort of open source license. So it's not impossible, but it would take some effort, but doing so would open up a whole new world of possibilities for you!
    • Does it still crash if you remove holdmyitems? Looks like that mod doesn't work on a server as far as I can tell from the error.  
    • Crashes the server when trying to start. Error code -1. Log  
  • Topics

  • Who's Online (See full list)

    • There are no registered users currently online
×
×
  • Create New...

Important Information

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