/// <summary> /// Plays a sound effect on the player's console. /// </summary> /// <param name="source">Mob the sound effect is located on.</param> /// <param name="attrName">Attribute name of the sound.</param> /// <param name="w">The world to use for its attribute generator.</param> /// <remarks> /// It's necessary to pass in a world here because, when this is called as part of a pulse /// notification, the player won't necessarily have a world. /// </remarks> public void playSound( Mob source, string attrName, World w ) { if( this.NewSound != null ) { string url = w.attributeUrlGenerator( source, attrName ); this.NewSound( url ); } }
public PulseRunner( World w ) { _world = w; }
/// <summary> /// Call when a new piece of input is received from the user. /// </summary> /// <param name="text">The new input</param> /// <returns>Some text to display to the user, if any.</returns> public string inputPush( string text, World world ) { use(false); if( this.inGame && text == "logout" ) { outputPush( new ConsoleCommand() { text = "<br/>Goodbye!<br/><br/>" } ); Game.Login.LogUserOut(this); return executeCommand( "look", world ); } else if( !this.inGame && text.StartsWithI( "login" ) ) { string[] pieces = text.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ); if( pieces.Length != 3 ) return "Could not log you in: incorrect syntax."; string result = Game.Login.LogUserIn( this, pieces[1], pieces[2] ); if( result != null ) return "Could not log you in: " + result; outputPush( "\nSuddenly you're falling...!\n\n" ); return executeCommand( "look", world ); } else { return executeCommand( text, world ); } }
// Executes a MOO command. string executeCommand( string text, World world ) { try { this.player.world = world; return MooCore.InputParser.ProcessInput(text, this.player); } catch (System.Exception ex) { return "<span class=\"error\">Exception: {0}".FormatI(ex.ToString()); } finally { world.waitForMerge(); this.player.world = null; } }
/// <summary> /// Call when a new piece of input is received from the user. /// </summary> /// <param name="text">The new input</param> /// <returns>Some text to display to the user, if any.</returns> public string inputPush( string text, World world ) { use(false); if( this.inGame && text == "logout" ) { outputPush( new ConsoleCommand() { text = "<br/>Goodbye!<br/><br/>" } ); Game.Login.LogUserOut(this); return executeCommand( "look", world ); } else if( !this.inGame && text.StartsWithI( "login" ) ) { string[] pieces = text.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ); if( pieces.Length != 3 ) return "Could not log you in: incorrect syntax."; string result = Game.Login.LogUserIn( this, pieces[1], pieces[2] ); if( result != null ) return "Could not log you in: " + result; outputPush( "\nSuddenly you're falling...!\n\n" ); return executeCommand( "look", world ); } else if( !this.inGame ) { // This is a sad shadow of what I'd hoped to attain with the public area, // but for now I wish to continue on with other things instead of fighting // the permissions system more. if( text == "look" ) return executeCommand( text, world ); else if( text == "help" ) outputPush( "\nType login to begin.\n" ); else outputPush( "\nSorry, I don't know what that means.\n" ); return ""; } else { return executeCommand( text, world ); } }
public void ConflictMerge() { createBasicWorld(); StringBuilder sb = new StringBuilder(); // Make a second shadow world to work with, to simluate two threads. ShadowWorld sw2 = new ShadowWorld( _cw ); World w2 = new World( sw2 ); Mob _test2 = Mob.Wrap( sw2.findObject( _testObj.id ) ); // Disable immediate updates. using( var token = _cw.getMergeToken() ) { // Do some interleaved writes. _testObj.attrSet( "testA", "Value A1" ); _test2.attrSet( "testA", "Value A2" ); _test2.attrSet( "testB", "Value B2" ); _testObj.attrSet( "testB", "Value B1" ); _testObj.verbSet( "testA", new Verb() { name = "testA", code = "//Value A1" } ); _test2.verbSet( "testA", new Verb() { name = "testA", code = "//Value A2" } ); _test2.verbSet( "testB", new Verb() { name = "testB", code = "//Value B2" } ); _testObj.verbSet( "testB", new Verb() { name = "testB", code = "//Value B1" } ); } _sw.waitForMerge(); sw2.waitForMerge(); sb.AppendLine( "Simultaneous merge:" ); sb.AppendLine( "Canon:" ); sb.AppendLine( printCanon() ); sb.AppendLine( "Shadow A:" ); sb.AppendLine( printWorld( _w ) ); sb.AppendLine( "Shadow B:" ); sb.AppendLine( printWorld( w2 ) ); // The second one will test one object getting a chance to update, and a second coming in later. _testObj.attrSet( "testC", "Value C1" ); using( var token = _cw.getMergeToken() ) { _test2.attrSet( "testC", "Value C2" ); _test2.attrSet( "testD", "Value D2" ); } _testObj.attrSet( "testD", "Value D1" ); using( var token = _cw.getMergeToken() ) { _testObj.verbSet( "testC", new Verb() { name = "testC", code = "//Value C1" } ); _test2.verbSet( "testC", new Verb() { name = "testC", code = "//Value C2" } ); } _test2.verbSet( "testD", new Verb() { name = "testD", code = "//Value D2" } ); _testObj.verbSet( "testD", new Verb() { name = "testD", code = "//Value D1" } ); _sw.waitForMerge(); sw2.waitForMerge(); sb.AppendLine( "Interleaved merge:" ); sb.AppendLine( "Canon:" ); sb.AppendLine( printCanon() ); sb.AppendLine( "Shadow A:" ); sb.AppendLine( printWorld( _w ) ); sb.AppendLine( "Shadow B:" ); sb.AppendLine( printWorld( w2 ) ); string results = sb.ToString(); TestCommon.CompareRef( Path.Combine( "WorldTest", "ConflictMerge" ), results ); }
string printWorld( World w ) { StringBuilder sb = new StringBuilder(); _w.findObjects( (mob) => { sb.AppendLine( printObject( mob ) ); return false; } ); return sb.ToString(); }
void createBasicWorld() { createBasicDatabase(); _cw = CanonWorld.FromWorldDatabase( _wdb, false, false ); _sw = new ShadowWorld( _cw ); _w = new World( _sw ); // We want to replace these with actual world copies now. _god = _w.findObject( 1 ); _templates = _w.findObject( 2 ); _playerTemplate = _w.findObject( 3 ); _player = _w.findObject( 4 ); _testObj = _w.findObject( 5 ); }
public void DeleteMerge() { createBasicWorld(); StringBuilder sb = new StringBuilder(); // Make a second shadow world to work with, to simluate two threads. ShadowWorld sw2 = new ShadowWorld( _cw ); World w2 = new World( sw2 ); Mob _test2 = Mob.Wrap( sw2.findObject( _testObj.id ) ); // Insert some values and make sure they show up for everyone. _testObj.attrSet( "test1", "Test 1" ); _testObj.attrSet( "test2", "Test 1" ); sb.AppendLine( "Pre-test:" ); sb.AppendLine( "Canon:" ); sb.AppendLine( printCanon() ); sb.AppendLine( "Shadow A:" ); sb.AppendLine( printWorld( _w ) ); sb.AppendLine( "Shadow B:" ); sb.AppendLine( printWorld( w2 ) ); // Now make some delete changes under conflict. using( var token = _cw.getMergeToken() ) { _testObj.attrSet( "test1", "Test 2" ); _test2.attrDel( "test1" ); _test2.attrDel( "test2" ); _testObj.attrSet( "test2", "Test 2" ); } _sw.waitForMerge(); sw2.waitForMerge(); sb.AppendLine( "Post-test:" ); sb.AppendLine( "Canon:" ); sb.AppendLine( printCanon() ); sb.AppendLine( "Shadow A:" ); sb.AppendLine( printWorld( _w ) ); sb.AppendLine( "Shadow B:" ); sb.AppendLine( printWorld( w2 ) ); string results = sb.ToString(); TestCommon.CompareRef( Path.Combine( "WorldTest", "DeleteMerge" ), results ); }