Start Info Community Spielen
 
 

Morgengrauner Dokumentation

Dateipfad: /home/mud/mudlib/doc//wiz/rm-howto

RM - HOWTO
**********

Vorlaeufiges Inhaltsverzeichnis:

1) Allgemeines
   - Konzepte fuer neue Gebiete
   - Fehlerteufel
   - Kommentierung von Aenderungen
   - eigene Anschluesse
   - "Datenhygiene" im Regionsverzeichnis
2) Abnahme von Code/Gebieten
   - Balance/Genehmigungen
   - Konzeptionelle Eignung
   - formale Pruefung
   - Gemeinschaftsarbeiten
3) Verlegung von Dateien
4) Seherhaeuser
   - Sonderwuensche/Unsichtbarkeit
   - anderer Befehl zum Betreten
   - Verweise auf Beispielcode
5) Debuggen von Code
6) besondere Funktionen/Funktionaelitaeten
   - catch_tell() / ReceiveMsg()
   - move()
   - Attack() / Defend()
   - call_out()
   - remove() / destruct()
   - for()-Schleifen
   - write_file()
   - Verwalten von charakterbezogenen Daten

1) Allgemeines
==============

1a) Konzepte und Dokumentation

  o Die Erfahrung zeigt, dass es aus verschiedenen Gruenden wirklich dringend
    zu empfehlen ist, sich fuer neue Gebiete ein Konzept vorlegen zu lassen,
    dieses gruendlich zu pruefen und zu durchdenken und mit dem betreffenden
    Regionsmitarbeiter zu diskutieren. Weiterhin empfiehlt es sich ebenfalls,
    eine ueber das Konzept erzielte Einigung im Verzeichnis "doc" Deiner
    Region zu dokumentieren. Hierdurch erreichst Du mehrere Dinge:
    - Du vermeidest Ueberraschungen ("Hier ist mein neues Gebiet zur Abnahme,
      sind nur 120 Raeume. Oh, hoppla, hab ich Dir nicht Bescheid gesagt?");
      auch fuer Deine etwaigen Nachfolger.
    - Du vermeidest bei absehbaren technischen Schwierigkeiten Frustration
      beim Deinem Regionsmitarbeiter.
    - Du erhoehst die Wahrscheinlichkeit, dass das Gebiet tatsaechlich
      fertiggestellt wird.
    - Jeder kann weitgehend verbindlich nachlesen, was Du genehmigt hast.
    - Es ist klar ersichtlich, welche Konzepte bekanntermassen schon in Arbeit
      sind, so dass inhaltliche Aehnlichkeiten im Vorfeld vermieden werden
      koennen.
    
    Du solltest den betreffenden Regionsmitarbeiter auch darauf hinweisen,
    dass er Dich informieren moege, wenn er eine groessere konzeptionelle
    Umstellung des neuen Gebietes durchfuehren will.

    Welche Kriterien man als RM ansetzt, um ein Gebiet als regionstauglich
    zu bewerten, liegt in der Entscheidung des RM.

  o Wenn ein Konzept fuer ein Gesellenstueck eingereicht wird, und es handelt
    sich um eine Gemeinschaftsarbeit mehrerer Magier (Kooperation mehrerer
    Lehrlinge oder Lehrling(e) + erfahrene Magier), UEBERLEGT EUCH GUT, OB
    IHR DAS ZULASSEN WOLLT! Erfahrungsgemaess laesst sich schwer beurteilen,
    welcher Teil des Codes von wem ist. Wenn es zugelassen wird, sollten mit
    den betreffenden Lehrlingen klare Vereinbarungen insbesondere ueber die
    Trennung des Codes nach Autor getroffen werden.

1b) Fehlerteufel / Abarbeitung von Bugs

  o Um stets einen Ueberblick ueber die in Deiner Region (hoffentlich selten)
    auftretenden Bugs und Warnungen zu behalten, solltest Du einen
    Fehlerteufel (/obj/tools/fehlerteufel.c) besitzen, bedienen koennen und
    regelmaessig dessen Listen durchsehen. Deinen Regionsmitarbeitern solltest
    Du, allein schon, um zusaetzliche Arbeit fuer Dich selbst zu reduzieren,
    dieses Werkzeug ebenfalls an die Hand geben und sie auffordern, ihren
    Kram moeglichst umfassend selbst zu reparieren.
    Neuen Magiern wird dieses Tool uebrigens automatisch von Merlin in die
    Hand gedrueckt, so dass sie sich vom ersten Tag an daran gewoehnen 
    koennen.

  o Wenn Du in fremdem Code Aenderungen vornehmen musst, die mehr beruehren
    als nur ein paar Tippfehler in Details oder Infos, dann fuege den 
    reparierten Code mit Kommentar ein. Wenn in Deiner Region git/gerrit zur
    Codeverwaltung verwendet werden, schreibe eine aussagekraeftige Commit-
    Message, bei Bedarf ergaenzt durch einen Kommentar im Code.

1c) Anschluss eigener Gebiete in der eigenen Region

  o Willst Du in Deiner eigenen Region ein Gebiet anschliessen, solltest Du
    diesen vor Anschluss entweder vom Co-RM oder von einem RM einer anderen
    Region lesen lassen. Auch wenn Du ein guter Programmierer bist, findet ein
    zweites Paar Augen oft Dinge, an die man nicht gedacht hat.

1d) "Hygiene" in den Regionsverzeichnissen

  o Wenn Du nicht angeschlossene Objekte aus Deiner Region aussortieren
    moechtest, sprich am besten einen EM an, der Dir dabei hilft:
    Einerseits kann man auf der Shell bequemer herausfinden, ob ein Objekt
    tatsaechlich nicht verwendet wird. Andererseits soll der ungenutzte
    Code in das /players-Verzeichnis des Autors verschoben werden, was
    haeufig ebenfalls EM-Rechte benoetigt.

  o Es wird dringend empfohlen, neuen Regionscode nur noch in /players zu
    entwickeln.

  o Als Regionsmagier hast Du aufgrund eines EM-Beschlusses die Moeglichkeit,
    fuer Deine jeweilige(n) Region(en) verbindlich festzulegen, ob es erlaubt
    ist, die Entwicklung neuer Gebiete im Regionsverzeichnis durchzufuehren.
    

2) Code wird zur Abnahme vorgelegt
==================================

o Bei Waffen und Ruestungen unbedingt darauf achten, dass Objekte, die die
  Genehmigungsgrenzen ueberschreiten, bei der Balance zur Genehmigung 
  vorgestellt wurden. Fuer alle Objekte mit Balance-relevanten Eigenschaften
  bitte penibel darauf achten, dass die Balance-Vorgaben eingehalten werden.
  Jeder Magier kann sich ein Balance-Tool "light" clonen, mit dem er den Text
  der Genehmigung selbst anschauen kann, um den vorgelegten Code damit zu
  vergleichen. Nicht genehmigte oder in der Funktion abweichende Objekte
  duerfen nicht angeschlossen werden. (Bei schon sehr lange angeschlossenen
  Objekten, deren Abweichung von der Genehmigung erst sehr spaet auffaellt,
  kann man ggf. auf das temporaere Abhaengen verzichten.)

o Sofern ein Objekt eine Balance-Genehmigung besitzt, muss die BTOP-Nummer,
  die die Balance als eindeutige ID fuer jeden Antrag vergibt, im Header
  des betreffenden Objektes erkennbar eingetragen sein. Bevorzugt traegt
  man auch die genehmigten Eigenschaften ein.

o Vor Anschluss sollte man kontrollieren, dass der Magier alle wesentlichen 
  Punkte beruecksichtigt hat:
  - Liegen alle Balance-Genehmigungen vor? 
    BTool light gibt's fuer alle, damit kann jeder fuer Objekte in seinem
    Zustaendigkeitsbereich die Genehmigungen einsehen.
  - Sind die FP eingetragen?
    FP kann der RM fuer das neue Gebiet selbst abfragen. 
  - Sind die ZTs eingetragen und getestet?
    Dies laesst sich mit dem Magierkommando "traenke" herausfinden.
  - Falls Sonder-EK-Stupse vorgesehen sind: sind diese genehmigt?
    Die Eintragung bzw. Anpassung der Stufenpunkte fuer den Kill wird
    erledigt, sobald der NPC das erste Mal getoetet wurde, dies muss also 
    nicht gesondert ueberprueft werden.
  - Gibt es Kollisionen zwischen NPC-Namen und Spielernamen? Falls noetig,
    sollten die Namen von NPC gebanisht werden, sofern es sich um 
    Personennamen handelt.

o Alle NPCs sollten vor Anschluss einmal gekillt werden, um sie auf
  grundsaetzliche Kampf-Funktionsfaehigkeit zu pruefen.

o Haben NPCs Namen, sollte ueberlegt werden, diese Namen ggf. zu banishen.
  (hilfe banish).

o Es existiert ein Shell-Skript, mit dessen Hilfe man offensichtliche
  Formfehler in einem kompletten Verzeichnis ermitteln kann (Umlaute im
  Code, zu lange Zeilen etc.), wobei bezueglich der Formalien auch auf
  den Regionsmitarbeiter-Leitfaden fuer neue Projekte verwiesen werden
  soll. Das Skript liegt im oeffentlichen Git-Repo "static-lpc-check" auf
  dem MG-Gerrit-Server. Man kann es mit git oder ueber das Webinterface
  herunterladen. Der Regionsmagier hat hierbei die Entscheidungsfreiheit,
  die Berichte dieses Skripts dem Programmierer des neuen Gebiets als
  Anhaltspunkte zur Verfuegung zu stellen, oder die Abarbeitung der 
  gemeldeten Punkte zur Voraussetzung fuer den Anschluss zu machen, aber
  auch jede Abstufung dazwischen ist OK. :-)
  Zusaetzlicher Tip: Das Skript differenziert zwischen eigentlich nicht
  akzeptablen Konstrukten und zumindest fragwuerdigen, d.h. man kann diese
  Unterscheidung an den Verantwortlichen mit entsprechenden Forderungen
  weitergeben.

o Sollte ein zur Abnahme anstehendes Gesellenstueck eine (grundsaetzlich
  selbstverstaendlich zulaessige) Gemeinschaftsarbeit sein, sollte man
  darauf bestehen, eine sauber getrennte Codebasis in unterschiedlichen
  Verzeichnissen vorgelegt zu bekommen, oder aber eine Auflistung, welcher
  Beitrag von welchem Magier stammt. Es sollte klar sein, dass die
  Beurteilung der Faehigkeiten eines Lehrlings darauf angewiesen ist, dass
  man den Code richtig zuordnen kann.
  Wenn eine solche Auflistung sich bis auf Funktionsebene erstreckt
  (z.B. "DoWield() ist von X, Details von Y, DefendFunc von Z"), ist
  das unschoen und an sich abzulehnen.


3) Verlegung von Dateien
========================

o Sollte ein Objekt aus einer anderen Region bzw. allgemein aus einem
  anderen Verzeichnis (z.B. /players) in Deine Region verlegt werden
  muessen, sind VOR dem Umhaengen folgende Punkte zu beachten:
  -- Forscherpunkte muessen umgetragen werden
  -- Quests und Minquests muessen umgetragen werden
  -- Erstkill-Stufenpunkte muessen umgetragen werden
  -- Zaubertraenke umtragen lassen
  -- Seherportal(e) verlegen lassen
  -- Ruestungen in Padreics Ruestungsskill umtragen lassen
  -- Waffen in der Liste legendaerer Waffen der Kaempfergilde umtragen
     (GM Kaempfer oder EM ansprechen)
  -- im Gebiet vorhandene Seherhaeuser umziehen, an P_SEHERHAUS_ERLAUBT im
     Zielraum denken
  -- evtl. im Gebiet vorhandene Kraeuterskill-Kraeuter beruecksichtigen
  -- evtl. vorhandene Autoload-Objekte pruefen; in einfachen Faellen kann
     man ein Wrapper-Objekt erstellen, das das alte beim Clonen durch das
     neue ersetzt.
  -- evtl. Briefempfaenger der Postquest beruecksichtigen,
  -- evtl. Fotomotive von Notstroms Miniquest im Wald umstellen,
  -- bei Kneipen: Pfad im Bierschuettler-Gildenmaster umtragen lassen
     (GM Bierschuettler oder EM ansprechen),
  -- ueber die Mudlib greppen lassen, um eventuell in anderen Regionen
     verwendete Referenzen auf die alten Pfade des umziehenden Codes
     zu finden und dort umzustellen. Hierbei sind in Ausnahmefaellen von
     fiesem Code auch in Spielersavefiles gespeicherte Pfade zu
     beruecksichtigen (*ARGL*).

  Sofern nichts anderes angegeben ist, muss Dir dabei ein EM helfen.

4) Seherhaeuser
===============

o Die Erlaubnis zum Bau eines Seherhauses in einem Gebiet haengt einzig und
  allein von dem verantwortlichen Magier ab. Sollte dieser laenger nicht
  erreichbar sein (auch nicht ueber externe Mail!), liegt die Entscheidung
  beim Regionsmagier, der aber in jedem Fall die Eignung des Bauplatzes
  in der Umgebung bewerten muss.

o Fuer Sonderwuensche bezueglich Unsichtbarkeit von Seherhaeusern oder
  besonderer Kommandos zum Betreten des Hauses sei auf die Datei
  /doc/beispiele/misc/seherhaus.c verwiesen, wo die Vorgehensweise
  erlaeutert wird. Ein Beispiel einer sehr umfangreichen Implementierung
  findet sich in /d/ebene/room/hp_str8a.c.

o Bei geaenderten Befehlen zum Betreten muss beachtet werden, dass bei einer
  Standardimplementierung die Erlaube-Liste umgangen wird, d.h. ohne
  besondere Vorkehrungen u.U. JEDER das Haus ungehindert betreten kann.
  Es ist hingegen moeglich, die Erlaube-Liste abzufragen und entsprechend
  zu behandeln, ein Beispiel hierfuer ist in /d/ebene/room/hp_str8a.c
  nachzulesen (derzeit jedoch auf Spielerwunsch deaktiviert).


5) Debuggen von Code
====================

o Nach dem Reparieren eines Objektes ist es meist erforderlich, das
  betreffende Objekt neu zu laden. Falls es sich dabei um Objekte handelt,
  die z.B. in einem Raum mittels AddItem() hinzugefuegt wurden (wie etwa
  ein NPC), dann ist es am besten, die Datei mit dem Befehl
   zu aktualisieren und somit saemtliche Clones zu
  zerstoeren. Wenn man mittels  die bestehenden Clones
  ersetzen wuerde, wuerden diese aus der Item-Liste des clonenden Raumes
  ausgetragen, so dass dieser Raum dann im reset() neue Items erzeugt und
  diese in der Folge doppelt existieren wuerden.


6) besondere Funktionen
=======================

Es kommt haeufig vor, dass Funktionen ueberschrieben werden muessen, und das
ist auch normalerweise vollkommen normal und nicht beanstandenswert. Jedoch
sollte man bei bestimmten Funktionen einiges Augenmerk auf die korrekte
Ausfuehrung richten. Einige Beispiele sind nachfolgend aufgefuehrt:

o catch_tell() / ReceiveMsg()
  Die Reaktion von Objekten, insbesondere NPCs, auf eingehende Textmeldungen
  laesst sich nutzen, um schoene und stimmungsvolle Gebiete mit dynamisch
  reagierenden Bewohnern zu schaffen. Es laesst sich auf der dunklen Seite
  der Macht hingegen auch verwenden, um ueble Konstrukte zu realisieren,
  fuer die es seit Ewigkeiten geeignete Implementierungen gibt, und die
  demzufolge niemals durch eine Endabnahme durch einen RM durchschluepfen
  duerfen. Ein paar reale NPC-Beispiele aus der Praxis:

  Schnipsel 1)

  if (sscanf(str, "  %s greift den Priester %s",name1, dummy) == 2)
  {
    pl = find_player(lower_case(name1));
    if (!pl || !living(pl))
      return;
    else
      Kill(pl);
  }
  Zweck:     Simulation von AddDefender() und InformDefend()/DefendOther()
  Kommentar: Absolutes No-Go! Mit Echo-Faehigkeiten von Spielern (Gilde oder
             anderweitig) ist hiermit ein indirekter Playerkill moeglich.
             Inakzeptable Implementierung.


  Schnipsel 2)

  if (sscanf(str, "%s sagt: %s\n", wer,was))
  {
    if (lower_case(was)=="ja" )
      this_player()->move(zielraum, M_TPORT);
  }
  Zweck:     Ausloesen eines Kommandos, ohne "sage ..." als Befehl
             ueberschreiben zu muessen.
  Kommentar: Ausnutzbar als Remote-Fluchtteleport, indem man die Meldung
             mittels teile-mit an den NPC sendet:
             "Robert teilt Dir mit: sagt: ja", was ungeprueft ein move() 
             zur Folge hat. Offensichtlich ebenso ungeeignet wie das 
             vorige Beispiel.


  Schnipsel 3)

  if (sscanf(lower_case(str),"%s sagt: %sversteck%s",s1,s2,s3))
    tell_room(environment(),sprintf("Der Fisch sagt: Das ist aber keine "
      "grosse Hilfe, %s.\n",capitalize(s1)),({TO}));

  sieht erstmal harmlos aus, fuehrt aber mit der Anweisung

  SetChats(8, ({ "Der Fisch sagt: Wo kann ich mich nur verstecken?"}) );

  dazu, dass der NPC dauernd mit sich selber schwatzt. Kein kritischer Bug
  im eigentlichen Sinn, aber auf jeden Fall der Atmosphaere im Gebiet
  sehr abtraeglich.

o move()
  Ueberschreiben von move() ist eine extrem heikle Angelegenheit, bei der
  beim kleinsten Fehler massive Probleme resultieren koennen, jedoch meist
  nicht offensichtlich ist, woher das resultiert. Als allgemeine Empfehlung
  sollte gelten, dass move() NIE ueberschrieben wird, und wenn, dann muss
  ausfuehrlich und aufmerksam geprueft werden, was da passiert, und ob der
  gewuenschte Effekt nicht anders sauberer erreicht werden kann.
  Als zusaetzlicher Hinweis sei auf NotifyMove() und PreventMove() verwiesen,
  mit deren Hilfe sich die allermeisten Faelle erschlagen lassen, in denen
  Magier faelschlicherweise glauben, move() ueberschreiben zu muessen.

o Defend()/Attack()
  hier ist ein beliebter Fehler einfach der, dass man am Ende der Funktion
  ::Defend() bzw. ::Attack() ruft, aber im Codeblock vorher das Objekt
  durch eigenen Tod oder anderes schon zerstoert wurde. Dann geht das schief.
  Einfach mal hinschauen - es ist aber kein wirklich gravierender Fehler,
  da sowas im Kampf meist ziemlich schnell auffaellt.

o call_out()
  Hierzu zwei Hinweise: zum einen fuehrt call_out("x",0) seit der Umstellung
  auf LDmud als Driver nicht mehr implizit zu einem call_out("x",1), wie es
  zuvor war, sondern tatsaechlich zu einem fast sofortigen Funktionsaufruf der
  Funktion x() - mit allen Konsequenzen, inklusive eines "too long eval"-
  Bugs. Wer eine echte Verzoegerung braucht, muss mindestens call_out("x",1)
  verwenden.
  Zum anderen wurde mit LDmud die Granularitaet des reset()-Aufrufes auf
  Heartbeat-Genauigkeit (2 s) verfeinert, so dass man bequem laengere
  Verzoegerungen auf die Verwendung von reset() umstellen kann.

o Zerstoeren von Objekten mit remove() oder destruct()
  Man sollte einen sehr kritischen Blick auf Konstrukte werfen, die
  nach einem remove() noch weiteren Code ausfuehren (Ausnahme: echte efuns 
  und Compiler-Konstrukte wie return).
  Wenn man Objekte zerstoeren will oder muss, sollte man immer zuerst 
  remove() verwenden. Destruct muss dem absoluten Ausnahmefall vorbehalten 
  bleiben. Man sollte im Hinterkopf behalten, dass Objekte gute Gruende haben
  koennen, sich einem remove() zu verweigern.

o for()-Schleifen
  Eigentlich keine Funktion, aber an dieser Stelle doch passend:
  for()-Schleifen sollten generell durch foreach()-Konstruktionen ersetzt
  werden, da dies signifikant und messbar schneller ist. Der groesste 
  Zeit- und Kostenfaktor ist die Verwendung von sizeof() als Abbruchkriterium
  in einer for()-Schleife. Wenn sich die Schleife also nicht ersetzen laesst,
  dann nehmt zumindest einen konstanten Wert als Abbruchkriterium.

o write_file()
  Benutzung dieser Funktion nur in begruendeten Ausnahmefaellen abnehmen, da
  keinerlei Begrenzung der Dateigroesse existiert. Insbesondere bei Logfiles
  entstehen hierdurch im Laufe der Zeit Monsterdateien, die nur Plattenplatz
  verbrauchen, aber kaum zu ueberschauen sind. Statt write_file() wird in
  den allermeisten Faellen log_file() mit der Standardgroesse von 50 kB fuer
  Logfile und eine ggf. vorhandene Altversion (*.OLD) ausreichend sein.
  Standardmaessig ist das Schreiben eines Questlog-Eintrages in /log/quest
  der einzige Einsatzzweck, wo write_file() wirklich notwendig ist.
  Ansonsten sind Ausnahmen vorstellbar, wenn die neuen Daten die alte Datei
  komplett ersetzen, d.h. nicht angehaengt werden.

o Verwalten von charakterbezogenen Daten
  Als Beispiel seien hier Statusdaten fuer den Ablauf von Quests genannt,
  oder Highscores in irgendwelchen Toplisten. Fuer die Umsetzung dieser
  Datenerfassung werden typischerweise zwei Techniken eingesetzt. Zum
  einen kann ein Masterobjekt erstellt werden, das die Daten sammelt und
  mittels save_object() dauerhaft speichert. Zum anderen kann man auch
  Daten in einer Property im Spieler ablegen und diese je nach Anwendungs-
  fall auf SAVE setzen.

  Bei der ersten Variante wird man ueblicherweise die UID oder UUID des 
  Spielers als Indizierungsmerkmal verwenden. Der erste Fallstrick ist nun,
  dass die UID bei Spielern (nicht Sehern) ggf. nach einer Selbstloeschung
  neu vergeben werden kann, so dass die Daten inkonsistent werden bzw. der
  Spieler scheinbar schon in Eurem Master eingetragen ist, obwohl es sich
  eigentlich um jemand ganz anderes handelt.
  Als Abhilfemassnahme bietet sich folgendes an: 
  a) UUID verwenden, da diese fuer jeden Spieler eindeutig ist.
  b) Hinweis: find_player() kann auch mit UUIDs umgehen und das zugehoerige
     Spielerobjekt ermitteln.
  c) Man sollte ggf. auf das Mudlib-Event EVT_LIB_PLAYER_DELETION lauschen, 
     um Spieler auszutragen, die sich loeschen, wodurch die zugehoerigen
     Daten obsolet werden.

  Bei der zweiten Variante muss man verschiedene Dinge beruecksichtigen:
  a) nicht endlos viele Properties machen, sondern pro Thema (z.B. Quest)
     einfach eine.
  b) nur die Properties speichern, bei denen das wirklich noetig ist.
  c) Speichert man Properties und die Aufgabe wird erledigt, d.h. der 
     Inhalt der Property obsolet, muss die Property wieder geloescht werden.


zurück zur Übersicht

YOUTUBE | FACEBOOK | TWITTER | DISCORD | FEEDBACK | IMPRESSUM | DATENSCHUTZ 1992–2023 © MorgenGrauen.