private void Game_OnWndProc(WndEventArgs args) { if (Game.IsChatOpen || args.WParam != this.key) { return; } if (args.Msg == WM_KEYDOWN || args.Msg == WM_SYSKEYDOWN) { if (!this.keyDown) { this.keyDown = true; this.startPos = Game.MouseScreenPosition - CircleSize / 2; } } else if (args.Msg == WM_KEYUP || args.Msg == WM_SYSKEYUP) { if (this.selectedAction != null) { GameDispatcher.BeginInvoke( () => { this.selectedAction.Execute(); this.selectedAction = null; }); } this.keyDown = false; } }
public async Task UnloadAsset(AssetId id) { GameDispatcher.EnsureAccess(); // Unload this object if it has already been loaded. using (await database.LockAsync()) { string url; if (AssetLoadingTimeUrls.TryGetValue(id, out url)) { UnloadContent(url); // Remove assets that were previously loaded but are not anymore from the assetLoadingTimeUrls map. foreach (var loadedUrls in AssetLoadingTimeUrls.Where(x => !Game.Content.IsLoaded(x.Value)).ToList()) { AssetLoadingTimeUrls.Remove(loadedUrls.Key); } } } }
private static async void UpdateOnLoad() { while (!loaderTask.IsCancellationRequested) { try { await Task.Delay(250, loaderTask.Token); if (OnLoad == null) { continue; } if (!IngameTrigger.Value) { continue; } var subscribers = OnLoad.GetInvocationList(); foreach (var subscriber in subscribers.Where(s => !NotifiedSubscribers.Contains(s))) { NotifiedSubscribers.Add(subscriber); GameDispatcher.BeginInvoke(() => { subscriber.DynamicInvoke(Type, EventArgs.Empty); }); } } catch (TaskCanceledException) { Console.WriteLine("Stopped LoaderTask"); } catch (Exception e) { Console.WriteLine(e); } } }
private Task CheckAssetsToReload() { return(GameDispatcher.InvokeTask(async() => { List <ReloadingAsset> assets; // Get assets to reload from queue lock (assetsToReloadLock) { // Nothing left, early exit if (assetsToReloadQueue.Count == 0) { return; } // Copy locally and clear queue assets = assetsToReloadQueue.ToList(); assetsToReloadQueue.Clear(); assetsToReloadMapping.Clear(); } // Update the colorspace Game.UpdateColorSpace(currentColorSpace); var objToFastReload = new Dictionary <string, object>(); using (await database.MountInCurrentMicroThread()) { // First, unload assets foreach (var assetToUnload in assets) { if (FastReloadTypes.Contains(assetToUnload.AssetItem.Asset.GetType()) && IsCurrentlyLoaded(assetToUnload.AssetItem.Asset.Id)) { // If this type supports fast reload, retrieve the current (old) value via a load var type = AssetRegistry.GetContentType(assetToUnload.AssetItem.Asset.GetType()); string url = GetLoadingTimeUrl(assetToUnload.AssetItem); var oldValue = Game.Content.Get(type, url); if (oldValue != null) { logger?.Debug($"Preparing fast-reload of {assetToUnload.AssetItem.Location}"); objToFastReload.Add(url, oldValue); } } else if (IsCurrentlyLoaded(assetToUnload.AssetItem.Asset.Id, true)) { // Unload this object if it has already been loaded. logger?.Debug($"Unloading {assetToUnload.AssetItem.Location}"); await UnloadAsset(assetToUnload.AssetItem.Asset.Id); } } // Process fast-reload objects var nonFastReloadAssets = new List <ReloadingAsset>(); foreach (var assetToLoad in assets) { object oldValue; string url = GetLoadingTimeUrl(assetToLoad.AssetItem); if (FastReloadTypes.Contains(assetToLoad.AssetItem.Asset.GetType()) && objToFastReload.TryGetValue(url, out oldValue)) { // Fill oldValue with the values from the database without reloading the object. // As a result, no reference needs to be updated. logger?.Debug($"Fast-reloading {assetToLoad.AssetItem.Location}"); ReloadContent(oldValue, assetToLoad.AssetItem); var loadedObject = oldValue; // This fast-reloaded content might have been already loaded through private reference, but if we're reloading it here, // it means that we expect a public reference (eg. it has just been referenced publicly). Reload() won't increase public reference count // so we have to do it manually. if (!IsCurrentlyLoaded(assetToLoad.AssetItem.Id, true)) { var type = AssetRegistry.GetContentType(assetToLoad.AssetItem.Asset.GetType()); LoadContent(type, url); } await Manager.ReplaceContent(assetToLoad.AssetItem.Asset.Id, loadedObject); assetToLoad.Result.SetResult(loadedObject); } else { nonFastReloadAssets.Add(assetToLoad); } } // Load all async object in a separate task // We avoid Game.Content.LoadAsync, which would wait next frame between every loaded asset var microThread = Scheduler.CurrentMicroThread; var bufferBlock = new BufferBlock <KeyValuePair <ReloadingAsset, object> >(); var task = Task.Run(() => { var initialContext = SynchronizationContext.Current; // This synchronization context gives access to any MicroThreadLocal values. The database to use might actually be micro thread local. SynchronizationContext.SetSynchronizationContext(new MicrothreadProxySynchronizationContext(microThread)); foreach (var assetToLoad in nonFastReloadAssets) { var type = AssetRegistry.GetContentType(assetToLoad.AssetItem.Asset.GetType()); string url = GetLoadingTimeUrl(assetToLoad.AssetItem); object loadedObject = null; try { loadedObject = LoadContent(type, url); } catch (Exception e) { logger?.Error($"Unable to load asset [{assetToLoad.AssetItem.Location}].", e); } // Post it in BufferBlock so that the game-side loop can process results incrementally bufferBlock.Post(new KeyValuePair <ReloadingAsset, object>(assetToLoad, loadedObject)); } bufferBlock.Complete(); SynchronizationContext.SetSynchronizationContext(initialContext); }); while (await bufferBlock.OutputAvailableAsync()) { var item = await bufferBlock.ReceiveAsync(); var assetToLoad = item.Key; var loadedObject = item.Value; if (loadedObject != null) { // If it's the first load of this asset, keep its loading url if (!AssetLoadingTimeUrls.ContainsKey(assetToLoad.AssetItem.Asset.Id)) { AssetLoadingTimeUrls.Add(assetToLoad.AssetItem.Asset.Id, assetToLoad.AssetItem.Location); } // Add assets that were not previously loaded to the assetLoadingTimeUrls map. var dependencyManager = Asset.AssetItem.Package.Session.DependencyManager; var dependencies = dependencyManager.ComputeDependencies(Asset.AssetItem.Id, AssetDependencySearchOptions.Out | AssetDependencySearchOptions.Recursive, ContentLinkType.Reference); if (dependencies != null) { foreach (var dependency in dependencies.LinksOut) { if (!AssetLoadingTimeUrls.ContainsKey(dependency.Item.Id)) { AssetLoadingTimeUrls.Add(dependency.Item.Id, dependency.Item.Location); } } } // Remove assets that were previously loaded but are not anymore from the assetLoadingTimeUrls map. foreach (var loadedUrls in AssetLoadingTimeUrls.Where(x => !Game.Content.IsLoaded(x.Value)).ToList()) { AssetLoadingTimeUrls.Remove(loadedUrls.Key); } } await Manager.ReplaceContent(assetToLoad.AssetItem.Asset.Id, loadedObject); assetToLoad.Result.SetResult(loadedObject); } // Make sure everything is complete before we return await task; } })); }
static void Main(string[] args) { string nodeName = args[0]; int nodeId = Int32.Parse(args[0]); Console.WriteLine("Node Id: " + nodeId); // These files are for asyncronous communication between this // worker and it's scheduler. // // Decks to evaluate come in the inbox and are dished out of the // outbox. string boxesDirectory = "boxes/"; string inboxPath = boxesDirectory + string.Format("deck-{0,4:D4}-inbox.tml", nodeId); string outboxPath = boxesDirectory + string.Format("deck-{0,4:D4}-outbox.tml", nodeId); // Hailing string activeDirectory = "active/"; string activeWorkerPath = activeDirectory + string.Format("worker-{0,4:D4}.txt", nodeId); string activeSearchPath = activeDirectory + "search.txt"; if (!File.Exists(activeSearchPath)) { Console.WriteLine("No search has been found."); return; } // The opponent deck doesn't change so we can load it here. string[] textLines = File.ReadAllLines(activeSearchPath); Console.WriteLine("Config File: " + textLines[1]); var config = Toml.ReadFile <Configuration>(textLines[1]); // Apply nerfs if nerfs are available ApplyNerfs(config.Nerfs); // Setup the pools of card decks for possible opponents. var deckPoolManager = new DeckPoolManager(); deckPoolManager.AddDeckPools(config.Evaluation.DeckPools); // Setup test suites: (strategy, deck) combos to play against. var suiteConfig = Toml.ReadFile <DeckSuite>( config.Evaluation.OpponentDeckSuite); var gameSuite = new GameSuite(suiteConfig.Opponents, deckPoolManager); // Let the scheduler know we are here. using (FileStream ow = File.Open(activeWorkerPath, FileMode.Create, FileAccess.Write, FileShare.None)) { WriteText(ow, "Hail!"); ow.Close(); } // Loop while the guiding search is running. while (File.Exists(activeSearchPath)) { // Wait until we have some work. while (!File.Exists(inboxPath) && File.Exists(activeSearchPath)) { Console.WriteLine("Waiting... (" + nodeId + ")"); Thread.Sleep(5000); } if (!File.Exists(activeSearchPath)) { break; } // Wait for the file to be finish being written Thread.Sleep(5000); // Run games, evaluate the deck, and then save the results. var playMessage = Toml.ReadFile <PlayMatchesMessage>(inboxPath); Deck playerDeck = playMessage.Deck.ContructDeck(); int numStrats = config.Evaluation.PlayerStrategies.Length; var stratStats = new StrategyStatistics[numStrats]; var overallStats = new OverallStatistics(); overallStats.UsageCounts = new int[playerDeck.CardList.Count]; RecordDeckProperties(playerDeck, overallStats); for (int i = 0; i < numStrats; i++) { // Setup the player with the current strategy PlayerStrategyParams curStrat = config.Evaluation.PlayerStrategies[i]; var player = new PlayerSetup(playerDeck, PlayerSetup.GetStrategy(curStrat.Strategy, config.Network, playMessage.Strategy)); List <PlayerSetup> opponents = gameSuite.GetOpponents(curStrat.NumGames); var launcher = new GameDispatcher( player, opponents ); // Run the game and collect statistics OverallStatistics stats = launcher.Run(); stratStats[i] = new StrategyStatistics(); stratStats[i].WinCount += stats.WinCount; stratStats[i].Alignment += stats.StrategyAlignment; overallStats.Accumulate(stats); } // Write the results overallStats.ScaleByNumStrategies(numStrats); var results = new ResultsMessage(); results.PlayerDeck = playMessage.Deck; results.OverallStats = overallStats; results.StrategyStats = stratStats; Toml.WriteFile <ResultsMessage>(results, outboxPath); // Wait for the TOML file to write (buffers are out of sync) // Then tell the search that we are done writing the file. Thread.Sleep(3000); File.Delete(inboxPath); // Cleanup. GC.Collect(); // Look at all the files in the current directory. // Eliminate anythings that matches our log file. /* * string[] oFiles = Directory.GetFiles(".", "DeckEvaluator.o*"); * foreach (string curFile in oFiles) * { * if (curFile.EndsWith(nodeName)) * { * File.Delete(curFile); * } * }*/ } }