public void LoadAsync(VMMarshal input)
{
FSOVAsyncLoading = true;
var lastBp = Context.Blueprint; //try keep this alive I suppose
//var oldWorld = Context.World;
//TS1 = input.TS1;
Context = new VMContext(input.Context, Context);
Context.VM = this;
var idMap = input.Context.Architecture.IDMap;
if (idMap != null)
{
idMap.Apply(this);
}
Context.Architecture.RegenRoomMap();
Context.RegeneratePortalInfo();
Context.Architecture.Terrain.RegenerateCenters();
if (VM.UseWorld)
{
Context.Blueprint.Altitude = Context.Architecture.Terrain.Heights;
Context.Blueprint.AltitudeCenters = Context.Architecture.Terrain.Centers;
}
var oldSounds = new List <VMSoundTransfer>();
if (Entities != null) //free any object resources here.
{
foreach (var obj in Entities)
{
obj.Dead = true;
if (obj.HeadlineRenderer != null)
{
if (UseWorld)
{
GameThread.InUpdate(() =>
{
obj.HeadlineRenderer.Dispose();
});
}
}
oldSounds.AddRange(obj.GetActiveSounds());
}
}
SoundEntities = new HashSet <VMEntity>();
Entities = new List <VMEntity>();
Scheduler.Reset();
ObjectsById = new Dictionary <short, VMEntity>();
FSOVObjTotal = input.Entities.Length;
foreach (var ent in input.Entities)
{
VMEntity realEnt;
var objDefinition = FSO.Content.Content.Get().WorldObjects.Get(ent.GUID);
if (objDefinition == null)
{
LoadErrors.Add(new VMLoadError(VMLoadErrorCode.MISSING_OBJECT,
"0x" + ent.GUID.ToString("X8") + " " + input.MultitileGroups.FirstOrDefault(x => x.Objects.Contains(ent.ObjectID))?.Name ?? "(unknown name)", (ushort)ent.ObjectID));
ent.LoadFailed = true;
continue;
}
if (ent is VMAvatarMarshal)
{
var avatar = new VMAvatar(objDefinition);
avatar.Load((VMAvatarMarshal)ent);
if (UseWorld)
{
Context.Blueprint.AddAvatar((AvatarComponent)avatar.WorldUI);
}
realEnt = avatar;
}
else
{
var worldObject = Context.MakeObjectComponent(objDefinition);
var obj = new VMGameObject(objDefinition, worldObject);
obj.Load((VMGameObjectMarshal)ent);
if (UseWorld)
{
Context.Blueprint.AddObject((ObjectComponent)obj.WorldUI);
Context.Blueprint.ChangeObjectLocation((ObjectComponent)obj.WorldUI, obj.Position);
}
obj.Position = obj.Position;
realEnt = obj;
}
realEnt.FetchTreeByName(Context);
Entities.Add(realEnt);
Context.ObjectQueries.NewObject(realEnt);
ObjectsById.Add(ent.ObjectID, realEnt);
FSOVObjLoaded++;
}
int i = 0;
int j = 0;
foreach (var ent in input.Entities)
{
if (ent.LoadFailed)
{
i++;
continue;
}
var threadMarsh = input.Threads[i];
var realEnt = Entities[j++];
i++;
realEnt.Thread = new VMThread(threadMarsh, Context, realEnt);
Scheduler.ScheduleTickIn(realEnt, 1);
if (realEnt is VMAvatar)
{
((VMAvatar)realEnt).LoadCrossRef((VMAvatarMarshal)ent, Context);
}
else
{
((VMGameObject)realEnt).LoadCrossRef((VMGameObjectMarshal)ent, Context);
}
}
foreach (var multi in input.MultitileGroups)
{
var grp = new VMMultitileGroup(multi, Context); //should self register
if (VM.UseWorld)
{
var b = grp.BaseObject;
var avgPos = new LotTilePos();
foreach (var obj in grp.Objects)
{
avgPos += obj.Position;
}
avgPos /= Math.Max(grp.Objects.Count, 1);
foreach (var obj in grp.Objects)
{
var off = obj.Position - avgPos;
obj.WorldUI.MTOffset = new Vector3(off.x, off.y, 0);
obj.Position = obj.Position;
}
}
var persist = grp.BaseObject?.PersistID ?? 0;
if (persist != 0 && grp.BaseObject is VMGameObject)
{
Context.ObjectQueries.RegisterMultitilePersist(grp, persist);
}
}
foreach (var ent in Entities)
{
if (ent.Container == null)
{
ent.PositionChange(Context, true); //called recursively for contained objects.
}
}
GlobalState = input.GlobalState;
if (TS1)
{
((VMTS1LotState)input.PlatformState).CurrentFamily = TS1State.CurrentFamily;
}
var lastPlatformState = PlatformState;
PlatformState = input.PlatformState;
PlatformState.ActivateValidator(this);
if (lastPlatformState != null && lastPlatformState is VMTSOLotState)
{
TSOState.Names = ((VMTSOLotState)lastPlatformState).Names;
}
ObjectId = input.ObjectId;
//just a few final changes to refresh everything, and avoid signalling objects
var clock = Context.Clock;
Context.Architecture.SetTimeOfDay();
Context.Architecture.SignalAllDirty();
Context.DisableRouteInvalidation = true;
Context.Architecture.Tick();
Context.DisableRouteInvalidation = false;
Context.Architecture.WallDirtyState(input.Context.Architecture);
if (oldSounds.Count > 0)
{
GameThread.InUpdate(() =>
{
foreach (var snd in oldSounds)
{
//find new owners
var obj = GetObjectById(snd.SourceID);
if (obj == null || obj.Object.GUID != snd.SourceGUID)
{
snd.SFX.Sound.RemoveOwner(snd.SourceID);
}
else
{
SoundEntities.Add(obj);
obj.SoundThreads.Add(snd.SFX); // successfully transfer sound to new object
}
}
});
}
Context.UpdateTSOBuildableArea();
Tuning = input.Tuning;
UpdateTuning();
if (OnFullRefresh != null)
{
OnFullRefresh();
}
}