/// <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--; } }
/// <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--; } }
/// <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--; } }
/// <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--; } }
/// <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--; } }