Changeset - 6919080271d5
[Not reviewed]
Tess Snider (Malkyne) - 3 years ago 2021-07-21 17:47:38
this@malkyne.org
Implemented a system that will allow ingredients to be safely renamed, in the
future, without invalidating profiles. Standardized to PP's "FalconBait."
7 files changed with 130 insertions and 41 deletions:
0 comments (0 inline, 0 general)
Data/ingredients.txt
Show inline comments
 
// Desert Paint Lab Ingredients
 
// Name | Practical Paint Name | RGB values
 
// These should be kept in the order they show up on the paint bench
 
// NOTE: EarthLight was replaced with Falcon's Bait in T9.
 

	
 
Cabbage Juice   | Cabbage     | 128, 64, 144
 
Carrot          | Carrot      | 224, 112, 32
 
Clay            | Clay        | 128, 96, 32
 
Dead Tongue     | DeadTongue  | 112, 64, 64
 
Toad Skin       | ToadSkin    | 48, 96, 48
 
Falcons Bait    | FalconsBait | 128, 240, 224
 
Falcons Bait    | FalconBait  | 128, 240, 224
 
Red Sand        | RedSand     | 144, 16, 24
 
Lead            | Lead        | 80, 80, 96
 
Silver Powder   | Silver	  | 16, 16, 32
 
Iron            | Iron		  | 96, 48, 32
 
Copper          | Copper	  | 64, 192, 192
 
Sulfur          | Sulfur	  | catalyst
 
Potash          | Potash	  | catalyst
 
Lime            | Lime		  | catalyst
 
Saltpeter       | Saltpeter	  | catalyst
Data/renames.txt
Show inline comments
 
new file 100644
 
# PracticalPaint
 

	
 
EarthLight | FalconBait
 
FalconsBait | FalconBait
 

	
 
# Internal
 

	
 
Earth Light | Falcons Bait
...
 
\ No newline at end of file
Data/template/ingredients.txt
Show inline comments
 
// Ingredients are in the form:
 
// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)
 
//
 
// It is recommended to only change the cost value
 
// It is not recommended to set many of the ingredients above 10 per paint
 

	
 
Cabbage		| 128, 64, 144   | 8      | Y | bulk    | 10
 
Carrot		| 224, 112, 32   | 8      | Y | bulk    | 10
 
Clay		| 128, 96, 32    | 10     | Y | bulk    | 20
 
DeadTongue	| 112, 64, 64    | 500    | Y | normal  | 4
 
ToadSkin	| 48, 96, 48     | 500    | Y | normal  | 4
 
FalconsBait	| 128, 240, 224  | 10000  | Y | normal  | 4
 
FalconBait	| 128, 240, 224  | 10000  | Y | normal  | 4
 
RedSand		| 144, 16, 24    | 4      | Y | bulk    | 20
 
Lead		| 80, 80, 96     | 50     | Y | normal  | 6
 
Silver		| 16, 16, 32     | 50     | Y | normal  | 6
 
Iron		| 96, 48, 32     | 30     | Y | normal  | 8
 
Copper		| 64, 192, 192   | 30     | Y | normal  | 8
 
Sulfur      | catalyst       | 15     | Y | normal  | 1
 
Potash      | catalyst       | 50     | Y | normal  | 1
 
Lime        | catalyst       | 20     | Y | normal  | 1
 
Saltpeter   | catalyst       | 10     | Y | normal  | 1
DesertPaintCodex.csproj
Show inline comments
 
<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
 
    <OutputType>WinExe</OutputType>
 
    <TargetFramework>net5.0</TargetFramework>
 
    <Nullable>enable</Nullable>
 
    <ApplicationIcon>Assets\desert_paint_codex_icon.ico</ApplicationIcon>
 
    <StartupObject>DesertPaintCodex.Program</StartupObject>
 
    <Platforms>AnyCPU;x64</Platforms>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
 
    <PlatformTarget>x64</PlatformTarget>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 
    <PlatformTarget>x64</PlatformTarget>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Folder Include="Models\" />
 
    <AvaloniaResource Include="Assets\**" />
 
    <None Remove="CodexTheme.xaml" />
 
    <None Update="Data\renames.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
  </ItemGroup>
 
  <ItemGroup>
 
    <PackageReference Include="Avalonia" Version="0.10.999-cibuild0014036-beta" />
 
    <PackageReference Include="Avalonia.Desktop" Version="0.10.999-cibuild0014036-beta" />
 
    <PackageReference Include="Avalonia.Diagnostics" Version="0.10.999-cibuild0014036-beta" />
 
    <PackageReference Include="Avalonia.ReactiveUI" Version="0.10.999-cibuild0014036-beta" />
 
    <PackageReference Include="System.Reactive" Version="5.0.0" />
 
  </ItemGroup>
 
  <ItemGroup>
 
    <None Update="Data\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Update="Data\colors.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Update="Data\template\clips.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Update="Data\template\dp_reactions.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Update="Data\template\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
Models/Reagent.cs
Show inline comments
 
using System;
 

	
 
namespace DesertPaintCodex.Models
 
{
 
    public class Reagent
 
    {
 
        private uint _cost;
 
        private uint _recipeMax = 10;
 

	
 
        public bool IsCatalyst { get; }
 
        public PaintColor? Color { get; }
 
        public string Name { get; }
 
        public string PracticalPaintName { get; }
 
        public bool Enabled { get; set; }
 
        
 
        public int Index { get; private set; }
 

	
 
        public uint Cost
 
        {
 
            get => _cost;
 
            set => _cost = Math.Max(1, value);
 
        }
 

	
 
        public uint RecipeMax
 
        {
 
            get => _recipeMax;
 
            set
 
            {
 
                if (!IsCatalyst)
 
                {
 
                    _recipeMax = Math.Max(0, value);
 
                }
 
            }
 
        }
 

	
 
        // catalyst
 
        public Reagent(string name, string ppName)
 
        public Reagent(string name, string ppName, int index)
 
        {
 
            Name = name;
 
            PracticalPaintName = ppName;
 
            Cost = 2;
 
            Enabled = true;
 
            RecipeMax = 1;
 
            IsCatalyst = true;
 
            Index = index;
 
        }
 

	
 
        public Reagent(string name, string ppName, byte red, byte green, byte blue)
 
        public Reagent(string name, string ppName, byte red, byte green, byte blue, int index)
 
        {
 
            Color = new PaintColor(red, green, blue);
 
            Name = name;
 
            PracticalPaintName = ppName;
 
            Cost = 1;
 
            RecipeMax = 10;
 
            Enabled = true;
 
            IsCatalyst = false;
 
            Index = index;
 
        }
 

	
 
        public override string ToString()
 
        {
 
            if (IsCatalyst)
 
            {
 
                return "[" + Name + ", catalyst]";
 
            }
 
            else
 
            {
 
                return "[" + Name + ", " + Color + "]";
 
            }
 
        }
 
    }
 
}
Services/ReagentService.cs
Show inline comments
 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Diagnostics;
 
using System.Text.RegularExpressions;
 
using DesertPaintCodex.Models;
 
using DesertPaintCodex.Util;
 

	
 
namespace DesertPaintCodex.Services
 
{
 
    internal static class ReagentService
 
    {
 
        // PP format
 
        private static readonly Regex _reagentRegex          = new(@"(?<name>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+)\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal))\s*\|\s*(?<max>\d+).*");
 
        private static readonly Regex _catalystRegex         = new(@"(?<name>\w+)\s*\|\s*catalyst\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal)).*");
 
        private static readonly Regex _ppReagentRegex        = new(@"(?<name>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+)\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal))\s*\|\s*(?<max>\d+).*");
 
        private static readonly Regex _ppCatalystRegex       = new(@"(?<name>(\w*\s)*\w+\w+)\s*\|\s*catalyst\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal)).*");
 
        private static readonly Regex _internalReagentRegex  = new(@"(?<name>(\w*\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+).*");
 
        private static readonly Regex _internalCatalystRegex = new(@"(?<name>(\w+\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*catalyst.*");
 
        private static readonly Regex _renameHeader          = new(@"#\s*(?<header>\w*)");
 
        private static readonly Regex _renameRegex           = new(@"(?<oldName>(\w+\s)*\w+)\s*\|\s*(?<newName>(\w+\s)*\w+)");
 

	
 
        private static readonly Dictionary<string, Reagent> _reagents   = new();
 
        private static readonly Dictionary<string, string>  _nameLookup = new(); // pp name to our name
 

	
 
        private static string _lastReagentsFile = string.Empty;
 

	
 
        private static readonly Dictionary<string, string>  _ppToInternalName = new(); // pp name to our name
 
        private static readonly Dictionary<string, string> _ppRenames = new();
 
        private static readonly Dictionary<string, string> _internalRenames = new();
 
        
 
        private static bool _initialized = false;
 

	
 
        public static List<string> Names { get; } = new();
 

	
 

	
 
        public static void Initialize()
 
        private static void Initialize()
 
        {
 
            if (_initialized) return;
 

	
 
            string? reagentsPath = FileUtils.FindApplicationResourceFile("ingredients.txt");
 
            Debug.Assert(reagentsPath != null);
 
    
 

 
            Load(reagentsPath);
 

	
 
            string? renamesPath = FileUtils.FindApplicationResourceFile("renames.txt");
 

	
 
            if (renamesPath != null)
 
            {
 
                LoadAliases(renamesPath);
 
            }
 

	
 
            _initialized = true;
 
        }
 
        
 
        // Loads reagent name/colors
 
        public static void Load(string file)
 
        private static void Load(string file)
 
        {
 
            if (_lastReagentsFile == file) return;
 
            _lastReagentsFile = file;
 
            
 
            _reagents.Clear();
 
            _nameLookup.Clear();
 
            _ppToInternalName.Clear();
 
            Names.Clear();
 

	
 
            int index = 0;
 

	
 
            using StreamReader reader = new(file);
 
            string? line;
 
            while ((line = reader.ReadLine()) != null)
 
            {
 
                Match match = _internalReagentRegex.Match(line);
 
                if (match.Success)
 
                {
 
                    string name   = match.Groups["name"].Value;
 
                    string ppname = match.Groups["ppname"].Value;
 
                    Debug.WriteLine("Adding reagent[" + name + "] from line: [" + line + "]");
 
                    _reagents.Add(name,
 
                        new Reagent(name, ppname,
 
                            byte.Parse(match.Groups["red"].Value),
 
                            byte.Parse(match.Groups["green"].Value),
 
                            byte.Parse(match.Groups["blue"].Value)));
 
                            byte.Parse(match.Groups["blue"].Value),
 
                            index++));
 
                    // nameStore.AppendValues(name);
 
                    Names.Add(name);
 
                    _nameLookup.Add(ppname, name);
 
                    _ppToInternalName.Add(ppname, name);
 
                }
 
                else
 
                {
 
                    match = _internalCatalystRegex.Match(line);
 
                    
 
                    if (!match.Success) continue;
 
                    
 
                    string name   = match.Groups["name"].Value;
 
                    string ppname = match.Groups["ppname"].Value;
 
                    _reagents.Add(name, new Reagent(ppname, ppname));
 
                    _reagents.Add(name, new Reagent(ppname, ppname, index++));
 
                    // nameStore.AppendValues(name);
 
                    Names.Add(name);
 
                    _nameLookup.Add(ppname, name);
 
                    _ppToInternalName.Add(ppname, name);
 
                }
 
            }
 
        }
 

	
 
        private static void LoadAliases(string file)
 
        {
 
            _ppRenames.Clear();
 
            _internalRenames.Clear();
 

	
 
            Dictionary<string, string>? renameDict = null;
 
            
 
            using StreamReader reader = new(file);
 
            string? line;
 
            while ((line = reader.ReadLine()) != null)
 
            {
 
                Match match = _renameHeader.Match(line);
 
                if (match.Success)
 
                {
 
                    string header = match.Groups["header"].Value;
 
                    renameDict = header switch
 
                    {
 
                        "PracticalPaint" => _ppRenames,
 
                        "Internal"       => _internalRenames,
 
                        _                => renameDict
 
                    };
 
                }
 

	
 
                if (renameDict == null) continue;
 
                
 
                match = _renameRegex.Match(line);
 
                
 
                if (!match.Success) continue;
 
                
 
                string oldName = match.Groups["oldName"].Value;
 
                string newName = match.Groups["newName"].Value;
 
                renameDict.Add(oldName, newName);
 
            }
 
        }
 

	
 
        public static void LoadProfileReagents(string file)
 
        {
 
            Initialize();
 
            
 
            using StreamReader reader = new(file);
 
            string? line;
 
            while ((line = reader.ReadLine()) != null)
 
            {
 
                Match match = _reagentRegex.Match(line);
 
                Match match = _ppReagentRegex.Match(line);
 
                if (match.Success)
 
                {
 
                    string ppname = match.Groups["name"].Value;
 
                    if (_nameLookup.TryGetValue(ppname, out string? name))
 
                    if (_ppRenames.TryGetValue(ppname, out string? rename))
 
                    {
 
                        ppname = rename; // Apply rename.
 
                    }
 
                    
 
                    if (_ppToInternalName.TryGetValue(ppname, out string? name))
 
                    {
 
                        Reagent reagent = GetReagent(name);
 
                        if (reagent.IsCatalyst) continue;
 
                        reagent.Enabled   = match.Groups["enabled"].Value.Equals("Y");
 
                        reagent.Cost      = uint.Parse(match.Groups["cost"].Value);
 
                        reagent.RecipeMax = uint.Parse(match.Groups["max"].Value);
 
                    }
 
                    else
 
                    {
 
                        // bad name?
 
                    }
 
                }
 
                else
 
                {
 
                    match = _catalystRegex.Match(line);
 
                    match = _ppCatalystRegex.Match(line);
 
                    
 
                    if (!match.Success) continue;
 
                    
 
                    string ppname = match.Groups["name"].Value;
 
                    if (_nameLookup.TryGetValue(ppname, out string? name))
 
                    if (_ppRenames.TryGetValue(ppname, out string? rename))
 
                    {
 
                        ppname = rename; // Apply rename.
 
                    }
 
                    
 
                    if (_ppToInternalName.TryGetValue(ppname, out string? name))
 
                    {
 
                        Reagent reagent = GetReagent(name);
 
                        
 
                        if (reagent is not {IsCatalyst: true}) continue;
 
                        
 
                        reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
 
                        reagent.Cost    = uint.Parse(match.Groups["cost"].Value);
 
                    }
 
                    else
 
                    {
 
                        // bad name?
 
                    }
 
                }
 
            }
 
        }
 

	
 
        public static void SaveProfileReagents(string file)
 
        {
 
            Initialize();
 
            
 
            using StreamWriter writer = new(file);
 
            writer.WriteLine("// Ingredients are in the form:");
 
            writer.WriteLine("// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)");
 
            writer.WriteLine("//");
 
            writer.WriteLine("// It is recommended to only change the cost value");
 
            writer.WriteLine("// It is not recommended to set many of the ingredients above 10 per paint");
 

	
 
            List<Reagent> sortedReagents = new(_reagents.Count);
 
            sortedReagents.AddRange(_reagents.Values);
 
            sortedReagents.Sort((x, y) =>
 
                ((x.IsCatalyst && !y.IsCatalyst) ?
 
                    1 : ((y.IsCatalyst && !x.IsCatalyst) ?
 
                        -1 : string.Compare(x.PracticalPaintName, y.PracticalPaintName, StringComparison.InvariantCulture))));
 
            
 
            foreach (Reagent reagent in sortedReagents)
 
            {
...
 
@@ -167,38 +215,64 @@ namespace DesertPaintCodex.Services
 
                        reagent.Enabled ? "Y" : "N");
 
                }
 
            }
 
        }
 

	
 

	
 
        public static void InitializeReactions(ReactionSet reactions)
 
        {
 
            Initialize();
 
            foreach (KeyValuePair<string, Reagent> pair1 in _reagents)
 
            {
 
                foreach (KeyValuePair<string, Reagent> pair2 in _reagents)
 
                {
 
                    if (pair1.Key != pair2.Key)
 
                    {
 
                        reactions.Set(pair1.Value, pair2.Value, null);
 
                    }
 
                }
 
            }
 
        }
 

	
 
        public static Reagent GetReagent(string reagentName)
 
        {
 
            Initialize();
 

	
 
            Reagent? returnVal = GetReagentByInternalName(reagentName);
 

	
 
            if (returnVal != null) return returnVal;
 

	
 
            returnVal = GetReagentByPPName(reagentName);
 

	
 
            if (returnVal != null) return returnVal;
 
            
 
            if (_reagents.TryGetValue(reagentName, out Reagent? returnVal)) return returnVal;
 
            // convert pp name to our internal name
 
            if (_nameLookup.TryGetValue(reagentName, out string? otherName))
 
            string? rename = null;
 
            if (_internalRenames.TryGetValue(reagentName, out rename))
 
            {
 
                _reagents.TryGetValue(otherName, out returnVal);
 
                returnVal = GetReagentByInternalName(rename);
 
                if (returnVal != null) return returnVal;
 
            }
 

	
 
            if (_ppRenames.TryGetValue(reagentName, out rename))
 
            {
 
                returnVal = GetReagentByPPName(rename);
 
                if (returnVal != null) return returnVal;
 
            }
 
            
 
            Debug.Assert(returnVal != null);
 

	
 
            return returnVal;
 
        }
 

	
 
        private static Reagent? GetReagentByInternalName(string internalName)
 
        {
 
            return _reagents.TryGetValue(internalName, out Reagent? returnVal) ? returnVal : null;
 
        }
 

	
 
        private static Reagent? GetReagentByPPName(string ppName)
 
        {
 
            if (!_ppToInternalName.TryGetValue(ppName, out string? otherName)) return null;
 
            
 
            return _reagents.TryGetValue(otherName, out Reagent? returnVal) ? returnVal : null;
 
        }
 
    }
 
}
Util/Constants.cs
Show inline comments
 
using DesertPaintCodex.Models;
 

	
 
namespace DesertPaintCodex.Util
 
{
 
    public static class Constants
 
    {
 
        public static int DefaultPixelMultiplier = 1;
 
        public static int DefaultScreenWidth = 1920;
 
        public static int DefaultScreenHeight = 1080;
 
        public static int DefaultScreenX = 0;
 
        public static int DefaultScreenY = 0;
 

	
 
        private static ReactionTest? _stubReactionTest = null;
 

	
 
        public static ReactionTest StubReactionTest
 
        {
 
            get
 
            {
 
                if (_stubReactionTest == null)
 
                {
 
                    _stubReactionTest = new(
 
                        new Reagent("Toad Skin", "ToadSkin", 48, 96, 48), 
 
                        new Reagent("Falcons Bait", "FalconsBait", 128, 240, 224), 
 
                    _stubReactionTest = new ReactionTest(
 
                        new Reagent("Toad Skin", "ToadSkin", 48, 96, 48, 0), 
 
                        new Reagent("Falcons Bait", "FalconBait", 128, 240, 224, 1), 
 
                        null, ClipType.None, true);
 
                }
 

	
 
                return _stubReactionTest;
 
            }
 
            
 
        }
 
    }
 
}
...
 
\ No newline at end of file
0 comments (0 inline, 0 general)