/// <summary>
        /// Add a supply chain link between the source and destination buildings.
        /// The supply chain link overrides all local area, all outside connections, and all district constraints.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        public static void AddSupplyChainConnection(ushort source, ushort destination)
        {
            if (!TransferManagerInfo.IsSupplyChainBuilding(source) || !TransferManagerInfo.IsSupplyChainBuilding(destination))
            {
                return;
            }

            if (!TransferManagerInfo.IsValidSupplyChainLink(source, destination))
            {
                Logger.Log($"Constraints::AddSupplyChainConnection: Could not add invalid supply chain link: source={source}, destination={destination}");
                return;
            }

            bool added = false;

            if (m_supplyDestinations[source] == null)
            {
                m_supplyDestinations[source] = new List <int>();
            }

            if (!m_supplyDestinations[source].Contains(destination))
            {
                added = true;
                m_supplyDestinations[source].Add(destination);
            }

            if (added)
            {
                var sourceBuildingName      = TransferManagerInfo.GetBuildingName(source);
                var destinationBuildingName = TransferManagerInfo.GetBuildingName(destination);
                Logger.Log($"Constraints::AddSupplyChainConnection: {sourceBuildingName} ({source}) => {destinationBuildingName} ({destination}) ...");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the input type of the building, used to determine which GUI elements are shown in the main panel.
        /// </summary>
        /// <param name="building"></param>
        /// <returns></returns>
        public static InputType GetBuildingInputType(int building)
        {
            if (building == 0)
            {
                return(InputType.NONE);
            }

            var result = InputType.NONE;

            // The only building type for which we will not show an outgoing tab is coal and heating power plants.
            var info = BuildingManager.instance.m_buildings.m_buffer[building].Info;

            if (TransferManagerInfo.IsDistrictServicesBuilding(building))
            {
                if ((info?.GetService() == ItemClass.Service.Electricity && info?.GetAI() is PowerPlantAI) ||
                    (info?.GetService() == ItemClass.Service.Water && info?.GetAI() is HeatingPlantAI) ||
                    (info?.GetService() == ItemClass.Service.Monument && info?.gameObject?.name == "ChirpX Launch Control Center"))
                {
                }
                else if (!Settings.enableIndustriesControl && info?.GetService() == ItemClass.Service.PlayerIndustry)
                {
                }
                else
                {
                    result |= InputType.OUTGOING;
                }
            }

            if (Settings.enableIndustriesControl && TransferManagerInfo.IsSupplyChainBuilding(building))
            {
                result |= InputType.SUPPLY_CHAIN;

                if (!(info?.GetAI() is ExtractingFacilityAI || info?.GetAI() is FishFarmAI || info?.GetAI() is FishingHarborAI))
                {
                    result |= InputType.INCOMING;
                }
            }

            if (TransferManagerInfo.IsCustomVehiclesBuilding(building))
            {
                result |= InputType.VEHICLES;
            }

            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Returns a descriptive text describing problems with this supply chain building ...
        /// </summary>
        /// <param name="building"></param>
        /// <returns></returns>
        public static string GetSupplyBuildingProblemsText(ushort building)
        {
            if (building == 0 || !TransferManagerInfo.IsSupplyChainBuilding(building))
            {
                return(string.Empty);
            }

            bool FindSourceBuilding(TransferManager.TransferReason material)
            {
                if (material == TransferManager.TransferReason.None)
                {
                    return(true);
                }

                // Assume for now that the outside connection can supply the building with the materials it needs.
                if (Constraints.InputOutsideConnections(building))
                {
                    return(true);
                }

                for (ushort buildingIn = 1; buildingIn < BuildingManager.MAX_BUILDING_COUNT; buildingIn++)
                {
                    if (!TransferManagerInfo.IsSupplyChainBuilding(building))
                    {
                        continue;
                    }

                    if (GetSupplyBuildingOutputMaterial(buildingIn) == material)
                    {
                        // Check if a supply link exists ...
                        if (Constraints.SupplyDestinations(buildingIn)?.Count > 0 && Constraints.SupplyDestinations(buildingIn).Contains(building))
                        {
                            return(true);
                        }

                        var requestDistrictPark  = TransferManagerInfo.GetDistrictPark(building);
                        var responseDistrictPark = TransferManagerInfo.GetDistrictPark(buildingIn);

                        if (!Constraints.InputAllLocalAreas(building))
                        {
                            var requestDistrictParksServed = Constraints.InputDistrictParkServiced(building);
                            if (!responseDistrictPark.IsServedBy(requestDistrictParksServed))
                            {
                                continue;
                            }
                        }

                        if (Constraints.OutputAllLocalAreas(buildingIn))
                        {
                            return(true);
                        }
                        else
                        {
                            // The call to TransferManagerInfo.GetDistrict applies to offers that are come from buildings, service
                            // vehicles, citizens, AND segments.  The latter needs to be considered for road maintenance.
                            var responseDistrictParksServed = Constraints.OutputDistrictParkServiced(buildingIn);
                            if (requestDistrictPark.IsServedBy(responseDistrictParksServed))
                            {
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }

            // Detect if we do have an other building that can supply materials to this building.
            List <TransferManager.TransferReason> notFound = new List <TransferManager.TransferReason>();

            switch (BuildingManager.instance.m_buildings.m_buffer[building].Info?.GetAI())
            {
            case ProcessingFacilityAI processingFacilityAI:
                if (!FindSourceBuilding(processingFacilityAI.m_inputResource1))
                {
                    notFound.Add(processingFacilityAI.m_inputResource1);
                }

                if (!FindSourceBuilding(processingFacilityAI.m_inputResource2))
                {
                    notFound.Add(processingFacilityAI.m_inputResource2);
                }

                if (!FindSourceBuilding(processingFacilityAI.m_inputResource3))
                {
                    notFound.Add(processingFacilityAI.m_inputResource3);
                }

                if (!FindSourceBuilding(processingFacilityAI.m_inputResource4))
                {
                    notFound.Add(processingFacilityAI.m_inputResource4);
                }

                break;

            default:
                break;
            }

            if (notFound.Count > 0)
            {
                return(string.Join(",", notFound.Select(x => x.ToString()).ToArray()));
            }
            else
            {
                return(string.Empty);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Helper method for displaying information, including district and supply chain constraints, about the
        /// building with given building id.
        /// </summary>
        /// <param name="building"></param>
        /// <returns></returns>
        private static string GetBuildingInfoText(ushort building)
        {
            var inputType = TransferManagerInfo.GetBuildingInputType(building);

            var txtItems = new List <string>();

            txtItems.Add($"{TransferManagerInfo.GetBuildingName(building)} ({building})");
            txtItems.Add(TransferManagerInfo.GetDistrictParkText(building));

            // Early return.  Rest of info pertains to building types that we deal with in the mod.
            if (!(TransferManagerInfo.IsDistrictServicesBuilding(building) || TransferManagerInfo.IsCustomVehiclesBuilding(building)))
            {
                return(string.Join("\n", txtItems.ToArray()));
            }

            txtItems.Add(TransferManagerInfo.GetBuildingInputTypeText(building));
            txtItems.Add(TransferManagerInfo.GetServicesText(building));

            if (!TransferManagerInfo.IsSupplyChainBuilding(building))
            {
                if (TransferManagerInfo.IsDistrictServicesBuilding(building))
                {
                    txtItems.Add("");
                    txtItems.Add(TransferManagerInfo.GetOutputDistrictsServedText(building));
                }

                if (Settings.enableCustomVehicles &&
                    !VehicleManagerMod.BuildingUseDefaultVehicles[building] &&
                    VehicleManagerMod.BuildingToVehicles[building] != null &&
                    (inputType & InputType.VEHICLES) != InputType.NONE)
                {
                    txtItems.Add("");
                    txtItems.Add(TransferManagerInfo.GetCustomVehiclesText(building));
                }

                return(string.Join("\n", txtItems.ToArray()));
            }

            if (Settings.enableIndustriesControl)
            {
                // From this point forth, we know this is a supply chain building ...
                txtItems.Add($"Supply Reserve: {Constraints.InternalSupplyBuffer(building)}");

                if ((inputType & InputType.INCOMING) != InputType.NONE)
                {
                    txtItems.Add("");
                    txtItems.Add(TransferManagerInfo.GetSupplyBuildingSourcesText(building));
                }

                if ((inputType & InputType.OUTGOING) != InputType.NONE)
                {
                    txtItems.Add("");
                    txtItems.Add(TransferManagerInfo.GetSupplyBuildingDestinationsText(building));
                }

                if (Settings.enableCustomVehicles &&
                    !VehicleManagerMod.BuildingUseDefaultVehicles[building] &&
                    VehicleManagerMod.BuildingToVehicles[building] != null &&
                    (inputType & InputType.VEHICLES) != InputType.NONE)
                {
                    txtItems.Add("");
                    txtItems.Add(TransferManagerInfo.GetCustomVehiclesText(building));
                }

                var problemText = TransferManagerInfo.GetSupplyBuildingProblemsText(building);
                if (problemText != string.Empty)
                {
                    txtItems.Add("");
                    txtItems.Add($"<<WARNING: Cannot find the following materials to procure!>>");
                    txtItems.Add(problemText);
                }
            }

            return(string.Join("\n", txtItems.ToArray()));
        }