예제 #1
0
        /// <summary>
        /// Execute the input as if it were a tiny MooScript verb attached to the player.
        /// </summary>
        /// <returns>
        /// If the MooScript returns a value, it will be sent back to the player.
        /// </returns>
        public static string ExecuteImmediate(string input, Player player)
        {
            Verb v = new Verb() {
            name = "inline",
            help = "",
            code = input.Substring(1) + ';'
            };

            var param = new Verb.VerbParameters() {
            input = input,
            self = player.world.findObject( player.id ),
            dobj = Mob.None,
            prep = Verb.Prep.None,
            iobj = Mob.None,
            player = player,
            world = player.world
            };

            object rv;
            using( var ac = new ActorContext( player, player.id ) )
            rv = v.invoke( param );

            // Try to do some reallly basic type massaging to make it viewable on the terminal.
            string rvs;
            if (rv is string) {
            rvs = "\"{0}\"".FormatI(rv);
            } else if (rv is System.Collections.IEnumerable) {
            rvs = string.Join(", ", (from object i in (System.Collections.IEnumerable)rv select i.ToStringI()));
            } else
            rvs = rv.ToStringI();

            return MooCode.PrepareForClient(rvs);
        }
예제 #2
0
        /// <summary>
        /// Process a line of input from the player: parse and execute any action.
        /// </summary>
        public static string ProcessInput(string input, Player player)
        {
            // Ignore empty lines.
            if( input.Length == 0 )
            return "";

            // Does the input start with a special character?
            if (input[0] == ';') {
            // Execute this as a chunk of MooScript, as if it was attached
            // to the player.
            return ExecuteImmediate(input, player);
            }
            if (input[0] == '"')
            input = "say " + input.Substring(1);
            if (input[0] == ':')
            input = "emote " + input.Substring(1);
            if (input[0] == '@')
            input = "whisper " + input.Substring(1);

            // Split the input.
            string[] pieces = input.Trim().Split(' ', '\t', '\n', '\r');
            if (pieces.Length == 0)
            return "";

            // For now, the verb is always one word.
            string verb = pieces[0];
            if (verb.EqualsI("/me") || verb == ":") verb = "emote";

            // Start gathering values for the verb call.
            var param = new Verb.VerbParameters() {
            input = input,
            inputwords = pieces,
            self = null,
            world = player.world,
            player = player
            };

            // Try for a #1._processInput verb first. If one exists and it returns anything
            // besides false, we'll let it deal with everything else.
            var root = player.world.findObject( 1 );
            var playerMob = player.world.findObject( player.id );
            Verb rootProcess = root.verbGet("_processInput");
            if (rootProcess != null) {
            param.self = root;
            param.caller = playerMob;
            try
            {
                // This verb doesn't get any special permissions. It's just processing input from the user.
                object results;
                using( var ac = new ActorContext( player, player.id ) )
                    results = rootProcess.invoke(param);
                if (results == null || (results is bool && (bool)results == false)) {
                    // Proceed jolly onwards...
                } else {
                    // Our work here is finished.
                    return "";
                }
            }
            catch( Exception ex )
            {
                // Just assume it didn't handle it. Sucks to get in a loop here if you
                // mess up your global handler..!
                Log.Error( "Error while processing _processInput: {0}", ex );
            }
            param.self = null;
            param.caller = null;
            }

            // Look for complete wildcard verbs on the player and in the player's location.
            // If we find one that matches, stop processing anything else.
            var selectedVerb = SearchWildcardVerbsFrom(playerMob, verb, param);
            if (!selectedVerb.Any())
            selectedVerb = SearchWildcardVerbsFrom(playerMob.location, verb, param);
            if (selectedVerb.Any()) {
            var v = selectedVerb.First();

            param.self = v.foundOn;
            using( var ac = new ActorContext( player, v.definedOn.ownerId ) )
                v.verb.invoke(param);

            return "";
            }

            // Skip forward until we find a preposition.
            var remaining = pieces.Skip(1);
            var start = remaining;
            Verb.PrepMatch p = Verb.PrepMatch.None;
            string dobjName = null;
            for (int skip=0; skip<remaining.Count(); ++skip) {
            var chunk = remaining.Skip(skip);
            p = Verb.MatchPrep(chunk);
            if (p.isReal) {
                // Skip over the preposition after saving its words.
                param.prepwords = p.words.ToArray();
                remaining = chunk.Skip(param.prepwords.Length);

                // What came before it is the direct object.
                param.dobjwords = start.Take(skip).ToArray();
                dobjName = string.Join(" ", param.dobjwords);
                break;
            }
            }

            if (p.prep == Verb.Prep.None) {
            // No preposition -> the rest of the string is the direct object.
            param.dobjwords = remaining.ToArray();
            dobjName = string.Join(" ", param.dobjwords);
            remaining = new string[0];
            }

            // For now, the indirect object is always the rest of the phrase.
            string iobjName = null;
            if (remaining.Count() > 0) {
            param.iobjwords = remaining.ToArray();
            iobjName = string.Join(" ", param.iobjwords);
            }

            // Look for objects around the player that might match the direct and indirect objects.
            Mob dobj = ObjectMatch(dobjName, playerMob);
            Mob iobj = ObjectMatch(iobjName, playerMob);

            // Save the objects we found so we can verb-search.
            param.dobj = dobj;
            param.prep = p.prep;
            param.iobj = iobj;

            // Look for a matching verb.
            selectedVerb = SearchVerbsFrom(playerMob, verb, param);
            if (selectedVerb.Count() == 0)
            selectedVerb = SearchVerbsFrom(playerMob.location, verb, param);
            if (selectedVerb.Count() == 0 && dobj != null)
            selectedVerb = SearchVerbsFrom(dobj, verb, param);
            if (selectedVerb.Count() == 0 && iobj != null)
            selectedVerb = SearchVerbsFrom(iobj, verb, param);

            // Couldn't find one?
            if (selectedVerb.Count() != 1) {
            // Try for a "_huh" verb on the room the player is in.
            SourcedItem<Verb> huh = playerMob.location.findVerb("_huh");
            if (huh != null) {
                param.self = playerMob.location;
                using( var ac = new ActorContext( player, huh.source.id ) )
                    huh.item.invoke(param);
                return "";
            }

            // Nothin' doin'. Just return a default error.
            return "Sorry, I don't know what that means.";
            }

            // Execute the verb.
            var v2 = selectedVerb.First();
            param.self = v2.foundOn;
            using( var ac = new ActorContext( player, v2.definedOn.ownerId ) )
            v2.verb.invoke(param);

            // Any output will come from the script.
            return "";
        }