Урна рабочего: партия до стака, одна ячейка очереди на предмет, сланец не плавить (#19)

- Рецепт ставится в очередь сразу на столько, на сколько хватает всех
  ингредиентов, не больше стака любого ингредиента и стака готового
  (было по одной штуке за шаг - «очень медленно»).
- Пока партия предмета в очереди станции, второй такой не ставится -
  прочие ячейки остаются другим урнам на той же станции.
- Горючее сырьё (нефтяной сланец) в кузню не кладётся.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-24 14:45:10 +03:00
co-authored by Claude Opus 5.5
parent 3938f1786a
commit fb9c50cdf9
3 changed files with 43 additions and 12 deletions
+43 -12
View File
@@ -133,13 +133,17 @@ namespace NecromancerTome
{
continue; // выход полон и ящики «куда» полны (или их нет) - ниже станция погаснет
}
if (InQueue(st.Te, sample.itemValue.type))
{
continue; // партия этого предмета уже в очереди - следующая, когда она кончится
}
foreach (Recipe r in CraftingManager.GetRecipes(name))
{
if (r.IsScrap || !AreaFits(r, st.Areas) || !ToolFits(r, st.Te) || owner != null && !r.IsUnlocked(owner))
{
continue;
}
if (!Ingredients(r, st.Te, src, out Vector3i? srcAt, out string shortUnit))
if (!Ingredients(r, st.Te, src, out Vector3i? srcAt, out string shortUnit, out int batches))
{
// Кузня: не хватает переплавленного материала - положить сырьё во вход (плавит сама, с огнём).
if (shortUnit != null && FeedMaterial(st, shortUnit, src, _dry, out Vector3i? rawAt))
@@ -158,10 +162,10 @@ namespace NecromancerTome
{
return st.Pos;
}
TakeIngredients(r, st.Te, src);
Enqueue(st.Te, slot, r);
TakeIngredients(r, st.Te, src, batches);
Enqueue(st.Te, slot, r, batches);
Ignite(st.Te, src, false);
Debug.Log("[NecromancerTome] Cinerarium: рабочий поставил " + name + " на станцию " + st.Pos);
Debug.Log("[NecromancerTome] Cinerarium: рабочий поставил " + name + " x" + batches + " на станцию " + st.Pos);
return st.Pos;
}
}
@@ -289,6 +293,21 @@ namespace NecromancerTome
return -1;
}
/// <summary>Есть ли в очереди станции рецепт этого предмета. 24.10, пользователь: партия - до стака, и «если бы их было
/// двое, то тут нужно занимать очередь на ячейку»: один предмет держит в очереди одну ячейку, прочие - другим урнам на
/// той же станции (иначе одна урна забила бы очередь стаками на часы вперёд).</summary>
static bool InQueue(TileEntityWorkstation _te, int _itemType)
{
foreach (RecipeQueueItem q in _te.Queue)
{
if (q != null && q.Recipe != null && q.Multiplier > 0 && q.Recipe.itemValueType == _itemType)
{
return true;
}
}
return false;
}
static bool OutputHasRoom(TileEntityWorkstation _te, ItemStack _sample)
{
foreach (ItemStack s in _te.Output)
@@ -325,11 +344,17 @@ namespace NecromancerTome
}
/// <summary>Хватает ли всего: переплавленное - в кузне, прочее - в ящиках «откуда». _srcAt - ящик, откуда первое;
/// _shortUnit - какого переплавленного не хватило (кузне можно подложить сырья).</summary>
static bool Ingredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, out Vector3i? _srcAt, out string _shortUnit)
/// _shortUnit - какого переплавленного не хватило (кузне можно подложить сырья). _batches - сколько раз рецепт ставится
/// в очередь за одно дело (24.10, пользователь: «в бетономешалку кладётся по одному камушку... ожидается, что он будет
/// класть хотя бы по целому стаку, а если на стак не хватает, то сколько найдёт»): на сколько хватает каждого
/// ингредиента, но не больше стака ни одного ингредиента и не больше стака готового.</summary>
static bool Ingredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, out Vector3i? _srcAt, out string _shortUnit, out int _batches)
{
_srcAt = null;
_shortUnit = null;
ItemClass outClass = ItemClass.GetForId(_r.itemValueType);
_batches = outClass != null && _r.count > 0 ? Mathf.Max(1, outClass.MaxCount / _r.count) : 1;
_batches = Mathf.Min(_batches, short.MaxValue);
foreach (ItemStack ing in _r.ingredients)
{
if (ing == null || ing.IsEmpty() || ing.count <= 0)
@@ -345,6 +370,7 @@ namespace NecromancerTome
_shortUnit = iname;
return false;
}
_batches = Mathf.Min(_batches, _te.Input[us].count / ing.count);
continue;
}
int have = 0;
@@ -367,11 +393,14 @@ namespace NecromancerTome
{
return false;
}
int stack = ing.itemValue.ItemClass != null ? ing.itemValue.ItemClass.MaxCount : ing.count;
_batches = Mathf.Min(_batches, Mathf.Max(1, stack / ing.count), have / ing.count);
}
_batches = Mathf.Max(1, _batches);
return true;
}
static void TakeIngredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src)
static void TakeIngredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, int _batches)
{
ItemStack[] input = _te.Input;
bool inputChanged = false;
@@ -384,11 +413,11 @@ namespace NecromancerTome
int us = UnitSlot(_te, ing.itemValue.ItemClass?.GetItemName() ?? "");
if (us >= 0)
{
input[us].count -= ing.count;
input[us].count -= ing.count * _batches;
inputChanged = true;
continue;
}
int need = ing.count;
int need = ing.count * _batches;
foreach ((Vector3i p, TEFeatureStorage box) s in _src)
{
ItemStack[] grid = s.box.ItemGrid.items;
@@ -413,7 +442,7 @@ namespace NecromancerTome
}
}
static void Enqueue(TileEntityWorkstation _te, int _slot, Recipe _r)
static void Enqueue(TileEntityWorkstation _te, int _slot, Recipe _r, int _batches)
{
RecipeQueueItem[] q = _te.Queue;
float t = _r.craftingTime > 0f ? _r.craftingTime : 1f;
@@ -421,7 +450,7 @@ namespace NecromancerTome
q[_slot] = new RecipeQueueItem
{
Recipe = _r,
Multiplier = 1,
Multiplier = (short)_batches,
CraftingTimeLeft = t,
OneItemCraftTime = t,
IsCrafting = _slot == q.Length - 1,
@@ -455,11 +484,13 @@ namespace NecromancerTome
ItemStack[] input = _st.Te.Input;
// 23.10 («вместо камней вплавляет булыжник»): сначала сырьё, у которого нет рецепта (камни, лом), сделанное руками
// (булыжник) - только если сырья нет. Раньше - первое подходящее по порядку ячеек.
// 24.10 («работник положил сланец в переплавку в печку»): горючее (нефтяной сланец - сырьё для бензина) не плавится
// вовсе - рецепта у него нет, и раньше оно шло наравне с камнями.
foreach ((Vector3i p, TEFeatureStorage box, int k) s in Ordered(_src, g =>
{
ItemClass c = g.itemValue.ItemClass;
if (c?.MadeOfMaterial?.ForgeCategory == null || !c.MadeOfMaterial.ForgeCategory.EqualsCaseInsensitive(mat) ||
c.GetItemName().StartsWith("unit_"))
c.GetItemName().StartsWith("unit_") || ItemClass.GetFuelValue(g.itemValue) > 0)
{
return -1;
}
Binary file not shown.
Binary file not shown.