Example #1
0
        public static Coroutine everyFrame(this GameObject go, Fn <bool> f)
        {
            var behaviour =
                go.GetComponent <ASyncHelperBehaviour>() ??
                go.AddComponent <ASyncHelperBehaviour>();

            return(ASync.EveryFrame(behaviour, f));
        }
Example #2
0
 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)
                            );
        }
Example #4
0
 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);
     }));
 }
Example #5
0
 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));
         }
     }));
 }
Example #6
0
 public void failure(Fn <A> result)
 {
     if (retries < retryCount)
     {
         retries++;
         ASync.WithDelay(retryDelay, tryAction);
     }
     else
     {
         failAction(result());
     }
 }
Example #7
0
        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))
                           )
                       ));
        }
Example #8
0
 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)
                 );
         }
     }));
 }
Example #9
0
        /* 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
        }
Example #10
0
        /* Initialization. */
        static OnMainThread()
        {
            mainThread = Thread.CurrentThread;
#if UNITY_EDITOR
            if (Application.isPlaying)
            {
                ASync.EveryFrame(onUpdate);
            }
            else
            {
                EditorApplication.update += () => onUpdate();
            }
#else
            ASync.EveryFrame(onUpdate);
#endif
        }
Example #11
0
        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();
                });
            }
        }
Example #12
0
        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); }
                }
            };
        }
Example #13
0
 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);
                 }
             });
         }
     });
 }
Example #14
0
        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);
                }
            });
        });
Example #15
0
 // 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)
     );
Example #16
0
 public static void invoke <A>(Fn <Act <A> > act, A a) =>
 ASync.OnMainThread(() => act()?.Invoke(a));
Example #17
0
 /* Initialization. */
 static OnMainThread()
 {
     mainThread = Thread.CurrentThread;
     ASync.EveryFrame(onUpdate);
 }
Example #18
0
 public static void invoke <A, B>(Fn <Act <A, B> > act, A a, B b) =>
 ASync.OnMainThread(() => act()?.Invoke(a, b));
Example #19
0
 [UsedImplicitly] void onClick(AndroidJavaObject dialog, int which)
 {
     dialog.Call("cancel");
     ASync.OnMainThread(callback);
 }
Example #20
0
 /* Initialization. */
 static OnMainThread()
 {
     ASync.EveryFrame(onUpdate);
 }
Example #21
0
 public override AndroidJavaObject Invoke(string methodName, object[] args)
 {
     ASync.OnMainThread(() => invokeOnMain(methodName, args));
     return(null);
 }
Example #22
0
        [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);
            }
        }
Example #23
0
 static FPS()
 {
     ASync.StartCoroutine(update());
     ASync.StartCoroutine(calculate());
 }
Example #24
0
 public static void invoke(Fn <Action> aFn) =>
 ASync.OnMainThread(() => aFn()?.Invoke());
Example #25
0
 public static Future <A> runOnUI <A>(Fn <A> f) => Future <A> .async(promise => runOnUI(() => {
     var ret = f();
     ASync.OnMainThread(() => promise.complete(ret));
 }));
Example #26
0
 public static Coroutine everyFrame(this GameObject go, Fn <bool> f) => ASync.EveryFrame(go, f);
Example #27
0
        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;
        }
Example #28
0
 static void defer(Action a) => ASync.OnMainThread(a, runNowIfOnMainThread: false);