// Merges all data from the given export to the live database. Does NOT // overwrite if entries already exist. public void MergeNonOverwrite(Database.Jsonable exported, HashSet <string> expectedBrainIds) { exported.AssertValid(); BeginBatchEdit("Merge"); try { exported.PerformUpgrades(expectedBrainIds); exported.AssertValid(); for (int i = 0; i < exported.behaviorIds.Length; i++) { string id = exported.behaviorIds[i]; if (!db.behaviors.Exists(id)) { PutBehavior(id, exported.behaviors[i]); } } for (int i = 0; i < exported.brainIds.Length; i++) { string id = exported.brainIds[i]; if (!db.brains.Exists(id)) { PutBrain(id, exported.brains[i]); } } } finally { EndBatchEdit("Merge"); } }
// Returns the brain ID of the imported brain in the active system. Ideally // wouldn't have this 'system' dependency..I think we need to move the // RPC/replication logic all into this class. Makes sense that the database // is responsible for keeping itself sync'd. public string ImportBrain(Database.Jsonable exported, string expectedBrainId) { exported.AssertValid(); BeginBatchEdit("ImportBrain"); try { exported.PerformUpgrades(new HashSet <string> { expectedBrainId }); exported.AssertValid(); Debug.Assert(exported.brainIds.Length == 1); Debug.Assert(exported.brains.Length == 1); Debug.Assert(exported.brainIds[0] == expectedBrainId); // Import all embedded behaviors, but give them new IDs Dictionary <string, string> exported2importedBehaviorId = new Dictionary <string, string>(); for (int i = 0; i < exported.behaviorIds.Length; i++) { string expId = exported.behaviorIds[i]; Behavior behavior = exported.behaviors[i]; string impId = GenerateUniqueId(); exported2importedBehaviorId[expId] = impId; PutBehavior(impId, behavior); } Brain brain = exported.brains[0]; // Convert all embedded behavior URIs to the imported ones. for (int i = 0; i < brain.behaviorUses.Length; i++) { var use = brain.behaviorUses[i]; if (IsEmbeddedBehaviorUri(use.behaviorUri)) { if (!exported2importedBehaviorId.ContainsKey(use.behaviorUri)) { // If the behavior URI doesn't exist, it was not exported. So just // assume this is meant to refer to some behavior that already // exists in the scene. Intended for scene actor library. // Check that it does exist. var existing = GetBehaviorData(use.behaviorUri); Debug.Assert(existing.javascript != null); continue; } // Freshly imported as a new behavior - update the URI. string expBehaviorId = BehaviorSystem.GetIdOfBehaviorUri(use.behaviorUri); string impBehaviorId = exported2importedBehaviorId[expBehaviorId]; use.behaviorUri = BehaviorSystem.IdToEmbeddedBehaviorUri(impBehaviorId); brain.behaviorUses[i] = use; } } // Ok, ready to go in! We want to import into a different brain ID, // though. string importedBrainId = GenerateUniqueId(); PutBrain(importedBrainId, brain); return(importedBrainId); } catch (System.Exception e) { Util.LogError($"ImportBrain exception: {e}"); throw e; } finally { EndBatchEdit("ImportBrain"); } }