• 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!

CommandExecutor-Probleme

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#1
Hey,

ich wollte meinen Command "auslagern". Allerdings gibt es einen Haufen Fehlermeldungen, wenn ich das wie folgt über einen CommandExecutor mache :(:


Ausschnitt CE_Heile.java (also die Command-Klasse):

Code:
package me.zentix.main;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import net.md_5.bungee.api.ChatColor;

public class CE_Heile implements CommandExecutor{

    private Main plugin;
    public CE_Heile(Main t) {
        this.plugin = t;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    if (cmd.getName().equalsIgnoreCase("heile")) ....
Meine Main-Klasse:

Code:
package me.zentix.main;

import org.bukkit.plugin.java.JavaPlugin;

import net.md_5.bungee.api.ChatColor;

public class Main extends JavaPlugin{

    @Override
    public void onEnable(){
    System.out.println("&4Uebung &8: &cPlugin geladen!");
    this.getCommand("heile").setPermissionMessage(ChatColor.RED + "Dir fehlt die Berechtigung!");
    CE_Heile heile = new CE_Heile(this);
           getCommand("heile").setExecutor(heile );
    }

Warnungen von Eclipse:

- The value of the field CE_Heile.plugin is not used

Fehler von Eclipse:

- The method getServer() is undefined for the type CE_Heile (das 4x halt pro Methode)


Ich bin noch recht am Anfang und habe im Internet schon recht viel gesucht. Allerdings gibt es derzeit keine fehlerfreien Lösungsansatz. Habt ihr vielleicht einen Link zu einem Tutorial (auch Englisch ;)) oder vielleicht eine Lösungsidee. Wenn es kein Problem wäre, würde ich euch auch um eine Erklärung bitten, da ich die Materie verstehen will.


Danke euch schon mal!


LG :)

//Edit by @Zentix_HD : Das Ziel ist es praktisch, dass ich das this von der Main auf die andere Klasse übertrage. Deshalb denke ich auch die Warnungen seitens Eclipse, dass es das nicht finden kann.
 
Zuletzt bearbeitet:

SirYwell

Schafhirte
Mitglied seit
Jun 30, 2017
Beiträge
106
Bewertungen
122
Alter
19
Minecraft
SirYwell
#2
Das "this" kannst du nicht übertragen. Bisher übergibst du dem Konstruktor deiner CE_Heile-Klasse eine Referenz deiner Hauptklasse. Diese weist du dem Feld "private Main plugin" zu. Um die Methode "getServer()" aus der Klasse "JavaPlugin" aufzurufen, musst du jetzt "plugin.getServer()" verwenden. Aber falls das der einzige Grund für den Konstruktor und die Referenzierung ist, solltest du eher die statische, gleichnamige Methode aus der Klasse Bukkit aufrufen ("Bukkit.getServer()").

Abgesehen davon würde ich dir davon abraten, Klassennamen mit Unterstrichen zu versehen. "HealCommand" o.Ä. wäre in diesem Fall aussagekräftiger und somit angemessener.
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#3
Das "this" kannst du nicht übertragen. Bisher übergibst du dem Konstruktor deiner CE_Heile-Klasse eine Referenz deiner Hauptklasse. Diese weist du dem Feld "private Main plugin" zu. Um die Methode "getServer()" aus der Klasse "JavaPlugin" aufzurufen, musst du jetzt "plugin.getServer()" verwenden. Aber falls das der einzige Grund für den Konstruktor und die Referenzierung ist, solltest du eher die statische, gleichnamige Methode aus der Klasse Bukkit aufrufen ("Bukkit.getServer()").

Abgesehen davon würde ich dir davon abraten, Klassennamen mit Unterstrichen zu versehen. "HealCommand" o.Ä. wäre in diesem Fall aussagekräftiger und somit angemessener.
Danke... Teste ich morgen mal aus. Wie ist das mit dem Fehler, soll ich den ignorieren? Oder kann ich den teil löschen und benötige blos des in der Main-Klasse?

LG
 

BlackHole

Workaholic
Mitglied seit
Jul 1, 2012
Beiträge
646
Bewertungen
210
Minecraft
BlackHole
#4
Warnungen "kann" man ignorieren, Fehler nicht. Warnungen der Art "The value of the field ... is not used" kann man während der Entwicklungszeit ignorieren, sie können aber wertvolle Hinweise bei der Fehlersuche geben.

Bei einem CommandExecutor ist die Abfrage auf den Namen des Befehls überflüssig, wenn du für jeden Befehl einen eigenen Executor verwendest.
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#5
Warnungen "kann" man ignorieren, Fehler nicht. Warnungen der Art "The value of the field ... is not used" kann man während der Entwicklungszeit ignorieren, sie können aber wertvolle Hinweise bei der Fehlersuche geben.

Bei einem CommandExecutor ist die Abfrage auf den Namen des Befehls überflüssig, wenn du für jeden Befehl einen eigenen Executor verwendest.
D.h. Ich benötige nur den teil in der MainKlasse? Ich nutze pro Befehl einen Executor...

LG
 

SirYwell

Schafhirte
Mitglied seit
Jun 30, 2017
Beiträge
106
Bewertungen
122
Alter
19
Minecraft
SirYwell
#6
Da du dem Command mit "getCommand(...).setExecutor(...)" einen CommandExecutor zuweist, wird cmd.getName() immer gleich sein. Die einzige Ausnahme, von der ich allerdings abrate, ist das Nutzen eine CommandExecutors für mehrere Befehle:

Code:
getCommand("command1").setExecutor(new MyCommandExecutor());
getCommand("command2").setExecutor(new MyCommandExecutor());
hier könnte der Name des Befehls entweder "command1" oder "command2" sein. Aufgrund der Übersichtlichkeit und der Lesbarkeit des Codes ist das aber nicht empfehlenswert.
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#7
Da du dem Command mit "getCommand(...).setExecutor(...)" einen CommandExecutor zuweist, wird cmd.getName() immer gleich sein. Die einzige Ausnahme, von der ich allerdings abrate, ist das Nutzen eine CommandExecutors für mehrere Befehle:

Code:
getCommand("command1").setExecutor(new MyCommandExecutor());
getCommand("command2").setExecutor(new MyCommandExecutor());
hier könnte der Name des Befehls entweder "command1" oder "command2" sein. Aufgrund der Übersichtlichkeit und der Lesbarkeit des Codes ist das aber nicht empfehlenswert.
Aber uch dachte, dass man in der Main oraktisch sagen muss, auf welche Commands das Plugin achten muss. Könnte mal jemand kruz und einprägsam erklären (vllt mit Codeschnipseln) wie ich das jetzt löse, also wie ich in der Main die 2.Klasse registiere bzw den Command.

LG
 

BlackHole

Workaholic
Mitglied seit
Jul 1, 2012
Beiträge
646
Bewertungen
210
Minecraft
BlackHole
#8
Also die Befehle werden ja durch die plugin.yml dem Plugin zugewiesen. Für jeden Befehl den dein Plugin behandeln soll erstellst du ein Klasse, die CommandExecutor (bzw. TabExecutor) implementiert.

In deiner Main-Klasse gehst du so vor wie du es schon für den einen Befehl gemacht hast:
Code:
getCommand("heile").setExecutor(new HeileExecutor(this));
getCommand("irgendwas").setExecutor(new IrgendwasExecutor(this));
Permissions für die Befehle und Ausgaben bei Fehlen dieser Permission kannst du in der plugin.yml definieren.
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#9
Also die Befehle werden ja durch die plugin.yml dem Plugin zugewiesen. Für jeden Befehl den dein Plugin behandeln soll erstellst du ein Klasse, die CommandExecutor (bzw. TabExecutor) implementiert.

In deiner Main-Klasse gehst du so vor wie du es schon für den einen Befehl gemacht hast:
Code:
getCommand("heile").setExecutor(new HeileExecutor(this));
getCommand("irgendwas").setExecutor(new IrgendwasExecutor(this));
Permissions für die Befehle und Ausgaben bei Fehlen dieser Permission kannst du in der plugin.yml definieren.
Und in der ExecutorKlasse muss ich nix machen außer statt „this“ jetzt „bukkit“, wenn ich das ganze mal benötige?

LG
 

SirYwell

Schafhirte
Mitglied seit
Jun 30, 2017
Beiträge
106
Bewertungen
122
Alter
19
Minecraft
SirYwell
#10
Und in der ExecutorKlasse muss ich nix machen außer statt „this“ jetzt „bukkit“, wenn ich das ganze mal benötige?
Nein, das kommt ganz drauf an, was du benötigst. Um zum Beispiel an "getConfig()" zu kommen, brauchst du den Konstruktor, in dem du deine Main übergibst um dann mit z.B. "plugin.getConfig()" in deiner CommandExecutor-Klasse die config aufzurufen. "getServer()" hingegen ist auch über "Bukkit.getServer()" erreichbar (und viele Methoden aus einem Server-Objekt sind auch direkt über Bukkit.xxxx() aufrufbar).
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#11
Nein, das kommt ganz drauf an, was du benötigst. Um zum Beispiel an "getConfig()" zu kommen, brauchst du den Konstruktor, in dem du deine Main übergibst um dann mit z.B. "plugin.getConfig()" in deiner CommandExecutor-Klasse die config aufzurufen. "getServer()" hingegen ist auch über "Bukkit.getServer()" erreichbar (und viele Methoden aus einem Server-Objekt sind auch direkt über Bukkit.xxxx() aufrufbar).
Danke! Sry, dass ich mich da etwas dumm angestellt habe. Ich teste des mal heute Abend. Noch ne Frage: Beim Konstruktor wird das „plugin“ in der ersten Zeile gelb unterringelt. Soll ich das igrnorieren? (Is auch die Warnung von Eclipse) benötige es ja jetzt erstmal nicht bloß, wenn ich mal darauf komme, dass wäre es ganz praktisch.

LG
 

SirYwell

Schafhirte
Mitglied seit
Jun 30, 2017
Beiträge
106
Bewertungen
122
Alter
19
Minecraft
SirYwell
#12
Vermutlich wird gekennzeichnet, dass es nirgends aufgerufen wird innerhalb deiner Klasse
 

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#13
Wenn ich jetzt ein Argument definiere.

Z.B. Beim /heal befehl, kommt nur, dass dies kein Spieler ist. Ich wollte, dass wenn man /heal alle eingibt es halt alle heilt. Habe des in einer IF-Clause gemacht.


Heal-Klasse:

Code:
package me.jan.main;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

public class HealCommand implements CommandExecutor{



    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String labels, String[] args) {
    if (args.length>1) {
        return false;
    }
    if (args.length == 0) {
        if (!(sender instanceof Player)) {
            System.out.println("Dieser Befehl ist nur für Spieler!");
            return true;
        }
        Player player = (Player) sender;
        player.setHealth(20.0);
        player.sendMessage(ChatColor.GREEN + "Du wurdest geheilt.");
        return true;
    }
    if (args.length==1) {
        Player ziel = Bukkit.getServer().getPlayer(args[0]);
        if (ziel == null) {
            sender.sendMessage(ChatColor.RED + "Heilung fehlgeschlagen! Spieler nicht gefunden!");
            return false;
        }
        ziel.setHealth(20.0);
        ziel.sendMessage(ChatColor.GREEN + "Du wurdest von "+sender.getName()+" geheilt!");
        return true;
    }
    if (args[0].equalsIgnoreCase("alle")) {
        if (Bukkit.getServer().getOnlinePlayers().isEmpty()) {
            System.out.println("Langeweile?");
            return true;
        }
        for (Player player : Bukkit.getServer().getOnlinePlayers()) {
            player.setHealth(20.0);
        }
        Bukkit.getServer().broadcastMessage(ChatColor.GREEN + sender.getName() + " hat alle Spieler geheilt!");
        return true;
    }
    return false;
    }

}
Habe ich nen Fehler oder muss man noch was definieren.
LG
 
Zuletzt bearbeitet:

Zentix_HD

Kuhfänger
Mitglied seit
Dez 28, 2016
Beiträge
62
Bewertungen
31
Alter
20
#15
Zeile 39 bis 49 musst du zwischen Zeile 29 und 30 verschieben.
Danke! Kann ich mir also merken, dass ich ausnahmen immer sozusagen vor der „Regel“ definieren muss? Also dass ich, wenn ich sagen das auf args immer etwas angegeben wird, aber es eine Ausnahme für etwas gibt, diese Ausnahme davor muss....


LG
 

SirYwell

Schafhirte
Mitglied seit
Jun 30, 2017
Beiträge
106
Bewertungen
122
Alter
19
Minecraft
SirYwell
#16
Java arbeitet den Code innerhalb eines Blocks immer von oben nach unten ab. Beispiel:
Code:
int i = 5;
if(i >= 3) {
    System.out.println(i + " ist größer oder gleich 3");
}
else if(i >= 5) {
     System.out.println(i + " ist größer oder gleich 5");
}
Der untere Block wird niemals ausgeführt. Würde man das else weglassen, würden beide Blöcke ausgeführt werden. Da du aber in deinem Code ein "return false;" hast, wenn der Spieler nicht gefunden wird (was ja auch immer der Fall sein würde, wenn man "/heal alle" eingibt, verlässt Java die komplette Methode.

Allerdings solltest du beachten, dass dein jetzt umgestellter Block für die "alle" Funktion auch ausgeführt wird, wenn args.length NICHT gleich 1 ist. Da du eine Längenüberorüfung auf 0 aber schon abblockst, wird args immer mehr als 0 Argumente enthalten. Man kann also nicht etliches hinter "alle" schreiben, das wird jedoch ignoriert.
 
F

Figz

Guest
#17
Ich glaube du hast es verstanden, jedoch wäre "Ausnahmen" in diesem Falle das falsche Wort.
Man fängt immer mit den Abfragen an, die am spezifischsten sind und wird dann immer allgemeiner.

So wie wenn man Exceptions abfängt.

Code:
try
  {
      // Datei öffnen
  }
catch(FileNotFoundException e)
  {

  }
catch(Exception e)
  {
  
  }

Abfrage bei Zahlen:

int zahl = 2;

if(zahl > 10)
// Alle Zahlen die größer als 10 sind
else if(zahl >5)
// Alle Zahlen zwischen 6 und 10
else if(zahl >1)
// Alle Zahlen zwischen 2 und 5
else
Alle Zahlen <= 1
 
Allgemein
Help Benutzer
    CowBot CowBot: Swissu has left the room.
    Oben