Example #1
0
        /// <summary>
        /// Find a paramater's target in code (methods)
        /// </summary>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the paramater we are after</param>
        public void SeekInCode(Type commandType, CommandParameterAttribute currentNeededParm)
        {
            var validTargetTypes      = commandsAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(currentNeededParm.ParameterType));
            var internalCommandString = CommandStringRemainder.ToList();

            var  parmWords = internalCommandString.Count();
            Type parm      = null;

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validParms = validTargetTypes.Where(comm => comm.GetCustomAttributes <CommandKeywordAttribute>()
                                                        .Any(att => att.Keyword.Equals(currentParmString)));

                if (validParms.Count() > 1)
                {
                    AccessErrors.Add(string.Format("There are {0} potential targets with that name for the {1} command.", validParms.Count(), commandType.Name));

                    AccessErrors.AddRange(validParms.Select(typ => typ.Name));

                    break;
                }
                else if (validParms.Count() == 1)
                {
                    parm = validParms.First();

                    if (parm != null)
                    {
                        switch (currentNeededParm.Usage)
                        {
                        case CommandUsage.Supporting:
                            Supporting = Activator.CreateInstance(parm);
                            break;

                        case CommandUsage.Subject:
                            Subject = Activator.CreateInstance(parm);
                            break;

                        case CommandUsage.Target:
                            Target = Activator.CreateInstance(parm);
                            break;
                        }
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
Example #2
0
        /// <summary>
        /// Find a parameter target in backing data
        /// </summary>
        /// <typeparam name="T">the system type of the data</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInBackingData <T>(Type commandType, CommandParameterAttribute currentNeededParm) where T : IData
        {
            var internalCommandString = CommandStringRemainder.ToList();

            var parmWords = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", internalCommandString.Take(parmWords));

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObject = default(T);

                long parmID = -1;
                if (!long.TryParse(currentParmString, out parmID))
                {
                    validObject = DataWrapper.GetOneBySharedKey <T>("Name", currentParmString);
                }
                else
                {
                    validObject = DataWrapper.GetOne <T>(parmID);
                }

                if (validObject != null && !validObject.Equals(default(T)))
                {
                    switch (currentNeededParm.Usage)
                    {
                    case CommandUsage.Supporting:
                        Supporting = validObject;
                        break;

                    case CommandUsage.Subject:
                        Subject = validObject;
                        break;

                    case CommandUsage.Target:
                        Target = validObject;
                        break;
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
Example #3
0
        /// <summary>
        /// Find a parameter target in reference data
        /// </summary>
        /// <typeparam name="T">the system type of the data</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInReferenceData <T>(Type commandType, CommandParameterAttribute currentNeededParm) where T : IReferenceData
        {
            var internalCommandString = CommandStringRemainder.ToList();

            var parmWords = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords)));

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObject = ReferenceWrapper.GetOne <T>(currentParmString);

                if (validObject != null && !validObject.Equals(default(T)))
                {
                    switch (currentNeededParm.Usage)
                    {
                    case CommandUsage.Supporting:
                        Supporting = validObject;
                        break;

                    case CommandUsage.Subject:
                        Subject = validObject;
                        break;

                    case CommandUsage.Target:
                        Target = validObject;
                        break;
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
Example #4
0
        /// <summary>
        /// Find a parameter target in the live world (entity)
        /// </summary>
        /// <typeparam name="T">the system type of the entity</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInLiveWorldContainer <T>(Type commandType, CommandParameterAttribute currentNeededParm, Type subjectType)
        {
            //Borked it here, we found nothing viable earlier
            if (Subject == null || !((ICollection <IEntity>)Subject).Any())
            {
                return;
            }

            var subjectCollection = (ICollection <IEntity>)Subject;

            //Containers are touch range only
            var internalCommandString = CommandStringRemainder.ToList();
            var disambiguator         = -1;
            var parmWords             = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                //We have disambiguation here, we need to pick the first object we get back in the list
                if (Regex.IsMatch(currentParmString, LiveWorldDisambiguationSyntax))
                {
                    disambiguator     = int.Parse(currentParmString.Substring(0, currentParmString.IndexOf(".")));
                    currentParmString = currentParmString.Substring(currentParmString.IndexOf(".") + 1);
                }

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObjects = new List <T>();

                validObjects.AddRange(subjectCollection.Select(sbj => sbj.CurrentLocation)
                                      .Where(cl => cl.Keywords.Any(key => key.Contains(currentParmString))).Select(ent => (T)ent));

                if (validObjects.Count() > 0)
                {
                    //Skip everything up to the right guy and then take the one we want so we don't have to horribly alter the following logic flows
                    if (disambiguator > -1 && validObjects.Count() > 1)
                    {
                        validObjects = validObjects.Skip(disambiguator - 1).Take(1).ToList();
                    }

                    if (validObjects.Count() > 1)
                    {
                        AccessErrors.Add(string.Format("There are {0} potential containers with that name for the {1} command. Try using one of the following disambiguators:", validObjects.Count(), commandType.Name));

                        int iterator = 1;
                        foreach (var obj in validObjects)
                        {
                            var entityObject = (IEntity)obj;

                            AccessErrors.Add(string.Format("{0}.{1}", iterator++, entityObject.DataTemplate.Name));
                        }

                        break;
                    }
                    else if (validObjects.Count() == 1)
                    {
                        var parm = validObjects.First();

                        if (parm != null)
                        {
                            switch (currentNeededParm.Usage)
                            {
                            case CommandUsage.Supporting:
                                Supporting = parm;
                                break;

                            case CommandUsage.Subject:
                                Subject = parm;
                                break;

                            case CommandUsage.Target:
                                Target = parm;
                                break;
                            }
                        }

                        CommandStringRemainder = CommandStringRemainder.Skip(parmWords);

                        //Now try to set the subject
                        var container = (IContains)parm;

                        var validSubjects = new List <IEntity>();

                        validSubjects.AddRange(subjectCollection.Where(sbj => sbj.CurrentLocation.Equals(container)));

                        if (validSubjects.Count() > 1)
                        {
                            AccessErrors.Add(string.Format("There are {0} potential targets with that name inside {1} for the {2} command. Try using one of the following disambiguators:"
                                                           , validObjects.Count(), parmWords, commandType.Name));

                            int iterator = 1;
                            foreach (var obj in validSubjects)
                            {
                                AccessErrors.Add(string.Format("{0}.{1}", iterator++, obj.DataTemplate.Name));
                            }
                        }
                        else if (validObjects.Count() == 1)
                        {
                            Subject = validSubjects.First();
                        }

                        return;
                    }
                }

                parmWords--;
            }
        }
Example #5
0
        /// <summary>
        /// Find a parameter target in the live world (entity)
        /// </summary>
        /// <typeparam name="T">the system type of the entity</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        /// <param name="hasContainer">does the command need a container to look for things in</param>
        /// <param name="seekRange">how far we can look</param>
        public void SeekInLiveWorld <T>(Type commandType, CommandParameterAttribute currentNeededParm, CommandRangeAttribute seekRange, bool hasContainer)
        {
            var internalCommandString = CommandStringRemainder.ToList();
            var disambiguator         = -1;
            var parmWords             = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                //We have disambiguation here, we need to pick the first object we get back in the list
                if (Regex.IsMatch(currentParmString, LiveWorldDisambiguationSyntax))
                {
                    disambiguator     = int.Parse(currentParmString.Substring(0, currentParmString.IndexOf(".")));
                    currentParmString = currentParmString.Substring(currentParmString.IndexOf(".") + 1);
                }

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObjects = new List <T>();

                switch (seekRange.Type)
                {
                case CommandRangeType.Self:
                    validObjects.Add((T)Actor);
                    break;

                case CommandRangeType.Touch:
                    validObjects.AddRange(Location.GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));

                    if (Actor.GetType().GetInterfaces().Any(typ => typ == typeof(IContains)))
                    {
                        validObjects.AddRange(((IContains)Actor).GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                    }

                    //Containers only matter for touch usage subject paramaters, actor's inventory is already handled
                    //Don't sift through another intelligence's stuff
                    //TODO: write "does entity have permission to another entity's inventories" function on IEntity
                    if (hasContainer && currentNeededParm.Usage == CommandUsage.Subject)
                    {
                        foreach (IContains thing in Location.GetContents <T>().Where(ent => ent.GetType().GetInterfaces().Any(intf => intf == typeof(IContains)) &&
                                                                                     !ent.GetType().GetInterfaces().Any(intf => intf == typeof(IMobile)) &&
                                                                                     !ent.Equals(Actor)))
                        {
                            validObjects.AddRange(thing.GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                        }
                    }
                    break;

                case CommandRangeType.Local:     //requires Range to be working
                    break;

                case CommandRangeType.Regional:     //requires range to be working
                    break;

                case CommandRangeType.Global:
                    validObjects.AddRange(LiveCache.GetAll <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                    break;
                }

                if (hasContainer && currentNeededParm.Usage == CommandUsage.Subject && validObjects.Count() > 0)
                {
                    Subject = validObjects;
                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }
                else if (validObjects.Count() > 0)
                {
                    //Skip everything up to the right guy and then take the one we want so we don't have to horribly alter the following logic flows
                    if (disambiguator > -1 && validObjects.Count() > 1)
                    {
                        validObjects = validObjects.Skip(disambiguator - 1).Take(1).ToList();
                    }

                    if (validObjects.Count() > 1)
                    {
                        AccessErrors.Add(string.Format("There are {0} potential targets with that name for the {1} command. Try using one of the following disambiguators:", validObjects.Count(), commandType.Name));

                        int iterator = 1;
                        foreach (var obj in validObjects)
                        {
                            var entityObject = (IEntity)obj;

                            AccessErrors.Add(string.Format("{0}.{1}", iterator++, entityObject.DataTemplate.Name));
                        }

                        break;
                    }
                    else if (validObjects.Count() == 1)
                    {
                        var parm = validObjects.First();

                        if (parm != null)
                        {
                            switch (currentNeededParm.Usage)
                            {
                            case CommandUsage.Supporting:
                                Supporting = parm;
                                break;

                            case CommandUsage.Subject:
                                Subject = parm;
                                break;

                            case CommandUsage.Target:
                                Target = parm;
                                break;
                            }
                        }

                        CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                        return;
                    }
                }

                parmWords--;
            }
        }
Example #6
0
        /// <summary>
        /// Tries to parse the parameters for the command
        /// </summary>
        /// <param name="commandType">the command's method type</param>
        /// <param name="neededParms">what paramaters are considered required by the command</param>
        private void ParseParamaters(Type commandType, IEnumerable <CommandParameterAttribute> neededParms, bool hasContainer)
        {
            //HUGE conceit for CacheReferenceType.Container usage
            // : We need to store all the found CommandUsage.Subjects and validate them once we get to the container
            Type subjectType = typeof(IEntity);

            //Flip through each remaining word and parse them
            foreach (var currentNeededParm in neededParms.OrderBy(parm => parm.Usage))
            {
                //why continue if we ran out of stuff
                if (CommandStringRemainder.Count() == 0)
                {
                    break;
                }

                if (hasContainer && currentNeededParm.Usage == CommandUsage.Subject)
                {
                    subjectType = currentNeededParm.ParameterType;
                }

                foreach (var seekType in currentNeededParm.CacheTypes)
                {
                    switch (seekType)
                    {
                    case CacheReferenceType.Code:
                        SeekInCode(commandType, currentNeededParm);
                        break;

                    case CacheReferenceType.Entity:
                        //So damn ugly, make this not use reflection if possible
                        MethodInfo entityMethod = GetType().GetMethod("SeekInLiveWorld")
                                                  .MakeGenericMethod(new Type[] { currentNeededParm.ParameterType });
                        entityMethod.Invoke(this, new object[] { commandType, currentNeededParm, commandType.GetCustomAttribute <CommandRangeAttribute>(), hasContainer });
                        break;

                    case CacheReferenceType.Container:
                        MethodInfo containerMethod = GetType().GetMethod("SeekInLiveWorldContainer")
                                                     .MakeGenericMethod(new Type[] { currentNeededParm.ParameterType });
                        containerMethod.Invoke(this, new object[] { commandType, currentNeededParm, subjectType });
                        break;

                    case CacheReferenceType.Reference:
                        MethodInfo referenceMethod = GetType().GetMethod("SeekInReferenceData")
                                                     .MakeGenericMethod(new Type[] { currentNeededParm.ParameterType });
                        referenceMethod.Invoke(this, new object[] { commandType, currentNeededParm });
                        break;

                    case CacheReferenceType.Help:
                        SeekInReferenceData <Help>(commandType, currentNeededParm);
                        break;

                    case CacheReferenceType.Data:
                        MethodInfo dataMethod = GetType().GetMethod("SeekInBackingData")
                                                .MakeGenericMethod(new Type[] { currentNeededParm.ParameterType });
                        dataMethod.Invoke(this, new object[] { commandType, currentNeededParm });
                        break;

                    case CacheReferenceType.Text:
                        //Text just means grab the remainder of the command string and dump it into a param
                        switch (currentNeededParm.Usage)
                        {
                        case CommandUsage.Supporting:
                            Supporting = string.Join(" ", CommandStringRemainder);
                            break;

                        case CommandUsage.Subject:
                            Subject = string.Join(" ", CommandStringRemainder);
                            break;

                        case CommandUsage.Target:
                            Target = string.Join(" ", CommandStringRemainder);
                            break;
                        }

                        //empty the remainder
                        CommandStringRemainder = Enumerable.Empty <string>();
                        //We return here to end the parsing
                        return;
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        /// Where we do the parsing, creates the context and parsed everything on creation
        /// </summary>
        /// <param name="fullCommand">the initial unparsed input string</param>
        /// <param name="actor">the entity issuing the command</param>
        public Context(string fullCommand, IActor actor)
        {
            commandsAssembly = Assembly.GetAssembly(typeof(CommandParameterAttribute));
            entitiesAssembly = Assembly.GetAssembly(typeof(IEntity));

            OriginalCommandString = fullCommand;
            Actor = actor;

            Location = (ILocation)Actor.CurrentLocation;

            AccessErrors           = new List <string>();
            CommandStringRemainder = Enumerable.Empty <string>();

            LoadedCommands = commandsAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICommand)));

            //NPCs can't use anything player rank can't use
            if (Actor.GetType().GetInterfaces().Contains(typeof(IPlayer)))
            {
                LoadedCommands = LoadedCommands.Where(comm => comm.GetCustomAttributes <CommandPermissionAttribute>().Any(att => att.MinimumRank <= ((ICharacter)Actor.DataTemplate).GamePermissionsRank));
            }
            else
            {
                LoadedCommands = LoadedCommands.Where(comm => comm.GetCustomAttributes <CommandPermissionAttribute>().Any(att => att.MinimumRank == StaffRank.Player));
            }

            //find out command's type
            var commandType = ParseCommand();

            if (commandType == null)
            {
                AccessErrors.Add("Unknown Command."); //TODO: Add generic errors class for rando error messages
                return;
            }

            //Log people using and even attempting to use admin commands in game
            if (commandType.GetCustomAttributes <CommandPermissionAttribute>().Any(att => att.MinimumRank == StaffRank.Admin))
            {
                LoggingUtility.LogAdminCommandUsage(OriginalCommandString, ((ICharacter)Actor.DataTemplate).AccountHandle);
            }

            try
            {
                //find the parameters
                var parmList = commandType.GetCustomAttributes <CommandParameterAttribute>();

                var hasContainer = parmList.Any(parm => parm.CacheTypes.Any(crt => crt == CacheReferenceType.Container));
                //why bother if we have no parms to find?
                if (CommandStringRemainder.Count() > 0)
                {
                    ParseParamaters(commandType, parmList, hasContainer);
                }

                //Did we get errors from the parameter parser? if so bail
                if (AccessErrors.Count > 0)
                {
                    return;
                }

                Command = Activator.CreateInstance(commandType) as ICommand;

                if (
                    (parmList.Any(parm => !parm.Optional && parm.Usage == CommandUsage.Subject) && Subject == null) ||
                    (parmList.Any(parm => !parm.Optional && parm.Usage == CommandUsage.Target) && Target == null) ||
                    (parmList.Any(parm => !parm.Optional && parm.Usage == CommandUsage.Supporting) && Supporting == null)
                    )
                {
                    AccessErrors.Add("Invalid command targets specified.");
                    AccessErrors.AddRange(Command.RenderSyntaxHelp());
                    return;
                }

                //Parms we got doesn't equal parms we loaded
                if (CommandStringRemainder.Count() != 0)
                {
                    AccessErrors.Add(string.Format("I could not find {0}.", string.Join(" ", CommandStringRemainder)));
                    AccessErrors.AddRange(Command.RenderSyntaxHelp());
                    return;
                }

                //double check container stuff
                if (hasContainer && Subject != null && Subject.GetType().GetInterfaces().Any(typ => typ == typeof(ICollection)))
                {
                    var collection = (ICollection <IEntity>)Subject;
                    if (collection.Count() == 1)
                    {
                        Subject = collection.First();
                    }
                    else
                    {
                        AccessErrors.Add("Invalid command targets specified.");
                        AccessErrors.AddRange(Command.RenderSyntaxHelp());
                        return;
                    }
                }

                Command.Actor          = Actor;
                Command.OriginLocation = Location;
                Command.Surroundings   = Surroundings;

                Command.Subject    = Subject;
                Command.Target     = Target;
                Command.Supporting = Supporting;
            }
            catch (MethodAccessException mEx)
            {
                Command = Activator.CreateInstance(commandType) as ICommand;
                AccessErrors.Add(mEx.Message);
                AccessErrors = AccessErrors.Concat(Command.RenderSyntaxHelp()).ToList();
            }
        }