Multithreading mit Bukkit?

3 Antworten

Einige Funktionen der Bukkit-API sind zum Grunde der Threadsicherheit nur im Hauptthread des Servers erlaubt. Wenn du es async zum Server laufen haben willst, kannst du z. B. die neuen Werte vorbereiten und mit Bukkit.getScheduler()#scheduleSyncDelayedTask die Aufgabe zum Aktualisieren an den Hauptthread übergeben. Wenn du den delay weglässt bzw. auf 0 setzt, wird er beim nächsten Servertick abgearbeitet.

Je nach Anwendungsfall, lassen sich solche Sachen auch vollständig über Bukkit-Scheduler lösen.

Woher ich das weiß:eigene Erfahrung

Klasse die onEnable() und Spielzeit managed:

public void onEnable() {
    instance = this;
    this.recordingTime = new HashMap<>();
    this.invincible = new HashMap<>();
    this.alive = new ArrayList<>();
    
    ScoreboardThread t1 = new ScoreboardThread("t1");
    ScoreboardThread t2 = new ScoreboardThread("t2");
    
    t1.start();
    t2.start();
  }


  public void onDisable() {
    Bukkit.getConsoleSender().sendMessage(getPrefix() + "§6" + getDescription().getName() + " v" + getDescription().getVersion() + " §cwurde deaktiviert.");
  }

  public void startChecking()
  {
    new BukkitRunnable()
    {
	public void run()
      {
        Calendar calendar = Calendar.getInstance();
        String name;
        if ((calendar.get(10) == 19) && (calendar.get(12) == 30) && (calendar.get(13) == 0)) {
          int boardRadius = Varo.this.borderRadius - 60 * (Varo.this.amountVaroPlayers - Varo.this.recordingTime.size());
          Varo.this.loadBorder(boardRadius);


          for (Iterator localIterator = Varo.this.recordingTime.keySet().iterator(); localIterator.hasNext(); ) { name = (String)localIterator.next();
            Varo.this.recordingTime.put(name, Integer.valueOf(Varo.this.recordTime));
          }
        }


        for (String name1 : Varo.this.recordingTime.keySet())
        {
          if (Bukkit.getPlayer(name1) == null)
            continue;
          if (!Bukkit.getPlayer(name1).isOp()) {
          if ((((Integer)Varo.this.recordingTime.get(name1)).intValue() == 15) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 10) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 5) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 4) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 3) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 2))
            Bukkit.broadcastMessage("§e" + name1 + " §3wird in §e" + Varo.this.recordingTime.get(name1) + " §3Sekunden gekickt.");
          else if (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 1)
            Bukkit.broadcastMessage("§e" + name1 + " §3wird in §eeiner §3Sekunde gekickt.");
          else if (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 0 && (Bukkit.getPlayer(name1).getName() != "Water_Storm")){
            Bukkit.getPlayer(name1).kickPlayer("§4Deine Aufnahmezeit ist aufgebraucht. §cDu wurdest deshalb gekickt.");
            kickZeit = calendar.DAY_OF_MONTH;
          }
          }
          else if (Bukkit.getPlayer(name1).isOp()){
        	  if ((((Integer)Varo.this.recordingTime.get(name1)).intValue() == 15) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 10) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 5) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 4) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 3) || (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 2)) {
                  Bukkit.broadcastMessage("§e" + name1 + " §3wird in §e" + Varo.this.recordingTime.get(name1) + " §3Sekunden gekickt.");
        	  	  Bukkit.getPlayer(name1).sendMessage("§3Deine Runde endet in §e" + Varo.this.recordingTime.get(name1) + " §3Sekunden.");}
                else if (((Integer)Varo.this.recordingTime.get(name1)).intValue() == 1) {
                  Bukkit.getPlayer(name1).sendMessage("§eDeine Runde§3 endet in einer Sekunde.");
                Bukkit.getPlayer(name1).sendMessage("§4Deine Aufnahmezeit ist aufgebraucht. Da du der Owner des Servers bist, kannst du dich noch im Server umschauen");
        	  Bukkit.getPlayer(name1).setGameMode(GameMode.SPECTATOR);
              kickZeit = calendar.DAY_OF_MONTH;
          }}


          if (((Integer)Varo.this.recordingTime.get(name1)).intValue() > 0) {
              Varo.this.recordingTime.put(name1, Integer.valueOf(((Integer)Varo.this.recordingTime.get(name1)).intValue() - 1));
            }


        }


        for (String name1 : Varo.this.invincible.keySet())
        {
          if (Bukkit.getPlayer(name1) != null)
          {
            if ((((Integer)Varo.this.invincible.get(name1)).intValue() == 3) || (((Integer)Varo.this.invincible.get(name1)).intValue() == 2)) {
              Bukkit.broadcastMessage("§e" + name1 + " §3ist in §e" + Varo.this.invincible.get(name1) + " §3Sekunden angreifbar");
            } else if (((Integer)Varo.this.invincible.get(name1)).intValue() == 1) {
              Bukkit.broadcastMessage("§e" + name1 + " §3ist in §eeiner §3Sekunde angreifbar");
            } else if (((Integer)Varo.this.invincible.get(name1)).intValue() == 0) {
              Bukkit.getPlayer(name1).sendMessage("§cDu bist nun verwundbar");
              Varo.this.invincible.remove(name1);
              continue;
            }


            if (((Integer)Varo.this.invincible.get(name1)).intValue() > 0)
              Varo.this.invincible.put(name1, Integer.valueOf(((Integer)Varo.this.invincible.get(name1)).intValue() - 1));
          }
          else {
            Varo.this.invincible.remove(name1);
          }
        }
      }
    }
    .runTaskTimer(this, 0L, 20L);
  }


  public void loadBorder(int boardRadius)
  {
    WorldBorder border = Bukkit.getWorld(this.worldName).getWorldBorder();
    border.setCenter(Bukkit.getWorld(this.worldName).getSpawnLocation());
    border.setSize(boardRadius);
    border.setDamageAmount(5.0D);
  }
}

Etwas unübersichtlich aber nur der obere Teil ist eigentlich wichtig.

Das Scoreboard hat noch keine Schleife, die die Spielzeit aktualisiert.

Ich frage mich, warum das nicht funktioniert, bin aber noch Anfänger und mache natürlich Fehler.

Könnt ihr mir weiterhelfen? Ist eine lange Frage aber ich möchte euch keine Info vorenthalten:)

MfG, Halllomenschen


realJackboyPlay  23.06.2019, 11:25

Das Erstellen von Scoreboards ist nicht threadsicher und kann daher nicht asynchron vonstatten gehen.

~Johannes

0
Halllomenschen 
Fragesteller
 23.06.2019, 12:54
@realJackboyPlay

Kannst du mir zeigen wie das geht wenn ich das im JoinListener machen will und das Scoreboard dieses ist:

Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard();
    	    Objective objective = ((org.bukkit.scoreboard.Scoreboard) board).registerNewObjective("abc", "abc");
    	    objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    	    objective.setDisplayName("§6§lWillkommen bei Ravo!");
    	    objective.getScore("§e ").setScore(8);
    	    objective.getScore("§eSpielzeit: " + (Varo.getPlugin().recordingTime.get(player.getName())/60)).setScore(7);
    	    objective.getScore("§5 ").setScore(6);
    	    objective.getScore("§bDu gehörst zum Team: #").setScore(5);
    	    objective.getScore("§4 ").setScore(4);
    	    objective.getScore("§cUnser TS3-Server: PlusTube.eu ").setScore(3);
    	    objective.getScore("§3 ").setScore(2);
    	    objective.getScore("§2Viel Spaß! ").setScore(1);
    	    player.setScoreboard(board);
0

Es gibt Sachen, die dürfen nicht von einem eigenen Threads aufgerufen werden. Z.b. das erstellen des Scoreboards oder Welt Veränderungen.

Woher ich das weiß:Berufserfahrung – Freiberuflicher Java Entwickler mit 10 Jahren Erfahrung