1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-08 20:13:29 +08:00
Files
DSP_Mods/LabOpt/Functions.cs
2025-09-21 15:38:03 +08:00

626 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
namespace LabOpt;
public static class LabOptPatchFunctions
{
public static void SetRootId(ref LabComponent lab, int rootId)
{
lab.pcId = rootId;
}
public static void SetRootLabIdForStacking(FactorySystem factorySystem, int labId, int nextEntityId)
{
var labPool = factorySystem.labPool;
var factory = factorySystem.factory;
var rootId = labPool[labId].pcId;
if (rootId <= 0)
{
var radiusBear = factory.planet.radius + 2.0f;
if (factory.entityPool[labPool[labId].entityId].pos.sqrMagnitude > radiusBear * radiusBear)
return;
rootId = labId;
}
ref var rootLab = ref labPool[rootId];
var needSetFunction = rootLab.researchMode || rootLab.recipeId > 0;
var entitySignPool = needSetFunction ? factorySystem.factory.entitySignPool : null;
var targetLabId = factory.entityPool[nextEntityId].labId;
do
{
ref var targetLab = ref labPool[targetLabId];
targetLab.pcId = rootId;
// LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {targetLabId} to {rootId}, {needSetFunction}");
if (needSetFunction)
{
SetFunctionInternal(ref targetLab, rootLab.researchMode, rootLab.recipeId, rootLab.techId, entitySignPool, labPool);
}
} while ((targetLabId = labPool[targetLabId].nextLabId) > 0);
}
public static void SetRootLabIdOnLoading(FactorySystem factorySystem)
{
var labCursor = factorySystem.labCursor;
var labPool = factorySystem.labPool;
var parentDict = new Dictionary<int, int>();
for (var id = 1; id < labCursor; id++)
{
if (labPool[id].id != id) continue;
ref var lab = ref labPool[id];
if (lab.researchMode)
{
var len = lab.matrixIncServed.Length;
for (var i = 0; i < len; i++)
{
if (lab.matrixIncServed[i] < 0)
{
lab.matrixIncServed[i] = 0;
}
}
}
else if (lab.recipeId > 0)
{
var len = lab.incServed.Length;
for (var i = 0; i < len; i++)
{
if (lab.incServed[i] < 0)
{
lab.incServed[i] = 0;
}
}
}
if (lab.nextLabId != 0) parentDict[lab.nextLabId] = id;
}
foreach (var pair in parentDict)
{
var rootId = pair.Value;
while (parentDict.TryGetValue(rootId, out var parentId)) rootId = parentId;
ref var targetLab = ref labPool[pair.Key];
targetLab.pcId = rootId;
// LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {pair.Key} to {rootId}");
AssignRootLabValues(ref labPool[rootId], ref targetLab);
}
}
private static void AssignRootLabValues(ref LabComponent rootLab, ref LabComponent thisLab)
{
int len;
if (rootLab.researchMode)
{
len = Math.Min(rootLab.matrixServed.Length, thisLab.matrixServed.Length);
for (var i = 0; i < len; i++)
{
if (thisLab.matrixServed[i] > 0)
{
rootLab.matrixServed[i] += thisLab.matrixServed[i];
thisLab.matrixServed[i] = 0;
}
if (thisLab.matrixIncServed[i] > 0)
{
rootLab.matrixIncServed[i] += thisLab.matrixIncServed[i];
thisLab.matrixIncServed[i] = 0;
}
}
}
else if (rootLab.recipeId > 0)
{
len = Math.Min(rootLab.produced.Length, thisLab.produced.Length);
for (var i = 0; i < len; i++)
{
if (thisLab.produced[i] <= 0) continue;
rootLab.produced[i] += thisLab.produced[i];
thisLab.produced[i] = 0;
}
len = Math.Min(rootLab.served.Length, thisLab.served.Length);
for (var i = 0; i < len; i++)
{
if (thisLab.served[i] > 0)
{
rootLab.served[i] += thisLab.served[i];
thisLab.served[i] = 0;
}
if (thisLab.incServed[i] > 0)
{
rootLab.incServed[i] += thisLab.incServed[i];
thisLab.incServed[i] = 0;
}
}
}
thisLab.needs = rootLab.needs;
thisLab.requires = rootLab.requires;
thisLab.requireCounts = rootLab.requireCounts;
thisLab.products = rootLab.products;
thisLab.productCounts = rootLab.productCounts;
thisLab.produced = rootLab.produced;
thisLab.served = rootLab.served;
thisLab.incServed = rootLab.incServed;
thisLab.matrixPoints = rootLab.matrixPoints;
thisLab.matrixServed = rootLab.matrixServed;
thisLab.matrixIncServed = rootLab.matrixIncServed;
thisLab.techId = rootLab.techId;
}
public static void LabExportZero(ref LabComponent lab, BinaryWriter w)
{
if (lab.matrixMode)
{
w.Write(lab.timeSpend);
w.Write(lab.extraTimeSpend);
w.Write(lab.requires.Length);
foreach (var n in lab.requires)
{
w.Write(n);
}
w.Write(lab.requireCounts.Length);
foreach (var n in lab.requireCounts)
{
w.Write(n);
}
w.Write(lab.served.Length);
for (var i = 0; i < lab.served.Length; i++)
{
w.Write(0);
}
w.Write(lab.incServed.Length);
for (var i = 0; i < lab.incServed.Length; i++)
{
w.Write(0);
}
w.Write(lab.needs.Length);
for (var i = 0; i < lab.needs.Length; i++)
{
w.Write(0);
}
w.Write(lab.products.Length);
foreach (var n in lab.products)
{
w.Write(n);
}
w.Write(lab.productCounts.Length);
foreach (var n in lab.productCounts)
{
w.Write(n);
}
w.Write(lab.produced.Length);
for (var i = 0; i < lab.produced.Length; i++)
{
w.Write(0);
}
}
if (lab.researchMode)
{
w.Write(lab.matrixPoints.Length);
foreach (var n in lab.matrixPoints)
{
w.Write(n);
}
w.Write(lab.matrixServed.Length);
for (var i = 0; i < lab.matrixServed.Length; i++)
{
w.Write(0);
}
w.Write(lab.needs.Length);
for (var i = 0; i < lab.needs.Length; i++)
{
w.Write(0);
}
w.Write(lab.matrixIncServed.Length);
for (var i = 0; i < lab.matrixIncServed.Length; i++)
{
w.Write(0);
}
}
}
public static uint InternalUpdateAssembleNew(ref LabComponent lab, float power, int[] productRegister, int[] consumeRegister)
{
if (power < 0.1f)
{
return 0U;
}
if (lab.extraTime >= lab.extraTimeSpend)
{
var len = lab.products.Length;
lock (lab.produced)
{
if (len == 1)
{
lab.produced[0] += lab.productCounts[0];
lock (productRegister)
{
productRegister[lab.products[0]] += lab.productCounts[0];
}
}
else
{
for (var i = 0; i < len; i++)
{
lab.produced[i] += lab.productCounts[i];
lock (productRegister)
{
productRegister[lab.products[i]] += lab.productCounts[i];
}
}
}
}
lab.extraTime -= lab.extraTimeSpend;
}
if (lab.time >= lab.timeSpend)
{
lab.replicating = false;
var len = lab.products.Length;
lock (lab.produced)
{
if (len == 1)
{
if (lab.produced[0] + lab.productCounts[0] > 30)
{
return 0U;
}
lab.produced[0] += lab.productCounts[0];
lock (productRegister)
{
productRegister[lab.products[0]] += lab.productCounts[0];
}
}
else
{
for (var j = 0; j < len; j++)
{
if (lab.produced[j] + lab.productCounts[j] > 30)
{
return 0U;
}
}
for (var k = 0; k < len; k++)
{
lab.produced[k] += lab.productCounts[k];
lock (productRegister)
{
productRegister[lab.products[k]] += lab.productCounts[k];
}
}
}
}
lab.extraSpeed = 0;
lab.speedOverride = lab.speed;
lab.extraPowerRatio = 0;
lab.time -= lab.timeSpend;
}
if (!lab.replicating)
{
var len = lab.requireCounts.Length;
int incLevel;
if (len > 0)
{
var served = lab.served;
lock (served)
{
for (var l = 0; l < len; l++)
{
if (served[l] >= lab.requireCounts[l] && served[l] != 0) continue;
lab.time = 0;
return 0U;
}
incLevel = 10;
for (var m = 0; m < len; m++)
{
var splittedIncLevel = lab.split_inc_level(ref served[m], ref lab.incServed[m], lab.requireCounts[m]);
if (splittedIncLevel < incLevel) incLevel = splittedIncLevel;
if (served[m] == 0)
{
lab.incServed[m] = 0;
}
lock (consumeRegister)
{
consumeRegister[lab.requires[m]] += lab.requireCounts[m];
}
}
if (incLevel < 0)
{
incLevel = 0;
}
}
}
else
{
incLevel = 0;
}
if (lab.productive && !lab.forceAccMode)
{
lab.extraSpeed = (int)(lab.speed * Cargo.incTableMilli[incLevel] * 10.0 + 0.1);
lab.speedOverride = lab.speed;
lab.extraPowerRatio = Cargo.powerTable[incLevel];
}
else
{
lab.extraSpeed = 0;
lab.speedOverride = (int)(lab.speed * (1.0 + Cargo.accTableMilli[incLevel]) + 0.1);
lab.extraPowerRatio = Cargo.powerTable[incLevel];
}
lab.replicating = true;
}
switch (lab.replicating)
{
case true when lab.time < lab.timeSpend && lab.extraTime < lab.extraTimeSpend:
lab.time += (int)(power * lab.speedOverride);
lab.extraTime += (int)(power * lab.extraSpeed);
break;
case false:
return 0U;
}
return (uint)(lab.products[0] - LabComponent.matrixIds[0] + 1);
}
public static void SetFunctionManually(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
{
var rootLabId = lab.pcId;
if (rootLabId > 0)
{
ref var rootLab = ref labPool[rootLabId];
if (researchMode != rootLab.researchMode)
{
SetFunctionManually(ref rootLab, researchMode, recpId, techId, signPool, labPool);
}
else if (researchMode)
{
if (techId != rootLab.techId)
{
SetFunctionManually(ref rootLab, true, recpId, techId, signPool, labPool);
}
}
else
{
if (recpId != rootLab.recipeId)
{
SetFunctionManually(ref rootLab, false, recpId, techId, signPool, labPool);
}
}
}
else
{
SetFunctionInternal(ref lab, researchMode, recpId, techId, signPool, labPool);
var thisId = lab.id;
var needs = lab.needs;
var nextLabId = lab.nextLabId;
while (nextLabId > 0)
{
ref var nextLab = ref labPool[nextLabId];
if (nextLab.pcId != thisId) break;
if (needs != nextLab.needs)
SetFunctionInternal(ref nextLab, researchMode, recpId, techId, signPool, labPool);
nextLabId = nextLab.nextLabId;
}
}
}
public static void SetFunctionInternal(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
{
// LabOptPatch.Logger.LogDebug($"SetFunctionInternal: id={lab.id} root={(int)RootLabIdField.GetValue(lab)} research={researchMode} recp={recpId} tech={techId}");
lab.replicating = false;
lab.time = 0;
lab.hashBytes = 0;
lab.extraHashBytes = 0;
lab.extraTime = 0;
lab.extraSpeed = 0;
lab.extraPowerRatio = 0;
lab.productive = false;
if (researchMode)
{
lab.forceAccMode = false;
lab.researchMode = true;
lab.recipeId = 0;
lab.techId = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
lab.productive = true;
var rootLabId = lab.pcId;
if (rootLabId > 0)
{
ref var rootLab = ref labPool[rootLabId];
lab.needs = rootLab.needs;
lab.matrixPoints = rootLab.matrixPoints;
lab.matrixServed = rootLab.matrixServed;
lab.matrixIncServed = rootLab.matrixIncServed;
lab.techId = rootLab.techId;
}
else
{
if (lab.needs == null || lab.needs.Length != LabComponent.matrixIds.Length)
{
lab.needs = new int[LabComponent.matrixIds.Length];
}
Array.Copy(LabComponent.matrixIds, lab.needs, LabComponent.matrixIds.Length);
if (lab.matrixPoints == null)
{
lab.matrixPoints = new int[LabComponent.matrixIds.Length];
}
else
{
Array.Clear(lab.matrixPoints, 0, lab.matrixPoints.Length);
}
lab.matrixServed ??= new int[LabComponent.matrixIds.Length];
lab.matrixIncServed ??= new int[LabComponent.matrixIds.Length];
TechProto techProto = LDB.techs.Select(techId);
if (techProto != null && techProto.IsLabTech)
{
lab.techId = techId;
for (var i = 0; i < techProto.Items.Length; i++)
{
var index = techProto.Items[i] - LabComponent.matrixIds[0];
if (index >= 0 && index < lab.matrixPoints.Length)
{
lab.matrixPoints[index] = techProto.ItemPoints[i];
}
}
}
}
signPool[lab.entityId].iconId0 = (uint)lab.techId;
signPool[lab.entityId].iconType = lab.techId == 0 ? 0U : 3U;
return;
}
lab.researchMode = false;
lab.recipeId = 0;
lab.techId = 0;
lab.matrixPoints = null;
lab.matrixServed = null;
lab.matrixIncServed = null;
RecipeProto recipeProto = null;
if (recpId > 0)
{
recipeProto = LDB.recipes.Select(recpId);
}
if (recipeProto != null && recipeProto.Type == ERecipeType.Research)
{
lab.recipeId = recipeProto.ID;
lab.speed = 10000;
lab.speedOverride = lab.speed;
lab.timeSpend = recipeProto.TimeSpend * 10000;
lab.extraTimeSpend = recipeProto.TimeSpend * 100000;
lab.productive = recipeProto.productive;
lab.forceAccMode &= lab.productive;
var rootLabId = lab.pcId;
if (rootLabId > 0)
{
ref var rootLab = ref labPool[rootLabId];
lab.needs = rootLab.needs;
lab.requires = rootLab.requires;
lab.requireCounts = rootLab.requireCounts;
lab.products = rootLab.products;
lab.productCounts = rootLab.productCounts;
lab.produced = rootLab.produced;
lab.served = rootLab.served;
lab.incServed = rootLab.incServed;
}
else
{
if (lab.needs == null || lab.needs.Length != 6)
lab.needs = new int[6];
else
Array.Clear(lab.needs, 0, 6);
lab.requires ??= new int[recipeProto.Items.Length];
Array.Copy(recipeProto.Items, lab.requires, lab.requires.Length);
lab.requireCounts ??= new int[recipeProto.ItemCounts.Length];
Array.Copy(recipeProto.ItemCounts, lab.requireCounts, lab.requireCounts.Length);
if (lab.served == null)
lab.served = new int[lab.requireCounts.Length];
else
Array.Clear(lab.served, 0, lab.served.Length);
if (lab.incServed == null)
lab.incServed = new int[lab.requireCounts.Length];
else
Array.Clear(lab.incServed, 0, lab.incServed.Length);
lab.products ??= new int[recipeProto.Results.Length];
Array.Copy(recipeProto.Results, lab.products, lab.products.Length);
lab.productCounts ??= new int[recipeProto.ResultCounts.Length];
Array.Copy(recipeProto.ResultCounts, lab.productCounts, lab.productCounts.Length);
if (lab.produced == null)
lab.produced = new int[lab.productCounts.Length];
else
Array.Clear(lab.produced, 0, lab.produced.Length);
}
}
else
{
lab.forceAccMode = false;
lab.recipeId = 0;
lab.speed = 0;
lab.speedOverride = 0;
lab.timeSpend = 0;
lab.extraTimeSpend = 0;
lab.requires = null;
lab.requireCounts = null;
lab.served = null;
lab.incServed = null;
lab.needs = null;
lab.products = null;
lab.productCounts = null;
lab.produced = null;
}
signPool[lab.entityId].iconId0 = (uint)lab.recipeId;
signPool[lab.entityId].iconType = lab.recipeId == 0 ? 0U : 2U;
}
public static int InsertIntoLab(PlanetFactory factory, int labId, int itemId, byte itemCount, byte itemInc, ref byte remainInc, int[] needs)
{
var factorySystem = factory.factorySystem;
var served = factorySystem.labPool[labId].served;
var incServed = factorySystem.labPool[labId].incServed;
var matrixServed = factorySystem.labPool[labId].matrixServed;
var matrixIncServed = factorySystem.labPool[labId].matrixIncServed;
var len = needs.Length;
for (var i = 0; i < len; i++)
{
if (needs[i] != itemId) continue;
if (served != null)
{
lock (served)
{
served[i] += itemCount;
incServed[i] += itemInc;
}
remainInc = 0;
return itemCount;
}
if (matrixServed != null)
{
lock (matrixServed)
{
matrixServed[i] += 3600 * itemCount;
matrixIncServed[i] += 3600 * itemInc;
}
remainInc = 0;
return itemCount;
}
}
return 0;
}
public static int PickFromLab(PlanetFactory factory, int labId, int filter, int[] needs)
{
var factorySystem = factory.factorySystem;
var products = factorySystem.labPool[labId].products;
if (products == null) return 0;
var produced = factorySystem.labPool[labId].produced;
if (produced == null) return 0;
lock (produced)
{
for (var j = 0; j < products.Length; j++)
{
if (produced[j] <= 0 || products[j] <= 0 ||
(filter != 0 && filter != products[j]) ||
(needs != null && needs[0] != products[j] && needs[1] != products[j] &&
needs[2] != products[j] && needs[3] != products[j] &&
needs[4] != products[j] && needs[5] != products[j])) continue;
produced[j]--;
return products[j];
}
}
return 0;
}
}