Урна рабочего: изготовление по образцу на станциях по нитям (CinerariumCraft), образец во второй ячейке, нити к станциям, топливо и огонь

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-18 00:11:56 +03:00
co-authored by Claude Opus 5.5
parent a5f166c161
commit eba17606d5
9 changed files with 843 additions and 40 deletions
+65 -4
View File
@@ -21,6 +21,10 @@ namespace NecromancerTome
/// (ItemValue.Clone со сменой типа). Как у стриппера: ПКМ - начать нить и закончить её (порядок = направление: ящик, потом
/// урна - «откуда»; урна, потом ящик - «куда»), ЛКМ по урне или ящику - снять его нити.
/// Первая версия - одиночная игра и хост (связи меняются на месте, клиентам сети - позже).
///
/// Урна рабочего (18.10): нити ящик -> урна - откуда брать ингредиенты и топливо, урна -> станция - где изготавливать,
/// урна -> ящик - куда класть готовое; станций и ящиков сколько угодно (до MaxFrom в каждую сторону). Нить между станцией
/// и урной рабочего - всегда «от урны», в каком бы порядке её ни тянули.
/// </summary>
public static class CinerariumThreads
{
@@ -66,6 +70,7 @@ namespace NecromancerTome
static Vector3i? _start;
static bool _startUrn;
static bool _startStation;
static GameObject _preview;
public static Vector3i? Start => _start;
@@ -98,6 +103,16 @@ namespace NecromancerTome
return comp.PlayerPlaced && comp.TryGetSelfOrFeature<TEFeatureStorage>(out TEFeatureStorage _);
}
/// <summary>Станция игры (верстак, костёр, кузня, химстанция, бетономешалка, ступка) в клетке _p; _owner - главная клетка.</summary>
public static TileEntityWorkstation StationAt(World _w, Vector3i _p, out Vector3i _owner)
{
BlockValue bv = _w.GetBlock(_p);
_owner = bv.ischild ? _p + bv.parent : _p;
return _w.GetTileEntity(_owner) as TileEntityWorkstation;
}
public static TileEntityWorkstation StationAt(World _w, Vector3i _p) => StationAt(_w, _p, out Vector3i _);
public static TEFeatureCinerarium UrnAt(World _w, Vector3i _p)
{
return _w.GetTileEntity(_p) is TileEntityComposite c && c.TryGetSelfOrFeature<TEFeatureCinerarium>(out TEFeatureCinerarium u) ? u : null;
@@ -113,6 +128,13 @@ namespace NecromancerTome
return;
}
bool ok = Resolve(w, hi.hit.blockPos, out Vector3i owner, out TEFeatureCinerarium urn);
bool station = false;
if (!ok && StationAt(w, hi.hit.blockPos, out Vector3i stOwner) != null)
{
ok = true;
station = true;
owner = stOwner;
}
if (!_connect)
{
if (_start.HasValue)
@@ -135,13 +157,14 @@ namespace NecromancerTome
}
if (!_start.HasValue)
{
if (urn != null && !urn.IsLogist)
if (urn != null && !urn.IsZoneless)
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadNeedLogist"));
return;
}
_start = owner;
_startUrn = urn != null;
_startStation = station;
_preview = new GameObject("NecroThreadPreview");
_preview.AddComponent<CinerariumThreadPreview>();
_pl.PlayOneShot("wiretool_grab");
@@ -150,19 +173,44 @@ namespace NecromancerTome
}
Vector3i s = _start.Value;
bool sUrn = _startUrn;
bool sStation = _startStation;
Cancel();
if (s == owner)
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadCancel"));
return;
}
// Станция - только с урной рабочего, нить всегда «от урны».
if (sStation || station)
{
TEFeatureCinerarium wu = sStation ? urn : UrnAt(w, s);
Vector3i st = sStation ? s : owner;
if (wu == null || !wu.IsWorker)
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadNeedWorker"));
return;
}
if (Vector3.Distance(s.ToVector3(), owner.ToVector3()) > MaxLength)
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadTooFar"));
return;
}
if (!wu.AddThreadOut(st))
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadLimit"));
return;
}
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadStation"));
_pl.PlayOneShot("wiretool_place");
return;
}
if (sUrn == (urn != null))
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadNeedPair"));
return;
}
TEFeatureCinerarium end = sUrn ? UrnAt(w, s) : urn;
if (end == null || !end.IsLogist)
if (end == null || !end.IsZoneless)
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadNeedLogist"));
return;
@@ -179,8 +227,21 @@ namespace NecromancerTome
{
return;
}
u.SetThreadTo(owner);
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadTo"));
if (u.IsWorker)
{
// У рабочего ящиков «куда» сколько угодно - туда готовое.
if (!u.AddThreadOut(owner))
{
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadLimit"));
return;
}
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadOut"));
}
else
{
u.SetThreadTo(owner);
GameManager.ShowTooltip(_pl, Localization.Get("necroThreadTo"));
}
}
else
{