Anleitung: Plugins erstellen

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Anleitung: Plugins erstellen

      Hallo, das hier soll eine Anleitung sein, wie man Plugins für AntMe! erstellt. Auch die 2D- und 3D-Visualisierungen sind Plugins. Man kann solche Darstellungen der Simulation als Plugin schreiben, aber auch statistische Auswertungen können als Plugin AntMe! hinzugefügt werden.

      Zum Pluginkonzept:

      Plugins sind dazu gedacht, bestimmte Programme beliebig erweitern zu können. Dafür muss es bestimmte Regeln für alle Plugins eines Programms geben, damit das Programm mit den Plugins kommunizieren kann. Diese Regeln werden durch ein Interface bestimmt. Jedes Plugin muss dieses Interface erben, sonst erkennt das Programm es nicht. Auch bei AntMe! gibt es dieses Interface. Es heißt IPlugin und findet sich im Projekt SharedComponents. Außerdem gibt es noch die Interfaces IConsumerPlugin und IProducerPlugin, die aber beide von IPlugin erben. Für die Visualisierungen wurde das Interface IConsumerPlugin benutzt, die ich auch hier verwenden werde.

      Verweis zu SharedComponents


      Um ein Plugin für AntMe! zu schreiben, muss man einfach ein neues, leeres Projekt erstellen. Dann ist ganz wichtig, in den Eigenschaften des Projekts das Zielframework auf .NET Framework 2.0 zu stellen, sonst ist es nicht mit AntMe! kompatibel. Außerdem sollte der Ausgabetyp eine Klassenbibliotek sein, da die Anwendung keinen Einstiegspunkt hat und nicht ausführbar sein muss. Jetzt muss man noch einen Verweis zu SharedComponents erzeugen. Dazu klickt man im Projektmappen-Explorer mit der rechten Maustaste auf Verweise und wählt Verweis hinzufügen. Unter dem Reiter Durchsuchen sucht man nach der Datei AntMe.SharedComponents.dll, die im Ordner bin im AntMe!-Verzeichnis liegt. Diese Datei wählt man aus und schon hat man einen Verweis zu den SharedComponents von AntMe!.

      Die Klasse Plugin

      Um die Schnittstelle IConsumerPlugin auch benutzen zu können, muss man eine neue Klasse erstellen. Also rechtsklick auf das Projekt im Explorer, Hinzufügen -> Klasse und dann als Namen Plugin.cs wählen. Die Klasse muss public sein und soll von dem Interface IConsumerPlugin erben. Außerdem muss man noch die SharedComponents in die Klasse einbinden. Das Dokument muss also etwa so aussehen:
      [cs]
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using AntMe.SharedComponents.Plugin;

      namespace MyPlugin
      {
      public class Plugin : IConsumerPlugin
      {
      }
      }
      [/cs]

      Die Schnittstelle implementieren

      Die Schnittstelle können wir jetzt einfach implementieren, indem wir den Mauszeiger über IConsumerPlugin halten und auf den Tooltip-Text IConsumerPlugin-Schnittstelle implementieren klicken. Dann werden alle Methodenstubs generiert, die die Schnittstelle fordert, und das sind ganz schön viele. Es wird jetzt noch einen Fehler geben, da eine der Eigenschaften die System.Windows.Forms braucht. Wir müssen also unter Verweis hinzufügen und dann im Reiter .NET System.Windows.Forms auswählen, dann klappt es.

      Jetzt wird es aber erst richtig interessant. Die Methoden werfen im Moment alle noch NotImplementedExceptions, aber das wird sich bald ändern.

      Die Methoden deklarieren

      Erstmal sollte man alle Ausnahme rauslöschen; die stören nur und niemand braucht sie im Moment. Die Datei sollte dann etwa so aussehen:
      [cs]
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using AntMe.SharedComponents.Plugin;

      namespace MyPlugin
      {
      public class Plugin : IConsumerPlugin
      {
      public void CreateState(ref AntMe.SharedComponents.States.SimulationState state)
      {
      }

      public void CreatedState(ref AntMe.SharedComponents.States.SimulationState state)
      {
      }

      public void CreatingState(ref AntMe.SharedComponents.States.SimulationState state)
      {
      }

      public bool Interrupt
      {
      get { }
      }

      public System.Windows.Forms.Control Control
      {
      get { }
      }

      public string Description
      {
      get { }
      }

      public Guid Guid
      {
      get { }
      }

      public string Name
      {
      get { }
      }

      public void Pause()
      {
      }

      public void SetVisibility(bool visible)
      {
      }

      public byte[] Settings
      {
      get
      {
      }
      set
      {
      }
      }

      public void Start()
      {
      }

      public void StartupParameter(string[] parameter)
      {
      }

      public PluginState State
      {
      get { }
      }

      public void Stop()
      {
      }

      public void UpdateUI(AntMe.SharedComponents.States.SimulationState state)
      {
      }

      public Version Version
      {
      get { }
      }
      }
      }

      [/cs]

      Zunächst brauchen wir ein paar grundsätzliche Dinge wie z.B. den Namen oder die Beschreibung des Plugins.

      [cs]
      private readonly string name = "Tutorial-Plugin"; // Der Name des Plugins
      private readonly string description = "Dies ist ein Testplugin"; // Eine Beschreibung des Plugins
      private readonly Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; // Die Version des Plugins
      private readonly Guid guid = new Guid("BBBD7C7A-FD3A-4656-B6DC-6A88463B2816"); // Die GUID, eine eindeutige Nummer im ganzen Programm, die aber mehr oder weniger zufällig gewählt werden kann.

      private PluginState pluginState = PluginState.Ready; // Der Status des Plugins
      [/cs]

      Diese privaten Variablen verwenden wir in den vorgegebenen Eigenschaften:

      [cs]
      public string Name
      {
      get { return name; }
      }

      public string Description
      {
      get { return description; }
      }

      public Version Version
      {
      get { return version; }
      }

      public Guid Guid
      {
      get { return guid; }
      }

      public PluginState State
      {
      get { return pluginState; }
      }
      [/cs]

      Bei den übrigen Eigenschaften geben wir null oder false zurück:

      [cs]
      public bool Interrupt // Gibt an, ob die Anwendung unterbrochen werden soll.
      {
      get { return false; }
      }

      public System.Windows.Forms.Control Control // Gibt ein Control zurück, das im Hauptprogramm angezeigt wird.
      {
      get { return null; }
      }

      public byte[] Settings // Die Settings des Plugins
      {
      get
      {
      return new byte[] { }; // Just no settings
      }
      set
      {
      }
      }
      [/cs]

      In den drei Methoden Start, Stop und Pause ändern wir den PluginStatus:

      [cs]
      public void Start()
      {
      pluginState = PluginState.Running;
      }

      public void Stop()
      {
      pluginState = PluginState.Ready;
      }

      public void Pause()
      {
      pluginState = PluginState.Paused;
      }
      [/cs]

      Jetzt fehlt vorallem noch die Methode UpdateUI, mit der wir die Informationen der Simulation bekommen.

      Auf die Simulation reagieren

      Damit wir auch mit dem Benutzer kommunizieren können, müssen wir noch ein Dialogfenster programmieren. Wir fügen dem Projekt also ein Windows Form hinzu (rechtsklick aufs Projekt im Explorer, Hinzufügen -> Windows Forms) und nennen es z.B. Window.cs. In dieses Form ziehen wir ein Label und nennen es lblRound.
      In den Code des Forms schreiben wir folgende Methode. Dafür müssen wir ganz oben noch using AntMe.SharedComponents.States; einfügen.

      [cs]
      public void ShowRound(SimulationState state)
      {
      lblRound.Text = state.CurrentRound.ToString();
      }
      [/cs]

      Die können wir in der Klasse Plugin benutzen. Wir müssen zuerst eine Variable window definieren und im Konstruktor aufrufen. Das Form öffnen wir in der Methode Start und in Stop schließen wir es.

      [cs]
      private Window window;

      public Plugin()
      {
      window = new Window();
      }

      public void Start()
      {
      pluginState = PluginState.Running;
      window.Show();
      }

      public void Stop()
      {
      pluginState = PluginState.Ready;
      window.Hide();
      }
      [/cs]

      Jetzt kommt die Methode UpdateUI zum Zuge. In ihr benutzen wir die Methode ShowRound.

      [cs]
      public void UpdateUI(AntMe.SharedComponents.States.SimulationState state)
      {
      window.ShowRound(state);
      }
      [/cs]

      Wenn wir das Plugin jetzt benutzen wollen, müssen wir nur die Datei erstellen (F6) und dann im Ordner bin -> Release die Datei [Projektname].dll. Diese Datei kann man im AntMe!-Programm einbinden, wenn man unter Einstellungen -> Plugins auf Plugin hinzufügen klickt und dann die Datei auswählt. Die meisten Fehler treten erst hier auf, also dann bitte hier posten! ^^

      Im Anhang findet ihr eine DLL, die das Plugin enthält. Ihr könnt sie euch runterladen und genau so wie oben beschrieben, benutzen.

      Somit haben wir ein einfaches Plugin geschaffen, das uns zumindest immer die aktuelle Rundenzahl anzeigt. Dieses Tutorial soll natürlich nur beispielhaft veranschaulichen, wie man ein Plugin programmiert. Es geht noch vieles mehr. Man denke nur an die Visualisierungs-Plugins, die bei AntMe! schon dabei sind...

      EDIT: Das Plugin gibts jetzt direkt als DLL.
      Dateien
      • MyPlugin.dll

        (6,66 kB, 180 mal heruntergeladen, zuletzt: )

      Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von Bmeise ()

    • Neitsch schrieb:

      Nein, das funktioniert auch nicht :( Allerdings fällt auf, dass auch bei Statistik 1.6 die gesammelten Früchte nicht richtig angezeigt werden... :(
      Da ist wohl tatsächlich ein Fehler in dem Source! :huh:

      Ich hab mal gesucht und in der Datei SimulationEnvironmentHelper.cs (Projekt SimulationCore) hab ich tatsächlich was seltsames gefunden:
      Da steht

      Quellcode

      1. colony.Statistik.CollectedFood += obst.Menge;

      , allerdings müsste es doch eigentlich heißen

      Quellcode

      1. colony.Statistik.CollectedFood += obst.Menge;
      2. colony.Statistik.CollectedFruits += obst.Menge;


      Wenn man das abändert, funktionierts bei mir. Bei den Statistiken tauchen dann unter Obst alle Punkte, die durch Äpfel entstanden sind, auf.
    • Ich greife hier mal vorab ein. Und versuche deine Frage zu beantworten. Natürlich kann ich dir keinen Liefertermin, bzw. auch keinen ETA nennen. Aber ich zitiere mal einen Beitrag von Tom,

      Auch von mir ein kleines Hallo in die Runde,

      ich bin Tom und einer der Nasen, die AntMe! verbrochen haben. Leider ist das komplette AntMe!-Team in alle Winde zerstreut und kann wenig am Projekt selbst machen. Ich kann euch aber verraten, dass es große Pläne gibt. So arbeite ich selbst öfter mal wieder an der Online-Version des Spiels, damit wir früher oder später all unsere Ameisen gegeneinander antreten lassen können. Aber auch Wolfgang und Co arbeiten an Version 2 mit vielen tollen, neuen Möglichkeiten. Außerdem wird an einer schöneren 3D-Version gearbeitet. Leider alles etwas langsamer als geplant - sorry dafür.

      Das alles soll eure Begeisterung für die Grabbeltiere nicht bremsen. Die aktuelle Version macht ja auch schon Spaß Sollte es dennoch Probleme oder Fragen gehen, ist dies sicher der beste Ort dafür, diese zu stellen.

      Viel Spaß
      Tom


      AntMe! ist von den Jungs immerhin ein Freizeit-Projekt und aktuell geht die Arbeit an AntMe! wie auch dort schon beschriebend eher schleichend und langsam vorran. Ich behaupte jetzt einfach mal (korrigiere mich falls etwas falsch ist bitte, Tom) dass die neue Version noch etwas auf sich warten lässt. Ich denke sobald ein ungefähres Datum bekannt ist, werden wir es als erstes erfahren. :P (Ich unterstelle das jetzt mal frech, in der Hoffnung das es so ist.)

      Gruß,
      Ameisenbaer
      AntMe!-Forum.de Administrator, Kontakt - kontakt@antme-forum.net

    • Kann man denen irgendwie helfen? Ich hab leider keinen Kontakt, aber ich fänd es echt cool, wenn es wieder etwas neues gäbe. Allerdings ist es auch schon echt super, was man mit den Plugins alles "anstellen" kann! :D

      Apropos Plugins:

      tomwendel schrieb:

      Öhm, kleiner Disclaimer an dieser Stelle: Leute, seid vorsichtig mit fremden dll's. Die Ameisen-Dateien laufen zwar in einer Sandbox, nicht aber die Plugins. Grundsätzlich kann so ein Plugin also Schadcode enthalten. :-/
      Kannst du vielleicht alle Plugins durchsehen und beurteilen, ob die OK sind. Ich mein, es kann ja auch was ausversehen schief gehen und muss garnicht bös gemeint sein! ^^

      Danke und viele Grüße
      Bmeise
    • Ich könnte mir vorstellen, dass wenn du Änderungen an der Profi-Version machst Patchfiles den beteiligten Entwicklern zukommen lassen kannst. Das wäre ne Idee wo ich denke, dass das klappen könnte. (svn diff, oder ein git diff)

      Zur Info: ariejan.net/2007/07/03/how-to-…y-a-patch-with-subversion
      AntMe!-Forum.de Administrator, Kontakt - kontakt@antme-forum.net