static void Import( Info info ) { Console.WriteLine( "Loading exported world database..." ); string baseDir = info.xmlDir; string binDir = Path.Combine( baseDir, "bin" ); string textDir = Path.Combine( baseDir, "text" ); string verbDir = Path.Combine( baseDir, "verb" ); string screenDir = Path.Combine( baseDir, "screen" ); XmlClimoo root = XmlPersistence.Load<XmlClimoo>( Path.Combine( baseDir, "mobs.xml" ) ); // Divine the next id from the existing ones. int nextId = -1; foreach( XmlMob m in root.mobs ) if( m.id > nextId ) nextId = m.id; ++nextId; Console.WriteLine( "Instantiating world objects..." ); var token = info.coredb.token(); // ?FIXME? This maybe should go through WorldDatabase too, but it gets unnecessarily // into the messy guts of World and Mob to do it that way. // Create a checkpoint. This will "overwrite" anything in the database // previously, but it will also allow for recovery. DBCheckpoint cp = new DBCheckpoint() { name = "Imported", time = DateTimeOffset.UtcNow }; info.coredb.insert( token, cp ); info.worlddb.setConfigInt( World.ConfigNextId, nextId ); // Load up the mobs. foreach( XmlMob m in root.mobs ) { DBMob dbmob = new DBMob() { objectId = m.id, location = m.locationId, owner = m.ownerId, parent = m.parentId, pathId = m.pathId, pulse = m.attrs.Any( a => a.name == "pulsefreq" ) }; info.coredb.insert( token, dbmob ); DBMobTable dbmobtable = new DBMobTable() { mob = dbmob.id, objectId = m.id, checkpoint = cp.id }; info.coredb.insert( token, dbmobtable ); foreach( XmlAttr attr in m.attrs ) { // We run attributes through the serializer to give it a chance to // convert it to another type. AttributeSerialized ser = new AttributeSerialized() { mimetype = attr.mimeType, binvalue = !String.IsNullOrEmpty( attr.dataContentName ) ? File.ReadAllBytes( Path.Combine( binDir, attr.dataContentName ) ) : null, strvalue = !String.IsNullOrEmpty( attr.textContentName ) ? File.ReadAllText( Path.Combine( textDir, attr.textContentName ) ) : null }; TypedAttribute ta = TypedAttribute.FromSerialized( ser ); ser = ta.serialize(); DBAttr dbattr = new DBAttr() { mime = ser.mimetype, name = attr.name, mob = dbmob.id, text = ser.strvalue, data = ser.binvalue }; info.coredb.insert( token, dbattr ); } foreach( XmlVerb verb in m.verbs ) { DBVerb dbverb = new DBVerb() { name = verb.name, code = !String.IsNullOrEmpty( verb.codeName ) ? File.ReadAllText( Path.Combine( verbDir, verb.codeName ) ) : null, mob = dbmob.id }; info.coredb.insert( token, dbverb ); } } Console.WriteLine( "Importing web database..." ); XmlClimooWeb web = XmlPersistence.Load<XmlClimooWeb>( Path.Combine( baseDir, "web.xml" ) ); foreach (var s in web.screens) { info.coredb.insert( token, new DBScreen() { name = s.name, text = File.ReadAllText( Path.Combine( screenDir, s.textName ) ) } ); } foreach (var u in web.users) { info.coredb.insert( token, new DBUser() { login = u.login, openId = u.openId, password = u.password, @object = u.objectId, name = u.name } ); } }
/// <summary> /// Loads the specified Mob from the current checkpoint. /// </summary> /// <param name="objectId">The Mob's object ID (not database ID)</param> /// <param name="world">The World object to attach this Mob to</param> /// <returns> /// The loaded Mob, or null if it doesn't exist in this checkpoint. /// </returns> public CanonMob loadMob( int objectId, CanonWorld world ) { // We don't need to write anything here, but the transaction may give us reader semantics too. lock( _lock ) using( var token = _db.token() ) using( var trans = _db.transaction( token ) ) { // Get the current checkpoint ID. ulong curCheckpoint = getLatestCheckpoint( token ); // Find the existing object in the MobTable. IEnumerable<DBMobTable> results = _db.select( token, new DBMobTable() { objectId = objectId, checkpoint = curCheckpoint }, new string[] { "objectId", "checkpoint" } ); if( !results.Any() ) return null; ulong mobDbId = results.First().mob; // Get the mob itself. IEnumerable<DBMob> mobs = _db.select( token, new DBMob() { id = mobDbId }, new string[] { "id" } ); if( !results.Any() ) throw new ArgumentException( "Database error: Mob is in mobtable, but non-existant" ); DBMob mob = mobs.First(); // Look for all of its attributes. IEnumerable<DBAttr> attrs = _db.select( token, new DBAttr() { mob = mobDbId }, new string[] { "mob" } ); // And all of its verbs. IEnumerable<DBVerb> verbs = _db.select( token, new DBVerb() { mob = mobDbId }, new string[] { "mob" } ); // Now put it all together into a world object. CanonMob cm = new CanonMob( world, objectId ); Mob m = Mob.Wrap( cm ); m.parentId = mob.parent ?? 0; m.locationId = mob.location ?? 0; m.ownerId = mob.owner; m.pathId = mob.pathId ?? null; foreach( DBAttr attr in attrs ) { AttributeSerialized ser = new AttributeSerialized() { mimetype = attr.mime, binvalue = attr.data, strvalue = attr.text }; var ta = TypedAttribute.FromSerialized( ser ); m.attrSet(attr.name, ta); } foreach( DBVerb verb in verbs ) { Verb v = new Verb() { name = verb.name, code = verb.code, }; m.verbSet(verb.name, v); } return cm; } }
public void TypedAttributeTest() { // Basic strings first. TypedAttribute str = TypedAttribute.FromValue( "Testing 1 2 3!" ); AttributeSerialized ser = str.serialize(); TypedAttribute strunser = TypedAttribute.FromSerialized( ser ); Assert.AreEqual( str.str, strunser.str ); // Simple CLR types. TypedAttribute intarr = TypedAttribute.FromValue( new int[] { 1, 2, 3, 4, 5 } ); ser = intarr.serialize(); TypedAttribute intunser = TypedAttribute.FromSerialized( ser ); Assert.AreEqual( intarr.getContents<int[]>(), intunser.getContents<int[]>() ); // An image. byte[] imgdata = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; TypedAttribute img = TypedAttribute.FromValue( imgdata, "image/jpeg" ); ser = img.serialize(); TypedAttribute imgunser = TypedAttribute.FromSerialized( ser ); Assert.AreEqual( imgdata, imgunser.getContents<byte[]>() ); // Deserialize old style binary data. int[] mobrefs = { 1, 2, 3, 4 }; var binser = new BinaryFormatter(); var stream = new MemoryStream(); binser.Serialize( stream, mobrefs ); AttributeSerialized attrser = new AttributeSerialized() { binvalue = stream.ToArray(), mimetype = "moo/objectrefs" }; TypedAttribute mobunser = TypedAttribute.FromSerialized( attrser ); Assert.AreEqual( mobrefs, ((object[])mobunser.contents).Select( m => ((Mob.Ref)m).id ).ToArray() ); Assert.Catch( typeof( ArgumentException ), () => { TypedAttribute attr = TypedAttribute.FromValue( new Undecorated() ); attr.serialize(); } ); Assert.Catch( typeof( ArgumentException ), () => { TypedAttribute attr2 = TypedAttribute.FromValue( new Undecorated[] { new Undecorated() } ); attr2.serialize(); } ); Assert.Catch( typeof( ArgumentException ), () => { TypedAttribute attr3 = TypedAttribute.FromValue( new Undecorated[][] { new Undecorated[] { new Undecorated() } } ); attr3.serialize(); } ); }