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(); } }
public void Load(VMMarshal input) { var clientJoin = (Context.Architecture == null); //var oldWorld = Context.World; Context = new VMContext(input.Context, Context); Context.VM = 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) { obj.HeadlineRenderer.Dispose(); } oldSounds.AddRange(obj.GetActiveSounds()); } } Entities = new List <VMEntity>(); Scheduler.Reset(); ObjectsById = new Dictionary <short, VMEntity>(); foreach (var ent in input.Entities) { VMEntity realEnt; var objDefinition = FSO.Content.Content.Get().WorldObjects.Get(ent.GUID); 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); } int i = 0; foreach (var ent in input.Entities) { var threadMarsh = input.Threads[i]; var realEnt = Entities[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 /= grp.Objects.Count; 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; PlatformState = input.PlatformState; ObjectId = input.ObjectId; //just a few final changes to refresh everything, and avoid signalling objects var clock = Context.Clock; Context.Architecture.SetTimeOfDay(clock.Hours / 24.0 + clock.Minutes / (24.0 * 60) + clock.Seconds / (24.0 * 60 * 60)); Context.Architecture.SignalAllDirty(); Context.DisableRouteInvalidation = true; Context.Architecture.Tick(); Context.DisableRouteInvalidation = false; Context.Architecture.WallDirtyState(input.Context.Architecture); 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 { obj.SoundThreads.Add(snd.SFX); // successfully transfer sound to new object } } if (clientJoin) { //run clientJoin functions to play object sounds, update some gfx. foreach (var obj in Entities) { obj.ExecuteEntryPoint(30, Context, true); } } Context.UpdateTSOBuildableArea(); if (OnFullRefresh != null) { OnFullRefresh(); } }