• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

Spigot Liste aller Blöcke zwischen 2 Eckpunkten holen (Performance-Freundlich)

Richie932

Minecrafter
Registriert
28 August 2019
Beiträge
8
Diamanten
317
Hi,

ich versuche mich schon seit längerer Zeit an dem Problem eine Liste aller Blöcke zwischen 2 Eckpunkten (von Y = 0 - 255) zu bekommen.
Am Anfang funktionierte dies mit 3 For-Schleifen(X, Y, Z) auch top. Bei größeren Bereichen friert leider der Server für mehrere Sekunden ein.

Daraufhin habe ich versucht dies Asynchron zu machen. Das Ergebnis ist, dass das selbe jetzt 30 Sekunden - 4 Minuten und mehr (je nach Anzahl der Blöcke) dauert, Selbst kleinere Bereiche die vorher innerhalb von ein paar Millisekunden ging. Geht also leider auch nicht.

Meine letzte Idee wäre es noch, dies über Fawe zu machen. Da man mit Fawe ja schnell Blöcke zählen kann und dies Asynchron funktioniert,
Da habe ich leider nichts gefunden was mir eine Liste an Blöcken gibt.

Kennt sich wer mit Fawe aus und kann mir helfen? Gibt es da eine Möglichkeit eine Liste der Blöcke zwischen 2 Eckpunkten zu bekommen?
Oder habt ihr einen Tipp wie ich es so ändern kann das der Server nicht mehr einfriert?

LG Richie
 

Chojo-chan

Teammaid
Social Media
Moderator
Administrator
Registriert
24 März 2013
Beiträge
293
Alter
5
Diamanten
645
Minecraft
Hadde
Was willst du denn machen? Das klingt für mich stark nach einem XY Problem.

Code Snippets wären praktisch, damit wir wissen, was du da fabrizierst.
Wofür brauchst du die Liste und was willst du mit den Blöcken machen?
 

Richie932

Minecrafter
Registriert
28 August 2019
Beiträge
8
Diamanten
317
@Hadde-chan hier kommt etwas code


Java:
for(Integer y = aY; y <= bY; y++) {
     for(Integer x = aX; x <= bX; x++) {
          for(Integer z = aZ; z <= bZ; z++) {
               Location locBlock = new Location(world, x, y, z);
               if(locBlock.getBlock().getType() != null &&
                    locBlock.getBlock().getType() != Material.AIR &&
                    locBlock.getBlock().getType() != Material.STONE) {
                   blockList.add(locBlock.getBlock());
             }
        }
   }
}

Luft und Stein sortier ich schon mal raus da das nur Speicher frisst und es die meist vorhandenen Blöcke sind

aY und bY = beide Y achsen;
X und Z genau so

Reicht der Code oder soll ich den Rest der Klasse einfügen? Der teil frisst die meiste Performance

am Ende muss ich bei einigen bestimmten Blöcken die Anzahl herausfinden und bei anderen Daten auslesen und bei Bienenkästen/Körben die Anzahl der Bienen bestimmen, ...

@Valaron danke für die Commands, sie sind mir bereits bekannt, daher dachte ich vielleicht gibts bei Fawe eine Api auf (Java-Ebene) wo ich für den oben genannten Zweck eine Liste mit Blöcken bekomme =)
 

SirYwell

PlotSquared Entwickler
Registriert
30 Juni 2017
Beiträge
540
Diamanten
488
Minecraft
SirYwell
Wenn du die WorldEdit API verwenden willst, kannst du dir ja mal den Code von dem //distr-Befehl anschauen. Das was da passiert, kannst du an sich einfach an deine Bedürfnisse anpassen. Weiteres zur WorldEdit-API findest du hier.

Wenn du es ohne WorldEdit machen willst und die Aufgabe nicht unbedingt in einem Tick abgearbeitet werden muss, kannst du sie auch auf mehrere Ticks verteilen. Damit sollten sich dann auch tausende Chunks innerhalb weniger Sekunden analysieren lassen, ohne dass es zu Lags kommt. Empfehlenswert ist hierbei, dass du möglichst chunkweise vorgehst.
 

Richie932

Minecrafter
Registriert
28 August 2019
Beiträge
8
Diamanten
317
@SirYwell benutze ich //distr mit einer Blockanzahl von x900, z900 und y0-255 Blöcken habe ich keine Probleme mit Fawe, aber sobald ich das über meinen Command mit 50 * 50 Blöcken ausführe kommt ein Error der sagt das der Server 10 Sekunden nicht reagiert

Java:
    try (EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(BukkitAdapter.adapt(locs.getLocationA().getWorld()), -1)) {
           CuboidRegion region2 = new CuboidRegion(BukkitAdapter.adapt(locs.getLocationA().getWorld()), new BlockVector3() {
               @Override
               public int getX() {
                   return locs.getLocationA().getBlockX();
               }

               @Override
               public int getY(){
                   return locs.getLocationA().getBlockY();
               }

               @Override
               public int getZ() {
                   return locs.getLocationA().getBlockZ();
               }
           }, new BlockVector3() {
               @Override
               public int getX() {
                   return locs.getLocationB().getBlockX();
               }

               @Override
               public int getY() {
                   return locs.getLocationB().getBlockY();
               }

               @Override
               public int getZ() {
                   return locs.getLocationB().getBlockZ();
               }
           });

           blockList = editSession.getBlockDistribution(region2, true);
        }

--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - git-Paper-135 (MC: 1.16.1) ---
The server has not responded for 10 seconds! Creating thread dump
------------------------------
Server thread dump (Look for plugins here before reporting to Paper!):
------------------------------
Current Thread: Server thread
PID: 30 | Suspended: false | Native: false | State: WAITING
Stack:
java.lang.Object.wait(Native Method)
java.util.concurrent.ForkJoinTask.externalAwaitDone(Unknown Source)
java.util.concurrent.ForkJoinTask.doJoin(Unknown Source)
java.util.concurrent.ForkJoinTask.quietlyJoin(Unknown Source)
com.boydti.fawe.beta.implementation.queue.ParallelQueueExtent.apply(ParallelQueueExtent.java:125)


versuche ich das Chunkweise mit verzögerung abzuarbeiten bekomme ich trotz +30 ticks tps unter 2

Java:
        int i = 0; int e = 0;
        List<ChunkSnapshot> chunks = new ArrayList<>();
        for (int posZ = z; posZ <= z2; posZ += 16) {
            for (int posX = x; posX <= x2; posX += 16) {
                int finalPosX = posX;
                int finalPosZ = posZ;
                Bukkit.getScheduler().runTaskLater(Main.getInstance(), new Runnable() {
                    @Override
                    public void run() {
                        if(locations.getLocationA().getWorld().getChunkAt(finalPosX, finalPosZ).isLoaded()) {
                            ChunkSnapshot snapshot = locations.getLocationA().getWorld().getChunkAt(finalPosX, finalPosZ).getChunkSnapshot();
                            for(int posX = 0; posX <= 15; posX++) {
                                for(int posY = 0; posY <= 255; posY++) {
                                    for(int posZ = 0; posZ <= 15; posZ++) {
                                        Material material = snapshot.getBlockType(posX, posY, posZ);
                                        if(material != null &&
                                                material != Material.AIR &&
                                                material != Material.STONE &&
                                                material != Material.COBBLESTONE) {
                                            blocks.put(material, new Location(locations.getLocationA().getWorld(), posX, posY, posZ));
                                        }
                                    }
                                }
                            }
                        } else {
                            Main.getAPI().console.sendError("Chunk by x=" + finalPosX + ", z=" + finalPosZ + "is not loaded!");
                        }
                    }
                }, i);
                e++;

                if(e > 5) {
                    e = 0;
                    i += 30;
                }
            }
        }

habe ich bei einem der zwei Codes einen Denkfehler?
 

JOO200

Braumeister
Registriert
18 Dezember 2016
Beiträge
442
Diamanten
228
BlockVector3 solltest du mit BlockVector3.at(...) Erstellen, alternativ bietet die Klasse BukkitAdapter Möglichkeiten, Bukkit Objekte zu WorldEdit Objekten zu konvertieren (und zurück).

Grundsätzlich sind 900*900*256 über 200 Millionen Blöcke. Das ist schlichtweg zu viel.
Und auch 640.000 Blöcke sind ganz schön viele.
 

Richie932

Minecrafter
Registriert
28 August 2019
Beiträge
8
Diamanten
317
Danke @JOO200
BlockVector3.at(...) kannte ich garnicht.
Ganz kleine Regionionen/Flächen(zb 15 chunks) laufen ohne Fawe auch ohne Abstürze, auf die TPS habe ich da noch nicht geschaut. :)

Zu den Größen:
  • 900 * 900 funktioniert komischer Weise mit dem Fawe-Command, wenn ich es genauso auf commandebene mit gleichen Fawe-Funktionen mache crasht mir mein Server. Selbst mit viel kleineren Werten.
  • Die Grundfunktionen des Plugins in welchem ich die Funktion verwende dient dazu Entities und bestimmte Performancelastigen Blöcke auf Membergrunstücken zu zählen und die Anzahl auszugeben. Am liebsten wäre es mir da, wenn ich Bienen auch in Kästen zählen kann wozu ich die Blockposition brauche. Die 900 * 900 sind sicher zuviel, sie dienten mir nur zum testen. Die 50 *50 sind dagegen im alltäglichen Gebrauch eher sehr wenig. So ein MemberGs ist etwas Größer als 50 * 50 Blöcke und kann auch bis zu ca. 200 * 200 groß werden.
Zu 1.13.2 Zeiten funktionierte meine alte nicht ganz so optimale Codelösung super. Seit der 1.16 ist sie leider spürbar unbrauchbar geworden da der Server regelmäßig einfriert oder sich verabschiedet.
Wodurch ich gezwungen war meinen Code komplett neu zu schreiben.

Der alte Code bestand nur aus ein paar Forschleifen und stammte von meinen Anfängen.
 

SirYwell

PlotSquared Entwickler
Registriert
30 Juni 2017
Beiträge
540
Diamanten
488
Minecraft
SirYwell
Der Befehl wird asynchron ausgeführt, das heißt EditSession#getBlockDistribution wird in einem anderen Thread aufgerufen. FAWE braucht zwar "nur" 40 Sekunden (zumindest bei mir, ist natürlich auch abhängig vom Server etc), allerdings wartet der gesamte Server so lange auf die Antwort dieser Methode.

Woran dein zweiter Ansatz genau scheitert seh ich jetzt auf Anhieb nicht, generell würde ich das dann aber so lösen, dass du einen sich wiederholenden Task hast, der jeden Tick aufgerufen wird, aber nach <50 ms die run-Methode wieder verlässt und sich selbst cancelt, sobald alles abgearbeitet ist.

Am liebsten wäre es mir da, wenn ich Bienen auch in Kästen zählen kann wozu ich die Blockposition brauche.
Das ermöglicht dir die Block Distribution von WorldEdit nicht, aber wenn du das auf mehrere Ticks verteilt machst, ist das Ergebnis sowieso nicht mehr zuverlässig.
 

JOO200

Braumeister
Registriert
18 Dezember 2016
Beiträge
442
Diamanten
228
Ich glaube tatsächlich, dass es für deinen Fall eine einfachere Lösung gibt: Speichere die Positionen der EntityEnterBlockEvent in einer Liste ab und zähle die Anzahl der Locations, die in der WorldEdit Region liegen. Dabei hast du zwar nur die Bienenstöcke, die seit dem letzten Neustart aktiv waren, aber das sollte nicht das Problem sein.

Tatsächlich kann man auch über die WorldEdit API auf NBT Code zugreifen, aber das ist wohl hier nicht notwendig.

Entities in einer WE Region zu zählen geht sehr gut, allerdings brauchst du dafür kein distr-Code, Entities werden anders gespeichert
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Du könntest auch einfach den Watchdog von Spigot abschalten, sofern es okay ist, dass der Server für 40 Sekunden einfach stehen bleibt, ist das die einfachste Lösung, da du mir aber bereits vor einem Monat nicht gesagt hast, wofür du das brauchst, kann ich dir halt auch nicht sagen, ob das eine Option ist.
 
Oben