static bool MatchObj(VerbParameters param, Mob m, Specifier spec) { if (spec == Specifier.Wildcard) return true; if (spec == Specifier.Any) return m != null && m != Mob.None; if (spec == Specifier.Self) return m != null && m.id == param.self.id; if (spec == Specifier.None && (m == null || m == Mob.None)) { return true; } return false; }
static bool MatchSig(VerbParameters param, Sig s) { if (s.wildcard) return true; return MatchObj(param, param.dobj, s.dobj) && MatchPrep(param.prep, s.prep) && MatchObj(param, param.iobj, s.iobj) && MatchPrep(param.prep2, s.prep2) && MatchObj(param, param.iobj2, s.iobj2); }
/// <summary> /// Finds matching verb signatures, given a set of input parameters, and taking into account wildcards. /// </summary> public IEnumerable<Sig> matchWildcards(VerbParameters param) { return from s in this.signatures where s.wildcard && MatchSig(param, s) select s; }
/// <summary> /// Finds matching verb signatures, given a set of input parameters. If the verb /// had none, then we find nothing. /// </summary> public IEnumerable<Sig> match(VerbParameters param) { if( this.signatures == null ) return new Sig[0]; return from s in this.signatures where MatchSig(param, s) select s; }
public object invoke( VerbParameters param, bool coralContinuation ) { // Inject the verb script blob parameters as script variables. var scope = new Dictionary<string, object>(); scope["input"] = param.input; scope["inputwords"] = param.inputwords; scope["self"] = new Proxies.MobProxy(param.self, param.player); scope["obj"] = new Proxies.MobProxy(param.dobj, param.player); if (param.prep != Prep.None) scope["prep"] = param.prep.ToString().ToLowerInvariant(); else scope["prep"] = null; scope["indobj"] = new Proxies.MobProxy(param.iobj, param.player); if (param.prep2 != Prep.None) scope["prep2"] = param.prep2.ToString().ToLowerInvariant(); else scope["prep2"] = null; scope["indobj2"] = new Proxies.MobProxy(param.iobj2, param.player); scope["objwords"] = param.dobjwords; scope["prepwords"] = param.prepwords; scope["indobjwords"] = param.iobjwords; scope["prep2words"] = param.prep2words; scope["indobj2words"] = param.iobj2words; // Inject some standard MOO objects. scope["ambiguous"] = Proxies.MobProxy.Ambiguous; scope["none"] = Proxies.MobProxy.None; // Inject the player object. Proxies.PlayerProxy player = null; if (param.player != null) player = new Proxies.PlayerProxy( param.player, param.world ); scope["player"] = player; // "caller" is the same as the player, unless otherwise specified. if (param.caller != null) scope["caller"] = new Proxies.MobProxy(param.caller, param.player); else scope["caller"] = player; scope["args"] = param.args; scope["world"] = new Proxies.WorldProxy(param.world, param.player); scope["$"] = new Proxies.MobProxy(param.world.findObject(1), param.player); scope["perms"] = Proxies.PermBitsProxy.Static; Func<string,object> querier = (name) => { if (name.StartsWithI("#")) { int number = CultureFree.ParseInt(name.Substring(1)); if( number == Mob.Anon.id ) { Mob m = param.player.anonMob; if( m != null ) return new Proxies.MobProxy( m, param.player ); } return new Proxies.MobProxy(param.world.findObject(number), param.player); } return null; }; // Is the verb valid / compiled properly? if( !_coral.success ) { player.write( "Verb was not properly compiled." ); if( _coral.errors != null ) { foreach( var err in _coral.errors ) player.write( " line {0}, col {1}: {2}".FormatI( err.line, err.col, err.message ) ); } return null; } // We have to run the code first, for it to define its verb. var runner = new Coral.Runner(); var tempScope = new Coral.StandardScope( runner.state.baseScope ); runner.pushScope( tempScope ); runner.setScopeCallback( querier ); foreach( var kv in scope ) runner.addToScope( kv.Key, kv.Value ); runner.runSync( _coral ); Coral.FValue verbFunc = (Coral.FValue)tempScope.get( "verb" ); tempScope.delete( "verb" ); // Now that's done, hook up to the main state. runner = new Coral.Runner( param.player.coralState ); runner.pushScope( tempScope ); // Pass these on literally to any down-stream invokes. runner.state.baggage.set( VerbParamsKey, param ); Coral.StackTrace.StackFrame frame = new Coral.StackTrace.StackFrame() { unitName = "<climoo>", funcName = "<trampoline>" }; // If there wasn't one, throw a sensible error. if( verbFunc == null ) throw new InvalidOperationException( "Verb does not define a function called 'verb'." ); // Print security context debug info if the player's debug flag is set. if( player.get.attrHas( "debug" ) ) { var value = player.get.attrGet( "debug" ).contents; if( value is bool && (bool)value ) { string securityStack = String.Join( "->", param.player.actorContextStack.Select( id => "{0}".FormatI( id ) ) .ToArray() ); string securityText = "[color=#0cc]Running {0} as {1} ({2})[/color]".FormatI( this.name, param.player.actorContext, securityStack ); param.player.writeError( securityText ); } } // If we came from Coral and we're going to Coral, use a continuation. if( coralContinuation ) { return new Coral.AsyncAction() { action = Coral.AsyncAction.Action.Call, function = verbFunc, args = param.args, frame = frame }; } else { try { runner.state.scope.set( "!verb-" + this.name, verbFunc ); return runner.callFunction( "!verb-" + this.name, param.args, typeof( object ), frame ); } catch( Coral.CoralException ex ) { param.player.writeError( "Unhandled exception {0}: {1}\n{2}".FormatI( ex.name, ex.Message, ex.trace ) ); return null; } } }
public object invoke( VerbParameters param ) { return invoke( param, false ); }
public object invoke(VerbParameters param) { // Inject the verb script blob parameters as script variables. var scope = new Scope(); scope.set("input", param.input); scope.set("inputwords", param.inputwords); scope.set("self", new Proxies.MobProxy(param.self, param.player)); scope.set("obj", new Proxies.MobProxy(param.dobj, param.player)); if (param.prep != Prep.None) scope.set("prep", param.prep.ToString().ToLowerInvariant()); else scope.set("prep", null); scope.set("indobj", new Proxies.MobProxy(param.iobj, param.player)); if (param.prep2 != Prep.None) scope.set("prep2", param.prep2.ToString().ToLowerInvariant()); else scope.set("prep2", null); scope.set("indobj2", new Proxies.MobProxy(param.iobj2, param.player)); scope.set("objwords", param.dobjwords); scope.set("prepwords", param.prepwords); scope.set("indobjwords", param.iobjwords); scope.set("prep2words", param.prep2words); scope.set("indobj2words", param.iobj2words); // Inject some standard MOO objects. scope.set("ambiguous", Proxies.MobProxy.Ambiguous); scope.set("none", Proxies.MobProxy.None); // Inject the player object. Proxies.PlayerProxy player = null; if (param.player != null) player = new Proxies.PlayerProxy( param.player, param.world ); scope.set("player", player); // "caller" is the same as the player, unless otherwise specified. if (param.caller != null) scope.set("caller", new Proxies.MobProxy(param.caller, param.player)); else scope.set("caller", player); scope.set("args", param.args); scope.set("world", new Proxies.WorldProxy(param.world, param.player)); scope.set("$", new Proxies.MobProxy(param.world.findObject(1), param.player)); scope.set( "perms", Proxies.PermBitsProxy.Static ); scope.queryForItem = (name) => { if (name.StartsWithI("#")) { int number = CultureFree.ParseInt(name.Substring(1)); if( number == Mob.Anon.id ) { Mob m = param.player.anonMob; if( m != null ) return new Proxies.MobProxy( m, param.player ); } return new Proxies.MobProxy(param.world.findObject(number), param.player); } return null; }; // Pass these on literally to any down-stream invokes. scope.baggageSet(VerbParamsKey, param); return _script.execute(scope); }