@longor1996
Danke! Das ist es, was ich gesucht habe. Das einzige was noch nicht passt ist, dass ich die Blöcke gerne relativ zum Ursprungsblock speichern würde, aber das bekomme ich auch selbst hin.
Jetzt verstehe ich es, glaub ich.
Du willst einen "Filler" Algoryhtmus habe!
Ein Algoryhtmus der einfach alle Blöcke rekursiv zu einer Liste (oder HashMap) hinzufügt.
Das währe sowas wie: (Pseudo-Code!)
Das ist jetzt nur ein Pseodo-Code Algoryhtmus, bitte nicht direkt so verwenden!Code:public ArrayList<TempBlock> doRecursiveSearch_(World world,int x,int y,int z) { ArrayList<TempBlock> list = ...; list.add(new TempBlock(world.getBlockID(x,y,z),x,y,z)); doRecursiveSearch(list,world,x,y,z); return list; } public void doRecursiveSearch(ArrayList<TempBlock> list,World world,int x,int y,int z) { //Für jeden Block muss übrigends noch geprüft werden, ob er nicht Luft ist, und er noch nicht in der Liste steht! list.addIfNotExist(new TempBlock(world.getBlockID(x+1,y,z),x+1,y,z)); list.addIfNotExist(new TempBlock(world.getBlockID(x-1,y,z),x-1,y,z)); list.addIfNotExist(new TempBlock(world.getBlockID(x,y+1,z),x,y+1,z)); list.addIfNotExist(new TempBlock(world.getBlockID(x,y-1,z),x,y-1,z)); list.addIfNotExist(new TempBlock(world.getBlockID(x,y,z+1),x,y,z+1)); list.addIfNotExist(new TempBlock(world.getBlockID(x,y,z-1),x,y,z-1)); //Führe die Suche bei den hinzugefügten Blöcken fort, hier sollte noch irgendein Distanz Check hin der verhindert, //das die gesamte Map Rekursiv durchsucht wird. doRecursiveSearch(list,world,x+1,y,z); doRecursiveSearch(list,world,x-1,y,z); doRecursiveSearch(list,world,x,y+1,z); doRecursiveSearch(list,world,x,y-1,z); doRecursiveSearch(list,world,x,y,z+1); doRecursiveSearch(list,world,x,y,z-1); }
Danach müssen die Blöcke in der Liste noch irgendwie in eine Datei gespeichert werden.
mfg Longor1996
AdventureCraft2 Entwickler! Ich gebe gerne (Modding/Tech-)Support über PN.
Me on Youtube
Gnoccy mag diesen Beitrag
@longor1996
Danke! Das ist es, was ich gesucht habe. Das einzige was noch nicht passt ist, dass ich die Blöcke gerne relativ zum Ursprungsblock speichern würde, aber das bekomme ich auch selbst hin.
Bitte!
Ich denke mal der Thread kann dann geschlossen werden. Oder?
mfg Longor1996
AdventureCraft2 Entwickler! Ich gebe gerne (Modding/Tech-)Support über PN.
Me on Youtube
Moment, eine Frage hätte ich da noch.
Und zwar muss ja bei jedem gefundenem Block nachgeschaut werden, ob er nicht schon in der Liste ist. Dafür muss die komplette Liste durchsucht werden. Meine Frage wäre nun, wie sich das auf die Performance auswirkt, wenn es dabei um ein mehrere tausend Blöcke großes Gebilde geht. Ist das auf einem normalen Rechner überhaupt noch in einer akzeptablen Zeit durchfürbar?
Und @longor1996 noch ne Frage, der Filler Algoryhtmus von dem du gesprochen hast ist der Floodfill Algoryhtmus, oder?
Geändert von Gnoccy (18.08.2012 um 18:47 Uhr)
Ja, das ist ein Floodfill Algoryhtmus.
Und das mit dem durchschauen der Liste...
keine Ahnung wie man das Lösen soll.
Auswirken würde sich das garantiert.
Eine Idee:
Du kannst die Liste immer nachdem so 10 - 20 Blöcke hinzugefügt worden sind sortieren.
Das Sortieren einfach über ein "TempBlock implements Comparable<TempBlock>",
die darauf resultierende Methode und die "Collections.sort(list)" Funktion machen.
In der Comparable Methode dann am besten die X,Y,Z Koodinaten die am nächsten zum Zentrum sind nach hinten in die Liste schieben.
Andere Idee:
Einfach die Liste rückwärts durchsuchen!
Da die ersten Elemente am anfang stehen, stehen die die du kontrollieren willst ganz am Ende.
Am Ende wird die Liste sowieso so sein, das die Blöcke "Spiralenförmig" um deinen Kern Block herum liegen.
Den Algoryhtmus habe ich schonmal getestet. Das geht eigentlich recht schnell.
Man köntne auch noch eine Liste Pro Chunk machen...
aber das ist dann wirklich ein bisschen zu viel Aufwand für ein bisschen Performance.
mfg Longor1996
PS: Ich bin gerade dabei ein eigenes Zip Format ähnliches Speicherformat zu erstellen,
folge: Ich geb mehr Konzentration fürs Programmieren her und der Text hier beinhaltet dadurch Fehler.
AdventureCraft2 Entwickler! Ich gebe gerne (Modding/Tech-)Support über PN.
Me on Youtube
Ok, hab mich mal dran gesetzt und schnell mal was zum testen hingeklatscht. So sieht das ganze bisher aus:
Code:protected ArrayList flood(World pWorld, int x, int y, int z, ArrayList list){ if(!(pWorld.getBlockId(x, y, z) == 0) && !doesBlockAlreadyExist(list, x, y, z)){ list.add(new SBlock(x, y, z, pWorld.getBlockId(x, y, z))); System.out.println(x + y + z); list = appendArrayListToArrayList(list, flood(pWorld, x + 1, y, z, list)); list = appendArrayListToArrayList(list, flood(pWorld, x - 1, y, z, list)); list = appendArrayListToArrayList(list, flood(pWorld, x , y + 1, z, list)); list = appendArrayListToArrayList(list, flood(pWorld, x , y - 1, z, list)); list = appendArrayListToArrayList(list, flood(pWorld, x , y, z + 1, list)); list = appendArrayListToArrayList(list, flood(pWorld, x , y, z - 1, list)); } return list; }Wenn ich das ganze nun ausführe, verabschiedet sich Miencraft mit der Meldung, es stehe nicht genug Speicher zur Verfügung. Das passiert aber schon nach etwa 10 durchläufen. Außerdem scheinen auch Blöcke, die schon in der ArrayList sind nochmal erkannt zu werden.Code:protected boolean doesBlockAlreadyExist(ArrayList list, int x, int y, int z){ Object[] s = list.toArray(); for(int i = 0; i < s.length; i++){ if (((SBlock) s[i]).getX() == x && ((SBlock) s[i]).getY() == y && ((SBlock) s[i]).getZ() == z){ return true; } } return false; }
Ich vermute deshalb mal, dass der Fehler in der "doesBlockAlreadyExist" steckt, nur finde ich ihn nicht.
Wie gesagt, das ganze ist nur mal schnell zum testen so hingeklatscht und es gibt sicher noch ein paar Ecken, an denen man Feilen könnte. Trotzdem würde ich mich freuen, wenn einfach nochmal jemand drüber schaut. Eventuell übersehe ich einfach nur eine Kleinigkeit, die anderen sofort ins Auge springt, oder ich habe mich irgendwo völlig verrannt oder sowas.
Geändert von Gnoccy (19.08.2012 um 13:41 Uhr)
AdventureCraft2 Entwickler! Ich gebe gerne (Modding/Tech-)Support über PN.
Me on Youtube
Ich glaube, du rufst die Methode zu oft auf...also die Methode ruft sich selber auf, und irgendwann gibt es ein "StackOverflowError" (ist der, den du meinst, oder?), weil zu viele Methoden hintereinander aufgerufen wurden.
Platziere einfach mal nur einen einzigen Block in der Luft, und teste das mit dem.
Mit freundlichen Grüßen
Johannes_C25
PS: Was ich rot gemacht habe, ist jetzt nicht sooo wichtig, daran sollte es eig. nicht liegen...
Ich habe es jetzt mal mit einem Block versucht. Dabei crasht Minecraft zumindest nicht. An anderer Stelle lasse ich mir aber die größe der ArrayList ausgeben. Das Ergebniss ist 4608. Bei zwei Blöcken kommt 295936 raus. Deshalb vermute ich immer noch, dass es an der doesBlockAlreadyExist Methode liegt.
Und hier nochmal der komplette Code:
Meinst du damit, aus welcher Datei ich den Code rauskopiert habe? Das ganze befindet sich in einem TileEntity eines Blockes.
Geändert von Gnoccy (19.08.2012 um 14:08 Uhr)
@Gnoccy
Probier es mal so:
Code:protected ArrayList flood(World pWorld, int x, int y, int z, ArrayList list){ if(pWorld.getBlockId(x, y, z) != 0 && !doesBlockAlreadyExist(list, x, y, z)){ list.add(new SBlock(x, y, z, pWorld.getBlockId(x, y, z))); System.out.println(x + y + z); flood(pWorld, x + 1, y, z, list); flood(pWorld, x - 1, y, z, list); flood(pWorld, x , y + 1, z, list); flood(pWorld, x , y - 1, z, list); flood(pWorld, x , y, z + 1, list); flood(pWorld, x , y, z - 1, list); } return list; }