private static void OnFuelChanged(
            IStaticWorldObject objectManufacturer,
            FuelBurningState state,
            CraftingQueue byproductsCraftQueue,
            ManufacturingConfig config)
        {
            if (!config.IsProduceByproducts)
            {
                return;
            }

            var currentByproductRecipe = byproductsCraftQueue.QueueItems.FirstOrDefault()?.Recipe
                                         as Recipe.RecipeForManufacturingByproduct;
            var newByproductRecipe = config.MatchRecipeForByproduct(state.CurrentFuelItemType);

            if (currentByproductRecipe == newByproductRecipe)
            {
                return;
            }

            byproductsCraftQueue.Clear();

            if (newByproductRecipe != null)
            {
                CraftingMechanics.ServerStartCrafting(
                    objectManufacturer,
                    null,
                    byproductsCraftQueue,
                    newByproductRecipe,
                    // unlimited count
                    countToCraft: ushort.MaxValue);
            }
        }
Пример #2
0
        /// <summary>
        /// Refreshes best matching recipe, auto-select it if needed by config.
        /// </summary>
        private static void RefreshRecipe(
            ManufacturingState state,
            ManufacturingConfig config,
            IStaticWorldObject objectManufacturer)
        {
            var selectedRecipe = state.SelectedRecipe;
            var bestRecipe     = SharedMatchBestRecipe(state,
                                                       config,
                                                       objectManufacturer);

            if (bestRecipe is not null &&
                config.IsAutoSelectRecipe)
            {
                // auto-select the best recipe
                selectedRecipe = state.SelectedRecipe = bestRecipe;
                bestRecipe     = null;
                state.CraftingQueue.Clear();
            }

            if (selectedRecipe is null)
            {
                return;
            }

            // refresh selected recipe
            var isSelectedRecipeCanBeCrafted = selectedRecipe.CanBeCrafted(
                character: null,
                objectManufacturer,
                state.CraftingQueue,
                countToCraft: 1);

            if (isSelectedRecipeCanBeCrafted)
            {
                var currentCraftingRecipe = state.CraftingQueue.QueueItems.FirstOrDefault();
                if (currentCraftingRecipe is null ||
                    currentCraftingRecipe.RecipeEntry?.Recipe != selectedRecipe)
                {
                    // there is nothing crafting or something different is crafting - start crafting the new selected recipe
                    Logger.Info($"Manufacturing of recipe {selectedRecipe} started at {objectManufacturer}");
                    CraftingMechanics.ServerStartCrafting(
                        objectManufacturer,
                        null,
                        state.CraftingQueue,
                        new RecipeWithSkin(selectedRecipe),
                        countToCraft: ushort.MaxValue);
                }
            }
            else if (state.CraftingQueue.QueueItems.Count > 0)
            {
                // the selected recipe cannot be crafted
                // clear current queue (progress is lost!)
                // nothing will be crafted now
                Logger.Info($"Manufacturing stopped at {objectManufacturer} - the recipe cannot be crafted anymore");
                state.CraftingQueue.Clear();
            }
        }
Пример #3
0
        /// <summary>
        /// Updates fuel burning state.
        /// </summary>
        /// <param name="objectManufacturer">Instance of world object performing manufacturing.</param>
        /// <param name="state">Instance of fuel burning state.</param>
        /// <param name="byproductsCraftQueue"></param>
        /// <param name="config">Manufacturing config.</param>
        /// <param name="deltaTime">Delta time to progress on.</param>
        /// <param name="isNeedFuelNow">The new fuel item will be not burned if the fuel is not needed now.</param>
        public static void Update(
            IStaticWorldObject objectManufacturer,
            FuelBurningState state,
            CraftingQueue byproductsCraftQueue,
            ManufacturingConfig config,
            double deltaTime,
            double byproductsQueueRate,
            bool isNeedFuelNow,
            bool forceRefreshFuel = false)
        {
            if (isNeedFuelNow &&
                (state.ContainerFuel.StateHash != state.ContainerFuelLastStateHash ||
                 forceRefreshFuel))
            {
                RefreshFuel(state, byproductsCraftQueue, config, objectManufacturer, isNeedFuelNow);
                state.ContainerFuelLastStateHash = state.ContainerFuel.StateHash;
            }

            var fuelUseTimeRemainsSeconds =
                state.FuelUseTimeRemainsSeconds
                + state.FuelUseTimeAccumulatedRemainder
                - deltaTime;

            if (fuelUseTimeRemainsSeconds <= 0)
            {
                // fuel is burned
                state.FuelUseTimeAccumulatedRemainder += state.FuelUseTimeRemainsSeconds;
                state.FuelUseTimeRemainsSeconds        = 0;

                if (isNeedFuelNow)
                {
                    // refresh fuel
                    RefreshFuel(state, byproductsCraftQueue, config, objectManufacturer, isNeedFuelNow);
                    return;
                }

                return;
            }

            // subtract fuel burn time
            state.FuelUseTimeAccumulatedRemainder = 0;
            state.FuelUseTimeRemainsSeconds       = fuelUseTimeRemainsSeconds;

            if (config.IsProduceByproducts)
            {
                if (byproductsCraftQueue is null)
                {
                    throw new Exception("No byproductsCraftQueue");
                }

                CraftingMechanics.ServerUpdate(byproductsCraftQueue,
                                               deltaTime * byproductsQueueRate);
            }
        }
Пример #4
0
        private void ServerRemote_CancelQueueItem(ushort localId)
        {
            var character            = ServerRemoteContext.Character;
            var characterServerState = PlayerCharacter.GetPrivateState(character);

            var queue = characterServerState.CraftingQueue.QueueItems;

            for (var index = 0; index < queue.Count; index++)
            {
                var item = queue[index];
                if (item.LocalId == localId)
                {
                    CraftingMechanics.ServerCancelCraftingQueueItem(character, item);
                    return;
                }
            }

            Logger.Warning("Cannot find crafting queue entry with localId=" + localId);
        }
Пример #5
0
 /// <summary>
 /// Updates only crafting queue recipe - please be sure to call <see cref="UpdateRecipeOnly" /> before that.
 /// </summary>
 /// <param name="state">Instance of manufacturing state.</param>
 /// <param name="deltaTime">Delta time to progress on.</param>
 public static void UpdateCraftingQueueOnly(ManufacturingState state, double deltaTime)
 {
     CraftingMechanics.ServerUpdate(state.CraftingQueue, deltaTime);
 }
Пример #6
0
        public bool ServerRemote_CraftRecipe(RecipeWithSkin recipeEntry, ushort countToCraft)
        {
            recipeEntry.Validate();
            var character            = ServerRemoteContext.Character;
            var characterServerState = PlayerCharacter.GetPrivateState(character);

            if (recipeEntry.ProtoItemSkinOverride is IProtoItemWithSkinData protoItemSkin)
            {
                if (!Server.Items.IsSkinOwned(character, (ushort)protoItemSkin.SkinId))
                {
                    throw new Exception("The skin is not owned: " + protoItemSkin + " for " + character);
                }
            }

            IStaticWorldObject station;
            var craftingQueue = characterServerState.CraftingQueue;

            switch (recipeEntry.Recipe)
            {
            case Recipe.RecipeForHandCrafting:
                // simply craft by character
                station = null;
                break;

            case Recipe.RecipeForStationCrafting recipeForStation:
                station = SharedFindNearbyStationOfTypes(recipeForStation.StationTypes, character);
                if (station is null)
                {
                    Logger.Error(
                        $"No crafting stations of types {recipeForStation.StationTypes.GetJoinedString()} found nearby character {character} at position {character.Position}");
                    return(false);
                }

                break;

            default:
                throw new Exception("Incorrect recipe for in-hand or station crafting: " + recipeEntry);
            }

            // extra check (it's also done in the recipe itself)
            if (!recipeEntry.Recipe.SharedIsTechUnlocked(character))
            {
                // locked recipe
                return(false);
            }

            var maxCraftingQueueEntriesCount = SharedGetMaxCraftingQueueEntriesCount(character);

            if (recipeEntry.Recipe.OutputItems.Items[0].ProtoItem.IsStackable)
            {
                // stackable items
                if (!SharedValidateQueueIsNotFull(character, recipeEntry, countToCraft, maxCraftingQueueEntriesCount))
                {
                    return(false);
                }

                CraftingMechanics.ServerStartCrafting(station,
                                                      character,
                                                      craftingQueue,
                                                      recipeEntry,
                                                      countToCraft,
                                                      maxQueueSize: maxCraftingQueueEntriesCount);
            }
            else
            {
                // non-stackable items
                countToCraft = MathHelper.Clamp(countToCraft,
                                                min: (ushort)1,
                                                max: maxCraftingQueueEntriesCount);
                for (var i = 0; i < countToCraft; i++)
                {
                    if (!SharedValidateQueueIsNotFull(character,
                                                      recipeEntry,
                                                      countToCraft: 1,
                                                      maxCraftingQueueEntriesCount))
                    {
                        return(false);
                    }

                    CraftingMechanics.ServerStartCrafting(station,
                                                          character,
                                                          craftingQueue,
                                                          recipeEntry,
                                                          countToCraft: 1,
                                                          maxQueueSize: maxCraftingQueueEntriesCount);
                }
            }

            return(true);
        }
Пример #7
0
        public bool ServerRemote_CraftRecipe(Recipe recipe, ushort countToCraft)
        {
            var character            = ServerRemoteContext.Character;
            var characterServerState = PlayerCharacter.GetPrivateState(character);

            IStaticWorldObject station;
            var craftingQueue = characterServerState.CraftingQueue;

            if (recipe.RecipeType == RecipeType.Hand)
            {
                // simply craft by character
                station = null;
            }
            else
            {
                var recipeForStation = (Recipe.BaseRecipeForStation)recipe;
                station = SharedFindNearbyStationOfTypes(recipeForStation.StationTypes, character);
                if (station == null)
                {
                    Logger.Error(
                        $"No crafting stations of types {recipeForStation.StationTypes.GetJoinedString()} found nearby character {character} at position {character.Position}");
                    return(false);
                }

                if (recipeForStation is Recipe.RecipeForManufacturing)
                {
                    // manufacture on station
                    throw new Exception("Cannot craft in hand recipe for station manufacturing");
                }
            }

            var maxCraftingQueueEntriesCount = SharedGetMaxCraftingQueueEntriesCount(character);

            if (recipe.OutputItems.Items[0].ProtoItem.IsStackable)
            {
                // stackable items
                if (!SharedValidateQueueIsNotFull(character, recipe, countToCraft, maxCraftingQueueEntriesCount))
                {
                    return(false);
                }

                CraftingMechanics.ServerStartCrafting(station,
                                                      character,
                                                      craftingQueue,
                                                      recipe,
                                                      countToCraft,
                                                      maxQueueSize: maxCraftingQueueEntriesCount);
            }
            else
            {
                // non-stackable items
                countToCraft = MathHelper.Clamp(countToCraft,
                                                min: (ushort)1,
                                                max: maxCraftingQueueEntriesCount);
                for (var i = 0; i < countToCraft; i++)
                {
                    if (!SharedValidateQueueIsNotFull(character,
                                                      recipe,
                                                      countToCraft: 1,
                                                      maxCraftingQueueEntriesCount))
                    {
                        return(false);
                    }

                    CraftingMechanics.ServerStartCrafting(station,
                                                          character,
                                                          craftingQueue,
                                                          recipe,
                                                          countToCraft: 1,
                                                          maxQueueSize: maxCraftingQueueEntriesCount);
                }
            }

            return(true);
        }