static void RegisterComponents(EventExchange global, IContainer services, string baseDir, CommandLineOptions commandLine) { PerfTracker.StartupEvent("Creating main components"); var factory = global.Resolve <ICoreFactory>(); global .Register <ICommonColors>(new CommonColors(factory)) .Register(CoreConfig.Load(baseDir)) .Register(GameConfig.Load(baseDir)) ; if (commandLine.AudioMode == AudioMode.InProcess) { services.Add(new AudioManager(false)); } services .Add(new GameState()) .Add(new GameClock()) .Add(new IdleClock()) .Add(new SlowClock()) .Add(new DeviceObjectManager()) .Add(new SpriteManager()) .Add(new TextureManager()) .Add(new EventChainManager()) .Add(new Querier()) .Add(new MapManager()) .Add(new CollisionManager()) .Add(new SceneStack()) .Add(new SceneManager() .AddScene((GameScene) new EmptyScene() .Add(new PaletteManager())) .AddScene((GameScene) new AutomapScene() .Add(new PaletteManager())) .AddScene((GameScene) new FlatScene() .Add(new ConversationManager()) .Add(new PaletteManager())) .AddScene((GameScene) new DungeonScene() .Add(new ConversationManager()) .Add(new PaletteManager())) .AddScene((GameScene) new MenuScene() .Add(new PaletteManager()) .Add(new MainMenu()) .Add(Sprite <PictureId> .ScreenSpaceSprite( PictureId.MenuBackground8, new Vector2(-1.0f, 1.0f), new Vector2(2.0f, -2.0f)))) .AddScene((GameScene) new InventoryScene() .Add(new ConversationManager()) .Add(new PaletteManager()) .Add(new InventoryInspector()))) .Add(new TextFormatter()) .Add(new TextManager()) .Add(new LayoutManager()) .Add(new DialogManager()) .Add(new InventoryScreenManager()) .Add(new DebugMapInspector(services) .AddBehaviour(new SpriteInstanceDataDebugBehaviour()) .AddBehaviour(new FormatTextEventBehaviour()) .AddBehaviour(new QueryEventDebugBehaviour())) .Add(new StatusBar()) .Add(new ContextMenu()) .Add(new CursorManager()) .Add(new InputManager() .RegisterInputMode(InputMode.ContextMenu, new ContextMenuInputMode()) .RegisterInputMode(InputMode.World2D, new World2DInputMode()) .RegisterMouseMode(MouseMode.DebugPick, new DebugPickMouseMode()) .RegisterMouseMode(MouseMode.MouseLook, new MouseLookMouseMode()) .RegisterMouseMode(MouseMode.Normal, new NormalMouseMode()) .RegisterMouseMode(MouseMode.RightButtonHeld, new RightButtonHeldMouseMode()) .RegisterMouseMode(MouseMode.ContextMenu, new ContextMenuMouseMode())) .Add(new SelectionManager()) .Add(new InputBinder(InputConfig.Load(baseDir))) .Add(new ItemTransitionManager()) ; }
public static void RunGame(EventExchange global, IContainer services, string baseDir, CommandLineOptions commandLine) { PerfTracker.StartupEvent("Creating engine"); using var engine = new VeldridEngine(commandLine.Backend, commandLine.UseRenderDoc) .AddRenderer(new SkyboxRenderer()) .AddRenderer(new SpriteRenderer()) .AddRenderer(new ExtrudedTileMapRenderer()) .AddRenderer(new FullScreenQuad()) .AddRenderer(new DebugGuiRenderer()) .AddRenderer(new ScreenDuplicator()) ; var backgroundThreadInitTask = Task.Run(() => RegisterComponents(global, services, baseDir, commandLine)); services .Add(new ShaderCache( Path.Combine(baseDir, "src", "Core", "Visual", "Shaders"), Path.Combine(baseDir, "data", "ShaderCache"))) .Add(engine); backgroundThreadInitTask.Wait(); if (commandLine.StartupOnly) { global.Raise(new QuitEvent(), null); } PerfTracker.StartupEvent("Running game"); global.Raise(new SetSceneEvent(SceneId.Empty), null); switch (commandLine.GameMode) { case GameMode.MainMenu: global.Raise(new SetSceneEvent(SceneId.MainMenu), null); break; case GameMode.NewGame: global.Raise(new NewGameEvent(MapDataId.Toronto2DGesamtkarteSpielbeginn, 30, 75), null); break; case GameMode.LoadGame: global.Raise(new LoadGameEvent(ushort.Parse(commandLine.GameModeArgument)), null); break; case GameMode.LoadMap: global.Raise(new NewGameEvent((MapDataId)int.Parse(commandLine.GameModeArgument), 40, 40), null); break; case GameMode.Inventory: global.Raise(new SetSceneEvent(SceneId.Inventory), null); break; default: throw new ArgumentOutOfRangeException(); } if (commandLine.Commands != null) { foreach (var command in commandLine.Commands) { global.Raise(Event.Parse(command), null); } } engine.Run(); // TODO: Ensure all sprite leases returned etc to weed out memory leaks }
public static (Container, IsometricBuilder) SetupEngine( EventExchange exchange, int tileWidth, int tileHeight, int baseHeight, int tilesPerRow, GraphicsBackend backend, bool useRenderDoc, Rectangle?windowRect) { if (exchange == null) { throw new ArgumentNullException(nameof(exchange)); } var framebuffer = new SimpleFramebuffer((uint)(tileWidth * tilesPerRow), (uint)tileHeight, "FB_Offscreen"); var builder = new IsometricBuilder(framebuffer, tileWidth, tileHeight, baseHeight, tilesPerRow); #pragma warning disable CA2000 // Dispose objects before losing scopes var config = exchange.Resolve <IGeneralConfig>(); var shaderCache = new ShaderCache(config.ResolvePath("$(CACHE)/ShaderCache")); var sceneRenderer = new SceneRenderer("MainPipeline", framebuffer) .AddRenderer(new SpriteRenderer(framebuffer), typeof(VeldridSpriteBatch)) .AddRenderer(new EtmRenderer(framebuffer), typeof(EtmWindow)) ; foreach (var shaderPath in exchange.Resolve <IModApplier>().ShaderPaths) { shaderCache.AddShaderPath(shaderPath); } var engine = new Engine( backend, useRenderDoc, false, windowRect != null, sceneRenderer, windowRect) ; var renderableSources = new IRenderableSource[] { new EtmManager(), new SpriteManager(), }; var services = new Container("IsometricLayoutServices"); services .Add(shaderCache) .Add(framebuffer) .Add(sceneRenderer) .Add(engine) .Add(new SpriteSamplerSource()) .Add(new TextureSource()) .Add(new ResourceLayoutSource()) .Add(new VeldridCoreFactory()) .Add(new SceneStack()) .Add(new SceneManager() .AddScene(new EmptyScene()) .AddScene((IScene) new IsometricBakeScene() .Add(new PaletteManager()) .Add(builder))) ; foreach (var source in renderableSources) { if (source is IComponent component) { services.Add(component); } sceneRenderer.AddSource(source); } return(services, builder); }
public void YesNoPromptTest() { AssetMapping.GlobalIsThreadLocal = true; AssetMapping.Global.Clear() .RegisterAssetType(typeof(Base.SystemText), AssetType.Text) ; var systemText = new Dictionary <TextId, string> { { Base.SystemText.MainMenu_DoYouReallyWantToQuit, "Do you really want to quit?" }, { Base.SystemText.MsgBox_Yes, "Yes" }, { Base.SystemText.MsgBox_No, "No" } }; var ex = new EventExchange(new LogExchange()); var dm = new DialogManager(); var lm = new LayoutManager(); var mma = new MockModApplier(GameLanguage.English) .Add(new AssetId(AssetType.MetaFont, (ushort)new MetaFontId(false, FontColor.White)), MockUniformFont.Font) ; foreach (var kvp in systemText) { mma.Add(kvp.Key, kvp.Value); } ex .Attach(mma) .Attach(new AssetManager()) .Attach(new TextFormatter()) .Attach(new TextManager()) .Attach(new SpriteManager()) .Attach(new WindowManager { Window = new MockWindow(1920, 1080) }) .Attach(new MockSettings { Language = GameLanguage.English }) .Attach(dm) .Attach(lm) ; var e = new YesNoPromptEvent((TextId)Base.SystemText.MainMenu_DoYouReallyWantToQuit); bool?result = null; ex.RaiseAsync <bool>(e, null, x => result = x); Assert.Null(result); var layout = lm.GetLayout(); Assert.Equal(1, layout.Children.Count); // Should only be one top-level dialog var yesText = layout.DepthFirstSearch(x => x.Element is TextLine txt && txt.ToString().Contains("\"Yes\"")).First(); var yesButton = (Button)yesText.Ancestors.First(x => x.Element is Button).Element; yesButton.Receive(new HoverEvent(), null); yesButton.Receive(new UiLeftClickEvent(), null); yesButton.Receive(new UiLeftReleaseEvent(), null); Assert.True(result); layout = lm.GetLayout(); Assert.Equal(0, layout.Children.Count); // Dialog should be closed, so no top-level dialogs // Open another yes/no dialog e = new YesNoPromptEvent((TextId)Base.SystemText.MainMenu_DoYouReallyWantToQuit); ex.RaiseAsync <bool>(e, this, x => result = x); layout = lm.GetLayout(); Assert.Equal(1, layout.Children.Count); // Should only be one top-level dialog var noText = layout.DepthFirstSearch(x => x.Element is TextLine txt && txt.ToString().Contains("\"No\"")).First(); var noButton = (Button)noText.Ancestors.First(x => x.Element is Button).Element; noButton.Receive(new HoverEvent(), null); noButton.Receive(new UiLeftClickEvent(), null); noButton.Receive(new UiLeftReleaseEvent(), null); Assert.False(result); }
public void YesNoPromptTest() { var systemText = new Dictionary <int, string> { { (int)SystemTextId.MainMenu_DoYouReallyWantToQuit, "Do you really want to quit?" }, { (int)SystemTextId.MsgBox_Yes, "Yes" }, { (int)SystemTextId.MsgBox_No, "No" } }; var ex = new EventExchange(new LogExchange()); var dm = new DialogManager(); var lm = new LayoutManager(); var alr = new MockAssetLocatorRegistry() .Add(new AssetKey(AssetType.SystemText), systemText) .Add(new AssetKey(AssetType.MetaFont, (ushort)new MetaFontId()), MockUniformFont.Font) ; ex .Attach(alr) .Attach(new AssetManager()) .Attach(new TextFormatter()) .Attach(new TextManager()) .Attach(new SpriteManager()) .Attach(new WindowManager { Window = new MockWindow(1920, 1080) }) .Attach(new MockSettings { Language = GameLanguage.English }) .Attach(dm) .Attach(lm) ; var e = new YesNoPromptEvent(SystemTextId.MainMenu_DoYouReallyWantToQuit); bool?result = null; ex.RaiseAsync <bool>(e, null, x => result = x); Assert.Null(result); var layout = lm.GetLayout(); Assert.Equal(1, layout.Children.Count); // Should only be one top-level dialog var yesText = layout.DepthFirstSearch(x => x.Element is TextLine txt && txt.ToString().Contains("\"Yes\"")).First(); var yesButton = (Button)yesText.Ancestors.First(x => x.Element is Button).Element; yesButton.Receive(new HoverEvent(), null); yesButton.Receive(new UiLeftClickEvent(), null); yesButton.Receive(new UiLeftReleaseEvent(), null); Assert.True(result); layout = lm.GetLayout(); Assert.Equal(0, layout.Children.Count); // Dialog should be closed, so no top-level dialogs // Open another yes/no dialog e = new YesNoPromptEvent(SystemTextId.MainMenu_DoYouReallyWantToQuit); ex.RaiseAsync <bool>(e, this, x => result = x); layout = lm.GetLayout(); Assert.Equal(1, layout.Children.Count); // Should only be one top-level dialog var noText = layout.DepthFirstSearch(x => x.Element is TextLine txt && txt.ToString().Contains("\"No\"")).First(); var noButton = (Button)noText.Ancestors.First(x => x.Element is Button).Element; noButton.Receive(new HoverEvent(), null); noButton.Receive(new UiLeftClickEvent(), null); noButton.Receive(new UiLeftReleaseEvent(), null); Assert.False(result); }
public void Attach(EventExchange exchange) { }
static void Main(string[] args) { //TransformTests(); _startupOnly = args.Contains("--startuponly"); _useRenderDoc = args.Contains("--renderdoc") || args.Contains("-rd"); if (args.Contains("-gl") || args.Contains("--opengl")) { _backend = GraphicsBackend.OpenGL; } if (args.Contains("-gles") || args.Contains("--opengles")) { _backend = GraphicsBackend.OpenGLES; } if (args.Contains("-vk") || args.Contains("--vulkan")) { _backend = GraphicsBackend.Vulkan; } if (args.Contains("-metal") || args.Contains("--metal")) { _backend = GraphicsBackend.Metal; } if (args.Contains("-d3d") || args.Contains("--direct3d")) { _backend = GraphicsBackend.Direct3D11; } PerfTracker.StartupEvent("Entered main"); //GraphTests(); //return; Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Required for code page 850 support in .NET Core PerfTracker.StartupEvent("Registered encodings"); /* * Console.WriteLine("Entry point reached. Press enter to continue"); * Console.ReadLine(); //*/ var baseDir = FormatUtil.FindBasePath(); if (baseDir == null) { throw new InvalidOperationException("No base directory could be found."); } PerfTracker.StartupEvent($"Found base directory {baseDir}"); var logger = new ConsoleLogger(); var settings = new Settings { BasePath = baseDir }; PerfTracker.StartupEvent("Registering asset manager"); using var assets = new AssetManager(); using var global = new EventExchange("Global", logger); Global = global; Global // Need to register settings first, as the AssetConfigLocator relies on it. .Register <ISettings>(settings) .Register <IEngineSettings>(settings) .Register <IAssetManager>(assets) ; PerfTracker.StartupEvent("Registered asset manager"); // Dump.CoreSprites(assets, baseDir); // Dump.CharacterSheets(assets); // Dump.Chests(assets); // Dump.ItemData(assets, baseDir); // Dump.MapEvents(assets, baseDir, MapDataId.Toronto2DGesamtkarteSpielbeginn); //return; RunGame(Global, baseDir); }
static async Task <(EventExchange, IContainer)> SetupAssetSystem(string baseDir) { var generalConfigTask = Task.Run(() => { var result = GeneralConfig.Load(Path.Combine(baseDir, "data", "config.json"), baseDir); PerfTracker.StartupEvent("Loaded general config"); return(result); }); var settingsTask = Task.Run(() => { var result = GeneralSettings.Load(Path.Combine(baseDir, "data", "settings.json")); PerfTracker.StartupEvent("Loaded settings"); return(result); }); var coreConfigTask = Task.Run(() => { var result = CoreConfig.Load(Path.Combine(baseDir, "data", "core.json")); PerfTracker.StartupEvent("Loaded core config"); return(result); }); var gameConfigTask = Task.Run(() => { var result = GameConfig.Load(Path.Combine(baseDir, "data", "game.json")); PerfTracker.StartupEvent("Loaded game config"); return(result); }); var assets = new AssetManager(); var factory = new VeldridCoreFactory(); var loaderRegistry = new AssetLoaderRegistry(); var locatorRegistry = new AssetLocatorRegistry(); var containerLoaderRegistry = new ContainerLoaderRegistry().AddLoader(new RawContainerLoader()) .AddLoader(new XldContainerLoader()) .AddLoader(new BinaryOffsetContainerLoader()) .AddLoader(new ItemListContainerLoader()) .AddLoader(new SpellListContainerLoader()) .AddLoader(new DirectoryContainerLoader()) ; var modApplier = new ModApplier() // Register post-processors for handling transformations of asset data that can't be done by UAlbion.Formats alone. .AddAssetPostProcessor(new AlbionSpritePostProcessor()) .AddAssetPostProcessor(new ImageSharpPostProcessor()) .AddAssetPostProcessor(new InterlacedBitmapPostProcessor()) .AddAssetPostProcessor(new InventoryPostProcessor()) .AddAssetPostProcessor(new ItemNamePostProcessor()); var settings = await settingsTask.ConfigureAwait(false); var services = new Container("Services", settings, // Need to register settings first, as the AssetLocator relies on it. loaderRegistry, locatorRegistry, containerLoaderRegistry, new MetafontBuilder(factory), new StdioConsoleLogger(), // new ClipboardManager(), new ImGuiConsoleLogger(), new WordLookup(), new AssetLocator(), modApplier, assets); var generalConfig = await generalConfigTask.ConfigureAwait(false); using var exchange = new EventExchange(new LogExchange()).Register <IGeneralConfig>(generalConfig) .Register <ICoreFactory>(factory) .Attach(services); PerfTracker.StartupEvent("Registered asset services"); Engine.GlobalExchange = exchange; generalConfig.SetPath("LANG", settings.Language.ToString() .ToUpperInvariant()); // Ensure that the LANG path is set before resolving any assets modApplier.LoadMods(generalConfig); PerfTracker.StartupEvent("Loaded mods"); var coreConfig = await coreConfigTask.ConfigureAwait(false); var gameConfig = await gameConfigTask.ConfigureAwait(false); exchange // Need to load game config after mods so asset ids can be parsed. .Register(coreConfig) .Register(gameConfig); PerfTracker.StartupEvent("Loaded core and game config"); return(exchange, services); }
static void RunGame(EventExchange global, string baseDir) { PerfTracker.StartupEvent("Creating engine"); using var engine = new Engine(_backend, _useRenderDoc) .AddRenderer(new SpriteRenderer()) .AddRenderer(new ExtrudedTileMapRenderer()) .AddRenderer(new FullScreenQuad()) .AddRenderer(new DebugGuiRenderer()) .AddRenderer(new ScreenDuplicator()) ; global .Register <IShaderCache>(new ShaderCache( Path.Combine(baseDir, "Core", "Visual"), Path.Combine(baseDir, "data", "ShaderCache"))) .Attach(engine); var backgroundThreadInitTask = Task.Run(() => { PerfTracker.StartupEvent("Creating main components"); global .Register <IInputManager>(new InputManager() .RegisterInputMode(InputMode.ContextMenu, new ContextMenuInputMode()) .RegisterInputMode(InputMode.World2D, new World2DInputMode()) .RegisterMouseMode(MouseMode.DebugPick, new DebugPickMouseMode()) .RegisterMouseMode(MouseMode.Exclusive, new ExclusiveMouseMode()) .RegisterMouseMode(MouseMode.MouseLook, new MouseLookMouseMode()) .RegisterMouseMode(MouseMode.Normal, new NormalMouseMode()) ) .Register <ILayoutManager>(new LayoutManager()) .Register <IMapManager>(new MapManager()) .Register <IPaletteManager>(new PaletteManager()) .Register <ISceneManager>(new SceneManager() .AddScene(new AutomapScene()) .AddScene(new FlatScene()) .AddScene(new DungeonScene()) .AddScene(new MenuScene()) .AddScene(new InventoryScene()) ) .Register <IClock>(new GameClock()) .Register <ISpriteResolver>(new SpriteResolver()) .Register <IGameState>(new GameState()) .Register <ITextManager>(new TextManager()) .Register <ITextureManager>(new TextureManager()) .Attach(new CursorManager()) .Attach(new DebugMapInspector()) .Attach(new InputBinder(InputConfig.Load(baseDir))) .Attach(new InputModeStack()) .Attach(new MouseModeStack()) .Attach(new SceneStack()) .Attach(new StatusBar()) ; PerfTracker.StartupEvent("Creating scene-specific components"); var inventoryConfig = InventoryConfig.Load(baseDir); global.Resolve <ISceneManager>().GetExchange(SceneId.Inventory) .Attach(new InventoryScreen(inventoryConfig)) ; var menuBackground = new ScreenSpaceSprite <PictureId>( PictureId.MenuBackground8, new Vector2(-1.0f, 1.0f), new Vector2(2.0f, -2.0f)); global.Resolve <ISceneManager>().GetExchange(SceneId.MainMenu) .Attach(new MainMenu()) .Attach(menuBackground) ; PerfTracker.StartupEvent("Starting new game"); //global.Raise(new LoadMapEvent(MapDataId.Jirinaar3D), null); /* /* * global.Raise(new LoadMapEvent(MapDataId.AltesFormergebäude), null); /* * global.Raise(new LoadMapEvent(MapDataId.HausDesJägerclans), null); //*/ /* * global.Raise(new SetSceneEvent(SceneId.Inventory), null); * //*/ //global.Raise(new SetSceneEvent((int)SceneId.MainMenu), null); global.Raise(new NewGameEvent(), null); ReflectionHelper.ClearTypeCache(); }); engine.Initialise(); backgroundThreadInitTask.Wait(); PerfTracker.StartupEvent("Running game"); if (_startupOnly) { global.Raise(new QuitEvent(), null); } engine.Run(); }
public static void RunGame(IEngine engine, EventExchange global, IContainer services, string baseDir, CommandLineOptions commandLine) { #pragma warning disable CA2000 // Dispose objects before losing scopes services .Add(new ShaderCache(Path.Combine(baseDir, "data", "ShaderCache")) .AddShaderPath(Path.Combine(baseDir, "src", "Core", "Visual", "Shaders")) // TODO: Pull from mod config .AddShaderPath(Path.Combine(baseDir, "src", "Game", "Visual", "Shaders"))) .Add(engine); #pragma warning restore CA2000 // Dispose objects before losing scopes RegisterComponents(global, services, baseDir, commandLine); if (commandLine.DebugMenus && engine is VeldridEngine ve) { services.Add(new DebugMenus(ve)); } if (commandLine.StartupOnly) { global.Raise(new QuitEvent(), null); } PerfTracker.StartupEvent("Running game"); global.Raise(new SetSceneEvent(SceneId.Empty), null); switch (commandLine.GameMode) { case GameMode.MainMenu: global.Raise(new SetSceneEvent(SceneId.MainMenu), null); break; case GameMode.NewGame: global.Raise(new NewGameEvent(Base.Map.TorontoBegin, 30, 75), null); break; case GameMode.LoadGame: global.Raise(new LoadGameEvent(ushort.Parse(commandLine.GameModeArgument, CultureInfo.InvariantCulture)), null); break; case GameMode.LoadMap: global.Raise(new NewGameEvent((Base.Map) int.Parse(commandLine.GameModeArgument, CultureInfo.InvariantCulture), 40, 40), null); break; case GameMode.Inventory: global.Raise(new SetSceneEvent(SceneId.Inventory), null); break; default: throw new ArgumentOutOfRangeException($"Unexpected game mode \"{commandLine.GameMode}\""); } if (commandLine.Commands != null) { foreach (var command in commandLine.Commands) { global.Raise(Event.Parse(command), null); } } engine.Run(); // TODO: Ensure all sprite leases returned etc to weed out memory leaks }
static void Main(string[] args) { PerfTracker.StartupEvent("Entered main"); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Required for code page 850 support in .NET Core PerfTracker.StartupEvent("Registered encodings"); var commandLine = new CommandLineOptions(args); if (commandLine.Mode == ExecutionMode.Exit) { return; } var baseDir = FormatUtil.FindBasePath(); if (baseDir == null) { throw new InvalidOperationException("No base directory could be found."); } PerfTracker.StartupEvent($"Found base directory {baseDir}"); PerfTracker.StartupEvent("Registering asset manager"); var factory = new VeldridCoreFactory(); using var locatorRegistry = new AssetLocatorRegistry() .AddAssetLocator(new StandardAssetLocator()) .AddAssetLocator(new AssetConfigLocator()) .AddAssetLocator(new CoreSpriteLocator()) .AddAssetLocator(new MetaFontLocator(factory)) .AddAssetLocator(new NewStringLocator()) .AddAssetLocator(new SoundBankLocator()) .AddAssetLocator(new SavedGameLocator()) .AddAssetPostProcessor(new AlbionSpritePostProcessor()) .AddAssetPostProcessor(new ImageSharpPostProcessor()) .AddAssetPostProcessor(new InterlacedBitmapPostProcessor()) .AddAssetPostProcessor(new InventoryPostProcessor()) ; var assets = new AssetManager(); var services = new Container("Services", new StdioConsoleLogger(), new ClipboardManager(), new ImGuiConsoleLogger(), Settings.Load(baseDir), // Need to register settings first, as the AssetConfigLocator relies on it. locatorRegistry, assets); using var exchange = new EventExchange(new LogExchange()) .Register <ICoreFactory>(factory) .Attach(services); Engine.GlobalExchange = exchange; PerfTracker.StartupEvent("Registered asset manager"); PerfTracker.StartupEvent($"Running as {commandLine.Mode}"); switch (commandLine.Mode) { case ExecutionMode.Game: case ExecutionMode.GameWithSlavedAudio: Albion.RunGame(exchange, services, baseDir, commandLine); break; case ExecutionMode.AudioSlave: exchange.Attach(new AudioManager(true)); break; case ExecutionMode.Editor: break; // TODO case ExecutionMode.SavedGameTests: SavedGameTests.RoundTripTest(baseDir); break; case ExecutionMode.DumpData: PerfTracker.BeginFrame(); // Don't need to show verbose startup logging while dumping var tf = new TextFormatter(); exchange.Attach(tf); DumpType dumpTypes = DumpType.All; if (commandLine.GameModeArgument != null) { dumpTypes = 0; foreach (var t in commandLine.GameModeArgument.Split(' ', StringSplitOptions.RemoveEmptyEntries)) { dumpTypes |= Enum.Parse <DumpType>(t); } } if ((dumpTypes & DumpType.Characters) != 0) { Dump.CharacterSheets(assets, tf, baseDir); } if ((dumpTypes & DumpType.Chests) != 0) { Dump.Chests(assets, baseDir); } if ((dumpTypes & DumpType.CoreSprites) != 0) { Dump.CoreSprites(assets, baseDir); } if ((dumpTypes & DumpType.EventSets) != 0) { Dump.EventSets(assets, baseDir); } if ((dumpTypes & DumpType.Items) != 0) { Dump.ItemData(assets, baseDir); } if ((dumpTypes & DumpType.MapEvents) != 0) { Dump.MapEvents(assets, baseDir); } if ((dumpTypes & DumpType.Maps) != 0) { Dump.MapData(assets, tf, baseDir); } if ((dumpTypes & DumpType.Spells) != 0) { Dump.Spells(assets, tf, baseDir); } if ((dumpTypes & DumpType.ThreeDMaps) != 0) { Dump.ThreeDMapAndLabInfo(assets, baseDir); } if ((dumpTypes & DumpType.MonsterGroups) != 0) { Dump.MonsterGroups(assets, baseDir); } break; case ExecutionMode.Exit: break; } }
public void RaiseAsyncTest() { var c1 = new BasicComponent(); var c2 = new BasicComponent(); var c3 = new BasicComponent(); var pending2 = new Queue <Action>(); var pending3 = new Queue <Action <bool> >(); c1.AddHandler <BoolAsyncEvent>(_ => { }); c1.AddHandler <BasicAsyncEvent>(_ => { }); c2.AddAsyncHandler <BasicAsyncEvent>((_, c) => { pending2.Enqueue(c); return(true); }); c3.AddAsyncHandler <BoolAsyncEvent, bool>((_, c) => { pending3.Enqueue(c); return(true); }); void Check(int seen1, int seen2, int seen3, int handled1, int handled2, int handled3) { Assert.Equal(seen1, c1.Seen); Assert.Equal(seen2, c2.Seen); Assert.Equal(seen3, c3.Seen); Assert.Equal(handled1, c1.Handled); Assert.Equal(handled2, c2.Handled); Assert.Equal(handled3, c3.Handled); } var boolEvent = new BoolAsyncEvent(); var nullEvent = new BasicAsyncEvent(); var ee = new EventExchange(new BasicLogExchange()); ee.Attach(c1); ee.Attach(c2); ee.Attach(c3); Check(0, 0, 0, 0, 0, 0); ee.Raise(boolEvent, this); Check(1, 0, 1, 1, 0, 0); Assert.Empty(pending2); Assert.Collection(pending3, _ => { }); pending3.Dequeue()(true); Check(1, 0, 1, 1, 0, 1); var recipients = ee.EnumerateRecipients(typeof(BoolAsyncEvent)).ToList(); Assert.Collection(recipients, x => Assert.Equal(x, c1), x => Assert.Equal(x, c3)); recipients = ee.EnumerateRecipients(typeof(BasicAsyncEvent)).ToList(); Assert.Collection(recipients, x => Assert.Equal(x, c1), x => Assert.Equal(x, c2)); int total = 0; int totalTrue = 0; void BoolContinuation(bool x) { total++; if (x) { totalTrue++; } } void PlainContinuation() => total++; Assert.Equal(1, ee.RaiseAsync(boolEvent, this, BoolContinuation)); // 1 async handler, 1 sync Check(2, 0, 2, 2, 0, 1); pending3.Dequeue()(true); Check(2, 0, 2, 2, 0, 2); Assert.Equal(1, total); Assert.Equal(1, totalTrue); Assert.Equal(1, ee.RaiseAsync(boolEvent, this, BoolContinuation)); // 1 async handler, 1 sync Check(3, 0, 3, 3, 0, 2); pending3.Dequeue()(false); Assert.Equal(2, total); Assert.Equal(1, totalTrue); Check(3, 0, 3, 3, 0, 3); Assert.Equal(1, c1.RaiseAsync(nullEvent, PlainContinuation)); // 1 async handlers, 1 sync but c1 is raising so shouldn't receive it. Check(3, 1, 3, 3, 0, 3); Assert.Empty(pending3); pending2.Dequeue()(); Check(3, 1, 3, 3, 1, 3); Assert.Equal(3, total); }
public void RaiseAsyncTest() { var pending2 = new Queue <Action>(); var pending3 = new Queue <Action <bool> >(); var c1 = new BasicComponent(); var c2 = new BasicComponent(); var c3 = new BasicComponent(); c1.AddHandler <BasicAsyncEvent>(_ => { }); c2.AddAsyncHandler <BasicAsyncEvent>((_, c) => { pending2.Enqueue(c); return(true); }); c3.AddAsyncHandler <BasicAsyncEvent, bool>((_, c) => { pending3.Enqueue(c); return(true); }); void Check(int seen1, int seen2, int seen3, int handled1, int handled2, int handled3) { Assert.Equal(seen1, c1.Seen); Assert.Equal(seen2, c2.Seen); Assert.Equal(seen3, c3.Seen); Assert.Equal(handled1, c1.Handled); Assert.Equal(handled2, c2.Handled); Assert.Equal(handled3, c3.Handled); } var e = new BasicAsyncEvent(); var ee = new EventExchange(new BasicLogExchange()); ee.Attach(c1); ee.Attach(c2); ee.Attach(c3); Assert.Equal(0, c1.Seen + c2.Seen + c3.Seen); Assert.Equal(0, c1.Handled + c2.Handled + c3.Handled); ee.Raise(e, this); Check(1, 1, 1, 1, 0, 0); Assert.Collection(pending2, _ => { }); Assert.Collection(pending3, _ => { }); pending2.Dequeue()(); Check(1, 1, 1, 1, 1, 0); pending3.Dequeue()(true); Check(1, 1, 1, 1, 1, 1); var recipients = ee.EnumerateRecipients(typeof(BasicAsyncEvent)).ToList(); Assert.Collection(recipients, x => Assert.Equal(x, c1), x => Assert.Equal(x, c2), x => Assert.Equal(x, c3) ); int total = 0; int totalTrue = 0; void BoolContinuation(bool x) { total++; if (x) { totalTrue++; } } void PlainContinuation() { total++; } Assert.Equal(2, ee.RaiseAsync <bool>(e, this, BoolContinuation)); // 2 async handlers, 1 sync Check(2, 2, 2, 2, 1, 1); pending2.Dequeue()(); // This attempted completion will not register as null cannot be coerced to bool. Check(2, 2, 2, 2, 2, 1); Assert.Equal(0, total); pending3.Dequeue()(true); Check(2, 2, 2, 2, 2, 2); Assert.Equal(1, total); Assert.Equal(1, totalTrue); Assert.Equal(1, c3.RaiseAsync(e, PlainContinuation)); // 2 async handlers, 1 sync but c3 is raising so shouldn't receive it. Check(3, 3, 2, 3, 2, 2); Assert.Empty(pending3); pending2.Dequeue()(); Check(3, 3, 2, 3, 3, 2); Assert.Equal(2, total); Assert.Equal(2, c1.RaiseAsync(e, BoolContinuation)); // 2 async handlers, 1 sync but c1 raises. Check(3, 4, 3, 3, 3, 2); pending2.Dequeue()(); // This attempted completion will not register as null cannot be coerced to bool. Check(3, 4, 3, 3, 4, 2); pending3.Dequeue()(true); Check(3, 4, 3, 3, 4, 3); }