Jump to content

[SOLVED] [1.7.10] Get all blocks touching each other


WARDOGSK93

Recommended Posts

ive being trying to do this for about an hour now and i just cant seem to find a way of doing it with out gettting java.lang.StackOverFlowError

all i want is a method to call and pass in a location (a tile entity or x,y,z) and get blocks touching the block at that location (this will include blocks touching blocks that are touching the center block and so on)

 

my TileEntity class

https://gist.github.com/WARDOGSK93/bc426050761844031acd#file-testtile-java

 

Console log (sorry about its length)

https://gist.github.com/WARDOGSK93/bc426050761844031acd#file-console-log

 

any source code that you want can be found here (War-Utility is just a core mod for my mods its War-Craft that has this code / problem in)

https://github.com/WARDOGSK93

Link to comment
Share on other sites

First of all... Bump after 25 minutes? Seriously? Consider this a warning.

 

What is that code in getBlock even... I am not even going to try and parse that deeply nested if-else stuff.

And what on earth is getConnectedSides supposed to do?

yeah sorry about the quick bump but im in a rush and getConnectedSides is meant to return all the a ForgeDirection[] of sides but not the side that it was called on (if it said getConnectedSides(ForgeDirection.NORTH) it would return all but NORTH) and getBlocks atm is just meant to return the amount of blocks found (the amount of blocks touching each other)

Link to comment
Share on other sites

It doesn't matter if you are in a rush. If you are in a rush, don't make a mod. Programming takes time.

 

I would go about this completely different.

Make a getAmount(ForgeDirection) method in your TE. This should check all sides but the one passed in and see if there is any TE connected. If there is, add one to a counter and also add the result of calling getAmount on that TE.

That will sum up all connected TEs and your getAmound method will be one single for loop.

the strangest thing is this is exactly what i was trying to do but i kept getting the exception java.lang.StackOverFlowError and i just seem to find away to do it with one for loop

 

so anyways you are saying do something like this

https://gist.github.com/WARDOGSK93/79d07b3f89f75b708417

 

but i have tried this and upon block right click (i have upon right click print out the amount) i get java.lang.StackOverFlowError

Link to comment
Share on other sites

Well, you have a logic error in that code.

Imagine this (prepare for epic paint skills):

fb7bCw1.jpg

 

Black is the TE that is checking and calling getAmount on the red TE (in the direction of the black arrow). The red TE now has to check all blue sides, but not the yellow one (that one would go backwards and cause an infinite loop). But this yellow one is the opposite of the black one, not the black one itself ;)

 

so instead of

 

if(side == null || side == from)

continue;

 

i should do this

 

if(side == null || side == from.getOpposite())

continue;

 

anyways im gonna try this out in game

 

and where can i get paint skills like that xD

Link to comment
Share on other sites

I did something like this once, my solution was to use an arraylist and check with contains if the block is already included in my list, if not add it and check its neighbors.. this can get quite expensive really fast, so its only good if you are checking small amounts of blocks..

Link to comment
Share on other sites

No, that part is correct. The error is when recursively calling getAmount. You need to pass the opposite of "side" there instead of "side" itself ("side" is the black arrow in my drawing).

this works perfectly fine until i create a circle / loop / square (for example it crashes if i make a 2x2x2 square) but other than that it works perfectly fine for

Link to comment
Share on other sites

Yeah, you have to keep a set of "already checked" (HashSet should be fine, do not use ArrayList as Failender said, it's contains method is slow!). Then pass that into each getAmount method and if the position is already in there, just return.

i know you are gonna say no to this but could you post some "reference" code or something cause im having a hard time with this :( i get so close but then a 2x2x2 destroys my dreams :(

Link to comment
Share on other sites

Dude, way too complicated.

 

Pseudocode:

int getBlocks() {
    Set<Coord> set = new HashSet();
    getBlocksRecursive(set, null);
    return set.size();
}

void getBlocksRecursive(Set<Coord> done, ForgeDirection from) {
    if (!done.add(this.position)) return;

    for (side : ForgeDirection.VALID) {
        if (side == from) continue;
        world.getTile(this.position.offset(side)).getBlocksRecursive(done, side.getOpposite());
    }
}

 

@Failender: Sometimes HashSet is faster, sometimes ArrayList is. It depends on your usecase.

ah thank fuck it now works but i have to say thats so simple yet i would never had thought of doing it like this

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.


×
×
  • Create New...

Important Information

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