private static void ServerCancelCraftingQueueItem( ICharacter character, CraftingQueueItem item, CraftingQueue craftingQueue, ref IItemsContainer groundContainer) { if (!item.Recipe.IsCancellable) { Logger.Info("Crafting queue item is not cancellable: " + item, character); return; } var index = craftingQueue.QueueItems.IndexOf(item); if (index < 0) { throw new Exception("Doesn't have the crafting queue item: " + item); } ServerReturnCharacterCraftingQueueItemInputItems(character, item, ref groundContainer); craftingQueue.QueueItems.RemoveAt(index); if (index == 0) { // first queue item was removed - reset crafting duration craftingQueue.SetDurationFromCurrentRecipe(); } Logger.Info("Crafting queue item successfully cancelled: " + item, character); }
private static void ServerReturnCharacterCraftingQueueItemInputItems( ICharacter character, CraftingQueueItem queueItem, ref IItemsContainer groundContainer) { foreach (var inputItem in queueItem.Recipe.InputItems) { var countToSpawn = queueItem.CountToCraftRemains * (uint)inputItem.Count; PlayerCharacter.ServerTrySpawnItemToCharacterOrGround(character, inputItem.ProtoItem, countToSpawn, ref groundContainer); } }
/// <summary> /// Cancel crafting queue item. /// </summary> public static void ServerCancelCraftingQueueItem( ICharacter character, CraftingQueueItem item) { var craftingQueue = character.GetPrivateState <PlayerCharacterPrivateState>() .CraftingQueue; IItemsContainer groundContainer = null; ServerCancelCraftingQueueItem(character, item, craftingQueue, ref groundContainer); if (groundContainer != null) { NotificationSystem.ServerSendNotificationNoSpaceInInventoryItemsDroppedToGround(character); } }
private static bool ServerTryCreateOutputItems(CraftingQueue craftingQueue, CraftingQueueItem queueItem) { if (craftingQueue.IsContainerOutputFull && craftingQueue.ContainerOutputLastStateHash == craftingQueue.ContainerOutput.StateHash) { return(false); } var recipe = queueItem.Recipe; var result = recipe.OutputItems.TrySpawnToContainer(craftingQueue.ContainerOutput); if (!result.IsEverythingCreated) { // cannot create items at specified container result.Rollback(); craftingQueue.IsContainerOutputFull = true; craftingQueue.ContainerOutputLastStateHash = craftingQueue.ContainerOutput.StateHash; return(false); } // something is created, assume crafting success craftingQueue.IsContainerOutputFull = false; craftingQueue.ContainerOutputLastStateHash = craftingQueue.ContainerOutput.StateHash; if (recipe is Recipe.RecipeForManufacturing recipeManufacturing) { recipeManufacturing.ServerOnManufacturingCompleted( ((ManufacturingCraftingQueue)craftingQueue).WorldObject, craftingQueue); } if (craftingQueue is CharacterCraftingQueue characterCraftingQueue) { NotificationSystem.ServerSendItemsNotification( characterCraftingQueue.Character, result); } return(true); }
/// <summary> /// Enqueue crafting selected recipe. /// </summary> /// <param name="craftingQueue">Crafting queue instance.</param> /// <param name="recipe">Recipe instance.</param> /// <param name="countToCraft">Count to craft - must be greater than zero.</param> public static void ServerStartCrafting( [CanBeNull] IStaticWorldObject station, [CanBeNull] ICharacter character, [NotNull] CraftingQueue craftingQueue, [NotNull] Recipe recipe, ushort countToCraft, ushort?maxQueueSize = null) { var characterOrStation = (IWorldObject)station ?? character; if (characterOrStation == null) { throw new NullReferenceException("Character AND station cannot be null simultaneously"); } if (countToCraft == 0) { throw new Exception("Are you really want to craft zero items?"); } var isAdminMode = character != null && CreativeModeSystem.SharedIsInCreativeMode(character); if (!isAdminMode && recipe.RecipeType != RecipeType.ManufacturingByproduct && !recipe.CanBeCrafted( characterOrStation, craftingQueue, countToCraft: recipe.RecipeType == RecipeType.Manufacturing ? (ushort)1 : countToCraft)) { Logger.Error($"Recipe cannot be crafted - check failed: {recipe} at {characterOrStation}."); return; } var queueCount = craftingQueue.QueueItems.Count; if (queueCount > 0) { foreach (var existingQueueItem in craftingQueue.QueueItems) { if (!existingQueueItem.CanCombineWith(recipe)) { continue; } // try to increase the count to craft var lastQueueItemCountBefore = existingQueueItem.CountToCraftRemains; var maxCountToCraft = ushort.MaxValue; var isManufacturingRecipe = recipe.RecipeType != RecipeType.Hand && recipe.RecipeType != RecipeType.StationCrafting; if (!isManufacturingRecipe) { maxCountToCraft = recipe.OutputItems.Items[0].ProtoItem.MaxItemsPerStack; } var originalRequestedCountToCraft = countToCraft; var lastQueueItemCountNew = (ushort)Math.Min(maxCountToCraft, lastQueueItemCountBefore + countToCraft); var canAddCount = lastQueueItemCountNew - lastQueueItemCountBefore; if (canAddCount > 0) { existingQueueItem.CountToCraftRemains = lastQueueItemCountNew; Logger.Info( $"Recipe count extended for crafting: {recipe} at {characterOrStation}: from x{lastQueueItemCountBefore} to x{countToCraft}"); ServerDestroyInputItems(craftingQueue, recipe, countToCraft: (ushort)canAddCount, isAdminMode); if (isManufacturingRecipe) { return; } var remainingCountToCraft = originalRequestedCountToCraft - canAddCount; if (remainingCountToCraft <= 0) { // the last queue item took all the requested items count to craft return; } // last queue item cannot accomodate all the requested count to craft // let's try to add to previous queue item or a new queue item countToCraft = (ushort)remainingCountToCraft; } } } if (maxQueueSize.HasValue && craftingQueue.QueueItems.Count + 1 >= maxQueueSize.Value) { Logger.Info( $"Recipe cannot be queue for crafting due to max queue size limitation: {recipe} at {characterOrStation} with max queue size {maxQueueSize.Value}."); return; } var queueItem = new CraftingQueueItem(recipe, countToCraft, craftingQueue.ServerLastQueueItemLocalId++); ServerDestroyInputItems(craftingQueue, recipe, countToCraft: queueItem.CountToCraftRemains, isAdminMode); craftingQueue.QueueItems.Add(queueItem); if (craftingQueue.QueueItems.Count == 1) { // the added recipe is first in queue - so we will craft it right now craftingQueue.SetDurationFromCurrentRecipe(); } Logger.Info($"Recipe queued for crafting: {recipe} at {characterOrStation}."); }
private static void ServerProgressQueueItem( CraftingQueue craftingQueue, CraftingQueueItem queueItem, ref double deltaTime) { if (craftingQueue.TimeRemainsToComplete > deltaTime) { // consume deltaTime craftingQueue.TimeRemainsToComplete -= deltaTime; deltaTime = 0; // need more time to complete crafting return; } // crafting of item completed deltaTime -= craftingQueue.TimeRemainsToComplete; craftingQueue.TimeRemainsToComplete = 0; if (!ServerTryCreateOutputItems(craftingQueue, queueItem)) { // need more space in output container return; } Logger.Info($"Crafting of {queueItem} completed."); var recipe = queueItem.Recipe; if (recipe.RecipeType == RecipeType.Manufacturing) { // auto-manufacturers: destroy input items when crafting completed ServerDestroyInputItems( recipe, new AggregatedItemsContainers(craftingQueue.InputContainersArray), countToCraft: 1, isAdminMode: false); } Api.SafeInvoke(() => ServerNonManufacturingRecipeCrafted?.Invoke(queueItem)); if (recipe.RecipeType == RecipeType.Manufacturing || recipe.RecipeType == RecipeType.ManufacturingByproduct) { // do not reduce count to craft as this is a manufacturing recipe var station = (IWorldObject)craftingQueue.GameObject; if (recipe.RecipeType == RecipeType.Manufacturing && !recipe.CanBeCrafted( station, craftingQueue, countToCraft: 1)) { Logger.Info( $"Manufacturing recipe cannot be crafted anymore - check failed: {recipe} at {station}."); queueItem.CountToCraftRemains = 0; } } else // if this is a non-manufacturing recipe { queueItem.CountToCraftRemains--; } if (queueItem.CountToCraftRemains == 0) { // remove from queue craftingQueue.QueueItems.Remove(queueItem); } craftingQueue.SetDurationFromCurrentRecipe(); }
public static void ClientMakeItemFirstInQueue(CraftingQueueItem craftingQueueItem) { Instance.CallServer(_ => _.ServerRemote_MakeFirstInQueue(craftingQueueItem.LocalId)); }
public static void ClientDeleteQueueItem(CraftingQueueItem craftingQueueItem) { Instance.CallServer(_ => _.ServerRemote_CancelQueueItem(craftingQueueItem.LocalId)); }