public void DetermineBuildStages() { BlockPitkiln blockpk = this.Block as BlockPitkiln; bool found = false; foreach (var val in blockpk.BuildStagesByBlock) { if (!inventory[0].Empty && WildcardUtil.Match(new AssetLocation(val.Key), inventory[0].Itemstack.Collectible.Code)) { buildStages = val.Value; shape = blockpk.ShapesByBlock[val.Key]; found = true; break; } } if (!found) { if (blockpk.BuildStagesByBlock.TryGetValue("*", out buildStages)) { shape = blockpk.ShapesByBlock["*"]; } } updateSelectiveElements(); }
/// <summary> /// Check if the multiblock structure is complete. Ignores air blocks /// </summary> /// <param name="world"></param> /// <param name="centerPos"></param> /// <returns></returns> public int InCompleteBlockCount(IWorldAccessor world, BlockPos centerPos, PositionMismatchDelegate onMismatch = null) { if (TransformedOffsets == null) { throw new InvalidOperationException("call InitForUse() first"); } int qinc = 0; for (int i = 0; i < TransformedOffsets.Count; i++) { Vec4i offset = TransformedOffsets[i]; Block block = world.BlockAccessor.GetBlock(centerPos.X + offset.X, centerPos.Y + offset.Y, centerPos.Z + offset.Z); if (!WildcardUtil.Match(BlockCodes[offset.W], block.Code)) { onMismatch?.Invoke(block, BlockCodes[offset.W]); //world.Logger.Notification("Expected: {0}, Is: {1}", BlockCodes[offset.W], block.Code); qinc++; } } return(qinc); }
public void HighlightIncompleteParts(IWorldAccessor world, IPlayer player, BlockPos centerPos) { List <BlockPos> blocks = new List <BlockPos>(); List <int> colors = new List <int>(); for (int i = 0; i < TransformedOffsets.Count; i++) { Vec4i offset = TransformedOffsets[i]; Block block = world.BlockAccessor.GetBlock(centerPos.X + offset.X, centerPos.Y + offset.Y, centerPos.Z + offset.Z); AssetLocation desireBlockLoc = BlockCodes[offset.W]; if (!WildcardUtil.Match(BlockCodes[offset.W], block.Code)) { blocks.Add(new BlockPos(offset.X, offset.Y, offset.Z).Add(centerPos)); if (block.Id != 0) { colors.Add(ColorUtil.ColorFromRgba(215, 94, 94, 64)); } else { int col = world.SearchBlocks(desireBlockLoc)[0].GetColor(world.Api as ICoreClientAPI, centerPos); col &= ~(255 << 24); col |= 96 << 24; colors.Add(col); } } } world.HighlightBlocks(player, HighlightSlotId, blocks, colors); }
public static ContentConfig getContentConfig(IWorldAccessor world, ContentConfig[] contentConfigs, ItemSlot sourceSlot) { if (sourceSlot.Empty) { return(null); } for (int i = 0; i < contentConfigs.Length; i++) { var cfg = contentConfigs[i]; if (cfg.Content.Code.Path.Contains("*")) { if (WildcardUtil.Match(cfg.Content.Code, sourceSlot.Itemstack.Collectible.Code)) { return(cfg); } continue; } if (sourceSlot.Itemstack.Equals(world, cfg.Content.ResolvedItemstack, GlobalConstants.IgnoredStackAttributes)) { return(cfg); } } return(null); }
public override bool MatchesForCrafting(ItemStack inputStack, GridRecipe gridRecipe, CraftingRecipeIngredient ingredient) { if (gridRecipe.Attributes?["liquidContainerProps"].Exists != true) { return(base.MatchesForCrafting(inputStack, gridRecipe, ingredient)); } string contentCode = gridRecipe.Attributes["liquidContainerProps"]["requiresContent"]["code"].AsString(); string contentType = gridRecipe.Attributes["liquidContainerProps"]["requiresContent"]["type"].AsString(); ItemStack contentStack = GetContent(api.World, inputStack); api.World.Logger.VerboseDebug("LiquidContainer.MatchesForCrafting: contentStack null? " + (contentStack == null)); if (contentStack == null) { return(false); } int q = gridRecipe.Attributes["liquidContainerProps"]["requiresQuantity"].AsInt(); bool a = contentStack.Class.ToString().ToLowerInvariant() == contentType.ToLowerInvariant(); bool b = WildcardUtil.Match(contentStack.Collectible.Code, new AssetLocation(contentCode)); bool c = contentStack.StackSize >= q; api.World.Logger.VerboseDebug("LiquidContainer.MatchesForCrafting: {0} && {1} && {2}", a, b, c); return(a && b && c); }
/// <summary> /// Resolves Wildcards in the ingredients /// </summary> /// <param name="world"></param> /// <returns></returns> public Dictionary <string, string[]> GetNameToCodeMapping(IWorldAccessor world) { Dictionary <string, string[]> mappings = new Dictionary <string, string[]>(); foreach (var val in Ingredients) { if (val.Value.Name == null || val.Value.Name.Length == 0) { continue; } if (!val.Value.Code.Path.Contains("*")) { continue; } int wildcardStartLen = val.Value.Code.Path.IndexOf("*"); int wildcardEndLen = val.Value.Code.Path.Length - wildcardStartLen - 1; List <string> codes = new List <string>(); if (val.Value.Type == EnumItemClass.Block) { for (int i = 0; i < world.Blocks.Count; i++) { if (world.Blocks[i] == null || world.Blocks[i].IsMissing) { continue; } if (WildcardUtil.Match(val.Value.Code, world.Blocks[i].Code, val.Value.AllowedVariants)) { string code = world.Blocks[i].Code.Path.Substring(wildcardStartLen); string codepart = code.Substring(0, code.Length - wildcardEndLen); codes.Add(codepart); } } } else { for (int i = 0; i < world.Items.Count; i++) { if (world.Items[i] == null || world.Items[i].IsMissing) { continue; } if (WildcardUtil.Match(val.Value.Code, world.Items[i].Code, val.Value.AllowedVariants)) { string code = world.Items[i].Code.Path.Substring(wildcardStartLen); string codepart = code.Substring(0, code.Length - wildcardEndLen); codes.Add(codepart); } } } mappings[val.Value.Name] = codes.ToArray(); } return(mappings); }
private void CreateDrop(EntityAgent byEntity, string fromBlockCode) { IPlayer player = (byEntity as EntityPlayer)?.Player; PanningDrop[] drops = null; foreach (var val in dropsBySourceMat.Keys) { if (WildcardUtil.Match(val, fromBlockCode)) { drops = dropsBySourceMat[val]; } } if (drops == null) { throw new InvalidOperationException("Coding error, no drops defined for source mat " + fromBlockCode); } string rocktype = api.World.GetBlock(new AssetLocation(fromBlockCode))?.Variant["rock"]; drops.Shuffle(api.World.Rand); for (int i = 0; i < drops.Length; i++) { PanningDrop drop = drops[i]; double rnd = api.World.Rand.NextDouble(); float extraMul = 1f; if (drop.DropModbyStat != null) { // If the stat does not exist, then GetBlended returns 1 \o/ extraMul = byEntity.Stats.GetBlended(drop.DropModbyStat); } float val = drop.Chance.nextFloat() * extraMul; ItemStack stack = drop.ResolvedItemstack; if (drops[i].Code.Path.Contains("{rocktype}")) { stack = Resolve(drops[i].Type, drops[i].Code.Path.Replace("{rocktype}", rocktype)); } if (rnd < val && stack != null) { stack = stack.Clone(); if (player == null || !player.InventoryManager.TryGiveItemstack(stack, true)) { api.World.SpawnItemEntity(stack, byEntity.ServerPos.XYZ); } break; } } }
void solveByType(JToken json, string codePath, OrderedDictionary <string, string> searchReplace) { List <string> propertiesToRemove = new List <string>(); Dictionary <string, JToken> propertiesToAdd = new Dictionary <string, JToken>(); if (json is JObject) { foreach (var entry in (json as JObject)) { if (entry.Key.EndsWith("byType", System.StringComparison.OrdinalIgnoreCase)) { foreach (var byTypeProperty in entry.Value.ToObject <OrderedDictionary <string, JToken> >()) { if (WildcardUtil.Match(byTypeProperty.Key, codePath)) { JToken typedToken = byTypeProperty.Value; solveByType(typedToken, codePath, searchReplace); propertiesToAdd.Add(entry.Key.Substring(0, entry.Key.Length - "byType".Length), typedToken); break; } } propertiesToRemove.Add(entry.Key); } } foreach (var property in propertiesToRemove) { (json as JObject).Remove(property); } foreach (var property in propertiesToAdd) { (json as JObject)[property.Key] = property.Value; } foreach (var entry in (json as JObject)) { solveByType(entry.Value, codePath, searchReplace); } } else if (json.Type == JTokenType.String) { string value = (string)(json as JValue).Value; if (value.Contains("{")) { (json as JValue).Value = RegistryObject.FillPlaceHolder(value, searchReplace); } } else if (json is JArray) { foreach (var child in (json as JArray)) { solveByType(child, codePath, searchReplace); } } }
public override void OnLoaded(ICoreAPI api) { // This figures out what item types are valid ammo and shows them as an interaction help. if (api.Side != EnumAppSide.Client) { return; } List <AssetLocation> locs = new List <AssetLocation>(); string codeNames = ""; if (Attributes.KeyExists("ammos")) { //foreach (string s in Attributes["ammos"].AsArray<string>()) foreach (string s in Attributes["ammos"].AsStringArray()) // Yes, this is deprecated, but the other one compiles wrong. { locs.Add(AssetLocation.Create(s, Code.Domain)); codeNames += "_" + s; } } else { locs.Add(AssetLocation.Create(Attributes["ammo"].AsString("arrow-*"), Code.Domain)); codeNames = Attributes["ammo"].AsString("arrow-*"); } ICoreClientAPI capi = api as ICoreClientAPI; interactions = ObjectCacheUtil.GetOrCreate(api, "ranged" + codeNames + "Interactions", () => { List <ItemStack> stacks = new List <ItemStack>(); foreach (CollectibleObject obj in api.World.Collectibles) { foreach (AssetLocation loc in locs) { if (WildcardUtil.Match(loc, obj.Code)) { // api.Logger.Error("stack " + obj.Code); stacks.Add(new ItemStack(obj)); break; } } } return(new WorldInteraction[] { new WorldInteraction() { ActionLangCode = Attributes["heldhelp"].AsString("heldhelp-chargebow"), MouseButton = EnumMouseButton.Right, Itemstacks = stacks.ToArray() } }); }); }
/*public static bool WildCardMatch(string wildCard, string text) * { * if (wildCard == text) return true; * string pattern = Regex.Escape(wildCard).Replace(@"\*", @"(.*)"); * return Regex.IsMatch(text, @"^" + pattern + @"$", RegexOptions.IgnoreCase); * }*/ public static bool WildCardMatches(string blockCode, List <string> wildCards, out string matchingWildcard) { foreach (string wildcard in wildCards) { if (WildcardUtil.Match(wildcard, blockCode)) //if (WildCardMatch(wildcard, blockCode)) { matchingWildcard = wildcard; return(true); } } matchingWildcard = null; return(false); }
public bool IsSuitableFor(Entity entity) { ContentConfig contentConfig = ((IEnumerable <ContentConfig>)nltConfig).FirstOrDefault <ContentConfig>(c => c.Code == contentCode); if (contentConfig == null) { return(false); } for (int index = 0; index < contentConfig.Foodfor.Length; ++index) { if (WildcardUtil.Match(contentConfig.Foodfor[index], entity.Code)) { return(true); } } return(false); }
ItemStack[] ResolveWildCard(IWorldAccessor world, CraftingRecipeIngredient ingred, ItemStack[] allStacks = null) { if (resolveCache.ContainsKey(ingred.Code)) { return(resolveCache[ingred.Code]); } List <ItemStack> matches = new List <ItemStack>(); if (allStacks != null) { foreach (var val in allStacks) { if (val.Collectible.Code == null) { continue; } if (val.Class != ingred.Type) { continue; } if (WildcardUtil.Match(ingred.Code, val.Collectible.Code, ingred.AllowedVariants)) { matches.Add(new ItemStack(val.Collectible, ingred.Quantity)); } } resolveCache[ingred.Code] = matches.ToArray(); return(matches.ToArray()); } foreach (var val in world.Collectibles) { if (WildcardUtil.Match(ingred.Code, val.Code, ingred.AllowedVariants)) { matches.Add(new ItemStack(val, ingred.Quantity)); } } resolveCache[ingred.Code] = matches.ToArray(); return(resolveCache[ingred.Code]); }
public bool IsSuitableFor(Entity entity) { ContentConfig config = contentConfigs.FirstOrDefault(c => c.Code == contentCode); if (config == null) { return(false); } for (int i = 0; i < config.Foodfor.Length; i++) { if (WildcardUtil.Match(config.Foodfor[i], entity.Code)) { return(inventory[0].StackSize >= config.QuantityPerFillLevel); } } return(false); }
public bool IsSuitableFor(Entity entity) { ContentConfig config = contentConfigs.FirstOrDefault(c => c.Code == contentCode); if (config == null) { return(false); } for (int i = 0; i < config.Foodfor.Length; i++) { if (WildcardUtil.Match(config.Foodfor[i], entity.Code)) { return(true); } } return(false); }
public static string[] GetCreativeTabs(AssetLocation code, Dictionary <string, string[]> CreativeInventory, OrderedDictionary <string, string> searchReplace) { List <string> tabs = new List <string>(); foreach (var val in CreativeInventory) { for (int i = 0; i < val.Value.Length; i++) { string blockCode = RegistryObject.FillPlaceHolder(val.Value[i], searchReplace); if (WildcardUtil.Match(blockCode, code.Path)) //if (WildCardMatch(blockCode, code.Path)) { string tabCode = val.Key; tabs.Add(tabCode); } } } return(tabs.ToArray()); }
ItemSlot GetNextAmmo(EntityAgent byEntity) { List <AssetLocation> locs = new List <AssetLocation>(); if (Attributes.KeyExists("ammos")) { //foreach (string s in Attributes["ammos"].AsArray<string>()) foreach (string s in Attributes["ammos"].AsStringArray()) // Yes, this is deprecated, but the other one compiles wrong. { locs.Add(AssetLocation.Create(s, Code.Domain)); } } else { locs.Add(AssetLocation.Create(Attributes["ammo"].AsString("arrow-*"), Code.Domain)); } ItemSlot slot = null; byEntity.WalkInventory((invslot) => { if (invslot is ItemSlotCreative) { return(true); } foreach (AssetLocation loc in locs) { if (invslot.Itemstack != null && WildcardUtil.Match(loc, invslot.Itemstack.Collectible.Code)) { // api.Logger.Error("ammoSlot " + invslot.Itemstack.Collectible.Code); slot = invslot; return(false); } } return(true); }); return(slot); }
public bool ExcludeBlock(AssetLocation needle) { if (needle == null) { return(false); } foreach (AssetLocation hay in excludeBlocks) { if (hay.Equals(needle)) { return(true); } if (hay.IsWildCard && WildcardUtil.GetWildcardValue(hay, needle) != null) { return(true); } } return(false); }
public void WalkMatchingBlocks(IWorldAccessor world, BlockPos centerPos, Action <Block, BlockPos> onBlock) { if (TransformedOffsets == null) { throw new InvalidOperationException("call InitForUse() first"); } BlockPos pos = new BlockPos(); for (int i = 0; i < TransformedOffsets.Count; i++) { Vec4i offset = TransformedOffsets[i]; pos.Set(centerPos.X + offset.X, centerPos.Y + offset.Y, centerPos.Z + offset.Z); Block block = world.BlockAccessor.GetBlock(pos); if (WildcardUtil.Match(BlockCodes[offset.W], block.Code)) { onBlock?.Invoke(block, pos); } } }
public bool FindMatchCode(AssetLocation needle) { if (needle == null) { return(false); } foreach (AssetLocation hay in plantBlocks) { if (hay.Equals(needle)) { return(true); } if (hay.IsWildCard && WildcardUtil.GetWildcardValue(hay, needle) != null) { return(true); } } return(false); }
/// <summary> /// Checks whether or not the input satisfies as an ingredient for the recipe. /// </summary> /// <param name="inputStack"></param> /// <returns></returns> public bool SatisfiesAsIngredient(ItemStack inputStack) { if (inputStack == null) { return(false); } if (IsWildCard) { if (Type != inputStack.Class) { return(false); } if (!WildcardUtil.Match(Code, inputStack.Collectible.Code, AllowedVariants)) { return(false); } if (inputStack.StackSize < Quantity) { return(false); } } else { if (!ResolvedItemstack.Satisfies(inputStack)) { return(false); } if (inputStack.StackSize < ResolvedItemstack.StackSize) { return(false); } } return(true); }
protected static void solveByType(JToken json, string codePath, OrderedDictionary <string, string> searchReplace) { if (json is JObject jsonObj) { List <string> propertiesToRemove = null; Dictionary <string, JToken> propertiesToAdd = null; foreach (var entry in jsonObj) { if (entry.Key.EndsWith("byType", StringComparison.OrdinalIgnoreCase)) { string trueKey = entry.Key.Substring(0, entry.Key.Length - 6); // 6 is the length of "byType" var jobj = entry.Value as JObject; foreach (var byTypeProperty in jobj) { if (WildcardUtil.Match(byTypeProperty.Key, codePath)) { JToken typedToken = byTypeProperty.Value; // Unnecessary to solveByType specifically on this new token's contents as we will be doing a solveByType on all the tokens in the jsonObj anyhow, after adding the propertiesToAdd if (propertiesToAdd == null) { propertiesToAdd = new Dictionary <string, JToken>(); } propertiesToAdd.Add(trueKey, typedToken); break; // Replaces for first matched key only } } if (propertiesToRemove == null) { propertiesToRemove = new List <string>(); } propertiesToRemove.Add(entry.Key); } } if (propertiesToRemove != null) { foreach (var property in propertiesToRemove) { jsonObj.Remove(property); } if (propertiesToAdd != null) { foreach (var property in propertiesToAdd) { if (jsonObj[property.Key] is JObject jobject) { jobject.Merge(property.Value); } else { jsonObj[property.Key] = property.Value; } } } } foreach (var entry in jsonObj) { solveByType(entry.Value, codePath, searchReplace); } } else if (json.Type == JTokenType.String) { string value = (string)(json as JValue).Value; if (value.Contains("{")) { (json as JValue).Value = RegistryObject.FillPlaceHolder(value, searchReplace); } } else if (json is JArray jarray) { foreach (var child in jarray) { solveByType(child, codePath, searchReplace); } } }
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); }
public bool TryCreateKiln(IWorldAccessor world, IPlayer byPlayer, BlockPos pos) { ItemSlot hotbarSlot = byPlayer.InventoryManager.ActiveHotbarSlot; if (hotbarSlot.Empty) { return(false); } BlockEntity be = world.BlockAccessor.GetBlockEntity(pos); if (be is BlockEntityGroundStorage beg) { if (!beg.OnTryCreateKiln()) { return(false); } ICoreClientAPI capi = api as ICoreClientAPI; bool ok = true; foreach (var face in BlockFacing.HORIZONTALS.Append(BlockFacing.DOWN)) { BlockPos npos = pos.AddCopy(face); Block block = world.BlockAccessor.GetBlock(npos); if (!block.CanAttachBlockAt(world.BlockAccessor, this, npos, face.Opposite)) { capi?.TriggerIngameError(this, "notsolid", Lang.Get("Pit kilns need to be surrounded by solid, non-flammable blocks")); ok = false; break; } if (block.CombustibleProps != null) { capi?.TriggerIngameError(this, "notsolid", Lang.Get("Pit kilns need to be surrounded by solid, non-flammable blocks")); ok = false; break; } } if (!ok) { return(false); } Block upblock = world.BlockAccessor.GetBlock(pos.UpCopy()); if (upblock.Replaceable < 6000) { ok = false; capi?.TriggerIngameError(this, "notairspace", Lang.Get("Pit kilns need one block of air space above them")); } if (!ok) { return(false); } BuildStage[] buildStages = null; bool found = false; foreach (var val in BuildStagesByBlock) { if (!beg.Inventory[0].Empty && WildcardUtil.Match(new AssetLocation(val.Key), beg.Inventory[0].Itemstack.Collectible.Code)) { buildStages = val.Value; found = true; break; } } if (!found) { BuildStagesByBlock.TryGetValue("*", out buildStages); } if (buildStages == null) { return(false); } if (!hotbarSlot.Itemstack.Equals(world, buildStages[0].Materials[0].ItemStack, GlobalConstants.IgnoredStackAttributes) || hotbarSlot.StackSize < buildStages[0].Materials[0].ItemStack.StackSize) { return(false); } var prevInv = beg.Inventory; world.BlockAccessor.SetBlock(Id, pos); var begs = world.BlockAccessor.GetBlockEntity(pos) as BlockEntityPitKiln; for (int i = 0; i < prevInv.Count; i++) { begs.Inventory[i] = prevInv[i]; } begs.OnCreated(byPlayer); begs.updateMeshes(); begs.MarkDirty(true); return(true); } return(false); }
internal ResolvedDepositBlock Resolve(string fileForLogging, ICoreServerAPI api, Block inblock, string key, string value) { AssetLocation oreLoc = Code.Clone(); oreLoc.Path = oreLoc.Path.Replace("{" + key + "}", value); Block[] oreBlocks = api.World.SearchBlocks(oreLoc); if (oreBlocks.Length == 0) { api.World.Logger.Warning("Deposit {0}: No block with code/wildcard '{1}' was found (unresolved code: {2})", fileForLogging, oreLoc, Code); } if (AllowedVariants != null) { List <Block> filteredBlocks = new List <Block>(); for (int i = 0; i < oreBlocks.Length; i++) { if (WildcardUtil.Match(oreLoc, oreBlocks[i].Code, AllowedVariants)) { filteredBlocks.Add(oreBlocks[i]); } } if (filteredBlocks.Count == 0) { api.World.Logger.Warning("Deposit {0}: AllowedVariants for {1} does not match any block! Please fix", fileForLogging, oreLoc); } oreBlocks = filteredBlocks.ToArray(); MaxGrade = AllowedVariants.Length; } if (AllowedVariantsByInBlock != null) { List <Block> filteredBlocks = new List <Block>(); for (int i = 0; i < oreBlocks.Length; i++) { if (AllowedVariantsByInBlock[inblock.Code].Contains(WildcardUtil.GetWildcardValue(oreLoc, oreBlocks[i].Code))) { filteredBlocks.Add(oreBlocks[i]); } } foreach (var val in AllowedVariantsByInBlock) { MaxGrade = Math.Max(MaxGrade, val.Value.Length); } if (filteredBlocks.Count == 0) { api.World.Logger.Warning("Deposit {0}: AllowedVariantsByInBlock for {1} does not match any block! Please fix", fileForLogging, oreLoc); } oreBlocks = filteredBlocks.ToArray(); } return(new ResolvedDepositBlock() { Blocks = oreBlocks }); }
public override void Init() { if (Radius == null) { Api.Server.LogWarning("Deposit {0} has no radius property defined. Defaulting to uniform radius 10", variant.fromFile); Radius = NatFloat.createUniform(10, 0); } if (variant.Climate != null && Radius.avg + Radius.var >= 32) { Api.Server.LogWarning("Deposit {0} has CheckClimate=true and radius > 32 blocks - this is not supported, sorry. Defaulting to uniform radius 10", variant.fromFile); Radius = NatFloat.createUniform(10, 0); } if (InBlock != null) { Block[] blocks = Api.World.SearchBlocks(InBlock.Code); if (blocks.Length == 0) { Api.Server.LogWarning("Deposit in file {0}, no such blocks found by code/wildcard '{1}'. Deposit will never spawn.", variant.fromFile, InBlock.Code); } foreach (var block in blocks) { if (InBlock.AllowedVariants != null && !WildcardUtil.Match(InBlock.Code, block.Code, InBlock.AllowedVariants)) { continue; } if (InBlock.AllowedVariantsByInBlock != null && !InBlock.AllowedVariantsByInBlock.ContainsKey(block.Code)) { continue; } string key = InBlock.Name; string value = WildcardUtil.GetWildcardValue(InBlock.Code, block.Code); placeBlockByInBlockId[block.BlockId] = PlaceBlock.Resolve(variant.fromFile, Api, block, key, value); if (SurfaceBlock != null) { surfaceBlockByInBlockId[block.BlockId] = SurfaceBlock.Resolve(variant.fromFile, Api, block, key, value); } if (variant.ChildDeposits != null) { foreach (var val in variant.ChildDeposits) { if (val.GeneratorInst == null) { val.InitWithoutGenerator(Api); val.GeneratorInst = new ChildDepositGenerator(Api, val, DepositRand, DistortNoiseGen); JsonUtil.Populate(val.Attributes.Token, val.GeneratorInst); } foreach (Block depositblock in placeBlockByInBlockId[block.BlockId].Blocks) { (val.GeneratorInst as ChildDepositGenerator).ResolveAdd(depositblock, key, value); } } } // Host rock for if (block.Attributes == null) { block.Attributes = new JsonObject(JToken.Parse("{}")); } int[] oreIds = block.Attributes["hostRockFor"].AsArray <int>(new int[0]); oreIds = oreIds.Append(placeBlockByInBlockId[block.BlockId].Blocks.Select(b => b.BlockId).ToArray()); block.Attributes.Token["hostRockFor"] = JToken.FromObject(oreIds); // In host rock Block[] placeBlocks = placeBlockByInBlockId[block.BlockId].Blocks; for (int i = 0; i < placeBlocks.Length; i++) { Block pblock = placeBlocks[i]; if (pblock.Attributes == null) { pblock.Attributes = new JsonObject(JToken.Parse("{}")); } oreIds = pblock.Attributes["hostRock"].AsArray <int>(new int[0]); oreIds = oreIds.Append(block.BlockId); pblock.Attributes.Token["hostRock"] = JToken.FromObject(oreIds); } } } else { Api.Server.LogWarning("Deposit in file {0} has no inblock defined, it will never spawn.", variant.fromFile); } }
/// <summary> /// Resolves Wildcards in the ingredients /// </summary> /// <param name="world"></param> /// <returns></returns> public override Dictionary <string, string[]> GetNameToCodeMapping(IWorldAccessor world) { Dictionary <string, string[]> mappings = new Dictionary <string, string[]>(); if (Ingredient.Name == null || Ingredient.Name.Length == 0) { return(mappings); } if (!Ingredient.Code.Path.Contains("*")) { return(mappings); } int wildcardStartLen = Ingredient.Code.Path.IndexOf("*"); int wildcardEndLen = Ingredient.Code.Path.Length - wildcardStartLen - 1; List <string> codes = new List <string>(); if (Ingredient.Type == EnumItemClass.Block) { for (int i = 0; i < world.Blocks.Count; i++) { if (world.Blocks[i]?.Code == null || world.Blocks[i].IsMissing) { continue; } if (WildcardUtil.Match(Ingredient.Code, world.Blocks[i].Code)) { string code = world.Blocks[i].Code.Path.Substring(wildcardStartLen); string codepart = code.Substring(0, code.Length - wildcardEndLen); if (Ingredient.AllowedVariants != null && !Ingredient.AllowedVariants.Contains(codepart)) { continue; } codes.Add(codepart); } } } else { for (int i = 0; i < world.Items.Count; i++) { if (world.Items[i]?.Code == null || world.Items[i].IsMissing) { continue; } if (WildcardUtil.Match(Ingredient.Code, world.Items[i].Code)) { string code = world.Items[i].Code.Path.Substring(wildcardStartLen); string codepart = code.Substring(0, code.Length - wildcardEndLen); if (Ingredient.AllowedVariants != null && !Ingredient.AllowedVariants.Contains(codepart)) { continue; } codes.Add(codepart); } } } mappings[Ingredient.Name] = codes.ToArray(); return(mappings); }
internal bool Matches(CollectibleObject?collectible) => (Type == collectible?.ItemClass) && WildcardUtil.Match(Code, collectible.Code, AllowedVariants);
/// <summary> /// Evals the specified source. /// </summary> /// <param name="source">The source.</param> /// <param name="element">The element.</param> /// <returns></returns> public static bool Eval(EntityObject source, FilterElement element) { if (source == null) { throw new ArgumentNullException("source"); } if (element == null) { throw new ArgumentNullException("element"); } switch (element.Type) { case FilterElementType.Abstract: throw new NotSupportedException(); case FilterElementType.Exists: throw new NotSupportedException(); case FilterElementType.NotExists: throw new NotSupportedException(); case FilterElementType.In: throw new NotSupportedException(); case FilterElementType.NotIn: throw new NotSupportedException(); case FilterElementType.AndBlock: { foreach (FilterElement childElement in element.ChildElements) { if (!Eval(source, childElement)) { return(false); } } return(true); } case FilterElementType.OrBlock: { foreach (FilterElement childElement in element.ChildElements) { if (Eval(source, childElement)) { return(true); } } return(false); } case FilterElementType.Between: { object propertyValue = GetPropertyValue(source, element.Source); object start = element.ChildElements[0].Value; object end = element.ChildElements[1].Value; int result1 = Compare(start, propertyValue); int result2 = Compare(propertyValue, end); return(result1 <= 0 && result2 <= 0); } case FilterElementType.Contains: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(propertyValue.IndexOf(mask, StringComparison.OrdinalIgnoreCase) != -1); } case FilterElementType.NotContains: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(!(propertyValue.IndexOf(mask, StringComparison.OrdinalIgnoreCase) != -1)); } case FilterElementType.Custom: throw new NotSupportedException(); case FilterElementType.EndsWith: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(propertyValue.EndsWith(mask, StringComparison.OrdinalIgnoreCase)); } case FilterElementType.NotEndsWith: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(!propertyValue.EndsWith(mask, StringComparison.OrdinalIgnoreCase)); } case FilterElementType.StartsWith: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(propertyValue.StartsWith(mask, StringComparison.OrdinalIgnoreCase)); } case FilterElementType.NotStartsWith: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } return(!propertyValue.StartsWith(mask, StringComparison.OrdinalIgnoreCase)); } case FilterElementType.Equal: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) == 0); } case FilterElementType.NotEqual: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) != 0); } case FilterElementType.Greater: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) > 0); } case FilterElementType.GreaterOrEqual: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) >= 0); } case FilterElementType.IsNotNull: { object propertyValue = GetPropertyValue(source, element.Source); return(propertyValue != null); } case FilterElementType.IsNull: { object propertyValue = GetPropertyValue(source, element.Source); return(propertyValue == null); } case FilterElementType.Less: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) < 0); } case FilterElementType.LessOrEqual: { object propertyValue = GetPropertyValue(source, element.Source); object srcValue = element.Value; return(Compare(propertyValue, srcValue) <= 0); } case FilterElementType.Like: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } // TODO: Support % Only mask = mask.Replace('%', '*'); return(WildcardUtil.PatternMatch(propertyValue, mask)); } case FilterElementType.NotLike: { string propertyValue = (string)GetPropertyValue(source, element.Source); string mask = (string)element.Value; if (propertyValue == null || mask == null) { return(false); } // TODO: Support % Only mask = mask.Replace('%', '*'); return(!WildcardUtil.PatternMatch(propertyValue, mask)); } } throw new NotSupportedException(); }
private bool ConsumeInputShapeLess(IPlayer byPlayer, ItemSlot[] inputSlots) { List <CraftingRecipeIngredient> exactMatchIngredients = new List <CraftingRecipeIngredient>(); List <CraftingRecipeIngredient> wildcardIngredients = new List <CraftingRecipeIngredient>(); for (int i = 0; i < resolvedIngredients.Length; i++) { CraftingRecipeIngredient ingredient = resolvedIngredients[i]; if (ingredient == null) { continue; } if (ingredient.IsWildCard || ingredient.IsTool) { wildcardIngredients.Add(ingredient.Clone()); continue; } ItemStack stack = ingredient.ResolvedItemstack; bool found = false; for (int j = 0; j < exactMatchIngredients.Count; j++) { if (exactMatchIngredients[j].ResolvedItemstack.Satisfies(stack)) { exactMatchIngredients[j].ResolvedItemstack.StackSize += stack.StackSize; found = true; break; } } if (!found) { exactMatchIngredients.Add(ingredient.Clone()); } } for (int i = 0; i < inputSlots.Length; i++) { ItemStack inStack = inputSlots[i].Itemstack; if (inStack == null) { continue; } for (int j = 0; j < exactMatchIngredients.Count; j++) { if (exactMatchIngredients[j].ResolvedItemstack.Satisfies(inStack)) { int quantity = Math.Min(exactMatchIngredients[j].ResolvedItemstack.StackSize, inStack.StackSize); inStack.Collectible.OnConsumedByCrafting(inputSlots, inputSlots[i], this, exactMatchIngredients[j], byPlayer, quantity); exactMatchIngredients[j].ResolvedItemstack.StackSize -= quantity; if (exactMatchIngredients[j].ResolvedItemstack.StackSize <= 0) { exactMatchIngredients.RemoveAt(j); } break; } } for (int j = 0; j < wildcardIngredients.Count; j++) { CraftingRecipeIngredient ingredient = wildcardIngredients[j]; if ( ingredient.Type == inStack.Class && WildcardUtil.Match(ingredient.Code, inStack.Collectible.Code, ingredient.AllowedVariants) && inStack.StackSize >= ingredient.Quantity ) { int quantity = Math.Min(ingredient.Quantity, inStack.StackSize); inStack.Collectible.OnConsumedByCrafting(inputSlots, inputSlots[i], this, ingredient, byPlayer, quantity); if (ingredient.IsTool) { wildcardIngredients.RemoveAt(j); } else { ingredient.Quantity -= quantity; if (ingredient.Quantity <= 0) { wildcardIngredients.RemoveAt(j); } } break; } } } return(exactMatchIngredients.Count == 0); }
private bool MatchesShapeLess(ItemSlot[] suppliedSlots, int gridWidth) { int gridHeight = suppliedSlots.Length / gridWidth; if (gridWidth < Width || gridHeight < Height) { return(false); } List <KeyValuePair <ItemStack, CraftingRecipeIngredient> > ingredientStacks = new List <KeyValuePair <ItemStack, CraftingRecipeIngredient> >(); List <ItemStack> suppliedStacks = new List <ItemStack>(); // Step 1: Merge all stacks from the supplied slots for (int i = 0; i < suppliedSlots.Length; i++) { if (suppliedSlots[i].Itemstack != null) { bool found = false; for (int j = 0; j < suppliedStacks.Count; j++) { if (suppliedStacks[j].Satisfies(suppliedSlots[i].Itemstack)) { suppliedStacks[j].StackSize += suppliedSlots[i].Itemstack.StackSize; found = true; break; } } if (!found) { suppliedStacks.Add(suppliedSlots[i].Itemstack.Clone()); } } } // Step 2: Merge all stacks from the recipe reference for (int i = 0; i < resolvedIngredients.Length; i++) { CraftingRecipeIngredient ingredient = resolvedIngredients[i]; if (ingredient == null) { continue; } if (ingredient.IsWildCard) { bool foundw = false; int j = 0; for (; !foundw && j < suppliedStacks.Count; j++) { ItemStack inputStack = suppliedStacks[j]; foundw = ingredient.Type == inputStack.Class && WildcardUtil.Match(ingredient.Code, inputStack.Collectible.Code, ingredient.AllowedVariants) && inputStack.StackSize >= ingredient.Quantity ; foundw &= inputStack.Collectible.MatchesForCrafting(inputStack, this, ingredient); } if (!foundw) { return(false); } suppliedStacks.RemoveAt(j - 1); continue; } ItemStack stack = ingredient.ResolvedItemstack; bool found = false; for (int j = 0; j < ingredientStacks.Count; j++) { if (ingredientStacks[j].Key.Equals(world, stack, GlobalConstants.IgnoredStackAttributes)) { ingredientStacks[j].Key.StackSize += stack.StackSize; found = true; break; } } if (!found) { ingredientStacks.Add(new KeyValuePair <ItemStack, CraftingRecipeIngredient>(stack.Clone(), ingredient)); } } if (ingredientStacks.Count != suppliedStacks.Count) { return(false); } bool equals = true; for (int i = 0; equals && i < ingredientStacks.Count; i++) { bool found = false; for (int j = 0; !found && j < suppliedStacks.Count; j++) { found = ingredientStacks[i].Key.Satisfies(suppliedStacks[j]) && ingredientStacks[i].Key.StackSize <= suppliedStacks[j].StackSize && suppliedStacks[j].Collectible.MatchesForCrafting(suppliedStacks[j], this, ingredientStacks[i].Value) ; if (found) { suppliedStacks.RemoveAt(j); } } equals &= found; } return(equals); }