/// <summary> /// Saves the specified Mob to the current checkpoint, overwriting any previous value. /// </summary> public void saveMob( Mob m ) { lock( _lock ) using( var token = _db.token() ) using( var trans = _db.transaction( token ) ) { // Get the current checkpoint ID. ulong curCheckpoint = getLatestCheckpoint( token ); // Is it in the mob table for this checkpoint? If not, we just write out a new one. IEnumerable<DBMobTable> mt = _db.select( token, new DBMobTable() { objectId = m.id }, new string[] { "objectId" } ); if( mt.Count( mtm => mtm.checkpoint == curCheckpoint ) > 0 ) { // Just delete the mobtable entry. _db.delete( token, new DBMobTable() { id = mt.First().id }, new string[] { "id" } ); // Is it used in any other checkpoints? If so, we have to make a new one too. if( mt.Count() == 1 ) { // Delete the existing data. ulong mobId = mt.First().mob; deleteMobInternal( token, mobId ); } } // Any old object will have been deleted by this point, so we make a new one. DBMob dbmob = new DBMob() { objectId = m.id, location = m.locationId, owner = m.ownerId, parent = m.parentId, pathId = m.pathId, pulse = m.pulseFreq != 0 }; _db.insert( token, dbmob ); // Write out a new mobtable entry. DBMobTable dbmobtable = new DBMobTable() { mob = dbmob.id, objectId = m.id, checkpoint = curCheckpoint }; _db.insert( token, dbmobtable ); // Save out all the attributes. foreach( var attrName in m.attrList ) { // Canon mobs can return timestamped empties for deletion. TypedAttribute attr = m.attrGet( attrName ); if( attr != null ) { AttributeSerialized ser = attr.serialize(); DBAttr dbattr = new DBAttr() { mime = ser.mimetype, name = attrName, mob = dbmob.id, text = ser.strvalue, data = ser.binvalue }; _db.insert( token, dbattr ); } } // Save out all the verbs. foreach( var verbName in m.verbList ) { // Canon mobs can return timestamped empties for deletion. Verb v = m.verbGet( verbName ); if( v != null ) { DBVerb dbverb = new DBVerb() { name = v.name, code = v.code, mob = dbmob.id, }; _db.insert( token, dbverb ); } } trans.commit(); } }
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 } ); } }