public void CanCompileCustomScriptContext() { CSharpScriptContext ctx = new CSharpScriptContext(); ctx.Script = "System.Console.WriteLine(\"monkey\");"; ctx.Execute(new Type[] {}, new Type[] {}); }
public static void __Start__(CSharpScriptContext context) { context.Dispatch.AddHandler <SPlayMoviePacket>((client, direction, packet, flags) => { return(false); }); context.Dispatch.AddHandler <CEndMoviePacket>((client, direction, packet, flags) => { return(false); }); context.Log.Basic("Started no cutscenes script"); }
public static void __Start__(CSharpScriptContext context) { _context = context; context.Dispatch.AddHandler <CCheckVersionPacket>((client, direction, packet, flags) => { foreach (var ver in packet.Versions) { _context.Log.Info("Client reported version: {0}", ver.Value); } return(true); }); context.Log.Basic("Started example script"); }
public static void __Stop__(CSharpScriptContext context) { context.Log.Basic("Stopped example script"); }
public static void __Stop__(CSharpScriptContext context) { context.Log.Basic("Stopped no cutscenes script"); }
public void Configure( IApplicationBuilder app, IWebHostEnvironment env, WebAppConfiguration webAppConfig, ProcessStore.IProcessStoreWriter processStoreWriter, Func <DateTimeOffset> getDateTimeOffset) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } var nextHttpRequestIndex = 0; var cyclicReductionStoreLock = new object(); DateTimeOffset?cyclicReductionStoreLastTime = null; var cyclicReductionStoreDistanceSeconds = (int)TimeSpan.FromHours(1).TotalSeconds; if (webAppConfig?.JsonStructure?.letsEncryptOptions != null) { app.UseFluffySpoonLetsEncryptChallengeApprovalMiddleware(); } var createVolatileHostAttempts = 0; var volatileHosts = new ConcurrentDictionary <string, CSharpScriptContext>(); InterfaceToHost.Result <InterfaceToHost.TaskResult.RunInVolatileHostError, InterfaceToHost.TaskResult.RunInVolatileHostComplete> performProcessTaskRunInVolatileHost( InterfaceToHost.Task.RunInVolatileHost runInVolatileHost) { if (!volatileHosts.TryGetValue(runInVolatileHost.hostId, out var volatileHost)) { return(new InterfaceToHost.Result <InterfaceToHost.TaskResult.RunInVolatileHostError, InterfaceToHost.TaskResult.RunInVolatileHostComplete> { err = new InterfaceToHost.TaskResult.RunInVolatileHostError { hostNotFound = new object(), } }); } var stopwatch = System.Diagnostics.Stopwatch.StartNew(); var fromVolatileHostResult = volatileHost.RunScript(runInVolatileHost.script); stopwatch.Stop(); return(new InterfaceToHost.Result <InterfaceToHost.TaskResult.RunInVolatileHostError, InterfaceToHost.TaskResult.RunInVolatileHostComplete> { ok = new InterfaceToHost.TaskResult.RunInVolatileHostComplete { exceptionToString = fromVolatileHostResult.Exception?.ToString(), returnValueToString = fromVolatileHostResult.ReturnValue?.ToString(), durationInMilliseconds = stopwatch.ElapsedMilliseconds, } }); } InterfaceToHost.TaskResult performProcessTask(InterfaceToHost.Task task) { if (task?.createVolatileHost != null) { var volatileHostId = System.Threading.Interlocked.Increment(ref createVolatileHostAttempts).ToString(); volatileHosts[volatileHostId] = new CSharpScriptContext(BlobLibrary.GetBlobWithSHA256); return(new InterfaceToHost.TaskResult { createVolatileHostResponse = new InterfaceToHost.Result <object, InterfaceToHost.TaskResult.CreateVolatileHostComplete> { ok = new InterfaceToHost.TaskResult.CreateVolatileHostComplete { hostId = volatileHostId, }, }, }); } if (task?.releaseVolatileHost != null) { volatileHosts.TryRemove(task?.releaseVolatileHost.hostId, out var volatileHost); return(new InterfaceToHost.TaskResult { completeWithoutResult = new object(), }); } if (task?.runInVolatileHost != null) { return(new InterfaceToHost.TaskResult { runInVolatileHostResponse = performProcessTaskRunInVolatileHost(task?.runInVolatileHost), }); } throw new NotImplementedException("Unexpected task structure."); } void performProcessTaskAndFeedbackEvent(InterfaceToHost.StartTask taskWithId) { var taskResult = performProcessTask(taskWithId.task); var interfaceEvent = new InterfaceToHost.Event { taskComplete = new InterfaceToHost.ResultFromTaskWithId { taskId = taskWithId.taskId, taskResult = taskResult, } }; processEventAndResultingRequests(interfaceEvent); } var processRequestCompleteHttpResponse = new ConcurrentDictionary <string, InterfaceToHost.HttpResponse>(); var persistentProcess = app.ApplicationServices.GetService <IPersistentProcess>(); void processEventAndResultingRequests(InterfaceToHost.Event interfaceEvent) { lock (processStoreWriter) { var serializedInterfaceEvent = Newtonsoft.Json.JsonConvert.SerializeObject(interfaceEvent, jsonSerializerSettings); var(eventResponses, compositionRecord) = persistentProcess.ProcessEvents(new[] { serializedInterfaceEvent }); processStoreWriter.AppendSerializedCompositionRecord(compositionRecord.serializedCompositionRecord); var serializedResponse = eventResponses.Single(); InterfaceToHost.ResponseOverSerialInterface structuredResponse = null; try { structuredResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <InterfaceToHost.ResponseOverSerialInterface>( serializedResponse); } catch (Exception parseException) { throw new Exception( "Failed to parse event response from app. Looks like the loaded elm app is not compatible with the interface.\nResponse from app follows:\n" + serializedResponse, parseException); } if (structuredResponse?.decodeEventSuccess == null) { throw new Exception("Hosted app failed to decode the event: " + structuredResponse.decodeEventError); } foreach (var requestFromProcess in structuredResponse.decodeEventSuccess) { if (requestFromProcess.completeHttpResponse != null) { processRequestCompleteHttpResponse[requestFromProcess.completeHttpResponse.httpRequestId] = requestFromProcess.completeHttpResponse.response; } if (requestFromProcess.startTask != null) { System.Threading.Tasks.Task.Run(() => performProcessTaskAndFeedbackEvent(requestFromProcess.startTask)); } } } } app .Use(async(context, next) => await Asp.MiddlewareFromWebAppConfig(webAppConfig, context, next)) .Run(async(context) => { var currentDateTime = getDateTimeOffset(); var timeMilli = currentDateTime.ToUnixTimeMilliseconds(); var httpRequestIndex = System.Threading.Interlocked.Increment(ref nextHttpRequestIndex); var httpRequestId = timeMilli.ToString() + "-" + httpRequestIndex.ToString(); { var httpEvent = AsPersistentProcessInterfaceHttpRequestEvent(context, httpRequestId, currentDateTime); var httpRequestInterfaceEvent = new InterfaceToHost.Event { httpRequest = httpEvent, }; processEventAndResultingRequests(httpRequestInterfaceEvent); } var waitForHttpResponseClock = System.Diagnostics.Stopwatch.StartNew(); while (true) { if (processRequestCompleteHttpResponse.TryRemove(httpRequestId, out var httpResponse)) { var headerContentType = httpResponse.headersToAdd ?.FirstOrDefault(header => header.name?.ToLowerInvariant() == "content-type") ?.values?.FirstOrDefault(); context.Response.StatusCode = httpResponse.statusCode; foreach (var headerToAdd in (httpResponse.headersToAdd).EmptyIfNull()) { context.Response.Headers[headerToAdd.name] = new Microsoft.Extensions.Primitives.StringValues(headerToAdd.values); } if (headerContentType != null) { context.Response.ContentType = headerContentType; } await context.Response.WriteAsync(httpResponse?.bodyAsString ?? ""); break; } if (60 <= waitForHttpResponseClock.Elapsed.TotalSeconds) { throw new TimeoutException( "Persistent process did not return a HTTP response within " + (int)waitForHttpResponseClock.Elapsed.TotalSeconds + " seconds."); } System.Threading.Thread.Sleep(100); } System.Threading.Thread.MemoryBarrier(); var cyclicReductionStoreLastAge = currentDateTime - cyclicReductionStoreLastTime; if (!(cyclicReductionStoreLastAge?.TotalSeconds < cyclicReductionStoreDistanceSeconds)) { if (System.Threading.Monitor.TryEnter(cyclicReductionStoreLock)) { try { var afterLockCyclicReductionStoreLastAge = currentDateTime - cyclicReductionStoreLastTime; if (afterLockCyclicReductionStoreLastAge?.TotalSeconds < cyclicReductionStoreDistanceSeconds) { return; } var reductionRecord = persistentProcess.ReductionRecordForCurrentState(); lock (processStoreWriter) { processStoreWriter.StoreReduction(reductionRecord); } cyclicReductionStoreLastTime = currentDateTime; System.Threading.Thread.MemoryBarrier(); } finally { System.Threading.Monitor.Exit(cyclicReductionStoreLock); } } } }); }