// Takes n lists of properties and returns every unique n-tuple // through a 2 dimensional array blockvariants[i, ni] // where i = n-tuple index and ni = index of current element in the n-tuple VariantEntry[,] MultiplyProperties(VariantEntry[][] variants) { int resultingQuantiy = 1; for (int i = 0; i < variants.Length; i++) { resultingQuantiy *= variants[i].Length; } VariantEntry[,] multipliedProperties = new VariantEntry[resultingQuantiy, variants.Length]; for (int i = 0; i < resultingQuantiy; i++) { int div = 1; for (int j = 0; j < variants.Length; j++) { VariantEntry variant = variants[j][(i / div) % variants[j].Length]; multipliedProperties[i, j] = new VariantEntry() { Code = variant.Code, Codes = variant.Codes, Types = variant.Types }; div *= variants[j].Length; } } return(multipliedProperties); }
private void CollectFromStateList(RegistryObjectVariantGroup variantGroup, RegistryObjectVariantGroup[] variantgroups, OrderedDictionary <string, VariantEntry[]> variantsMul, List <ResolvedVariant> blockvariantsFinal, AssetLocation filename) { if (variantGroup.Code == null) { api.Server.LogError( "Error in itemtype {0}, a variantgroup using a state list must have a code. Ignoring.", filename ); return; } string[] states = variantGroup.States; string type = variantGroup.Code; // Additive state list if (variantGroup.Combine == EnumCombination.Add) { for (int j = 0; j < states.Length; j++) { ResolvedVariant resolved = new ResolvedVariant(); resolved.CodeParts.Add(type, states[j]); blockvariantsFinal.Add(resolved); } } // Multiplicative state list if (variantGroup.Combine == EnumCombination.Multiply) { List <VariantEntry> stateList = new List <VariantEntry>(); for (int j = 0; j < states.Length; j++) { stateList.Add(new VariantEntry() { Code = states[j] }); } for (int i = 0; i < variantgroups.Length; i++) { RegistryObjectVariantGroup cvg = variantgroups[i]; if (cvg.Combine == EnumCombination.SelectiveMultiply && cvg.OnVariant == variantGroup.Code) { for (int k = 0; k < stateList.Count; k++) { if (cvg.Code != stateList[k].Code) { continue; } VariantEntry old = stateList[k]; stateList.RemoveAt(k); for (int j = 0; j < cvg.States.Length; j++) { List <string> codes = old.Codes == null ? new List <string>() { old.Code } : old.Codes; List <string> types = old.Types == null ? new List <string>() { variantGroup.Code } : old.Types; codes.Add(cvg.States[j]); types.Add(cvg.Code); stateList.Insert(k, new VariantEntry() { Code = old.Code + "-" + cvg.States[j], Codes = codes, Types = types }); } } } } if (variantsMul.ContainsKey(type)) { stateList.AddRange(variantsMul[type]); variantsMul[type] = stateList.ToArray(); } else { variantsMul.Add(type, stateList.ToArray()); } } }
List <ResolvedVariant> GatherVariants(AssetLocation baseCode, RegistryObjectVariantGroup[] variantgroups, AssetLocation location, AssetLocation[] allowedVariants, AssetLocation[] skipVariants) { List <ResolvedVariant> variantsFinal = new List <ResolvedVariant>(); if (variantgroups == null || variantgroups.Length == 0) { return(variantsFinal); } OrderedDictionary <string, VariantEntry[]> variantsMul = new OrderedDictionary <string, VariantEntry[]>(); // 1. Collect all types for (int i = 0; i < variantgroups.Length; i++) { if (variantgroups[i].LoadFromProperties != null) { CollectFromWorldProperties(variantgroups[i], variantgroups, variantsMul, variantsFinal, location); } if (variantgroups[i].LoadFromPropertiesCombine != null) { CollectFromWorldPropertiesCombine(variantgroups[i].LoadFromPropertiesCombine, variantgroups[i], variantgroups, variantsMul, variantsFinal, location); } if (variantgroups[i].States != null) { CollectFromStateList(variantgroups[i], variantgroups, variantsMul, variantsFinal, location); } } // 2. Multiply multiplicative groups VariantEntry[,] variants = MultiplyProperties(variantsMul.Values.ToArray()); // 3. Add up multiplicative groups for (int i = 0; i < variants.GetLength(0); i++) { ResolvedVariant resolved = new ResolvedVariant(); for (int j = 0; j < variants.GetLength(1); j++) { VariantEntry variant = variants[i, j]; if (variant.Codes != null) { for (int k = 0; k < variant.Codes.Count; k++) { resolved.CodeParts.Add(variant.Types[k], variant.Codes[k]); } } else { resolved.CodeParts.Add(variantsMul.GetKeyAtIndex(j), variant.Code); } } variantsFinal.Add(resolved); } foreach (ResolvedVariant var in variantsFinal) { var.ResolveCode(baseCode); } if (skipVariants != null) { List <ResolvedVariant> filteredVariants = new List <ResolvedVariant>(); HashSet <AssetLocation> skipVariantsHash = new HashSet <AssetLocation>(); List <AssetLocation> skipVariantsWildCards = new List <AssetLocation>(); foreach (var val in skipVariants) { if (val.IsWildCard) { skipVariantsWildCards.Add(val); } else { skipVariantsHash.Add(val); } } foreach (ResolvedVariant var in variantsFinal) { if (skipVariantsHash.Contains(var.Code)) { continue; } if (skipVariantsWildCards.FirstOrDefault(v => WildcardUtil.Match(v, var.Code)) != null) { continue; } filteredVariants.Add(var); } variantsFinal = filteredVariants; } if (allowedVariants != null) { List <ResolvedVariant> filteredVariants = new List <ResolvedVariant>(); HashSet <AssetLocation> allowVariantsHash = new HashSet <AssetLocation>(); List <AssetLocation> allowVariantsWildCards = new List <AssetLocation>(); foreach (var val in allowedVariants) { if (val.IsWildCard) { allowVariantsWildCards.Add(val); } else { allowVariantsHash.Add(val); } } foreach (ResolvedVariant var in variantsFinal) { if (allowVariantsHash.Contains(var.Code) || allowVariantsWildCards.FirstOrDefault(v => WildcardUtil.Match(v, var.Code)) != null) { filteredVariants.Add(var); } } variantsFinal = filteredVariants; } return(variantsFinal); }