예제 #1
0
파일: Program.cs 프로젝트: kayateia/climoo
        static void Main( string[] args )
        {
            if( args.Length != 2 )
            {
            Console.WriteLine( "Please specify the filename of an ImpExporter database config file and a player login name." );
            return;
            }

            // Load up the config.
            ImpExporterConfig cfg = XmlPersistence.Load<ImpExporterConfig>( args[0] );

            // Create a world, sans realtime save and pulse.
            Assembly asm = Assembly.Load( cfg.DatabaseAssembly );
            Type dbType = asm.GetType( cfg.DatabaseClass );
            IDatabase db = (IDatabase)Activator.CreateInstance( dbType );
            db.setup( cfg.ConnectionString, new TableInfo() );
            var coredb = new CoreDatabase( db );
            var worlddb = new WorldDatabase( coredb );
            var world = CanonWorld.FromWorldDatabase( worlddb, true, true );
            world.attributeUrlGenerator = ( obj, name ) => CultureFree.Format( "<attr:{0}.{1}>", obj.name, name );

            // Look up the player. If they passed "anon", then we use an anonymous, pre-login player.
            int mobid;
            if( args[1] == "anon" )
            {
            mobid = Mob.Anon.id;
            }
            else
            {
            using( var token = coredb.token() )
            {
                var users = coredb.select( token, new DBUser() { login = args[1] }, new string[] { "login" } );
                if( users.Count() != 1 )
                {
                    Console.WriteLine( "Couldn't match exactly one user with the login '{0}'", args[1] );
                    return;
                }

                mobid = users.First().@object;
            }
            }

            // Make a shadow world for us to use.
            var shadowWorld = new ShadowWorld( world );
            Mob playerMob = mobid > 0 ? Mob.Wrap( shadowWorld.findObject( mobid ) ) : null;

            // Make a player object.
            Player player = new Player( mobid );
            player.NewOutput = (o) =>
            {
            Console.WriteLine( "{0}", o );
            };
            player.NewSound = (o) =>
            {
            Console.WriteLine( "Would play sound: {0}", o );
            };
            player.NewErrorOutput = (o) =>
            {
            Console.WriteLine( "[error] {0}", o );
            };
            player.world = World.Wrap( shadowWorld );
            if( playerMob != null )
            playerMob.player = player;

            while( true )
            {
            Console.Write( "climoo> " );

            string command = Console.ReadLine();
            if( command == "exit" )
                break;

            string result = MooCore.InputParser.ProcessInput( command, player );
            if( !result.IsNullOrEmpty() )
                Console.WriteLine( result );

            shadowWorld.waitForMerge();
            }

            // Clear out any changes and timers.
            shadowWorld.Dispose();
            world.Dispose();
        }
예제 #2
0
        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 );
        }
예제 #3
0
        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 );
        }
예제 #4
0
        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 );
        }