#region Arthea License /*********************************************************************** * Arthea MUD by R. Jennings (2007) http://arthea.googlecode.com/ * * By using this code you comply with the Artistic and GPLv2 Licenses. * ***********************************************************************/ #endregion using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Xml.Serialization; using Arthea.Connections; using Arthea.Connections.Players; using Arthea.Continents; using Arthea.Continents.Areas; using Arthea.Continents.Areas.Characters; using Arthea.Continents.Areas.Items; using Arthea.Continents.Areas.Rooms; using Arthea.Creation.Attributes; namespace Arthea.Creation { /// <summary> /// Implements On Line Creation methods /// </summary> public class Olc { #region [rgn] Fields (4) private const BindingFlags bindingFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic; private readonly Connection conn; private readonly object editing; private FieldInfo fieldInfo; #endregion [rgn] #region [rgn] Constructors (1) /// <summary> /// Initializes a new instance of the <see cref="Olc"/> class. /// </summary> /// <param name="connection">The connection.</param> /// <param name="obj">The obj.</param> public Olc(Connection connection, object obj) { conn = connection; editing = obj; } #endregion [rgn] #region [rgn] Methods (11) // [rgn] Public Methods (9) /// <summary> /// Creates a new object for editing given an object type. /// </summary> /// <param name="player">the player doing the editing.</param> /// <param name="type">the type of object to create.</param> /// <param name="argument">additional arguments</param> public static void Create(Player player, Type type, String argument) { switch (type.Name) { case "Room": Room.Create(player, argument); break; case "ItemIndex": ItemIndex.Create(player, argument); break; case "Help": Help.Create(player, argument); break; case "Area": Area.Create(player, argument); break; case "ScriptCode": CharIndex.Create(player, argument); break; case "Social": Social.Create(player, argument); break; case "Continent": Continent.Create(player, argument); break; default: player.WriteLine("Unable to create a {0}.", type.Name.ToLower()); break; } } /// <summary> /// Shows available commands for a players editor. /// </summary> public void DisplayCommands() { FieldInfo[] fields = GetAllFields(editing.GetType(), false); string[] names = new string[fields.Length]; for (int i = 0; i < fields.Length; i++) names[i] = fields[i].Name; Columns.Show(conn.Player, 4, 10, names); } /// <summary> /// Edits a field for an object begin edited by a player. /// </summary> /// <param name="line">the field and value.</param> /// <returns>true if a field matching argument was found.</returns> public bool Edit(String line) { String argument = new String(line); String arg = argument.FirstArg(); if (!arg || arg == "show") { Show(); return true; } if (arg == "done") { conn.Editing = null; return true; } if (arg == "?") { DisplayCommands(); return true; } if (arg == "create") { Create(conn.Player, editing.GetType(), argument); return true; } fieldInfo = GetField(editing.GetType(), arg); if (fieldInfo == null) { return false; } if (EnterStringEditor()) { return true; } if (!argument) { conn.WriteLine("Set {0} to what?", FieldToWords(fieldInfo.Name)); return true; } new OlcField(editing, fieldInfo).Edit(conn.Player, argument); return true; } /// <summary> /// Formats a field name into human readable form. /// </summary> /// <param name="name">the (field) name</param> /// <returns>the name formated</returns> public static string FieldToWords(string name) { StringBuilder buf = new StringBuilder(); CharEnumerator c = name.GetEnumerator(); if (!c.MoveNext()) return name; buf.Append(char.ToUpper(c.Current)); while (c.MoveNext()) { if (char.IsUpper(c.Current)) { buf.Append(" "); } buf.Append(c.Current); } return buf.ToString(); } /// <summary> /// Gets all properties. /// </summary> /// <param name="type">The type.</param> /// <param name="toShow"><c>true</c> if we are using fields to display values.</param> /// <returns>an array of editable fields</returns> public static FieldInfo[] GetAllFields(Type type, bool toShow) { List<FieldInfo> fields = new List<FieldInfo>(type.GetFields(bindingFlags)); Type baseType = type.BaseType; while (baseType != null) { fields.AddRange(baseType.GetFields(bindingFlags)); baseType = baseType.BaseType; } fields.RemoveAll(delegate(FieldInfo f) { return IgnoreField(f, toShow); }); return fields.ToArray(); } /// <summary> /// Gets a field by name from a type. /// </summary> /// <param name="type">The type.</param> /// <param name="arg">The arg.</param> /// <returns>a fieldinfo object</returns> public static FieldInfo GetField(Type type, String arg) { foreach (FieldInfo info in GetAllFields(type, false)) { if (arg.IsPrefixOf(info.Name)) return info; } return null; } /// <summary> /// Shows all fields and values for a players editor. /// </summary> public void Show() { foreach (FieldInfo info in GetAllFields(editing.GetType(), true)) { conn.WriteLine("{0}: {1}", FieldToWords(info.Name), info.GetValue(editing)); } } /// <summary> /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>. /// </summary> /// <returns> /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>. /// </returns> public override string ToString() { return editing.GetType().Name + "Edit"; } /// <summary> /// Takes a human readable word and reformats it into a field name. /// </summary> /// <param name="name">the (field) name</param> /// <returns>a field name</returns> public static string WordsToField(string name) { StringBuilder buf = new StringBuilder(); CharEnumerator c = name.GetEnumerator(); if (!c.MoveNext()) return name; buf.Append(char.ToLower(name[0])); while (c.MoveNext()) { if (c.Current == ' ') { if (!c.MoveNext()) break; buf.Append(char.ToUpper(c.Current)); } else { buf.Append(c.Current); } } return buf.ToString(); } // [rgn] Private Methods (2) private bool EnterStringEditor() { if (fieldInfo.GetValue(editing) is string) { foreach (object attr in fieldInfo.GetCustomAttributes(true)) { if (attr is TextEdit) { string obj = fieldInfo.GetValue(editing) as string; conn.Composing = new StringEditor().Append(conn, obj); return true; } } } return false; } /// <summary> /// Checks a fields attributes to see if it should be ignored. /// </summary> /// <param name="info">the field info</param> /// <param name="show">is the method being called from Olc.Show</param> /// <returns>true if the field should be ignored</returns> private static bool IgnoreField(ICustomAttributeProvider info, bool show) { foreach (object attr in info.GetCustomAttributes(true)) { if (attr is EditIgnore || attr is XmlIgnoreAttribute || (attr is EditShow && !show)) { return true; } } return false; } #endregion [rgn] } }