internal static ClientAcceptanceStatus ClientConnected(NetworkClient Client) { var ban = ProscriptionList.IsBanned(Client.IPString); if (ban.Banned) { Core.LogError("Rejected connection from " + Client.IPString + ". Matched ban " + ban.SourceBan.Glob + " Reason: " + ban.SourceBan.Reason); return ClientAcceptanceStatus.Rejected; } ClientLock.WaitOne(); var dummyPlayer = new Actor(); dummyPlayer.CommandHandler = new LoginCommandHandler(); Core.TiePlayerToClient(Client, dummyPlayer); MudObject.SendMessage(Client, Core.SettingsObject.Banner); MudObject.SendMessage(Client, Core.SettingsObject.MessageOfTheDay); ConnectedClients.Add(Client); Core.SendPendingMessages(); ClientLock.ReleaseMutex(); return ClientAcceptanceStatus.Accepted; }
public PasswordCommandHandler(Actor Actor, Action<Actor, String, String> AuthenticatingCommand, String UserName) { this.ParentHandler = Actor.CommandHandler; this.AuthenticatingCommand = AuthenticatingCommand; this.UserName = UserName; MudObject.SendMessage(Actor, "Password: "); }
public static void SendMessage(Actor Actor, String Message, params Object[] MentionedObjects) { if (String.IsNullOrEmpty(Message)) return; if (Core.SilentFlag) return; Core.OutputQueryTriggered = true; if (Actor != null && Actor.ConnectedClient != null) Core.PendingMessages.Add(new PendingMessage(Actor.ConnectedClient, Core.FormatMessage(Actor, Message, MentionedObjects))); }
public String Expand(Actor Viewer, MudObject Source) { switch (TextType) { case DescriptiveTextType.LambdaText: return LambdaText(Viewer, Source); case DescriptiveTextType.TaggedText: return RawText; } return null; }
public static void OfferQuest(this MudObject This, Actor Actor, MudObject Quest) { var player = Actor as Player; if (player != null) { MudObject.SendMessage(Actor, "[To accept this quest, enter the command 'accept quest'.]"); if (player.GetProperty<MudObject>("active-quest") != null) MudObject.SendMessage(Actor, "[Accepting this quest will abandon your active quest.]"); player.SetProperty("offered-quest", Quest); } }
void IOpenable.HandleOpen(Actor Actor) { if (!Open) { if (Actor.ConnectedClient != null) Mud.SendEventMessage(Actor, EventMessageScope.Single, "You open the door.\r\n"); Mud.SendEventMessage(Actor, EventMessageScope.External, Actor.Short + " opens the door.\r\n"); } Open = true; }
void IOpenable.HandleClose(Actor Actor) { if (Open) { if (Actor.ConnectedClient != null) Mud.SendEventMessage(Actor, EventMessageScope.Single, "You close the door.\r\n"); Mud.SendEventMessage(Actor, EventMessageScope.External, Actor.Short + " closes the door.\r\n"); } Open = false; }
public static void KickPlayer(Actor Player, Actor Actor) { if (Player.ConnectedClient != null) { Core.MarkLocaleForUpdate(Player); MudObject.SendMessage(Player, Actor.Short + " has removed you from the server."); Player.ConnectedClient.Disconnect(); Clients.SendGlobalMessage(Actor.Short + " has removed " + Player.Short + " from the server."); } }
public void Authenticate(Actor Actor, String UserName, String Password) { var existingAccount = Accounts.LoadAccount(UserName); if (existingAccount == null || Accounts.VerifyAccount(existingAccount, Password) == false) { MudObject.SendMessage(Actor, "Could not verify account."); return; } LoginCommandHandler.LogPlayerIn(Actor.ConnectedClient as NetworkClient, existingAccount); }
public static void ProcessPlayerCommand(CommandEntry Command, PossibleMatch Match, Actor Actor) { ExecutingCommand = Match; try { ExecuteCommand(Command, Match, Actor); } finally { ExecutingCommand = null; } }
public static void SendExternalMessage(Actor Actor, String Message, params Object[] MentionedObjects) { if (String.IsNullOrEmpty(Message)) return; if (Core.SilentFlag) return; Core.OutputQueryTriggered = true; if (Actor == null) return; var location = Actor.Location as Room; if (location == null) return; foreach (var other in location.EnumerateObjects<Actor>().Where(a => !Object.ReferenceEquals(a, Actor) && (a.ConnectedClient != null))) Core.PendingMessages.Add(new PendingMessage(other.ConnectedClient, Core.FormatMessage(other, Message, MentionedObjects))); }
/// <summary> /// Try to execute a command immediately. This does not bypass the before and after command rules. This is intended /// to be used by rules to implement implicit actions. For example, the 'go' command will attempt to open closed /// doors by calling /// Core.Try("StandardActions:Open", Core.ExecutingCommand.With("SUBJECT", link), actor); /// </summary> /// <param name="CommandID">The ID of the command to try, assigned when the command is created.</param> /// <param name="Match"></param> /// <param name="Actor"></param> /// <returns>The result of the command's proceedural rules.</returns> public static PerformResult Try(String CommandID, PossibleMatch Match, Actor Actor) { var parentCommand = ExecutingCommand; try { var command = Core.DefaultParser.FindCommandWithID(CommandID); if (command == null) return PerformResult.Stop; return ExecuteCommand(command, Match, Actor); } finally { ExecutingCommand = parentCommand; } }
internal MatchedCommand ParseCommand(String Command, Actor Actor) { var tokens = new LinkedList<String>(Command.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)); var rootMatch = new PossibleMatch(tokens.First); //Find all objects in scope var matchContext = new MatchContext { ExecutingActor = Actor }; foreach (var command in Commands) { var matches = command.Matcher.Match(rootMatch, matchContext); var firstGoodMatch = matches.Find(m => m.Next == null); if (firstGoodMatch != null) return new MatchedCommand(command, firstGoodMatch); } return null; }
public void Authenticate(Actor Actor, String UserName, String Password) { var existingAccount = Accounts.LoadAccount(UserName); if (existingAccount != null) { MudObject.SendMessage(Actor, "Account already exists."); return; } var newAccount = Accounts.CreateAccount(UserName, Password); if (newAccount == null) { MudObject.SendMessage(Actor, "Could not create account."); return; } LoginCommandHandler.LogPlayerIn(Actor.ConnectedClient as NetworkClient, newAccount); }
public static void AddPlayer(Actor Actor) { Actor.Rank = 500; GlobalRules.ConsiderPerformRule("player joined", Actor); }
public bool Match(string Word, Actor Actor) { return CouldMatch(Word); }
public void Perform(PossibleMatch Match, Actor Actor) { Processor(Match, Actor); }
public DisambigCommandHandler( Actor Actor, CommandParser.MatchedCommand MatchedCommand, ParserCommandHandler ParentHandler) { this.ParentHandler = ParentHandler; this.MatchedCommand = MatchedCommand; // Find an object parameter such that // a) each match has a parameter with that name // b) at least one match has a value different from the others var foundAmbiguousArgument = false; // Note that we iterate only over the arguments in the first match. If the first match doesn't have the // argument, that argument can't satisfy condition a above. foreach (var argument in MatchedCommand.Matches[0]) { // It's only possible to disambiguate on MudObjects. If any match - including the first one - has // a value for that argument that is not a MudObject, disambiguation will fail. if (argument.Value is MudObject) { var uniqueMatchables = new List<MudObject>(); var rejected = false; foreach (var match in MatchedCommand.Matches) { if (match.ContainsKey(argument.Key) && match[argument.Key] is MudObject) { var matchableObject = match[argument.Key] as MudObject; if (!uniqueMatchables.Contains(matchableObject)) uniqueMatchables.Add(matchableObject); } else { rejected = true; break; } } if (!rejected && uniqueMatchables.Count > 1) { // Disambiguate on this object. DisambigArgument = argument.Key; DisambigObjects = uniqueMatchables; foundAmbiguousArgument = true; break; } } } if (foundAmbiguousArgument) { var response = new StringBuilder(); response.Append("Which did you mean?\r\n"); for (var i = 0; i < DisambigObjects.Count; ++i) response.Append(String.Format("{0}: {1}\r\n", i, Core.GlobalRules.ConsiderValueRule<String>("printed name", Actor, DisambigObjects[i], "the"))); MudObject.SendMessage(Actor, response.ToString()); } else { MudObject.SendMessage(Actor, "I couldn't figure out how to disambiguate that command."); } }
bool Commands.ITakeRules.CanTake(Actor Actor) { return false; }
bool IOpenable.CanClose(Actor Actor) { return Open; }
public bool Match(String Word, Actor Actor) { foreach (var noun in Nouns) if (noun.Match(Word, Actor)) return true; return false; }
/// <summary> /// Parse and format a message intended for a specific recipient. /// </summary> /// <param name="Recipient"></param> /// <param name="Message">The message, possibly containing specifiers.</param> /// <param name="Objects">Specifier indicies refer to this list of objects.</param> /// <returns></returns> public static String FormatMessage(Actor Recipient, String Message, params Object[] Objects) { //A leading @ indicates that the message should be interpretted as an entry in the global message table. if (Message[0] == '@') Message = Core.GetMessage(Message.Substring(1)); var formattedMessage = new StringBuilder(); var iterator = new StringIterator(Message); while (!iterator.AtEnd) { if (iterator.Next == '<') //We have located a specifier. { var type = ""; var index = 0; if (MessageFormatParser.ReadSpecifier(iterator, out type, out index)) { if (index < 0 || index >= Objects.Length) continue; //A blank in the output is preferable to crashing. #region Expand Specifier if (type == "the" && Objects[index] is MudObject) { //'the' overrides the object's article property. formattedMessage.Append(GlobalRules.ConsiderValueRule<String>("printed name", Recipient, Objects[index], "the")); } else if (type == "a" && Objects[index] is MudObject) { formattedMessage.Append(GlobalRules.ConsiderValueRule<String>("printed name", Recipient, Objects[index], (Objects[index] as MudObject).Article)); } else if (type == "l") //No connective clause is used for this style of list. eg 1, 2, 3. { FormatList(Recipient, Objects[index], formattedMessage, ""); } else if (type == "lor") //Use or. eg 1, 2, or 3. { FormatList(Recipient, Objects[index], formattedMessage, "or"); } else if (type == "land") //Use and. eg 1, 2, and 3. { FormatList(Recipient, Objects[index], formattedMessage, "and"); } else if (type == "lnor") //Use nor. eg 1, 2, nor 3. { FormatList(Recipient, Objects[index], formattedMessage, "nor"); } else if (type == "s") { formattedMessage.Append(Objects[index].ToString()); } #endregion } } else { formattedMessage.Append(iterator.Next); iterator.Advance(); } } Message = formattedMessage.ToString(); formattedMessage.Clear(); iterator = new StringIterator(Message); //Apply the ^ transform: Capitalize the letter following the ^ and remove the ^. while (!iterator.AtEnd) { if (iterator.Next == '^') { iterator.Advance(); if (iterator.AtEnd) break; formattedMessage.Append(new String(iterator.Next, 1).ToUpper()); iterator.Advance(); } else { formattedMessage.Append(iterator.Next); iterator.Advance(); } } return formattedMessage.ToString(); }
bool IOpenable.CanOpen(Actor Actor) { return !Open; }
/// <summary> /// Format a list of mud objects using commas and a coordinating conjunction. EG, into the form 'a, b, and c'. /// </summary> /// <param name="Recipient">The actor that will, eventually, see the output.</param> /// <param name="ListObject">Either a MudObject or a List<MudObject>. The actual items to format.</param> /// <param name="FormattedMessage">Append the formatted message to this StringBuilder.</param> /// <param name="CoordinatingConjunction">The word that separates the final item of a list from those proceeding it. EG, and, or, nor.</param> private static void FormatList( Actor Recipient, Object ListObject, StringBuilder FormattedMessage, String CoordinatingConjunction) { // ListObject can be a MudObject or a List<MudObject>. The algorithm expects a list, so transform it. List<MudObject> list = null; if (ListObject is MudObject) { list = new List<MudObject>(); list.Add(ListObject as MudObject); } else list = ListObject as List<MudObject>; // If ListObject was neither a MudObject nor a List<MudObject>... if (list == null) return; for (int x = 0; x < list.Count; ++x) { FormattedMessage.Append(GlobalRules.ConsiderValueRule<String>("printed name", Recipient, list[x], list[x].Article)); if (x != list.Count - 1) FormattedMessage.Append(", "); if (x == list.Count - 2 && !String.IsNullOrEmpty(CoordinatingConjunction)) FormattedMessage.Append(CoordinatingConjunction + " "); } }
public bool Match(String Word, Actor Actor) { if (!Value.Contains(Word)) return false; if (Available != null) return Available(Actor); return true; }
public bool Match(String Word, Actor Actor) { if (Word != Value) return false; if (Available != null) return Available(Actor); return true; }
/// <summary> /// Actually carryout the command, following all of it's rules, including the before and after command rules. /// </summary> /// <param name="Command"></param> /// <param name="Match"></param> /// <param name="Actor"></param> /// <returns>The result of the command's procedural rules.</returns> private static PerformResult ExecuteCommand(CommandEntry Command, PossibleMatch Match, Actor Actor) { var result = PerformResult.Stop; Match.Upsert("COMMAND", Command); if (GlobalRules.ConsiderMatchBasedPerformRule("before command", Match, Actor) == PerformResult.Continue) { result = Command.ProceduralRules.Consider(Match, Actor); GlobalRules.ConsiderMatchBasedPerformRule("after command", Match, Actor); } GlobalRules.ConsiderPerformRule("after every command", Actor); return result; }
public static void RemovePlayer(Actor Actor) { GlobalRules.ConsiderPerformRule("player left", Actor); Actor.ConnectedClient = null; MudObject.Move(Actor, null); }
public static void TiePlayerToClient(Client Client, Actor Actor) { Client.Player = Actor; Actor.ConnectedClient = Client; }
public static void SendEventMessage(Actor Actor, EventMessageScope Scope, String Message) { DatabaseLock.WaitOne(); switch (Scope) { //Send message only to the player case EventMessageScope.Single: { if (Actor == null) break; if (Actor.ConnectedClient == null) break; PendingMessages.Add(new RawPendingMessage(Actor.ConnectedClient, Message)); } break; //Send message to everyone in the same location as the player case EventMessageScope.Local: { if (Actor == null) break; var location = Actor.Location as Room; if (location == null) break; foreach (var thing in location.Contents) { var other = thing as Actor; if (other == null) continue; if (other.ConnectedClient == null) continue; PendingMessages.Add(new RawPendingMessage(other.ConnectedClient, Message)); } } break; //Send message to everyone in the same location EXCEPT the player. case EventMessageScope.External: { if (Actor == null) break; var location = Actor.Location as Room; if (location == null) break; foreach (var thing in location.Contents) { var other = thing as Actor; if (other == null) continue; if (Object.ReferenceEquals(other, Actor)) continue; if (other.ConnectedClient == null) continue; PendingMessages.Add(new RawPendingMessage(other.ConnectedClient, Message)); } } break; } DatabaseLock.ReleaseMutex(); }