// The standard constructor for most purposes public Map(string path) { Path = path; Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"), path)); FieldLoader.Load(this, yaml); // Support for formats 1-3 dropped 2011-02-11. // Use release-20110207 to convert older maps to format 4 // Use release-20110511 to convert older maps to format 5 // Use release-20141029 to convert older maps to format 6 if (MapFormat < 6) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } var nd = yaml.ToDictionary(); // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum if (MapFormat < 7) { MiniYaml useAsShellmap; if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) { Visibility = MapVisibility.Shellmap; } else if (Type == "Mission" || Type == "Campaign") { Visibility = MapVisibility.MissionSelector; } } SpawnPoints = Exts.Lazy(() => { var spawns = new List <CPos>(); foreach (var kv in ActorDefinitions.Where(d => d.Value.Value == "mpspawn")) { var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary()); spawns.Add(s.InitDict.Get <LocationInit>().Value(null)); } return(spawns.ToArray()); }); RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules"); SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences"); VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons"); VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices"); NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications"); TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations"); PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players"); ActorDefinitions = MiniYaml.NodesOrEmpty(yaml, "Actors"); SmudgeDefinitions = MiniYaml.NodesOrEmpty(yaml, "Smudges"); MapTiles = Exts.Lazy(LoadMapTiles); MapResources = Exts.Lazy(LoadResourceTiles); MapHeight = Exts.Lazy(LoadMapHeight); TileShape = Game.ModData.Manifest.TileShape; SubCellOffsets = Game.ModData.Manifest.SubCellOffsets; LastSubCell = (SubCell)(SubCellOffsets.Length - 1); DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex; if (Container.Exists("map.png")) { using (var dataStream = Container.GetContent("map.png")) CustomPreview = new Bitmap(dataStream); } PostInit(); // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. // TODO: this isn't very nice if (MapFormat < 7) { Save(path); } Uid = ComputeHash(); }
public void Save(string toPath) { MapFormat = 7; var root = new List <MiniYamlNode>(); var fields = new[] { "MapFormat", "RequiresMod", "Title", "Description", "Author", "Tileset", "MapSize", "Bounds", "Visibility", "Type", }; foreach (var field in fields) { var f = this.GetType().GetField(field); if (f.GetValue(this) == null) { continue; } root.Add(new MiniYamlNode(field, FieldSaver.FormatValue(this, f))); } root.Add(new MiniYamlNode("Videos", FieldSaver.SaveDifferences(Videos, new MapVideos()))); root.Add(new MiniYamlNode("Options", FieldSaver.SaveDifferences(Options, new MapOptions()))); root.Add(new MiniYamlNode("Players", null, PlayerDefinitions)); root.Add(new MiniYamlNode("Actors", null, ActorDefinitions)); root.Add(new MiniYamlNode("Smudges", null, SmudgeDefinitions)); root.Add(new MiniYamlNode("Rules", null, RuleDefinitions)); root.Add(new MiniYamlNode("Sequences", null, SequenceDefinitions)); root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions)); root.Add(new MiniYamlNode("Weapons", null, WeaponDefinitions)); root.Add(new MiniYamlNode("Voices", null, VoiceDefinitions)); root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions)); root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions)); var entries = new Dictionary <string, byte[]>(); entries.Add("map.bin", SaveBinaryData()); var s = root.WriteToString(); entries.Add("map.yaml", Encoding.UTF8.GetBytes(s)); // Add any custom assets if (Container != null) { foreach (var file in Container.AllFileNames()) { if (file == "map.bin" || file == "map.yaml") { continue; } entries.Add(file, Container.GetContent(file).ReadAllBytes()); } } // Saving the map to a new location if (toPath != Path) { Path = toPath; // Create a new map package Container = GlobalFileSystem.CreatePackage(Path, int.MaxValue, entries); } // Update existing package Container.Write(entries); }
// this code is insanely stupid, and mostly my fault -- chrisf void PrepareMapResources(ModData modData, Map map) { Program.Rules = map.Rules; tileset = Program.Rules.TileSets[map.Tileset]; tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize); var shadowIndex = new int[] { 3, 4 }; var palette = new ImmutablePalette(GlobalFileSystem.Open(tileset.Palette), shadowIndex); // required for desert terrain in RA var playerPalette = tileset.PlayerPalette ?? tileset.Palette; var shadowedPalette = new ImmutablePalette(GlobalFileSystem.Open(playerPalette), shadowIndex); surface1.Bind(map, tileset, tilesetRenderer, palette, shadowedPalette); // construct the palette of tiles var palettes = new[] { tilePalette, actorPalette, resourcePalette }; foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); } var templateOrder = tileset.EditorTemplateOrder ?? new string[] { }; foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => Array.IndexOf(templateOrder, t.Key))) { var category = tc.Key ?? "(Uncategorized)"; var categoryHeader = new Label { BackColor = SystemColors.Highlight, ForeColor = SystemColors.HighlightText, Text = category, AutoSize = false, Height = 24, TextAlign = ContentAlignment.MiddleLeft, Width = tilePalette.ClientSize.Width, }; // hook this manually, anchoring inside FlowLayoutPanel is flaky. tilePalette.Resize += (_, e) => categoryHeader.Width = tilePalette.ClientSize.Width; if (tilePalette.Controls.Count > 0) { tilePalette.SetFlowBreak( tilePalette.Controls[tilePalette.Controls.Count - 1], true); } tilePalette.Controls.Add(categoryHeader); foreach (var t in tc) { try { var bitmap = tilesetRenderer.RenderTemplate((ushort)t.Key, palette); var ibox = new PictureBox { Image = bitmap, Width = bitmap.Width / 2, Height = bitmap.Height / 2, SizeMode = PictureBoxSizeMode.StretchImage }; var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key }; ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate)); var template = t.Value; tilePalette.Controls.Add(ibox); tt.SetToolTip(ibox, "{1}:{0} ({2}x{3})".F(template.Image, template.Id, template.Size.X, template.Size.Y)); } catch { } } } var actorTemplates = new List <ActorTemplate>(); foreach (var a in Program.Rules.Actors.Keys) { try { var info = Program.Rules.Actors[a]; if (!info.Traits.Contains <RenderSimpleInfo>()) { continue; } var etf = info.Traits.GetOrDefault <EditorTilesetFilterInfo>(); if (etf != null && etf.ExcludeTilesets != null && etf.ExcludeTilesets.Contains(tileset.Id)) { continue; } if (etf != null && etf.RequireTilesets != null && !etf.RequireTilesets.Contains(tileset.Id)) { continue; } var templatePalette = shadowedPalette; var rsi = info.Traits.GetOrDefault <RenderSimpleInfo>(); // exception for desert buildings if (rsi != null && rsi.Palette != null && rsi.Palette.Contains("terrain")) { templatePalette = palette; } var template = RenderUtils.RenderActor(info, tileset, templatePalette); var ibox = new PictureBox { Image = template.Bitmap, Width = 32, Height = 32, SizeMode = PictureBoxSizeMode.Zoom, BorderStyle = BorderStyle.FixedSingle }; ibox.Click += (_, e) => surface1.SetTool(new ActorTool(template)); actorPalette.Controls.Add(ibox); tt.SetToolTip(ibox, "{0}".F(info.Name)); actorTemplates.Add(template); } catch { } } surface1.BindActorTemplates(actorTemplates); var resourceTemplates = new List <ResourceTemplate>(); foreach (var a in Program.Rules.Actors["world"].Traits.WithInterface <ResourceTypeInfo>()) { try { var template = RenderUtils.RenderResourceType(a, tileset.Extensions, shadowedPalette); var ibox = new PictureBox { Image = template.Bitmap, Width = 32, Height = 32, SizeMode = PictureBoxSizeMode.Zoom, BorderStyle = BorderStyle.FixedSingle }; ibox.Click += (_, e) => surface1.SetTool(new ResourceTool(template)); resourcePalette.Controls.Add(ibox); tt.SetToolTip(ibox, "{0}:{1}cr".F(template.Info.Name, template.Info.ValuePerUnit)); resourceTemplates.Add(template); } catch { } } surface1.BindResourceTemplates(resourceTemplates); foreach (var p in palettes) { p.Visible = true; p.ResumeLayout(); } miniMapBox.Image = Minimap.RenderMapPreview(tileset, surface1.Map, true); propertiesToolStripMenuItem.Enabled = true; toolStripMenuItemProperties.Enabled = true; resizeToolStripMenuItem.Enabled = true; toolStripMenuItemResize.Enabled = true; saveToolStripMenuItem.Enabled = true; toolStripMenuItemSave.Enabled = true; saveAsToolStripMenuItem.Enabled = true; miniMapToPng.Enabled = true; PopulateActorOwnerChooser(); }
public static List <MiniYamlNode> FromFileInPackage(string path) { using (var stream = GlobalFileSystem.Open(path)) return(FromLines(stream.ReadAllLines(), path)); }
public void StartGame(Arguments args) { Ui.ResetAll(); Game.Settings.Save(); // Check whether the mod content is installed // TODO: The installation code has finally been beaten into shape, so we can // finally move it all into the planned "Manage Content" panel in the modchooser mod. var installData = Game.ModData.Manifest.Get <ContentInstaller>(); var installModContent = !installData.TestFiles.All(f => GlobalFileSystem.Exists(f)); var installModMusic = args != null && args.Contains("Install.Music"); if (installModContent || installModMusic) { var widgetArgs = new WidgetArgs() { { "continueLoading", () => Game.InitializeMod(Game.Settings.Game.Mod, args) }, }; if (installData.BackgroundWidget != null) { Ui.LoadWidget(installData.BackgroundWidget, Ui.Root, widgetArgs); } var menu = installModContent ? installData.MenuWidget : installData.MusicMenuWidget; Ui.OpenWindow(menu, widgetArgs); return; } // Join a server directly var connect = string.Empty; if (args != null) { if (args.Contains("Launch.Connect")) { connect = args.GetValue("Launch.Connect", null); } if (args.Contains("Launch.URI")) { connect = args.GetValue("Launch.URI", null); if (connect != null) { connect = connect.Replace("openra://", ""); connect = connect.TrimEnd('/'); } } } if (!string.IsNullOrEmpty(connect)) { var parts = connect.Split(':'); if (parts.Length == 2) { var host = parts[0]; var port = Exts.ParseIntegerInvariant(parts[1]); Game.LoadShellMap(); Game.RemoteDirectConnect(host, port); return; } } // Load a replay directly var replayFilename = args != null?args.GetValue("Launch.Replay", null) : null; if (!string.IsNullOrEmpty(replayFilename)) { var replayMeta = ReplayMetadata.Read(replayFilename); if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap)) { Game.JoinReplay(replayFilename); } if (replayMeta != null) { var mod = replayMeta.GameInfo.Mod; if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod)) { Game.InitializeMod(mod, args); } } return; } Game.LoadShellMap(); Game.Settings.Save(); }
public Shader(string name) { // Vertex shader string vertexCode; using (var file = new StreamReader(GlobalFileSystem.Open("glsl{0}{1}.vert".F(Path.DirectorySeparatorChar, name)))) vertexCode = file.ReadToEnd(); var vertexShader = GL.CreateShader(ShaderType.VertexShader); ErrorHandler.CheckGlError(); GL.ShaderSource(vertexShader, vertexCode); ErrorHandler.CheckGlError(); GL.CompileShader(vertexShader); ErrorHandler.CheckGlError(); int success; GL.GetShader(vertexShader, ShaderParameter.CompileStatus, out success); ErrorHandler.CheckGlError(); if (success == (int)All.False) { throw new InvalidProgramException("Compile error in glsl{0}{1}.vert".F(Path.DirectorySeparatorChar, name)); } // Fragment shader string fragmentCode; using (var file = new StreamReader(GlobalFileSystem.Open("glsl{0}{1}.frag".F(Path.DirectorySeparatorChar, name)))) fragmentCode = file.ReadToEnd(); var fragmentShader = GL.CreateShader(ShaderType.FragmentShader); ErrorHandler.CheckGlError(); GL.ShaderSource(fragmentShader, fragmentCode); ErrorHandler.CheckGlError(); GL.CompileShader(fragmentShader); ErrorHandler.CheckGlError(); GL.GetShader(vertexShader, ShaderParameter.CompileStatus, out success); ErrorHandler.CheckGlError(); if (success == (int)All.False) { throw new InvalidProgramException("Compile error in glsl{0}{1}.frag".F(Path.DirectorySeparatorChar, name)); } // Assemble program program = GL.CreateProgram(); ErrorHandler.CheckGlError(); GL.AttachShader(program, vertexShader); ErrorHandler.CheckGlError(); GL.AttachShader(program, fragmentShader); ErrorHandler.CheckGlError(); GL.LinkProgram(program); ErrorHandler.CheckGlError(); GL.GetProgram(program, ProgramParameter.LinkStatus, out success); ErrorHandler.CheckGlError(); if (success == (int)All.False) { throw new InvalidProgramException("Linking error in {0} shader".F(name)); } GL.UseProgram(program); ErrorHandler.CheckGlError(); int numUniforms; GL.GetProgram(program, ProgramParameter.ActiveUniforms, out numUniforms); ErrorHandler.CheckGlError(); var nextTexUnit = 0; for (var i = 0; i < numUniforms; i++) { int length, size; ActiveUniformType type; var sb = new StringBuilder(128); GL.GetActiveUniform(program, i, 128, out length, out size, out type, sb); var sampler = sb.ToString(); ErrorHandler.CheckGlError(); if (type == ActiveUniformType.Sampler2D) { samplers.Add(sampler, nextTexUnit); var loc = GL.GetUniformLocation(program, sampler); ErrorHandler.CheckGlError(); GL.Uniform1(loc, nextTexUnit); ErrorHandler.CheckGlError(); nextTexUnit++; } } }
public AssetBrowserLogic(Widget widget, Action onExit, World world) { this.world = world; panel = widget; assetSource = GlobalFileSystem.MountedFolders.First(); var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER"); if (ticker != null) { ticker.OnTick = () => { if (animateFrames) { SelectNextFrame(); } }; } var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR"); if (sourceDropdown != null) { sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); sourceDropdown.GetText = () => { var name = assetSource != null?Platform.UnresolvePath(assetSource.Name) : "All Packages"; if (name.Length > 15) { name = "..." + name.Substring(name.Length - 15); } return(name); }; } var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE"); if (spriteWidget != null) { spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; currentPalette = spriteWidget.Palette; spriteWidget.GetPalette = () => currentPalette; spriteWidget.IsVisible = () => !isVideoLoaded; } var playerWidget = panel.GetOrNull <VqaPlayerWidget>("PLAYER"); if (playerWidget != null) { playerWidget.IsVisible = () => isVideoLoaded; } var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR"); if (paletteDropDown != null) { paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); paletteDropDown.GetText = () => currentPalette; } var colorPreview = panel.GetOrNull <ColorPreviewManagerWidget>("COLOR_MANAGER"); if (colorPreview != null) { colorPreview.Color = Game.Settings.Player.Color; } var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR"); if (colorDropdown != null) { colorDropdown.IsDisabled = () => currentPalette != colorPreview.PaletteName; colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, world); panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB; } filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT"); filenameInput.OnTextEdited = () => ApplyFilter(filenameInput.Text); filenameInput.OnEscKey = filenameInput.YieldKeyboardFocus; var frameContainer = panel.GetOrNull("FRAME_SELECTOR"); if (frameContainer != null) { frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) || (isVideoLoaded && player != null && player.Video != null && player.Video.Frames > 1); } frameSlider = panel.Get <SliderWidget>("FRAME_SLIDER"); if (frameSlider != null) { frameSlider.OnChange += x => { if (!isVideoLoaded) { currentFrame = (int)Math.Round(x); } }; frameSlider.GetValue = () => isVideoLoaded ? player.Video.CurrentFrame : currentFrame; frameSlider.IsDisabled = () => isVideoLoaded; } var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT"); if (frameText != null) { frameText.GetText = () => isVideoLoaded ? "{0} / {1}".F(player.Video.CurrentFrame + 1, player.Video.Frames) : "{0} / {1}".F(currentFrame, currentSprites.Length - 1); } var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY"); if (playButton != null) { playButton.Key = new Hotkey(Keycode.SPACE, Modifiers.None); playButton.OnClick = () => { if (isVideoLoaded) { player.Play(); } else { animateFrames = true; } }; playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames; } var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE"); if (pauseButton != null) { pauseButton.Key = new Hotkey(Keycode.SPACE, Modifiers.None); pauseButton.OnClick = () => { if (isVideoLoaded) { player.Pause(); } else { animateFrames = false; } }; pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : animateFrames; } var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP"); if (stopButton != null) { stopButton.Key = new Hotkey(Keycode.RETURN, Modifiers.None); stopButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } else { frameSlider.Value = 0; currentFrame = 0; animateFrames = false; } }; } var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT"); if (nextButton != null) { nextButton.Key = new Hotkey(Keycode.RIGHT, Modifiers.None); nextButton.OnClick = () => { if (!isVideoLoaded) { nextButton.OnClick = SelectNextFrame; } }; nextButton.IsVisible = () => !isVideoLoaded; } var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV"); if (prevButton != null) { prevButton.Key = new Hotkey(Keycode.LEFT, Modifiers.None); prevButton.OnClick = () => { if (!isVideoLoaded) { SelectPreviousFrame(); } }; prevButton.IsVisible = () => !isVideoLoaded; } assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST"); template = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE"); PopulateAssetList(); var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON"); if (closeButton != null) { closeButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } Ui.CloseWindow(); onExit(); } } ; } void SelectNextFrame() { currentFrame++; if (currentFrame >= currentSprites.Length) { currentFrame = 0; } } void SelectPreviousFrame() { currentFrame--; if (currentFrame < 0) { currentFrame = currentSprites.Length - 1; } } Dictionary <string, bool> assetVisByName = new Dictionary <string, bool>(); bool FilterAsset(string filename) { var filter = filenameInput.Text; if (string.IsNullOrWhiteSpace(filter)) { return(true); } if (filename.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) { return(true); } return(false); } void ApplyFilter(string filename) { assetVisByName.Clear(); assetList.Layout.AdjustChildren(); assetList.ScrollToTop(); // Select the first visible var firstVisible = assetVisByName.FirstOrDefault(kvp => kvp.Value); if (firstVisible.Key != null) { LoadAsset(firstVisible.Key); } } void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template) { var filename = Path.GetFileName(filepath); var item = ScrollItemWidget.Setup(template, () => currentFilename == filename, () => { LoadAsset(filename); }); item.Get <LabelWidget>("TITLE").GetText = () => filepath; item.IsVisible = () => { bool visible; if (assetVisByName.TryGetValue(filepath, out visible)) { return(visible); } visible = FilterAsset(filepath); assetVisByName.Add(filepath, visible); return(visible); }; list.AddChild(item); } bool LoadAsset(string filename) { if (isVideoLoaded) { player.Stop(); player = null; isVideoLoaded = false; } if (string.IsNullOrEmpty(filename)) { return(false); } if (!GlobalFileSystem.Exists(filename)) { return(false); } if (Path.GetExtension(filename.ToLowerInvariant()) == ".vqa") { player = panel.Get <VqaPlayerWidget>("PLAYER"); currentFilename = filename; player.Load(filename); player.DrawOverlay = false; isVideoLoaded = true; frameSlider.MaximumValue = (float)player.Video.Frames - 1; frameSlider.Ticks = 0; return(true); } else { currentFilename = filename; currentSprites = world.Map.SequenceProvider.SpriteCache[filename]; currentFrame = 0; frameSlider.MaximumValue = (float)currentSprites.Length - 1; frameSlider.Ticks = currentSprites.Length; } return(true); } bool ShowSourceDropdown(DropDownButtonWidget dropdown) { Func <IFolder, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => assetSource == source, () => { assetSource = source; PopulateAssetList(); }); item.Get <LabelWidget>("LABEL").GetText = () => source != null?Platform.UnresolvePath(source.Name) : "All Packages"; return(item); }; // TODO: Re-enable "All Packages" once list generation is done in a background thread // var sources = new[] { (IFolder)null }.Concat(GlobalFileSystem.MountedFolders); var sources = GlobalFileSystem.MountedFolders; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem); return(true); } void PopulateAssetList() { assetList.RemoveChildren(); availableShps.Clear(); // TODO: This is too slow to run in the main thread // var files = AssetSource != null ? AssetSource.AllFileNames() : // GlobalFileSystem.MountedFolders.SelectMany(f => f.AllFileNames()); if (assetSource == null) { return; } var files = assetSource.AllFileNames().OrderBy(s => s); foreach (var file in files) { if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) { AddAsset(assetList, file, template); availableShps.Add(file); } } } bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world) { Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (name, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => currentPalette == name, () => currentPalette = name); item.Get <LabelWidget>("LABEL").GetText = () => name; return(item); }; var palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>() .SelectMany(p => p.PaletteNames); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem); return(true); } }
public ScriptContext(World world, WorldRenderer worldRenderer, IEnumerable <string> scripts) { runtime = new MemoryConstrainedLuaRuntime(); World = world; WorldRenderer = worldRenderer; knownActorCommands = Game.modData.ObjectCreator .GetTypesImplementing <ScriptActorProperties>() .ToArray(); ActorCommands = new Cache <ActorInfo, Type[]>(FilterActorCommands); PlayerCommands = Game.modData.ObjectCreator .GetTypesImplementing <ScriptPlayerProperties>() .ToArray(); runtime.DoBuffer(GlobalFileSystem.Open(Path.Combine("lua", "scriptwrapper.lua")).ReadAllText(), "scriptwrapper.lua").Dispose(); tick = (LuaFunction)runtime.Globals["Tick"]; // Register globals using (var fn = runtime.CreateFunctionFromDelegate((Action <string>)FatalError)) runtime.Globals["FatalError"] = fn; runtime.Globals["MaxUserScriptInstructions"] = MaxUserScriptInstructions; using (var registerGlobal = (LuaFunction)runtime.Globals["RegisterSandboxedGlobal"]) { using (var fn = runtime.CreateFunctionFromDelegate((Action <string>)Console.WriteLine)) registerGlobal.Call("print", fn).Dispose(); // Register global tables var bindings = Game.modData.ObjectCreator.GetTypesImplementing <ScriptGlobal>(); foreach (var b in bindings) { var ctor = b.GetConstructors(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(c => { var p = c.GetParameters(); return(p.Length == 1 && p.First().ParameterType == typeof(ScriptContext)); }); if (ctor == null) { throw new InvalidOperationException("{0} must define a constructor that takes a ScriptContext context parameter".F(b.Name)); } var binding = (ScriptGlobal)ctor.Invoke(new[] { this }); using (var obj = binding.ToLuaValue(this)) registerGlobal.Call(binding.Name, obj).Dispose(); } } // System functions do not count towards the memory limit runtime.MaxMemoryUse = runtime.MemoryUse + MaxUserScriptMemory; using (var loadScript = (LuaFunction)runtime.Globals["ExecuteSandboxedScript"]) { foreach (var s in scripts) { loadScript.Call(s, GlobalFileSystem.Open(s).ReadAllText()).Dispose(); } } }
// The standard constructor for most purposes public Map(string path) { Path = path; Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"), path)); FieldLoader.Load(this, yaml); // Support for formats 1-3 dropped 2011-02-11. // Use release-20110207 to convert older maps to format 4 // Use release-20110511 to convert older maps to format 5 // Use release-20141029 to convert older maps to format 6 if (MapFormat < 6) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } var nd = yaml.ToDictionary(); // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum if (MapFormat < 7) { MiniYaml useAsShellmap; if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) { Visibility = MapVisibility.Shellmap; } else if (Type == "Mission" || Type == "Campaign") { Visibility = MapVisibility.MissionSelector; } } // Load players foreach (var my in nd["Players"].ToDictionary().Values) { var player = new PlayerReference(my); Players.Add(player.Name, player); } Actors = Exts.Lazy(() => { var ret = new Dictionary <string, ActorReference>(); foreach (var kv in nd["Actors"].ToDictionary()) { ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary())); } return(ret); }); // Smudges Smudges = Exts.Lazy(() => { var ret = new List <SmudgeReference>(); foreach (var name in nd["Smudges"].ToDictionary().Keys) { var vals = name.Split(' '); var loc = vals[1].Split(','); ret.Add(new SmudgeReference(vals[0], new int2( Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1])), Exts.ParseIntegerInvariant(vals[2]))); } return(ret); }); RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules"); SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences"); VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons"); VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices"); NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications"); TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations"); MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); MapHeight = Exts.Lazy(() => LoadMapHeight()); TileShape = Game.ModData.Manifest.TileShape; SubCellOffsets = Game.ModData.Manifest.SubCellOffsets; LastSubCell = (SubCell)(SubCellOffsets.Length - 1); DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex; if (Container.Exists("map.png")) { using (var dataStream = Container.GetContent("map.png")) CustomPreview = new Bitmap(dataStream); } PostInit(); // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. // TODO: this isn't very nice if (MapFormat < 7) { Save(path); } Uid = ComputeHash(); }
void SelectMap(Map map) { selectedMapPreview = Game.ModData.MapCache[map.Uid]; // Cache the rules on a background thread to avoid jank new Thread(selectedMapPreview.CacheRules).Start(); var briefingVideo = selectedMapPreview.Map.Videos.Briefing; var briefingVideoVisible = briefingVideo != null; var briefingVideoDisabled = !(briefingVideoVisible && GlobalFileSystem.Exists(briefingVideo)); var infoVideo = selectedMapPreview.Map.Videos.BackgroundInfo; var infoVideoVisible = infoVideo != null; var infoVideoDisabled = !(infoVideoVisible && GlobalFileSystem.Exists(infoVideo)); startBriefingVideoButton.IsVisible = () => briefingVideoVisible && playingVideo != PlayingVideo.Briefing; startBriefingVideoButton.IsDisabled = () => briefingVideoDisabled || playingVideo != PlayingVideo.None; startBriefingVideoButton.OnClick = () => PlayVideo(videoPlayer, briefingVideo, PlayingVideo.Briefing, () => StopVideo(videoPlayer)); startInfoVideoButton.IsVisible = () => infoVideoVisible && playingVideo != PlayingVideo.Info; startInfoVideoButton.IsDisabled = () => infoVideoDisabled || playingVideo != PlayingVideo.None; startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info, () => StopVideo(videoPlayer)); var text = map.Description != null?map.Description.Replace("\\n", "\n") : ""; text = WidgetUtils.WrapText(text, description.Bounds.Width, descriptionFont); description.Text = text; description.Bounds.Height = descriptionFont.Measure(text).Y; descriptionPanel.ScrollToTop(); descriptionPanel.Layout.AdjustChildren(); if (difficultyButton != null) { difficultyButton.IsDisabled = () => !map.Options.Difficulties.Any(); difficulty = map.Options.Difficulties.FirstOrDefault(); difficultyButton.GetText = () => difficulty ?? "Normal"; difficultyButton.OnMouseDown = _ => { var options = map.Options.Difficulties.Select(d => new DropDownOption { Title = d, IsSelected = () => difficulty == d, OnClick = () => difficulty = d }); Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; difficultyButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } if (gameSpeedButton != null) { var speeds = Game.ModData.Manifest.Get <GameSpeeds>().Speeds; gameSpeed = "default"; gameSpeedButton.GetText = () => speeds[gameSpeed].Name; gameSpeedButton.OnMouseDown = _ => { var options = speeds.Select(s => new DropDownOption { Title = s.Value.Name, IsSelected = () => gameSpeed == s.Key, OnClick = () => gameSpeed = s.Key }); Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; gameSpeedButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } }
public void Run(ModData modData, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.modData = modData; GlobalFileSystem.LoadFromManifest(Game.modData.Manifest); var file = new IniFile(File.Open(args[1], FileMode.Open)); var templateIndex = 0; var extension = "tem"; var terrainTypes = new Dictionary <int, string>() { { 1, "Clear" }, // Desert sand(?) { 5, "Road" }, // Paved road { 6, "Rail" }, // Monorail track { 7, "Impassable" }, // Building { 9, "Water" }, // Deep water(?) { 10, "Water" }, // Shallow water { 11, "Road" }, // Paved road (again?) { 12, "DirtRoad" }, // Dirt road { 13, "Clear" }, // Regular clear terrain { 14, "Rough" }, // Rough terrain (cracks etc) { 15, "Cliff" }, // Cliffs }; // Loop over template sets try { for (var tilesetGroupIndex = 0; ; tilesetGroupIndex++) { var section = file.GetSection("TileSet{0:D4}".F(tilesetGroupIndex)); var sectionCount = int.Parse(section.GetValue("TilesInSet", "1")); var sectionFilename = section.GetValue("FileName", ""); var sectionCategory = section.GetValue("SetName", ""); // Loop over templates for (var i = 1; i <= sectionCount; i++, templateIndex++) { var templateFilename = "{0}{1:D2}.{2}".F(sectionFilename, i, extension); if (!GlobalFileSystem.Exists(templateFilename)) { continue; } using (var s = GlobalFileSystem.Open(templateFilename)) { Console.WriteLine("\tTemplate@{0}:", templateIndex); Console.WriteLine("\t\tCategory: {0}", sectionCategory); Console.WriteLine("\t\tId: {0}", templateIndex); Console.WriteLine("\t\tImage: {0}{1:D2}", sectionFilename, i); var templateWidth = s.ReadUInt32(); var templateHeight = s.ReadUInt32(); /* var tileWidth = */ s.ReadInt32(); /* var tileHeight = */ s.ReadInt32(); var offsets = new uint[templateWidth * templateHeight]; for (var j = 0; j < offsets.Length; j++) { offsets[j] = s.ReadUInt32(); } Console.WriteLine("\t\tSize: {0}, {1}", templateWidth, templateHeight); Console.WriteLine("\t\tTiles:"); for (var j = 0; j < offsets.Length; j++) { if (offsets[j] == 0) { continue; } s.Position = offsets[j] + 40; /* var height = */ s.ReadUInt8(); var terrainType = s.ReadUInt8(); /* var rampType = */ s.ReadUInt8(); /* var height = */ s.ReadUInt8(); if (!terrainTypes.ContainsKey(terrainType)) { throw new InvalidDataException("Unknown terrain type {0} in {1}".F(terrainType, templateFilename)); } Console.WriteLine("\t\t\t{0}: {1}", j, terrainTypes[terrainType]); // Console.WriteLine("\t\t\t\tHeight: {0}", height); // Console.WriteLine("\t\t\t\tTerrainType: {0}", terrainType); // Console.WriteLine("\t\t\t\tRampType: {0}", rampType); // Console.WriteLine("\t\t\t\tLeftColor: {0},{1},{2}", s.ReadUInt8(), s.ReadUInt8(), s.ReadUInt8()); // Console.WriteLine("\t\t\t\tRightColor: {0},{1},{2}", s.ReadUInt8(), s.ReadUInt8(), s.ReadUInt8()); } } } } } catch (InvalidOperationException) { // GetSection will throw when we run out of sections to import } }
public void Run(ModData modData, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; GlobalFileSystem.LoadFromManifest(Game.ModData.Manifest); var imageField = typeof(TerrainTemplateInfo).GetField("Image"); var pickAnyField = typeof(TerrainTemplateInfo).GetField("PickAny"); var tileInfoField = typeof(TerrainTemplateInfo).GetField("tileInfo", BindingFlags.NonPublic | BindingFlags.Instance); var terrainTypeField = typeof(TerrainTileInfo).GetField("TerrainType"); var terrainLeftColorField = typeof(TerrainTileInfo).GetField("LeftColor"); var terrainRightColorField = typeof(TerrainTileInfo).GetField("RightColor"); var empty = new Size(0, 0); var single = new int2(1, 1); var exts = new[] { "" }.Concat(args[1].Split(',')); foreach (var t in Game.ModData.Manifest.TileSets) { var ts = new TileSet(Game.ModData, t); var frameCache = new FrameCache(Game.ModData.SpriteLoaders); Console.WriteLine("Tileset: " + ts.Name); foreach (var template in ts.Templates.Values) { // Find the sprite associated with this template foreach (var ext in exts) { Stream s; if (!GlobalFileSystem.TryOpen(template.Images[0] + ext, out s)) { continue; } // Rewrite the template image (normally readonly) using reflection imageField.SetValue(template, template.Images[0] + ext); // Fetch the private tileInfo array so that we can write new entries var tileInfo = (TerrainTileInfo[])tileInfoField.GetValue(template); // Open the file and search for any implicit frames var allFrames = frameCache[template.Images[0]]; var frames = template.Frames != null?template.Frames.Select(f => allFrames[f]).ToArray() : allFrames; // Resize array for new entries if (frames.Length > template.TilesCount) { var ti = new TerrainTileInfo[frames.Length]; Array.Copy(tileInfo, ti, template.TilesCount); tileInfoField.SetValue(template, ti); tileInfo = ti; } for (var i = 0; i < template.TilesCount; i++) { if (template[i] == null && frames[i] != null && frames[i].Size != empty) { tileInfo[i] = new TerrainTileInfo(); var ti = ts.GetTerrainIndex("Clear"); terrainTypeField.SetValue(tileInfo[i], ti); terrainLeftColorField.SetValue(tileInfo[i], ts[ti].Color); terrainRightColorField.SetValue(tileInfo[i], ts[ti].Color); Console.WriteLine("Fixing entry for {0}:{1}", template.Images[0], i); } } if (template.TilesCount > 1 && template.Size == single) { pickAnyField.SetValue(template, true); } s.Dispose(); } } ts.Save(t); } }
public void Run(ModData modData, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; GlobalFileSystem.LoadFromManifest(Game.ModData.Manifest); var file = new IniFile(File.Open(args[1], FileMode.Open)); var extension = args[2]; var templateIndex = 0; var terrainTypes = new string[] { "Clear", "Clear", // Note: sometimes "Ice" "Ice", "Ice", "Ice", "Road", // TS defines this as "Tunnel", but we don't need this "Rail", "Impassable", // TS defines this as "Rock", but also uses it for buildings "Impassable", "Water", "Water", // TS defines this as "Beach", but uses it for water...? "Road", "DirtRoad", // TS defines this as "Road", but we may want different speeds "Clear", "Rough", "Cliff" // TS defines this as "Rock" }; // Loop over template sets try { for (var tilesetGroupIndex = 0;; tilesetGroupIndex++) { var section = file.GetSection("TileSet{0:D4}".F(tilesetGroupIndex)); var sectionCount = int.Parse(section.GetValue("TilesInSet", "1")); var sectionFilename = section.GetValue("FileName", ""); var sectionCategory = section.GetValue("SetName", ""); // Loop over templates for (var i = 1; i <= sectionCount; i++, templateIndex++) { var templateFilename = "{0}{1:D2}.{2}".F(sectionFilename, i, extension); if (!GlobalFileSystem.Exists(templateFilename)) { continue; } using (var s = GlobalFileSystem.Open(templateFilename)) { Console.WriteLine("\tTemplate@{0}:", templateIndex); Console.WriteLine("\t\tCategory: {0}", sectionCategory); Console.WriteLine("\t\tId: {0}", templateIndex); var images = new List <string>(); images.Add("{0}{1:D2}.{2}".F(sectionFilename, i, extension)); for (var v = 'a'; v <= 'z'; v++) { var variant = "{0}{1:D2}{2}.{3}".F(sectionFilename, i, v, extension); if (GlobalFileSystem.Exists(variant)) { images.Add(variant); } } Console.WriteLine("\t\tImage: {0}", images.JoinWith(", ")); var templateWidth = s.ReadUInt32(); var templateHeight = s.ReadUInt32(); /* var tileWidth = */ s.ReadInt32(); /* var tileHeight = */ s.ReadInt32(); var offsets = new uint[templateWidth * templateHeight]; for (var j = 0; j < offsets.Length; j++) { offsets[j] = s.ReadUInt32(); } Console.WriteLine("\t\tSize: {0}, {1}", templateWidth, templateHeight); Console.WriteLine("\t\tTiles:"); for (var j = 0; j < offsets.Length; j++) { if (offsets[j] == 0) { continue; } s.Position = offsets[j] + 40; var height = s.ReadUInt8(); var terrainType = s.ReadUInt8(); var rampType = s.ReadUInt8(); if (terrainType >= terrainTypes.Length) { throw new InvalidDataException("Unknown terrain type {0} in {1}".F(terrainType, templateFilename)); } Console.WriteLine("\t\t\t{0}: {1}", j, terrainTypes[terrainType]); if (height != 0) { Console.WriteLine("\t\t\t\tHeight: {0}", height); } if (rampType != 0) { Console.WriteLine("\t\t\t\tRampType: {0}", rampType); } Console.WriteLine("\t\t\t\tLeftColor: {0},{1},{2}", s.ReadUInt8(), s.ReadUInt8(), s.ReadUInt8()); Console.WriteLine("\t\t\t\tRightColor: {0},{1},{2}", s.ReadUInt8(), s.ReadUInt8(), s.ReadUInt8()); } } } } } catch (InvalidOperationException) { // GetSection will throw when we run out of sections to import } }
public void LoadPalettes(WorldRenderer wr) { var filename = world.TileSet.PlayerPalette ?? world.TileSet.Palette; wr.AddPalette(info.Name, new ImmutablePalette(GlobalFileSystem.Open(filename), info.ShadowIndex), info.AllowModifiers); }
public void LoadPalettes(WorldRenderer wr) { wr.AddPalette(info.Name, new ImmutablePalette(GlobalFileSystem.Open(world.TileSet.Palette), info.ShadowIndex), info.AllowModifiers); }
public void MountFiles() { GlobalFileSystem.LoadFromManifest(Manifest); }
enum IniMapFormat { RedAlert = 3 } // otherwise, cnc (2 variants exist, we don't care to differentiate) public void ConvertIniMap(string iniFile) { using (var stream = GlobalFileSystem.Open(iniFile)) { var file = new IniFile(stream); var basic = file.GetSection("Basic"); var mapSection = file.GetSection("Map"); var legacyMapFormat = (IniMapFormat)Exts.ParseIntegerInvariant(basic.GetValue("NewINIFormat", "0")); var offsetX = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0")); var offsetY = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0")); var width = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0")); var height = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0")); mapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64; var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8); map = new Map(rules.TileSets[tileset], mapSize, mapSize) { Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile)), Author = "Westwood Studios" }; var tl = new PPos(offsetX, offsetY); var br = new PPos(offsetX + width - 1, offsetY + height - 1); map.SetBounds(tl, br); if (legacyMapFormat == IniMapFormat.RedAlert) { UnpackRATileData(ReadPackedSection(file.GetSection("MapPack"))); UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); ReadRATrees(file); } else { // CnC using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")) UnpackCncTileData(s); ReadCncOverlay(file); ReadCncTrees(file); } LoadVideos(file, "BASIC"); LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); LoadActors(file, "SHIPS"); LoadSmudges(file, "SMUDGE"); var wps = file.GetSection("Waypoints") .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))); // Add waypoint actors foreach (var kv in wps) { if (kv.First <= 7) { var ar = new ActorReference("mpspawn") { new LocationInit((CPos)kv.Second), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save())); } else { var ar = new ActorReference("waypoint") { new LocationInit((CPos)kv.Second), new OwnerInit("Neutral") }; map.ActorDefinitions.Add(new MiniYamlNode("waypoint" + kv.First, ar.Save())); } } // Create default player definitions only if there are no players to import mapPlayers = new MapPlayers(map.Rules, (players.Count == 0) ? map.SpawnPoints.Value.Length : 0); foreach (var p in players) { LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert); } map.PlayerDefinitions = mapPlayers.ToMiniYaml(); } }
internal static void Initialize(Arguments args) { Console.WriteLine("Platform is {0}", Platform.CurrentPlatform); AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly; InitializeSettings(args); Log.AddChannel("perf", "perf.log"); Log.AddChannel("debug", "debug.log"); Log.AddChannel("sync", "syncreport.log"); Log.AddChannel("server", "server.log"); Log.AddChannel("sound", "sound.log"); Log.AddChannel("graphics", "graphics.log"); Log.AddChannel("geoip", "geoip.log"); if (Settings.Server.DiscoverNatDevices) { UPnP.TryNatDiscovery(); } else { Settings.Server.NatDeviceAvailable = false; Settings.Server.AllowPortForward = false; } try { GeoIpDatabase = new DatabaseReader("GeoLite2-Country.mmdb"); } catch (Exception e) { Log.Write("geoip", "DatabaseReader failed: {0}", e); } GlobalFileSystem.Mount(Platform.GameDir); // Needed to access shaders var renderers = new[] { Settings.Graphics.Renderer, "Sdl2", null }; foreach (var r in renderers) { if (r == null) { throw new InvalidOperationException("No suitable renderers were found. Check graphics.log for details."); } Settings.Graphics.Renderer = r; try { Renderer = new Renderer(Settings.Graphics, Settings.Server); break; } catch (Exception e) { Log.Write("graphics", "{0}", e); Console.WriteLine("Renderer initialization failed. Fallback in place. Check graphics.log for details."); } } try { Sound.Create(Settings.Sound.Engine); } catch (Exception e) { Log.Write("sound", "{0}", e); Console.WriteLine("Creating the sound engine failed. Fallback in place. Check sound.log for details."); Settings.Sound.Engine = "Null"; Sound.Create(Settings.Sound.Engine); } Console.WriteLine("Available mods:"); foreach (var mod in ModMetadata.AllMods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); } InitializeMod(Settings.Game.Mod, args); if (Settings.Server.DiscoverNatDevices) { RunAfterDelay(Settings.Server.NatDiscoveryTimeout, UPnP.StoppingNatDiscovery); } }
enum IniMapFormat { RedAlert = 3 } // otherwise, cnc (2 variants exist, we don't care to differentiate) public void ConvertIniMap(string iniFile) { var file = new IniFile(GlobalFileSystem.Open(iniFile)); var basic = file.GetSection("Basic"); var mapSection = file.GetSection("Map"); var legacyMapFormat = (IniMapFormat)Exts.ParseIntegerInvariant(basic.GetValue("NewINIFormat", "0")); var offsetX = Exts.ParseIntegerInvariant(mapSection.GetValue("X", "0")); var offsetY = Exts.ParseIntegerInvariant(mapSection.GetValue("Y", "0")); var width = Exts.ParseIntegerInvariant(mapSection.GetValue("Width", "0")); var height = Exts.ParseIntegerInvariant(mapSection.GetValue("Height", "0")); mapSize = (legacyMapFormat == IniMapFormat.RedAlert) ? 128 : 64; var size = new Size(mapSize, mapSize); var tileset = Truncate(mapSection.GetValue("Theater", "TEMPERAT"), 8); map = Map.FromTileset(rules.TileSets[tileset]); map.Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(iniFile)); map.Author = "Westwood Studios"; map.MapSize.X = mapSize; map.MapSize.Y = mapSize; map.Bounds = Rectangle.FromLTRB(offsetX, offsetY, offsetX + width, offsetY + height); map.Selectable = true; map.Smudges = Exts.Lazy(() => new List <SmudgeReference>()); map.Actors = Exts.Lazy(() => new Dictionary <string, ActorReference>()); map.MapResources = Exts.Lazy(() => new CellLayer <ResourceTile>(TileShape.Rectangle, size)); map.MapTiles = Exts.Lazy(() => new CellLayer <TerrainTile>(TileShape.Rectangle, size)); map.Options = new MapOptions(); if (legacyMapFormat == IniMapFormat.RedAlert) { UnpackRATileData(ReadPackedSection(file.GetSection("MapPack"))); UnpackRAOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); ReadRATrees(file); } else { // CnC using (var s = GlobalFileSystem.Open(iniFile.Substring(0, iniFile.Length - 4) + ".bin")) UnpackCncTileData(s); ReadCncOverlay(file); ReadCncTrees(file); } LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); LoadSmudges(file, "SMUDGE"); foreach (var p in players) { LoadPlayer(file, p, legacyMapFormat == IniMapFormat.RedAlert); } var wps = file.GetSection("Waypoints") .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))) .ToArray(); // Add waypoint actors foreach (var kv in wps) { if (kv.First <= 7) { var a = new ActorReference("mpspawn"); a.Add(new LocationInit((CPos)kv.Second)); a.Add(new OwnerInit("Neutral")); map.Actors.Value.Add("Actor" + map.Actors.Value.Count.ToString(), a); } else { var a = new ActorReference("waypoint"); a.Add(new LocationInit((CPos)kv.Second)); a.Add(new OwnerInit("Neutral")); map.Actors.Value.Add("waypoint" + kv.First, a); } } }
// Support upgrading format 5 maps to a more // recent version by defining upgradeForMod. public Map(string path, string upgradeForMod) { Path = path; Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"))); FieldLoader.Load(this, yaml); // Support for formats 1-3 dropped 2011-02-11. // Use release-20110207 to convert older maps to format 4 // Use release-20110511 to convert older maps to format 5 if (MapFormat < 5) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } // Format 5 -> 6 enforces the use of RequiresMod if (MapFormat == 5) { if (upgradeForMod == null) { throw new InvalidDataException("Map format {0} is not supported, but can be upgraded.\n File: {1}".F(MapFormat, path)); } Console.WriteLine("Upgrading {0} from Format 5 to Format 6", path); // TODO: This isn't very nice, but there is no other consistent way // of finding the mod early during the engine initialization. RequiresMod = upgradeForMod; } var nd = yaml.ToDictionary(); // Load players foreach (var my in nd["Players"].ToDictionary().Values) { var player = new PlayerReference(my); Players.Add(player.Name, player); } Actors = Exts.Lazy(() => { var ret = new Dictionary <string, ActorReference>(); foreach (var kv in nd["Actors"].ToDictionary()) { ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary())); } return(ret); }); // Smudges Smudges = Exts.Lazy(() => { var ret = new List <SmudgeReference>(); foreach (var name in nd["Smudges"].ToDictionary().Keys) { var vals = name.Split(' '); var loc = vals[1].Split(','); ret.Add(new SmudgeReference(vals[0], new int2( Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1])), Exts.ParseIntegerInvariant(vals[2]))); } return(ret); }); RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules"); SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences"); VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons"); VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices"); NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications"); TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations"); MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); TileShape = Game.modData.Manifest.TileShape; // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. // TODO: this isn't very nice if (MapFormat < 6) { Save(path); } Uid = ComputeHash(); if (Container.Exists("map.png")) { CustomPreview = new Bitmap(Container.GetContent("map.png")); } PostInit(); }
public AssetBrowserLogic(Widget widget, Action onExit, World world) { this.world = world; panel = widget; assetSource = GlobalFileSystem.MountedFolders.First(); var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER"); if (ticker != null) { ticker.OnTick = () => { if (animateFrames) { SelectNextFrame(); } }; } var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR"); if (sourceDropdown != null) { sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); sourceDropdown.GetText = () => { var name = assetSource != null?assetSource.Name.Replace(Platform.SupportDir, "^") : "All Packages"; if (name.Length > 15) { name = "..." + name.Substring(name.Length - 15); } return(name); }; } var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE"); if (spriteWidget != null) { spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; currentPalette = spriteWidget.Palette; spriteWidget.GetPalette = () => currentPalette; } var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR"); if (paletteDropDown != null) { paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); paletteDropDown.GetText = () => currentPalette; } var colorPreview = panel.GetOrNull <ColorPreviewManagerWidget>("COLOR_MANAGER"); if (colorPreview != null) { colorPreview.Color = Game.Settings.Player.Color; } var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR"); if (colorDropdown != null) { colorDropdown.IsDisabled = () => currentPalette != colorPreview.Palette; colorDropdown.OnMouseDown = _ => ShowColorDropDown(colorDropdown, colorPreview, world); panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB; } filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT"); filenameInput.OnEnterKey = () => LoadAsset(filenameInput.Text); var frameContainer = panel.GetOrNull("FRAME_SELECTOR"); if (frameContainer != null) { frameContainer.IsVisible = () => currentSprites != null && currentSprites.Length > 1; } frameSlider = panel.Get <SliderWidget>("FRAME_SLIDER"); frameSlider.OnChange += x => { currentFrame = (int)Math.Round(x); }; frameSlider.GetValue = () => currentFrame; var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT"); if (frameText != null) { frameText.GetText = () => "{0} / {1}".F(currentFrame + 1, currentSprites.Length); } var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY"); if (playButton != null) { playButton.OnClick = () => animateFrames = true; playButton.IsVisible = () => !animateFrames; } var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE"); if (pauseButton != null) { pauseButton.OnClick = () => animateFrames = false; pauseButton.IsVisible = () => animateFrames; } var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP"); if (stopButton != null) { stopButton.OnClick = () => { frameSlider.Value = 0; currentFrame = 0; animateFrames = false; }; } var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT"); if (nextButton != null) { nextButton.OnClick = SelectNextFrame; } var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV"); if (prevButton != null) { prevButton.OnClick = SelectPreviousFrame; } var loadButton = panel.GetOrNull <ButtonWidget>("LOAD_BUTTON"); if (loadButton != null) { loadButton.OnClick = () => LoadAsset(filenameInput.Text); } assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST"); template = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE"); PopulateAssetList(); var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON"); if (closeButton != null) { closeButton.OnClick = () => { Ui.CloseWindow(); onExit(); } } ; } void SelectNextFrame() { currentFrame++; if (currentFrame >= currentSprites.Length) { currentFrame = 0; } } void SelectPreviousFrame() { currentFrame--; if (currentFrame < 0) { currentFrame = currentSprites.Length - 1; } } void AddAsset(ScrollPanelWidget list, string filepath, ScrollItemWidget template) { var filename = Path.GetFileName(filepath); var item = ScrollItemWidget.Setup(template, () => currentFilename == filename, () => { filenameInput.Text = filename; LoadAsset(filename); }); item.Get <LabelWidget>("TITLE").GetText = () => filepath; list.AddChild(item); } bool LoadAsset(string filename) { if (string.IsNullOrEmpty(filename)) { return(false); } if (!GlobalFileSystem.Exists(filename)) { return(false); } currentFilename = filename; currentSprites = world.Map.SequenceProvider.SpriteLoader.LoadAllSprites(filename); currentFrame = 0; frameSlider.MaximumValue = (float)currentSprites.Length - 1; frameSlider.Ticks = currentSprites.Length; return(true); } bool ShowSourceDropdown(DropDownButtonWidget dropdown) { Func <IFolder, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => assetSource == source, () => { assetSource = source; PopulateAssetList(); }); item.Get <LabelWidget>("LABEL").GetText = () => source != null?source.Name.Replace(Platform.SupportDir, "^") : "All Packages"; return(item); }; // TODO: Re-enable "All Packages" once list generation is done in a background thread // var sources = new[] { (IFolder)null }.Concat(GlobalFileSystem.MountedFolders); var sources = GlobalFileSystem.MountedFolders; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem); return(true); } void PopulateAssetList() { assetList.RemoveChildren(); availableShps.Clear(); // TODO: This is too slow to run in the main thread // var files = AssetSource != null ? AssetSource.AllFileNames() : // GlobalFileSystem.MountedFolders.SelectMany(f => f.AllFileNames()); if (assetSource == null) { return; } var files = assetSource.AllFileNames().OrderBy(s => s); foreach (var file in files) { if (AllowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) { AddAsset(assetList, file, template); availableShps.Add(file); } } } bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world) { Func <PaletteFromFile, ScrollItemWidget, ScrollItemWidget> setupItem = (palette, itemTemplate) => { var name = palette.Name; var item = ScrollItemWidget.Setup(itemTemplate, () => currentPalette == name, () => currentPalette = name); item.Get <LabelWidget>("LABEL").GetText = () => name; return(item); }; var palettes = world.WorldActor.TraitsImplementing <PaletteFromFile>(); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem); return(true); }