예제 #1
0
        public void CallRef(int refIndex, byte[] argsSerialized, out IntPtr retvalSerialized, out int retvalSize)
        {
            // not using using statements here as old Mono on Linux build doesn't know of these
#if IS_FXSERVER
            using (var syncContext = new SyncContextScope())
#endif
            {
                if (GameInterface.SnapshotStackBoundary(out var b))
                {
                    ScriptHost.SubmitBoundaryStart(b, b.Length);
                }

                try
                {
                    var retvalData = FunctionReference.Invoke(refIndex, argsSerialized);

                    if (retvalData != null)
                    {
                        if (m_retvalBuffer == IntPtr.Zero)
                        {
                            m_retvalBuffer     = Marshal.AllocHGlobal(32768);
                            m_retvalBufferSize = 32768;
                        }

                        if (m_retvalBufferSize < retvalData.Length)
                        {
                            m_retvalBuffer     = Marshal.ReAllocHGlobal(m_retvalBuffer, new IntPtr(retvalData.Length));
                            m_retvalBufferSize = retvalData.Length;
                        }

                        Marshal.Copy(retvalData, 0, m_retvalBuffer, retvalData.Length);

                        retvalSerialized = m_retvalBuffer;
                        retvalSize       = retvalData.Length;
                    }
                    else
                    {
                        retvalSerialized = IntPtr.Zero;
                        retvalSize       = 0;
                    }
                }
                catch (Exception e)
                {
                    retvalSerialized = IntPtr.Zero;
                    retvalSize       = 0;

                    PrintError($"reference call", e.InnerException ?? e);
                }
            }
        }
예제 #2
0
        public void TriggerEvent(string eventName, byte[] argsSerialized, string sourceString)
        {
            // not using using statements here as old Mono on Linux build doesn't know of these
#if IS_FXSERVER
            using (var syncContext = new SyncContextScope())
#endif
            {
                if (GameInterface.SnapshotStackBoundary(out var bo))
                {
                    ScriptHost.SubmitBoundaryStart(bo, bo.Length);
                }

                try
                {
#if IS_FXSERVER
                    var netSource = (sourceString.StartsWith("net") || sourceString.StartsWith("internal-net")) ? sourceString : null;
#else
                    var netSource = sourceString.StartsWith("net") ? sourceString : null;
#endif

                    var obj = MsgPackDeserializer.Deserialize(argsSerialized, netSource) as List <object> ?? (IEnumerable <object>) new object[0];

                    var scripts = ms_definedScripts.ToArray();

                    var objArray = obj.ToArray();

                    NetworkFunctionManager.HandleEventTrigger(eventName, objArray, sourceString);

                    foreach (var script in scripts)
                    {
                        Task.Factory.StartNew(() =>
                        {
                            BaseScript.CurrentName = $"eventHandler {script.GetType().Name} -> {eventName}";
                            var t = script.EventHandlers.Invoke(eventName, sourceString, objArray);
                            BaseScript.CurrentName = null;

                            return(t);
                        }, CancellationToken.None, TaskCreationOptions.None, CitizenTaskScheduler.Instance).Unwrap().ContinueWith(a =>
                        {
                            if (a.IsFaulted)
                            {
                                Debug.WriteLine($"Error invoking event handlers for {eventName}: {a.Exception?.InnerExceptions.Aggregate("", (b, s) => s + b.ToString() + "\n")}");
                            }
                        });
                    }

                    ExportDictionary.Invoke(eventName, objArray);

                    // invoke a single task tick
                    CitizenTaskScheduler.Instance.Tick();
                }
                catch (Exception e)
                {
                    PrintError($"event ({eventName})", e);
                }
                finally
                {
                    ScriptHost.SubmitBoundaryStart(null, 0);
                }
            }
        }