public static Coroutine everyFrame(this GameObject go, Fn <bool> f) { var behaviour = go.GetComponent <ASyncHelperBehaviour>() ?? go.AddComponent <ASyncHelperBehaviour>(); return(ASync.EveryFrame(behaviour, f)); }
public RegionClickObservable(int gridWidth = 2, int gridHeight = 2) { this.gridWidth = gridWidth; this.gridHeight = gridHeight; ASync.EveryFrame(() => { onUpdate(); return(true); }); }
static void WhenGameObjectDestroyed(GameObject go) { var sub = new Subject <Unit>().subscribeWhileAlive(go, _ => { }); Assert.AreEqual(sub.isSubscribed, true); Destroy(go); ASync.NextFrame(() => Assert.AreEqual(sub.isSubscribed, false) ); }
public static IObservable <DateTime> interval( Duration interval, Option <Duration> delay = default(Option <Duration>) ) { Option.ensureValue(ref delay); return(new Observable <DateTime>(observer => { var cr = ASync.StartCoroutine(intervalEnum(observer, interval, delay)); return new Subscription(cr.stop); })); }
public static ErrorReporter.OnError createEditorOnError( string apiKey, ErrorReporter.AppInfo appInfo ) { return(data => ASync.NextFrame(() => { if (Log.isInfo) { Log.info("Airbrake error:\n\n" + data + "\n" + xml(apiKey, appInfo, data)); } })); }
public void failure(Fn <A> result) { if (retries < retryCount) { retries++; ASync.WithDelay(retryDelay, tryAction); } else { failAction(result()); } }
public static Tpl <IAsyncOperation, Future <Either <ErrorMsg, A> > > loadAsync <A>( PathStr loadPath ) where A : Object { var path = loadPath.unityPath; IResourceRequest request = new WrappedResourceRequest(Resources.LoadAsync <A>(path)); return(F.t( request.upcast(default(IAsyncOperation)), Future <Either <ErrorMsg, A> > .async( p => ASync.StartCoroutine(waitForLoadCoroutine <A>(request, p.complete, path)) ) )); }
public static ErrorReporter.OnError createLogOnError( string loggerName, DSN dsn, ErrorReporter.AppInfo appInfo, ExtraData addExtraData ) { return(data => ASync.NextFrame(() => { if (Log.isInfo) { Log.info( $"Sentry error:\n\n{data}\nreporting url={dsn.reportingUrl}\n" + message(loggerName, dsn.keys, appInfo, data, addExtraData) ); } })); }
/* Initialization. */ static OnMainThread() { mainThread = Thread.CurrentThread; if (Application.isPlaying) { // In players isPlaying is always true. ASync.EveryFrame(onUpdate); } #if UNITY_EDITOR else { UnityEditor.EditorApplication.update += () => onUpdate(); } #endif }
/* Initialization. */ static OnMainThread() { mainThread = Thread.CurrentThread; #if UNITY_EDITOR if (Application.isPlaying) { ASync.EveryFrame(onUpdate); } else { EditorApplication.update += () => onUpdate(); } #else ASync.EveryFrame(onUpdate); #endif }
void onLogMessageReceived(string message, string stackTrace, LogType type) { foreach (var instance in current) { ASync.OnMainThread(() => { var entry = instance.view.logEntryPrefab.clone(); var shortText = $"{DateTime.Now} {type} {message}"; entry.text = shortText; entry.GetComponent <RectTransform>().SetParent( instance.view.logEntriesHolder.transform, worldPositionStays: false ); entry.transform.SetAsFirstSibling(); }); } }
public static void registerToUnity(OnError onError, bool logWarnings) { Action <Exception> logExceptionSafe = e => { ASync.OnMainThread( () => { // Log at info level so that we wouldn't trigger this handler again. Log.info( $"[{nameof(ErrorReporter)}] Exception in " + $"{nameof(Application)}.{nameof(Application.logMessageReceivedThreaded)}" + $" handler!\n\n{e}" ); }, // https://fogbugz.unity3d.com/default.asp?832198_48nbh0a3a8cjpr12 runNowIfOnMainThread: false ); }; Application.logMessageReceivedThreaded += (message, backtrace, type) => { if ( type == LogType.Assert || type == LogType.Error || type == LogType.Exception || logWarnings && type == LogType.Warning ) { try { // We want to collect backtrace on the current thread var parsedBacktrace = // backtrace may be empty in release mode. string.IsNullOrEmpty(backtrace) ? BacktraceElem.generateFromHere(1) : BacktraceElem.parseUnityBacktrace(backtrace); var data = new ErrorData(type, message, parsedBacktrace); // But call our error handler on main thread // because handlers are not guaranteed to be thread safe // and Log.info would not work in our handler ASync.OnMainThread( () => { try { onError(data); } catch (Exception e) { logExceptionSafe(e); } }, runNowIfOnMainThread: false ); } catch (Exception e) { logExceptionSafe(e); } } }; }
Application.LogCallback onLogMessageReceived( GameObjectPool <VerticalLayoutLogEntry> pool, List <string> resultsTo ) { return((message, stackTrace, type) => { foreach (var instance in current) { ASync.OnMainThread(() => { foreach (var e in createEntries( new LogEntry(message, type), pool, resultsTo, instance.view.lineWidth )) { instance.dynamicVerticalLayout.appendDataIntoLayoutData(e); } }); } }); }
Future <Either <WWWError, UsageCountedDisposable <Texture2D> > > download(Url url) => Future <Either <WWWError, UsageCountedDisposable <Texture2D> > > .async((promise, f) => { ASync.StartCoroutine(textureLoader( new WWW(url), promise, onDispose: t => { Object.Destroy(t); cache.Remove(url); if (Log.d.isDebug()) { Log.d.debug($"{nameof(ImageDownloader)} disposed texture: {url}"); } }) ); f.onComplete(e => { // remove from cache if image was not downloaded if (e.isLeft) { cache.Remove(url); } }); });
// TODO: test with ITimeContext public static SubscribeFn <A> delayed <A>(IObservable <A> o, Duration delay) => obs => o.subscribe( v => ASync.WithDelay(delay, () => obs.push(v)), () => ASync.WithDelay(delay, obs.finish) );
public static void invoke <A>(Fn <Act <A> > act, A a) => ASync.OnMainThread(() => act()?.Invoke(a));
/* Initialization. */ static OnMainThread() { mainThread = Thread.CurrentThread; ASync.EveryFrame(onUpdate); }
public static void invoke <A, B>(Fn <Act <A, B> > act, A a, B b) => ASync.OnMainThread(() => act()?.Invoke(a, b));
[UsedImplicitly] void onClick(AndroidJavaObject dialog, int which) { dialog.Call("cancel"); ASync.OnMainThread(callback); }
/* Initialization. */ static OnMainThread() { ASync.EveryFrame(onUpdate); }
public override AndroidJavaObject Invoke(string methodName, object[] args) { ASync.OnMainThread(() => invokeOnMain(methodName, args)); return(null); }
[OnWorldSave(Order = int.MaxValue)] // has to be last, obviously private static void SaveData() { if (!MyAPIGateway.Multiplayer.IsServer) { return; } try { // fetching data needs to happen on game thread as not every script has locks Builder_ArmsData data = new Builder_ArmsData(); data.SaveTime = Globals.ElapsedTimeTicks; data.ArmsVersion = Settings.ServerSettings.CurrentVersion; // network data Dictionary <long, RelayStorage.Builder_NetworkStorage> storages = new Dictionary <long, RelayStorage.Builder_NetworkStorage>(); Registrar.ForEach <RelayNode>(node => { if (node.Block != null && node.Storage != null && !storages.ContainsKey(node.Storage.PrimaryNode.EntityId)) { RelayStorage.Builder_NetworkStorage bns = node.Storage.GetBuilder(); if (bns != null) { storages.Add(bns.PrimaryNode, bns); } } }); data.AntennaStorage = storages.Values.ToArray(); // disruption List <Disruption.Builder_Disruption> systemDisrupt = new List <Disruption.Builder_Disruption>(); foreach (Disruption disrupt in Disruption.AllDisruptions) { systemDisrupt.Add(disrupt.GetBuilder()); } data.SystemDisruption = systemDisrupt.ToArray(); // autopilot List <ShipAutopilot.Builder_Autopilot> buildAuto = new List <ShipAutopilot.Builder_Autopilot>(); Registrar.ForEach <ShipAutopilot>(autopilot => { ShipAutopilot.Builder_Autopilot builder = autopilot.GetBuilder(); if (builder != null) { buildAuto.Add(builder); } }); data.Autopilot = buildAuto.ToArray(); // Sync data.Sync = ASync.GetBuilder(); MyAPIGateway.Utilities.SetVariable(SaveXml, MyAPIGateway.Utilities.SerializeToXML(data)); if (Instance.m_fileMaster != null) { string identifier = Instance.LegacyIdentifier(false); if (identifier != null) { if (Instance.m_fileMaster.Delete(identifier)) { Rynchodon.Logger.DebugLog("file deleted: " + identifier); } } } } catch (Exception ex) { Rynchodon.Logger.AlwaysLog("Exception: " + ex, Rynchodon.Logger.severity.ERROR); Rynchodon.Logger.Notify("ARMS: failed to save data", 60000, Rynchodon.Logger.severity.ERROR); } }
static FPS() { ASync.StartCoroutine(update()); ASync.StartCoroutine(calculate()); }
public static void invoke(Fn <Action> aFn) => ASync.OnMainThread(() => aFn()?.Invoke());
public static Future <A> runOnUI <A>(Fn <A> f) => Future <A> .async(promise => runOnUI(() => { var ret = f(); ASync.OnMainThread(() => promise.complete(ret)); }));
public static Coroutine everyFrame(this GameObject go, Fn <bool> f) => ASync.EveryFrame(go, f);
private void LoadSaveData(Builder_ArmsData data) { if (data == null) { Logger.DebugLog("No data to load"); return; } #pragma warning disable 612, 618 if (Comparer <Version> .Default.Compare(data.ArmsVersion, default(Version)) == 0) { Logger.DebugLog("Old version: " + data.ModVersion); data.ArmsVersion = new Version(data.ModVersion); } #pragma warning restore 612, 618 Logger.AlwaysLog("Save version: " + data.ArmsVersion, Rynchodon.Logger.severity.INFO); // relay Dictionary <Message.Builder_Message, Message> messages = MyAPIGateway.Multiplayer.IsServer ? new Dictionary <Message.Builder_Message, Message>() : null; SerializableGameTime.Adjust = new TimeSpan(data.SaveTime); foreach (RelayStorage.Builder_NetworkStorage bns in data.AntennaStorage) { RelayNode node; if (!Registrar.TryGetValue(bns.PrimaryNode, out node)) { Logger.AlwaysLog("Failed to get node for: " + bns.PrimaryNode, Rynchodon.Logger.severity.WARNING); continue; } RelayStorage store = node.Storage; if (store == null) // probably always true { node.ForceCreateStorage(); store = node.Storage; if (store == null) { Logger.AlwaysLog("failed to create storage for " + node.DebugName, Rynchodon.Logger.severity.ERROR); continue; } } foreach (LastSeen.Builder_LastSeen bls in bns.LastSeenList) { LastSeen ls = new LastSeen(bls); if (ls.IsValid) { store.Receive(ls); } else { Logger.AlwaysLog("failed to create a valid last seen from builder for " + bls.EntityId, Rynchodon.Logger.severity.WARNING); if (m_failedLastSeen == null) { m_failedLastSeen = new CachingDictionary <long, CachingList <LastSeen.Builder_LastSeen> >(); UpdateManager.Register(100, RetryLastSeen); } CachingList <LastSeen.Builder_LastSeen> list; if (!m_failedLastSeen.TryGetValue(bns.PrimaryNode, out list)) { list = new CachingList <LastSeen.Builder_LastSeen>(); m_failedLastSeen.Add(bns.PrimaryNode, list, true); } list.Add(bls); list.ApplyAdditions(); } } Logger.DebugLog("added " + bns.LastSeenList.Length + " last seen to " + store.PrimaryNode.DebugName, Rynchodon.Logger.severity.DEBUG); // messages in the save file belong on the server if (messages == null) { continue; } foreach (Message.Builder_Message bm in bns.MessageList) { Message msg; if (!messages.TryGetValue(bm, out msg)) { msg = new Message(bm); messages.Add(bm, msg); } else { Logger.DebugLog("found linked message", Rynchodon.Logger.severity.TRACE); } if (msg.IsValid) { store.Receive(msg); } else { Logger.AlwaysLog("failed to create a valid message from builder for " + bm.DestCubeBlock + "/" + bm.SourceCubeBlock, Rynchodon.Logger.severity.WARNING); } } Logger.DebugLog("added " + bns.MessageList.Length + " message to " + store.PrimaryNode.DebugName, Rynchodon.Logger.severity.DEBUG); } // past this point, only synchronized data if (!MyAPIGateway.Multiplayer.IsServer) { data = null; return; } // system disruption foreach (Disruption.Builder_Disruption bd in data.SystemDisruption) { Disruption disrupt; switch (bd.Type) { case "AirVentDepressurize": disrupt = new AirVentDepressurize(); break; case "CryoChamberMurder": disrupt = new CryoChamberMurder(); break; case "DisableTurret": disrupt = new DisableTurret(); break; case "DoorLock": disrupt = new DoorLock(); break; case "EMP": disrupt = new EMP(); break; case "GravityReverse": disrupt = new GravityReverse(); break; case "JumpDriveDrain": disrupt = new JumpDriveDrain(); break; case "MedicalRoom": disrupt = new MedicalRoom(); break; case "TraitorTurret": disrupt = new TraitorTurret(); break; default: Logger.AlwaysLog("Unknown disruption: " + bd.Type, Rynchodon.Logger.severity.WARNING); continue; } disrupt.Start(bd); } // autopilot if (data.Autopilot != null) { foreach (ShipAutopilot.Builder_Autopilot ba in data.Autopilot) { ShipAutopilot autopilot; if (Registrar.TryGetValue(ba.AutopilotBlock, out autopilot)) { autopilot.ResumeFromSave(ba); } else { Logger.AlwaysLog("failed to find autopilot block " + ba.AutopilotBlock, Rynchodon.Logger.severity.WARNING); } } } // programmable block if (data.ProgrammableBlock != null) { foreach (ProgrammableBlock.Builder_ProgrammableBlock bpa in data.ProgrammableBlock) { ProgrammableBlock pb; if (Registrar.TryGetValue(bpa.BlockId, out pb)) { pb.ResumeFromSave(bpa); } else { Logger.AlwaysLog("failed to find programmable block " + bpa.BlockId, Rynchodon.Logger.severity.WARNING); } } } // text panel if (data.TextPanel != null) { foreach (TextPanel.Builder_TextPanel btp in data.TextPanel) { TextPanel panel; if (Registrar.TryGetValue(btp.BlockId, out panel)) { panel.ResumeFromSave(btp); } else { Logger.AlwaysLog("failed to find text panel " + btp.BlockId, Rynchodon.Logger.severity.WARNING); } } } // weapon if (data.Weapon != null) { foreach (WeaponTargeting.Builder_WeaponTargeting bwt in data.Weapon) { WeaponTargeting targeting; if (WeaponTargeting.TryGetWeaponTargeting(bwt.WeaponId, out targeting)) { targeting.ResumeFromSave(bwt); } else { Logger.AlwaysLog("failed to find weapon " + bwt.WeaponId, Rynchodon.Logger.severity.WARNING); } } } // entity values if (data.EntityValues != null) { UpgradeEntityValue.Load(data.EntityValues); } // sync if (data.Sync != null) { ASync.SetBuilder(data.Sync); } data = null; }
static void defer(Action a) => ASync.OnMainThread(a, runNowIfOnMainThread: false);