private RequestDispatcher BuildRequestDispatcher(IModuleContainer container) { var moduleCatalog = new ModuleCatalog( () => { return(container.GetAllModules()); }, (Type moduleType) => { return(container.GetModule(moduleType)); } ); var routeSegmentExtractor = new RouteSegmentExtractor(); var routeDescriptionProvider = new RouteDescriptionProvider(); var routeCache = new RouteCache(routeSegmentExtractor, routeDescriptionProvider); routeCache.BuildCache(moduleCatalog.GetAllModules()); var trieNodeFactory = new TrieNodeFactory(); var routeTrie = new RouteResolverTrie(trieNodeFactory); routeTrie.BuildTrie(routeCache); var serializers = new List <ISerializer>() { new JsonSerializer(), new XmlSerializer() }; var responseFormatterFactory = new ResponseFormatterFactory(serializers); var moduleBuilder = new ModuleBuilder(responseFormatterFactory); var routeResolver = new RouteResolver(moduleCatalog, moduleBuilder, routeTrie); var negotiator = new ResponseNegotiator(); var routeInvoker = new RouteInvoker(negotiator); var requestDispatcher = new RequestDispatcher(routeResolver, routeInvoker); return(requestDispatcher); }
/// <summary> /// Attack a character /// </summary> /// <param name="attackingCharacter">The attacking character</param> /// <param name="targetItem">The target string</param> public static void Attack(SMCharacter attackingCharacter, SMCharacter targetCharacter) { // Check that the target has hitpoints if (targetCharacter.Attributes.HitPoints > 0) { // Work out if this is an NPC or not SMRoom room = attackingCharacter.GetRoom(); SMNPC targetNPC = room.GetNPCs().FirstOrDefault(checkChar => checkChar.GetFullName() == targetCharacter.GetFullName()); if (targetNPC != null) { room.ProcessNPCReactions("PlayerCharacter.AttacksThem", attackingCharacter); } List <SMNPC> NPCsInRoom = targetCharacter.GetRoom().GetNPCs().FindAll(npc => npc.GetFullName() != attackingCharacter.GetFullName()); if (NPCsInRoom.Count > 0) { room.ProcessNPCReactions("PlayerCharacter.Attack", attackingCharacter); } // Use the skill attackingCharacter.UseSkill(GetSkillToUse(attackingCharacter), targetCharacter.GetFullName(), true); } else // Report that the target is already dead... { attackingCharacter.sendMessageToPlayer(ResponseFormatterFactory.Get().General($"{targetCharacter.GetFullName()} is already dead!")); } }
/// <summary> /// SMHelp class constructor, populate commandsList /// </summary> public SMHelp(string UserId) { this.commandList = this.GetCommandsList(); this.character = new SlackMud().GetCharacter(UserId); this.responseFormatter = ResponseFormatterFactory.Get(); }
/// <summary> /// Attack a Creature /// </summary> /// <param name="attackingCharacter">The attacking character</param> /// <param name="targetCharacter">The target character</param> public static void Attack(SMCharacter attackingCharacter, SMCreature targetCreature) { // Check that the target has hitpoints if (targetCreature.Attributes.HitPoints > 0) { // Use the skill attackingCharacter.UseSkill(GetSkillToUse(attackingCharacter), targetCreature.CreatureName, true); } else // Report that the target can not be found { attackingCharacter.sendMessageToPlayer(ResponseFormatterFactory.Get().General($"{targetCreature.CreatureName} can not be found")); } }
/// <summary> /// Gets the items listing of a given container in a string ready for outputting. /// </summary> /// <param name="container">Container SMItem to get the listings for.</param> /// <returns>Containers item listings.</returns> public static string GetContainerContents(SMItem container) { // Return null it not a container if (!container.CanHoldOtherItems()) { return(null); } // If the container is empty if (container.HeldItems == null || !container.HeldItems.Any()) { return(ResponseFormatterFactory.Get().Italic("Empty", 1)); } // Get list of item counts // TODO bring this functionality into this class List <ItemCountObject> lines = SMItemUtils.GetItemCountList(container.HeldItems); string output = ""; foreach (ItemCountObject line in lines) { string itemDetails = $"{line.Count} x "; if (line.Count > 1) { itemDetails += line.PluralName; } else { itemDetails += line.SingularName; } output += ResponseFormatterFactory.Get().ListItem(itemDetails); } return(output); }
/// <summary> /// Runs the parsed command. /// </summary> /// <param name="command">Parsed Command.</param> private void RunCommand(SMParsedCommand command) { object result; this.UpdateLastRunCommand(); // Get the Class name of the command class for use in the ClassBuilder string commandClassName = command.Command.CommandClass.Split('.').Last(); // Get class instance from ClassBuilder to run the command with ClassBuilder cb = new ClassBuilder(commandClassName, this.UserID); object commandClass = cb.GetClassInstance(); // If null returned by ClassBuilder, run the command with the CommandClass name // this lets UserCallFuncArray handle object instantiation. if (commandClass == null) { result = Utils.CallUserFuncArray( command.Command.CommandClass, command.Command.CommandMethod, command.Parameters ); } // Run the command using the object instance returned by the ClassBuilder. else { result = Utils.CallUserFuncArray( commandClass, command.Command.CommandMethod, command.Parameters ); } if (result != null && result.GetType() == typeof(SMCommandException)) { this.SendMessage(ResponseFormatterFactory.Get().Italic(this.GetCommandFailureMsg())); } }
public static string GetSkillToUse(SMCharacter attackingCharacter) { string skillToUse = "Brawl"; if (!attackingCharacter.AreHandsEmpty()) { // Get the equipped item from the character if any SMItem smi = attackingCharacter.GetEquippedItem(); skillToUse = "Basic Attack"; if ((smi != null) && (smi.RequiredSkills != null)) { // Check the player has the required skills bool hasAllRequiredSkills = true; bool isFirst = true; foreach (SMRequiredSkill smrs in smi.RequiredSkills) { if (hasAllRequiredSkills) { hasAllRequiredSkills = attackingCharacter.HasRequiredSkill(smrs.SkillName, smrs.SkillLevel); if (isFirst) { skillToUse = smrs.SkillName; } } } // If the player has all the required skills if (!hasAllRequiredSkills) { // Tell the player they can't really wield that item. attackingCharacter.sendMessageToPlayer(ResponseFormatterFactory.Get().General($"You are not skilled with the {smi.ItemFamily}, practicing gives you a chance to increase your skill")); } } } return(skillToUse); }
public string GetLocationDetails(string roomID, SMCharacter smc) { // Variable for the return string string returnString = ""; // Get the room from memory SMRoom smr = GetRoom(roomID); // Check if the character exists.. if (smr == null) { // If they don't exist inform the person as to how to create a new user returnString = ResponseFormatterFactory.Get().Italic("Location does not exist? Please report this as an error to [email protected]"); } else { // Return the room description, exits, people and objects returnString = smr.GetLocationInformation(smc); } // Return the text output return(returnString); }
/// <summary> /// Recover a given number of HP up to the maxhp attribute. /// </summary> /// <param name="Amount">The integer amount of HP to recover.</param> /// <param name="invokingCharacter">The character invoking the HP recovery.</param> public void RecoverHp(Int32 Amount, SMCharacter invokingCharacter) { // Workout how many HP the character is from its max Int32 missingHp = this.MaxHitPoints - this.HitPoints; // Do nothing if HP already at its max if (missingHp == 0) { invokingCharacter.sendMessageToPlayer(ResponseFormatterFactory.Get().Italic($"Your hit points are already full!")); return; } // Workout how many hp to recover to ensure we dont go over the characters max HP Int32 hpToGain = missingHp < Amount ? missingHp : Amount; // Recover the HP this.HitPoints += hpToGain; // Inform the player how many HP they recovered invokingCharacter.sendMessageToPlayer(ResponseFormatterFactory.Get().Italic($"You feel better \"{hpToGain}hp\" recovered.")); return; }
/// <summary> /// Handles initialisation of the users command on a new thread if the command is valid. /// </summary> /// <param name="commandText"></param> /// <returns>Empyt string if the command was passed off to a new thread, otherwise an error meesage.</returns> public string InitateCommand(string commandText) { if (commandText.ToLower() != "login") { // Replay the last used command if the command text is a ! if (commandText == "!") { return(this.HandleRepeats()); } // Process the commandText to check short codes for NPC responses or movement commandText = this.ProcessShortCodes(commandText); } // Instantiate a new command helper. this.CmdHelper = new SMCommandHelper(this.UserID, commandText); // Validate command exists and the character has the appropriate access level to execute it before threading. if (this.CmdHelper.CommandExists() && this.CmdHelper.CharacterCanExecuteCommand()) { HttpContext ctx = HttpContext.Current; Thread commandThread = new Thread(new ThreadStart(() => { HttpContext.Current = ctx; this.RunCommand(this.CmdHelper.GetParsedCommand()); })); commandThread.Start(); return(String.Empty); } // Return a message if the command does not exist or insufficient access level to execute. this.SendMessage(ResponseFormatterFactory.Get().Italic(this.GetCommandNotFoundMsg(commandText))); return(String.Empty); }
/// <summary> /// Pulse the world /// </summary> public void Pulse() { // Work out the start time int currentUnixTime = Utility.Utils.GetUnixTime(); // Get ingame date time info SMDay smd = new SMDay(); smd = (SMDay)HttpContext.Current.Application["SMDay"]; int totalDayNightHours = 24 / (smd.LengthOfDay + smd.LengthOfNight); int numberOfMinutesPerGameDay = totalDayNightHours * 60; int numberOfMinutesPerDayTime = (numberOfMinutesPerGameDay / (smd.LengthOfDay + smd.LengthOfNight)) * smd.LengthOfDay; int numberOfMinutesPerNightTime = (numberOfMinutesPerGameDay / (smd.LengthOfDay + smd.LengthOfNight)) * smd.LengthOfNight; List <SMNotices> smn = (List <SMNotices>)HttpContext.Current.Application["SMNotices"]; // Update in game time int newTime = this.TimeOfDay + (Utility.Utils.GetDifferenceBetweenUnixTimestampsInMinutes(this.LastUpdate, currentUnixTime) * totalDayNightHours); string dayOrNight = HttpContext.Current.Application["DayOrNight"].ToString(); if (newTime > numberOfMinutesPerGameDay) { string noticeS = smn.FirstOrDefault(notice => notice.NoticeType == "DayStart").Notice ?? "A new day begins..."; newTime = newTime - numberOfMinutesPerGameDay; new SlackMud().BroadcastMessage(ResponseFormatterFactory.Get().Italic(noticeS)); HttpContext.Current.Application["DayOrNight"] = "D"; } else if ((newTime > numberOfMinutesPerDayTime) && (HttpContext.Current.Application["DayOrNight"].ToString() != "N")) { string noticeS = smn.FirstOrDefault(notice => notice.NoticeType == "NightStart").Notice ?? "Night falls"; new SlackMud().BroadcastMessage(ResponseFormatterFactory.Get().Italic(noticeS)); HttpContext.Current.Application["DayOrNight"] = "N"; } // Update the variables this.LastUpdate = currentUnixTime; this.TimeOfDay = newTime; // NPC Cycles in the game world List <SMNPC> smnpcl = new List <SMNPC>(); smnpcl = (List <SMNPC>)HttpContext.Current.Application["SMNPCs"]; if (smnpcl != null) { smnpcl = smnpcl.FindAll(npc => npc.NPCResponses.Count(response => response.ResponseType == "Pulse") > 0); if (smnpcl != null) { foreach (SMNPC npc in smnpcl) { npc.RespondToAction("Pulse", null); } } } // Spawns // Find all rooms that are in memory that could have a spawn List <SMRoom> smrl = new List <SMRoom>(); smrl = (List <SMRoom>)HttpContext.Current.Application["SMRooms"]; // If there are any rooms in memory... if (smrl != null) { // ... find the rooms that have any possible NPC spawns. List <SMRoom> roomsWithNPCSpawns = smrl.FindAll(room => room.NPCSpawns != null); if (roomsWithNPCSpawns != null) { // loop around the rooms foreach (SMRoom smr in roomsWithNPCSpawns) { // Check whether there are any spawns. smr.Spawn(); } } // ... find the rooms that have any possible Item spawns. List <SMRoom> roomsWithItemSpawns = smrl.FindAll(room => room.ItemSpawns != null); if (roomsWithItemSpawns != null) { // loop around the rooms foreach (SMRoom smr in roomsWithItemSpawns) { // Check whether there are any spawns. smr.ItemSpawn(); } } } // TODO Randonly decide whether the weather effect will change. // Find all players List <SMCharacter> lsmc = (List <SMCharacter>)HttpContext.Current.Application["SMCharacters"]; foreach (SMCharacter c in lsmc.ToList()) { // Remove any attribute effects that have expired if (c.Attributes.Effects != null) { int currentTime = Utility.Utils.GetUnixTime(); c.Attributes.Effects.RemoveAll(e => e.EffectLength <= currentTime); } // Hurt. if (c.Attributes.HitPoints < c.Attributes.MaxHitPoints) { Random rNumber = new Random(); double rDouble = (rNumber.NextDouble() * 100); if (rDouble <= 5) { c.Attributes.HitPoints++; if (c.Attributes.Effects != null) { List <SMEffect> smel = c.Attributes.Effects.FindAll(e => e.EffectType.ToLower() == "Healing Rate".ToLower()); if (smel != null) { int increasedHealingRate = 0; foreach (SMEffect sme in smel) { increasedHealingRate += int.Parse(sme.AdditionalData); } c.Attributes.HitPoints = c.Attributes.HitPoints + increasedHealingRate; } } c.SaveToApplication(); c.SaveToFile(); } } // ... remove any daily quests that have expired. if (c.QuestLog != null) { c.QuestLog.RemoveAll(qs => ((qs.Completed == true) && (qs.Daily == true) && (Utility.Utils.GetDifferenceBetweenUnixTimestamps(qs.LastDateUpdated, Utility.Utils.GetUnixTime()) > 86400))); c.SaveToApplication(); c.SaveToFile(); } } // Work out the end time // If less than two minutes // Let the thread sleep for the remainder of the time int timeToWait = Utility.Utils.GetDifferenceBetweenUnixTimestamps(currentUnixTime, Utility.Utils.GetUnixTime()); // If the time between the pulses is less than two minutes... if (timeToWait < (120 * 1000)) { // ... send the thread to sleep Thread.Sleep((120 * 1000) - timeToWait); } // Recall the pulse. Pulse(); }
public void GlobalAnnounce(string msg) { BroadcastMessage(ResponseFormatterFactory.Get().Bold($"GLOBAL MESSAGE: {msg}")); }
/// <summary> /// Logs someone in with the Slack UserID /// </summary> /// <param name="userID">Slack UserID</param> /// <returns>A string response</returns> public string Login(string userID, bool newCharacter = false, string responseURL = null, string connectionService = "slack", string password = null) { // Variables for the return string string returnString = ""; // Get all current characters List <SMCharacter> smcs = (List <SMCharacter>)HttpContext.Current.Application["SMCharacters"]; SMCharacter character = smcs.FirstOrDefault(smc => smc.UserID == userID); // Get the right path, and work out if the file exists. string path = FilePathSystem.GetFilePath("Characters", "Char" + userID); // Check if the character exists.. if (!File.Exists(path)) { // If they don't exist inform the person as to how to create a new user returnString = ResponseFormatterFactory.Get().General("You must create a character, to do so, use the command /sm CreateCharacter FIRSTNAME,LASTNAME,SEX,AGE"); returnString += ResponseFormatterFactory.Get().General("i.e. /sm CreateCharacter Paul,Hutson,m,34"); // return information [need to return this without a player!] return(returnString); } else { if ((character != null) && (!newCharacter)) { returnString = ResponseFormatterFactory.Get().General("You're already logged in!"); return(returnString); } else { // Get the character character = GetCharacter(userID, password); // Reset the character activity, just in case! character.CurrentActivity = null; // Set the response URL of the character if (responseURL != null) { character.ResponseURL = responseURL; } // Set the connection service character.ConnectionService = connectionService; // Set the last login datetime character.LastLogindate = DateTime.Now; // Check that the currency is OK. if (character.Currency == null) { character.Currency = new SMCurrency(); character.Currency.AmountOfCurrency = 50; } if (!newCharacter) { returnString = ResponseFormatterFactory.Get().Bold("Welcome back " + character.FirstName + " " + character.LastName + " (you are level " + character.CalculateLevel() + ")", 1); } else { returnString = ResponseFormatterFactory.Get().Bold("Welcome to SlackMud!"); returnString += ResponseFormatterFactory.Get().General("We've created your character in the magical world of Arrelvia!"); // TODO, use a welcome script! } // Check if the player was last in an instanced location. if (character.RoomID.Contains("||")) { // Find the details of the original room type SMRoom originalRoom = GetRoom(character.RoomID.Substring(0, character.RoomID.IndexOf("||"))); character.RoomID = originalRoom.InstanceReloadLocation; } // Clear out any old party references character.PartyReference = null; // Get the location details returnString += GetLocationDetails(character.RoomID, character); // Clear old responses an quests from the character character.ClearQuests(); if (character.NPCsWaitingForResponses != null) { character.NPCsWaitingForResponses.RemoveAll(a => a.NPCID != ""); } // Return the text output character.sendMessageToPlayer(returnString); // Walk the character in SMRoom room = character.GetRoom(); if (room != null) { // Announce someone has walked into the room. room.Announce(ResponseFormatterFactory.Get().Italic(character.GetFullName() + " walks in.")); room.ProcessNPCReactions("PlayerCharacter.Enter", character); } return(""); } } }
/// <summary> /// Create new character method /// </summary> /// <param name="userID">UserID - from the Slack UserID</param> /// <param name="firstName">The first name of the character</param> /// <param name="lastName">The last name of the character</param> /// <param name="age">The age of the character</param> /// <param name="sexIn">M or F for the male / Female character</param> /// <param name="characterType">M or F for the male / Female character</param> /// <returns>A string with the character information</returns> public string CreateCharacter(string userID, string firstName, string lastName, string sexIn, string age, string characterType = "BaseCharacter", string responseURL = null, string userName = null, string password = null, bool autoLogin = true) { // Get the path for the character string path = FilePathSystem.GetFilePath("Characters", "Char" + userID); // If the file doesn't exist i.e. the character doesn't exist if (!File.Exists(path)) { // Create the character options SMCharacter SMChar = new SMCharacter(); SMChar.UserID = userID; SMChar.FirstName = firstName; SMChar.LastName = lastName; SMChar.LastLogindate = DateTime.Now; SMChar.LastInteractionDate = DateTime.Now; SMChar.PKFlag = false; SMChar.Sex = char.Parse(sexIn); SMChar.Age = int.Parse(age); if (userName != null) { SMChar.Username = userName; } if (password != null) { SMChar.Password = Utility.Crypto.EncryptStringAES(password); } // Add default attributes to the character SMChar.Attributes = CreateBaseAttributesFromJson("Attribute." + characterType); // Set default character slots before adding items to them SMChar.Slots = CreateSlotsFromJSON("Slots." + characterType); // Add default items to the character SMSlot back = SMChar.GetSlotByName("Back"); back.EquippedItem = SMItemFactory.Get("Container", "SmallBackpack"); // Add default body parts to the new character SMChar.BodyParts = CreateBodyPartsFromJSON("BodyParts." + characterType); // Add the base currency SMChar.Currency = CreateCurrencyFromJSON("Currency.BaseCharacter"); // Set the start location SMChar.RoomID = "1"; string defaultRoomPath = FilePathSystem.GetFilePath("Scripts", "EnterWorldProcess-FirstLocation"); if (File.Exists(defaultRoomPath)) { // Use a stream reader to read the file in (based on the path) using (StreamReader r = new StreamReader(defaultRoomPath)) { // Create a new JSON string to be used... string json = r.ReadToEnd(); // ... get the information from the the start location token.. SMStartLocation sl = JsonConvert.DeserializeObject <SMStartLocation>(json); // Set the start location. SMChar.RoomID = sl.StartLocation; // TODO Add room to memory if not already there. } } // Write the character to the stream SMChar.SaveToFile(); // Write an account reference to the CharNamesList new SMAccountHelper().AddNameToList(SMChar.GetFullName(), SMChar.UserID, SMChar); // Check if there is a response URL if ((responseURL != null) && (autoLogin)) { // Log the newly created character into the game if in something like Slack Login(userID, true, responseURL); return(""); } else { // Return the userid ready for logging in return(userID); } } else { // If they already have a character tell them they do and that they need to login. // log the newly created character into the game // Login(userID, true, responseURL); // Get all current characters List <SMCharacter> smcs = (List <SMCharacter>)HttpContext.Current.Application["SMCharacters"]; SMCharacter character = smcs.FirstOrDefault(smc => smc.UserID == userID); return(ResponseFormatterFactory.Get().General("You already have a character, you cannot create another.")); } }
public ModuleBuilder(ResponseFormatterFactory responseFormatterFactory) { this.responseFormatterFactory = responseFormatterFactory; }
/// <summary> /// Class constructor /// </summary> public SMRoom() { this.Formatter = ResponseFormatterFactory.Get(); }
public SMShop() { this.Formatter = ResponseFormatterFactory.Get(); }