/// <summary>Raised after buildings are added/removed in any location.</summary> private void OnBuildingListChanged(object sender, BuildingListChangedEventArgs e) { // Add added furnaces to the controller list foreach (Building building in e.Added) { if (IsBuildingIndustrialFurnace(building)) { // Add the controller that takes care of the functionality of the furnace IndustrialFurnaceController controller = new IndustrialFurnaceController(furnacesBuilt, false, this) { furnace = building }; furnaces.Add(controller); furnacesBuilt++; } } // Remove destroyed furnaces from the controller list foreach (Building building in e.Removed) { if (IsBuildingIndustrialFurnace(building)) { int index = GetIndexOfFurnaceControllerWithTag(building.maxOccupants.Value); if (index > -1) { furnaces.RemoveAt(index); } } } }
/// <summary>Parses the furnace controller data from the save data</summary> public void ParseModSaveDataToControllers(List <IndustrialFurnaceController> furnaces, ModEntry mod) { // Assume the lists are equally as long for (int i = 0; i < FurnaceControllerId.Count; i++) { IndustrialFurnaceController controller = new IndustrialFurnaceController(FurnaceControllerId[i], FurnaceControllerCurrentlyOn[i], mod); Dictionary <int, int> tempDictionary = FurnaceControllerInput[i]; foreach (KeyValuePair <int, int> kvp in tempDictionary) { StardewValley.Object item = new StardewValley.Object(kvp.Key, kvp.Value); controller.input.addItem(item); } tempDictionary = FurnaceControllerOutput[i]; foreach (KeyValuePair <int, int> kvp in tempDictionary) { StardewValley.Object item = new StardewValley.Object(kvp.Key, kvp.Value); controller.output.addItem(item); } furnaces.Add(controller); } }
/// <summary>Processes the input chest's items and places the result to the output</summary> /// <param name="furnace"></param> private void FinishSmelting(IndustrialFurnaceController furnace) { // TODO: Add checks to prevent loss of items, since it is possible that 'output amount' > 'input amount' Monitor.Log("Processing the outputs."); // Collect the object data to a dictionary (ID, amount) first to fix losing items with over 999 stacks Dictionary <int, int> smeltablesDictionary = new Dictionary <int, int>(); foreach (Item item in furnace.input.items) { int objectId = item.ParentSheetIndex; if (smeltablesDictionary.ContainsKey(objectId)) { smeltablesDictionary[objectId] += item.Stack; } else { smeltablesDictionary.Add(objectId, item.Stack); } } // Now the dictionary consists of ItemID: Amount foreach (KeyValuePair <int, int> kvp in smeltablesDictionary) { SmeltingRule rule = newSmeltingRules.GetSmeltingRuleFromInputID(kvp.Key); if (rule is null) { // This should never be hit, but let's error it just incase... Monitor.Log($"Item with ID {kvp.Key} wasn't in the smelting rules despite being in the input chest!", LogLevel.Error); continue; } if (rule.InputItemAmount == 0) { Monitor.Log($"The input amount for object {kvp.Key} was 0. The result can't be processed so the item will be voided.", LogLevel.Error); } int outputAmount = (kvp.Value / rule.InputItemAmount) * rule.OutputItemAmount; Monitor.Log($"Found {kvp.Value} objects with ID {kvp.Key}. The smelting result is {outputAmount} objects of ID {rule.OutputItemID}."); // Add the result defined by the smelting rule to the output chest // Assumes the value is divisible with the input amount furnace.AddItemsToSmeltedChest(rule.OutputItemID, outputAmount); } for (int i = 0; i < furnace.input.items.Count; i++) { furnace.input.items[i] = null; } furnace.input.clearNulls(); furnace.ChangeCurrentlyOn(false); // Update the texture of the furnace UpdateTexture(furnace.furnace, false); }
/// <summary> /// Create a new light source and link it to the furnace /// </summary> /// <param name="controller"></param> private void CreateLight(IndustrialFurnaceController controller) { Building building = controller.furnace; Vector2 pos = new Vector2(building.tileX.Value * 64 + fireAnimationData.LightSourceXOffset, building.tileY.Value * 64 + fireAnimationData.LightSourceYOffset); LightSource light = new LightSource(4, pos, fireAnimationData.LightSourceScaleMultiplier, Color.DarkCyan, controller.ID * lightSourceIDMultiplier); // Make the furnace light up the area Game1.currentLightSources.Add(light); controller.lightSource = light; }
/// <summary>Called when the player tries to interact with the output chest</summary> /// <param name="furnace">The furnace controller that's being interacted with</param> private void CollectItemsFromTheFurnace(IndustrialFurnaceController furnace) { // Clear the output of removed items furnace.output.clearNulls(); // Show output chest only if it contains something if (furnace.output.items.Count == 0) { return; } currentlyLookingAtFurnace = furnace.ID; DrawOutputMenu(furnace); }
private void DrawOutputMenu(IndustrialFurnaceController furnace) { // Display the menu for the output chest Game1.activeClickableMenu = (IClickableMenu) new ItemGrabMenu( furnace.output.items, false, true, new InventoryMenu.highlightThisItem(InventoryMenu.highlightAllItems), null, (string)null, (item, farmer) => furnace.GrabItemFromChest(item, farmer), false, true, true, true, false, 0, null, -1, null); }
/// <summary>Place items to the furnace</summary> /// <param name="furnace">The furnace controller</param> /// <returns>Whether the placement was successful or not</returns> private bool PlaceItemsToTheFurnace(IndustrialFurnaceController furnace) { // Items can be placed only if the furnace is NOT on if (furnace.CurrentlyOn) { DisplayMessage(i18n.Get("message.furnace-running"), 3, "cancel"); return(false); } // Get the current held object, null for tools etc. SObject heldItem = Game1.player.ActiveObject; if (heldItem == null) { return(false); } int objectId = heldItem.ParentSheetIndex; SmeltingRule rule = newSmeltingRules.GetSmeltingRuleFromInputID(objectId); // Check if the object is on the smeltables list if (rule != null) { // Prevent the game from division by 0, even if the player edits the rules if (rule.InputItemAmount == 0) { Monitor.Log($"The smelting rule for object {objectId} had 0 for input amount.", LogLevel.Error); return(false); } int amount = heldItem.Stack; // Check if the player has enough to smelt if (amount >= rule.InputItemAmount) { // Remove multiples of the required input amount int smeltAmount = amount / rule.InputItemAmount; Game1.player.removeItemsFromInventory(objectId, smeltAmount * rule.InputItemAmount); furnace.AddItemsToSmelt(objectId, smeltAmount * rule.InputItemAmount); Monitor.Log($"{Game1.player.Name} placed {smeltAmount * rule.InputItemAmount} {heldItem.Name} to the furnace {furnace.ID}."); return(true); } else { DisplayMessage(i18n.Get("message.need-more-ore", new { oreAmount = rule.InputItemAmount }), 3, "cancel"); return(false); } } // Check if the player tries to put coal in the furnace and start the smelting else if (objectId == SObject.coal && !furnace.CurrentlyOn) { // The input has items to smelt if (furnace.input.items.Count > 0) { if (heldItem.Stack >= config.CoalAmount) { Game1.player.removeItemsFromInventory(objectId, config.CoalAmount); Monitor.Log($"{Game1.player.Name} started the furnace {furnace.ID} with {config.CoalAmount} {heldItem.Name}."); if (config.InstantSmelting) { Monitor.Log("And it finished immediately."); FinishSmelting(furnace); } else { furnace.ChangeCurrentlyOn(true); UpdateTexture(furnace.furnace, true); CreateLight(furnace); } Game1.playSound("furnace"); return(true); } else { DisplayMessage(i18n.Get("message.more-coal", new { coalAmount = config.CoalAmount }), 3, "cancel"); return(false); } } else { DisplayMessage(i18n.Get("message.place-something-first"), 3, "cancel"); return(false); } } else { DisplayMessage(i18n.Get("message.cant-smelt-this"), 3, "cancel"); return(false); } }