Jump to content

Recommended Posts

Posted

I try to make Blocks that are flying in the air (when something explode under the Blocks) falling on the ground. I have a List with Blocks that "have to fall", but how can I make Blocks falling?

Posted

Possibly the parent class, BlockFalling.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Hmm:

public class BlockFalling extends Block
{
    public static boolean fallInstantly;

    public BlockFalling()
    {
        super(Material.sand);
        this.setCreativeTab(CreativeTabs.tabBlock);
    }

    public BlockFalling(Material materialIn)
    {
        super(materialIn);
    }

    public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
    {
        worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
    }

    /**
     * Called when a neighboring block changes.
     */
    public void onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock)
    {
        worldIn.scheduleUpdate(pos, this, this.tickRate(worldIn));
    }

    public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
    {
        if (!worldIn.isRemote)
        {
            this.checkFallable(worldIn, pos);
        }
    }

    private void checkFallable(World worldIn, BlockPos pos)
    {
        if (canFallInto(worldIn, pos.down()) && pos.getY() >= 0)
        {
            int i = 32;

            if (!fallInstantly && worldIn.isAreaLoaded(pos.add(-i, -i, -i), pos.add(i, i, i)))
            {
                if (!worldIn.isRemote)
                {
                    EntityFallingBlock entityfallingblock = new EntityFallingBlock(worldIn, (double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, worldIn.getBlockState(pos));
                    this.onStartFalling(entityfallingblock);
                    worldIn.spawnEntityInWorld(entityfallingblock);
                }
            }
            else
            {
                worldIn.setBlockToAir(pos);
                BlockPos blockpos;

                for (blockpos = pos.down(); canFallInto(worldIn, blockpos) && blockpos.getY() > 0; blockpos = blockpos.down())
                {
                    ;
                }

                if (blockpos.getY() > 0)
                {
                    worldIn.setBlockState(blockpos.up(), this.getDefaultState());
                }
            }
        }
    }

    protected void onStartFalling(EntityFallingBlock fallingEntity)
    {
    }

    /**
     * How many world ticks before ticking
     */
    public int tickRate(World worldIn)
    {
        return 2;
    }

    public static boolean canFallInto(World worldIn, BlockPos pos)
    {
        if (worldIn.isAirBlock(pos)) return true;
        Block block = worldIn.getBlockState(pos).getBlock();
        Material material = block.blockMaterial;
        return block == Blocks.fire || material == Material.air || material == Material.water || material == Material.lava;
    }

    public void onEndFalling(World worldIn, BlockPos pos)
    {
    }
}

But how can I make any Block (not Air) with this to a Falling Block?

Posted

Ok I see there is a Constructor with Material. I made a new Object BlockFalling for every block in the List but how can I make the blockfalling fall?

Posted

Oh for fuck's sake.

 

EntityFallingBlock entityfallingblock = new EntityFallingBlock(worldIn, (double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, worldIn.getBlockState(pos));

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Ok I dont get any futher. What I want:

When something explodes, I want to get all Blocks over the explosion, then I want that all this blocks falling down but I dont know why it isnt working:

@SubscribeEvent
public void onExplode(ExplosionEvent e) {
	HashMap<Block,BlockPos> fallingBlocks = getBlocksToFall(e);
	System.out.println(fallingBlocks.keySet().size() + "");
	for (Block b : fallingBlocks.keySet()) {
		BlockPos blockPos = fallingBlocks.get(b);
		EntityFallingBlock entityFallingBlock = new EntityFallingBlock(e.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), e.world.getBlockState(blockPos));
		entityFallingBlock.shouldDropItem = false;
		e.world.spawnEntityInWorld(entityFallingBlock);
	}
}

private HashMap<Block,BlockPos> getBlocksToFall(ExplosionEvent e){
	List<Integer> xs = new ArrayList<Integer>();
	List<Integer> zs = new ArrayList<Integer>();
	int exY = (int) Math.round(e.explosion.getPosition().yCoord);
	for(BlockPos loc : e.explosion.getAffectedBlockPositions()){
		int x = loc.getX();
		if(!xs.contains(x)){
			xs.add(x);
		}
		int z = loc.getZ();
		if(!zs.contains(z)){
			zs.add(z);
		}
	}
	HashMap<Block,BlockPos> blocksToFall = new HashMap<Block,BlockPos>();
	for(int y = exY; y <= e.world.getHeight(); y++){
		for(int x : xs){
			for(int z : zs){
				BlockPos pos = new BlockPos(x, y, z);
				Block b = e.world.getBlockState(pos).getBlock();
				if(!b.getRegistryName().contains("air")){
					blocksToFall.put(b,pos);
				}
			}
		}
	}
	return blocksToFall;
}

Posted

Firstly, "isn't working" isn't very helpful.  I'll assume you mean that it just doesn't spawn a falling block rather than it fails with an exception etc.

 

The explosion event is fired before any blocks are actually destroyed, so if you want to spawn a falling block, it's up to you to set the block being replaced with air.  Also, if there's a block underneath, you might want to add a small amount to the falling block's Y co-ord so it isn't considered on the ground (or it will immediately turn back into a real block).  You may also want to give newly spawned falling blocks an initial velocity (based on their position and proximity to the explosion centre) so they fly outwards.

 

Also, a map of Block->BlockPos makes no sense at all.  Block is a singleton class; you'll just end up with one element for each type of block affected.  And I don't follow what your getBlocksToFall() method is doing - why not just iterate over event.getAffectedBlockPositions() directly?

 

Update: OK, I understand what you need better now.  I'd suggest just converting the list of affected locations to a Set<Pair<Integer,Integer>>, where the two ints are the X & Z positions of the affected blocks.  Then for each element, you can iterate upward to world height and convert blocks to falling blocks.  If you work upwards, you shouldn't need to worry about the block underneath being solid.

 

(Also, be sure to test what happens with tile entity blocks, with or without held items).

Posted

Cool.  You'll also want to consider what happens if someone sets off multiple explosions down at bedrock level (the amount of scanning for blocks and more so the number of entities being rapidly created will make your server cry).

Posted

Yeah. Not my probleme^^ hm I calculate something: a explosion has a radius of 3 i think you place 5 tnts that is a length of 30 blocks. The world has a 64 height that are 30x6x64 blocks = 11.500 nooooo this will not lagging xD. Yeah but how can I do that?

Posted

TNT radius is 6.9, according to the official Wiki.  Now consider a couple of hundred TNT under some amplified biome, or mesa, or extreme hills... that could easily be millions of blocks.  (And it will be your problem if & when your publicly released mod gets fingered as a server killer  :) )

 

Mitigation might be not to create falling blocks immediately, but add them to a queue of limited (tunable) size.  Then pull a certain (tunable) number from the queue every tick, validate that the block hasn't already changed in the intervening ticks since they were added, and then create the falling block.  And if the queue is full, just don't add them.  A queue of Pair<BlockPos,IBlockState> should work here (remembering that IBlockState object can be validly and cheaply compared with ==).

Posted
@SubscribeEvent
public void onExplode(ExplosionEvent e) {
	HashMap<Block,BlockPos> fallingBlocks = getBlocksToFall(e);
	System.out.println(fallingBlocks.keySet().size() + "");
	for (Block b : fallingBlocks.keySet()) {
		BlockPos blockPos = fallingBlocks.get(b);
		EntityFallingBlock entityFallingBlock = new EntityFallingBlock(e.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), e.world.getBlockState(blockPos));
		entityFallingBlock.shouldDropItem = false;
		e.world.spawnEntityInWorld(entityFallingBlock);
	}
}

private HashMap<Block,BlockPos> getBlocksToFall(ExplosionEvent e){
	List<Integer> xs = new ArrayList<Integer>();
	List<Integer> zs = new ArrayList<Integer>();
	int exY = (int) Math.round(e.explosion.getPosition().yCoord);
	for(BlockPos loc : e.explosion.getAffectedBlockPositions()){
		int x = loc.getX();
		if(!xs.contains(x)){
			xs.add(x);
		}
		int z = loc.getZ();
		if(!zs.contains(z)){
			zs.add(z);
		}
	}
	HashMap<Block,BlockPos> blocksToFall = new HashMap<Block,BlockPos>();
	for(int y = exY; y <= e.world.getHeight(); y++){
		for(int x : xs){
			for(int z : zs){
				BlockPos pos = new BlockPos(x, y, z);
				Block b = e.world.getBlockState(pos).getBlock();
				if(!b.getRegistryName().contains("air")){
					blocksToFall.put(b,pos);
				}
			}
		}
	}
	return blocksToFall;
}

Posted

@SubscribeEvent
public void onExplode(ExplosionEvent e) {
	HashMap<Block,BlockPos> fallingBlocks = getBlocksToFall(e);
	System.out.println(fallingBlocks.keySet().size() + "");
	for (Block b : fallingBlocks.keySet()) {
		BlockPos blockPos = fallingBlocks.get(b);
		EntityFallingBlock entityFallingBlock = new EntityFallingBlock(e.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), e.world.getBlockState(blockPos));
		entityFallingBlock.shouldDropItem = false;
		e.world.spawnEntityInWorld(entityFallingBlock);
	}
}

private HashMap<Block,BlockPos> getBlocksToFall(ExplosionEvent e){
	List<Integer> xs = new ArrayList<Integer>();
	List<Integer> zs = new ArrayList<Integer>();
	int exY = (int) Math.round(e.explosion.getPosition().yCoord);
	for(BlockPos loc : e.explosion.getAffectedBlockPositions()){
		int x = loc.getX();
		if(!xs.contains(x)){
			xs.add(x);
		}
		int z = loc.getZ();
		if(!zs.contains(z)){
			zs.add(z);
		}
	}
	HashMap<Block,BlockPos> blocksToFall = new HashMap<Block,BlockPos>();
	for(int y = exY; y <= e.world.getHeight(); y++){
		for(int x : xs){
			for(int z : zs){
				BlockPos pos = new BlockPos(x, y, z);
				Block b = e.world.getBlockState(pos).getBlock();
				if(!b.getRegistryName().contains("air")){
					blocksToFall.put(b,pos);
				}
			}
		}
	}
	return blocksToFall;
}

You have not followed any of desht's advice, and you should be using the sub event of ExplosionEvent.Start

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

You also can't map Block -> BlockPos.  There are more BlockPos locations than there are Blocks, and the nature of a Hashmap is specifically One-to-One.  Your code right now will create exactly 1 falling block for an explosion taking place inside pure stone.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

You also can't map Block -> BlockPos.  There are more BlockPos locations than there are Blocks, and the nature of a Hashmap is specifically One-to-One.  Your code right now will create exactly 1 falling block for an explosion taking place inside pure stone.

Yep.  Hence why I suggested a Set<Pair<Integer,Integer>> as the appropriate data structure here; a unique set of (x,z) positions from which columns can be traced vertically upwards.  OP needs to be paying attention :)

Posted

You also can't map Block -> BlockPos.  There are more BlockPos locations than there are Blocks, and the nature of a Hashmap is specifically One-to-One.  Your code right now will create exactly 1 falling block for an explosion taking place inside pure stone.

Yep.  Hence why I suggested a Set<Pair<Integer,Integer>> as the appropriate data structure here; a unique set of (x,z) positions from which columns can be traced vertically upwards.  OP needs to be paying attention :)

That wont work because theny position is not identifable.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

Yep.  Hence why I suggested a Set<Pair<Integer,Integer>> as the appropriate data structure here; a unique set of (x,z) positions from which columns can be traced vertically upwards.  OP needs to be paying attention :)

That wont work because theny position is not identifable.

Explain please?  Seems totally workable to me.

Posted

I mean really, what's wrong with List<BlockPos>?

 

Also this:

if(!b.getRegistryName().contains("air")){

Block#isAirBlock() much?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Use your debugger and find out.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Yep.  Hence why I suggested a Set<Pair<Integer,Integer>> as the appropriate data structure here; a unique set of (x,z) positions from which columns can be traced vertically upwards.  OP needs to be paying attention :)

That wont work because theny position is not identifable.

Explain please?  Seems totally workable to me.

Two things multiple blocks on the same x and z coord, and second how would I even find the correct y coord. Would it be at the highest possible y position there is a block or would it be at the first block with air above them.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

Two things multiple blocks on the same x and z coord, and second how would I even find the correct y coord. Would it be at the highest possible y position there is a block or would it be at the first block with air above them.

Hence using a Set<Pair> - just store one instance of each (X,Z) pair.  But you're right - you'd need to store a Y-value as well; so perhaps a Map<Pair<Integer,Integer>, Integer> would be better, where the key is (X,Z) and the value is Y.  As for which Y-value, that's up to the mod developer; the smallest Y would be a reasonable choice.

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.