mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-08 20:53:28 +08:00
Work in progress
This commit is contained in:
@@ -1,23 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace LabOpt;
|
||||
|
||||
public class LabOptPatchFunctions
|
||||
public static class LabOptPatchFunctions
|
||||
{
|
||||
private static readonly FieldInfo RootLabIdField = AccessTools.Field(typeof(LabComponent), "rootLabId");
|
||||
private const int RequireCountForAssemble = 15;
|
||||
private const int RequireCountForResearch = 54000;
|
||||
|
||||
public static void SetRootLabIdForStacking(FactorySystem factorySystem, int labId, int nextEntityId)
|
||||
{
|
||||
var rootId = (int)RootLabIdField.GetValue(factorySystem.labPool[labId]);
|
||||
var labPool = factorySystem.labPool;
|
||||
var rootId = (int)RootLabIdField.GetValue(labPool[labId]);
|
||||
var targetLabId = factorySystem.factory.entityPool[nextEntityId].labId;
|
||||
if (rootId <= 0) rootId = labId;
|
||||
RootLabIdField.SetValueDirect(__makeref(factorySystem.labPool[targetLabId]), rootId);
|
||||
LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {targetLabId} to {rootId}");
|
||||
do
|
||||
{
|
||||
RootLabIdField.SetValueDirect(__makeref(labPool[targetLabId]), rootId);
|
||||
LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {targetLabId} to {rootId}");
|
||||
} while ((targetLabId = labPool[targetLabId].nextLabId) > 0);
|
||||
}
|
||||
|
||||
public static void SetRootLabIdOnLoading(FactorySystem factorySystem)
|
||||
@@ -40,7 +43,7 @@ public class LabOptPatchFunctions
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (lab.recipeId > 0)
|
||||
{
|
||||
var len = lab.incServed.Length;
|
||||
for (var i = 0; i < len; i++)
|
||||
@@ -53,329 +56,451 @@ public class LabOptPatchFunctions
|
||||
}
|
||||
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;
|
||||
RootLabIdField.SetValueDirect(__makeref(labPool[pair.Key]), rootId);
|
||||
LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {pair.Key} to {rootId}");
|
||||
AssignRootLabValues(ref labPool[rootId], ref labPool[pair.Key]);
|
||||
}
|
||||
}
|
||||
|
||||
ref var rootLab = ref labPool[rootId];
|
||||
ref var thisLab = ref labPool[pair.Key];
|
||||
int len;
|
||||
if (rootLab.researchMode)
|
||||
public 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++)
|
||||
{
|
||||
len = Math.Min(rootLab.matrixServed.Length, thisLab.matrixServed.Length);
|
||||
for (var i = 0; i < len; i++)
|
||||
if (thisLab.matrixServed[i] > 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
rootLab.matrixServed[i] += thisLab.matrixServed[i];
|
||||
thisLab.matrixServed[i] = 0;
|
||||
productRegister[lab.products[0]] += lab.productCounts[0];
|
||||
}
|
||||
if (thisLab.matrixIncServed[i] != 0)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
rootLab.matrixIncServed[i] += thisLab.matrixIncServed[i];
|
||||
thisLab.matrixIncServed[i] = 0;
|
||||
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 (int 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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
incLevel = 0;
|
||||
}
|
||||
|
||||
LabOptPatch.Logger.LogDebug($"Set rootLabId of lab {pair.Key} to {rootId}");
|
||||
}
|
||||
}
|
||||
|
||||
public static uint InternalUpdateAssembleNew(ref LabComponent lab, float power, int[] productRegister, int[] consumeRegister, LabComponent[] labPool)
|
||||
{
|
||||
if (power < 0.1f)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
var extraPassed = lab.extraTime >= lab.extraTimeSpend;
|
||||
var timePassed = lab.time >= lab.timeSpend;
|
||||
if (extraPassed || timePassed || !lab.replicating)
|
||||
{
|
||||
var rootLabId = (int)RootLabIdField.GetValue(lab);
|
||||
ref var rootLab = ref rootLabId > 0 ? ref labPool[rootLabId] : ref lab;
|
||||
if (extraPassed)
|
||||
if (lab.productive && !lab.forceAccMode)
|
||||
{
|
||||
int len = lab.products.Length;
|
||||
lock (rootLab.produced)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
rootLab.produced[0] += lab.productCounts[0];
|
||||
lock (productRegister)
|
||||
{
|
||||
productRegister[lab.products[0]] += lab.productCounts[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
rootLab.produced[i] += lab.productCounts[i];
|
||||
lock (productRegister)
|
||||
{
|
||||
productRegister[lab.products[i]] += lab.productCounts[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lab.extraTime -= lab.extraTimeSpend;
|
||||
}
|
||||
|
||||
if (timePassed)
|
||||
{
|
||||
lab.replicating = false;
|
||||
int len = lab.products.Length;
|
||||
lock (rootLab.produced)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
if (rootLab.produced[0] + lab.productCounts[0] > 30)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
rootLab.produced[0] += lab.productCounts[0];
|
||||
lock (productRegister)
|
||||
{
|
||||
productRegister[lab.products[0]] += lab.productCounts[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < len; j++)
|
||||
{
|
||||
if (rootLab.produced[j] + lab.productCounts[j] > 30)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < len; k++)
|
||||
{
|
||||
rootLab.produced[k] += lab.productCounts[k];
|
||||
lock (productRegister)
|
||||
{
|
||||
productRegister[lab.products[k]] += lab.productCounts[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lab.extraSpeed = 0;
|
||||
lab.extraSpeed = (int)(lab.speed * Cargo.incTableMilli[incLevel] * 10.0 + 0.1);
|
||||
lab.speedOverride = lab.speed;
|
||||
lab.extraPowerRatio = 0;
|
||||
lab.time -= lab.timeSpend;
|
||||
lab.extraPowerRatio = Cargo.powerTable[incLevel];
|
||||
}
|
||||
|
||||
if (!lab.replicating)
|
||||
else
|
||||
{
|
||||
int len = lab.requireCounts.Length;
|
||||
int incLevel;
|
||||
if (len > 0)
|
||||
{
|
||||
var served = rootLab.served;
|
||||
lock (served)
|
||||
{
|
||||
for (int l = 0; l < len; l++)
|
||||
{
|
||||
if (served[l] < lab.requireCounts[l] || served[l] == 0)
|
||||
{
|
||||
lab.time = 0;
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
incLevel = 10;
|
||||
for (int m = 0; m < len; m++)
|
||||
{
|
||||
int splittedIncLevel = lab.split_inc_level(ref served[m], ref rootLab.incServed[m], lab.requireCounts[m]);
|
||||
if (splittedIncLevel < incLevel) incLevel = splittedIncLevel;
|
||||
if (served[m] == 0)
|
||||
{
|
||||
rootLab.incServed[m] = 0;
|
||||
}
|
||||
rootLab.needs[m] = served[m] < RequireCountForAssemble ? rootLab.requires[0] : 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)((double)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)((double)lab.speed * (1.0 + Cargo.accTableMilli[incLevel]) + 0.1);
|
||||
lab.extraPowerRatio = Cargo.powerTable[incLevel];
|
||||
}
|
||||
|
||||
lab.replicating = true;
|
||||
lab.extraSpeed = 0;
|
||||
lab.speedOverride = (int)(lab.speed * (1.0 + Cargo.accTableMilli[incLevel]) + 0.1);
|
||||
lab.extraPowerRatio = Cargo.powerTable[incLevel];
|
||||
}
|
||||
|
||||
lab.replicating = true;
|
||||
}
|
||||
|
||||
if (lab.replicating && lab.time < lab.timeSpend && lab.extraTime < lab.extraTimeSpend)
|
||||
switch (lab.replicating)
|
||||
{
|
||||
lab.time += (int)(power * (float)lab.speedOverride);
|
||||
lab.extraTime += (int)(power * (float)lab.extraSpeed);
|
||||
}
|
||||
|
||||
if (!lab.replicating)
|
||||
{
|
||||
return 0U;
|
||||
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 uint InternalUpdateResearchNew(ref LabComponent lab, float power, float speed, int[] consumeRegister, ref TechState ts, ref int techHashedThisFrame, ref long uMatrixPoint, ref long hashRegister, LabComponent[] labPool)
|
||||
public static void SetFunctionNew(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
|
||||
{
|
||||
if (power < 0.1f)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
var rootLabId = (int)RootLabIdField.GetValue(lab);
|
||||
ref var rootLab = ref rootLabId > 0 ? ref labPool[rootLabId] : ref lab;
|
||||
|
||||
int multiplier = (int)(speed + 2f);
|
||||
var matrixServed = rootLab.matrixServed;
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
if (lab.matrixPoints[i] <= 0) continue;
|
||||
int mult = matrixServed[i] / lab.matrixPoints[i];
|
||||
if (mult < multiplier)
|
||||
LabOptPatch.Logger.LogDebug($"SetFunctionNew: {lab.id} {(int)RootLabIdField.GetValue(lab)} {researchMode} {recpId} {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 = (int)RootLabIdField.GetValue(lab);
|
||||
if (rootLabId > 0)
|
||||
{
|
||||
multiplier = mult;
|
||||
if (multiplier == 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.replicating = false;
|
||||
return 0U;
|
||||
lab.needs = new int[LabComponent.matrixIds.Length];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lab.replicating = true;
|
||||
if (multiplier < speed) speed = multiplier;
|
||||
int hashBytes = (int)(power * 10000f * speed + 0.5f);
|
||||
lab.hashBytes += hashBytes;
|
||||
long count = lab.hashBytes / 10000;
|
||||
lab.hashBytes -= (int)count * 10000;
|
||||
long maxNeeded = ts.hashNeeded - ts.hashUploaded;
|
||||
if (maxNeeded < count) count = maxNeeded;
|
||||
if (multiplier < count) count = multiplier;
|
||||
int icount = (int)count;
|
||||
if (icount > 0)
|
||||
{
|
||||
int len = matrixServed.Length;
|
||||
int incLevel = ((len == 0) ? 0 : 10);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (lab.matrixPoints[i] <= 0) continue;
|
||||
int matrixBefore = matrixServed[i] / 3600;
|
||||
int splittedIncLevel = lab.split_inc_level(ref matrixServed[i], ref rootLab.matrixIncServed[i], lab.matrixPoints[i] * icount);
|
||||
incLevel = incLevel < splittedIncLevel ? incLevel : splittedIncLevel;
|
||||
if (matrixServed[i] <= 0)
|
||||
Array.Copy(LabComponent.matrixIds, lab.needs, LabComponent.matrixIds.Length);
|
||||
if (lab.matrixPoints == null)
|
||||
{
|
||||
rootLab.matrixIncServed[i] = 0;
|
||||
}
|
||||
rootLab.needs[i] = matrixServed[i] < RequireCountForResearch ? LabComponent.matrixIds[i] : 0;
|
||||
consumeRegister[LabComponent.matrixIds[i]] += matrixBefore - matrixServed[i] / 3600;
|
||||
}
|
||||
|
||||
if (incLevel < 0)
|
||||
{
|
||||
incLevel = 0;
|
||||
}
|
||||
|
||||
lab.extraSpeed = (int)(10000.0 * Cargo.incTableMilli[incLevel] * 10.0 + 0.1);
|
||||
lab.extraPowerRatio = Cargo.powerTable[incLevel];
|
||||
lab.extraHashBytes += (int)(power * lab.extraSpeed * speed + 0.5f);
|
||||
long extraCount = lab.extraHashBytes / 100000;
|
||||
lab.extraHashBytes -= (int)extraCount * 100000;
|
||||
if (extraCount < 0L) extraCount = 0L;
|
||||
int iextraCount = (int)extraCount;
|
||||
ts.hashUploaded += count + extraCount;
|
||||
hashRegister += count + extraCount;
|
||||
uMatrixPoint += ts.uPointPerHash * count;
|
||||
techHashedThisFrame += icount + iextraCount;
|
||||
if (ts.hashUploaded >= ts.hashNeeded)
|
||||
{
|
||||
TechProto techProto = LDB.techs.Select(lab.techId);
|
||||
if (ts.curLevel >= ts.maxLevel)
|
||||
{
|
||||
ts.curLevel = ts.maxLevel;
|
||||
ts.hashUploaded = ts.hashNeeded;
|
||||
ts.unlocked = true;
|
||||
lab.matrixPoints = new int[LabComponent.matrixIds.Length];
|
||||
}
|
||||
else
|
||||
{
|
||||
ts.curLevel++;
|
||||
ts.hashUploaded = 0L;
|
||||
ts.hashNeeded = techProto.GetHashNeeded(ts.curLevel);
|
||||
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 = (int)RootLabIdField.GetValue(lab);
|
||||
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
|
||||
{
|
||||
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);
|
||||
lab.served = new int[lab.requireCounts.Length];
|
||||
lab.incServed = new int[lab.requireCounts.Length];
|
||||
Assert.True(lab.requires.Length == lab.requireCounts.Length);
|
||||
if (lab.needs == null || lab.needs.Length != 6)
|
||||
{
|
||||
lab.needs = new int[6];
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Clear(lab.needs, 0, 6);
|
||||
}
|
||||
|
||||
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);
|
||||
Assert.True(lab.products.Length == lab.productCounts.Length);
|
||||
lab.produced = new int[lab.productCounts.Length];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lab.extraSpeed = 0;
|
||||
lab.extraPowerRatio = 0;
|
||||
}
|
||||
|
||||
return 1U;
|
||||
}
|
||||
|
||||
public static void UpdateNeedsAssembleSingle(ref LabComponent lab, int m)
|
||||
{
|
||||
lab.needs[m] = lab.served[m] < RequireCountForAssemble ? lab.requires[m] : 0;
|
||||
}
|
||||
|
||||
public static void UpdateNeedsResearchSingle(ref LabComponent lab, int m)
|
||||
{
|
||||
lab.needs[m] = lab.matrixServed[m] < RequireCountForResearch ? LabComponent.matrixIds[m] : 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
574
LabOpt/LabOpt.cs
574
LabOpt/LabOpt.cs
@@ -8,6 +8,9 @@ namespace LabOpt;
|
||||
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
|
||||
public class LabOptPatch : BaseUnityPlugin
|
||||
{
|
||||
private const int RequireCountForAssemble = 15;
|
||||
private const int RequireCountForResearch = 54000;
|
||||
|
||||
public new static readonly BepInEx.Logging.ManualLogSource Logger =
|
||||
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
|
||||
|
||||
@@ -15,6 +18,83 @@ public class LabOptPatch : BaseUnityPlugin
|
||||
{
|
||||
Harmony.CreateAndPatchAll(typeof(LabOptPatch));
|
||||
}
|
||||
|
||||
// Patch LabComponent.Export() to save zero value if rootLabId > 0.
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.Export))]
|
||||
private static IEnumerable<CodeInstruction> LabComponent_Export_Transpiler(
|
||||
IEnumerable<CodeInstruction> instructions,
|
||||
ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(LabComponent), nameof(LabComponent.matrixMode)))
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.LabExportZero))),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
matcher.Instruction.labels.Add(label1);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Patch UpdateNeedsAssemble() and UpdateNeedsResearch() to remove the execution if rootLabId > 0.
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.UpdateNeedsAssemble))]
|
||||
private static IEnumerable<CodeInstruction> LabComponent_UpdateNeedsAssemble_Transpiler(
|
||||
IEnumerable<CodeInstruction> instructions,
|
||||
ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher.Start().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
matcher.Instruction.labels.Add(label1);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldelem_I4),
|
||||
new CodeMatch(OpCodes.Ldc_I4_4)
|
||||
);
|
||||
matcher.Repeat(codeMatcher =>
|
||||
codeMatcher.Advance(1).SetAndAdvance(OpCodes.Ldc_I4_S, RequireCountForAssemble)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.UpdateNeedsResearch))]
|
||||
private static IEnumerable<CodeInstruction> LabComponent_UpdateNeedsResearch_Transpiler(
|
||||
IEnumerable<CodeInstruction> instructions,
|
||||
ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher.Start().InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
matcher.Instruction.labels.Add(label1);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldc_I4, 0x8CA0)
|
||||
);
|
||||
matcher.Repeat(codeMatcher =>
|
||||
codeMatcher.SetAndAdvance(OpCodes.Ldc_I4, RequireCountForResearch)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Remove use of LabComponent.UpdateOutputToNext() for single-thread mode
|
||||
[HarmonyTranspiler]
|
||||
@@ -70,284 +150,7 @@ public class LabOptPatch : BaseUnityPlugin
|
||||
LabOptPatchFunctions.SetRootLabIdOnLoading(__instance);
|
||||
}
|
||||
|
||||
// Insert to root lab
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.InsertInto))]
|
||||
private static IEnumerable<CodeInstruction> PlanetFactory_InsertInto_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
var local1 = generator.DeclareLocal(typeof(LabComponent).MakeArrayType());
|
||||
matcher.MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EntityData), nameof(EntityData.labId))))
|
||||
.MatchForward(false, new CodeMatch(OpCodes.Ret))
|
||||
.Advance(1);
|
||||
var labels = matcher.Instruction.labels;
|
||||
matcher.InsertAndAdvance(
|
||||
// labPool = this.factorySystem.labPool;
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Stloc_S, local1),
|
||||
// rootLabId = labPool[labId].rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 5),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 6),
|
||||
// if (rootLabId <= 0) goto label1;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 6),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
// labId = rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 6),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 5),
|
||||
// entityId = labPool[labId].entityId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 5),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.entityId))),
|
||||
new CodeInstruction(OpCodes.Starg_S, 1),
|
||||
new CodeInstruction(OpCodes.Ldarg_S, 1),
|
||||
// array = this.entityNeeds[entityId];
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.entityNeeds))),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Ldelem_Ref),
|
||||
new CodeInstruction(OpCodes.Stloc_1)
|
||||
// lable1:
|
||||
);
|
||||
matcher.Instruction.labels = new List<Label> { label1 };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.factorySystem))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
var labels2 = matcher.Instruction.labels;
|
||||
var instr = new CodeInstruction(OpCodes.Ldloc_S, local1).WithLabels(labels2);
|
||||
matcher.RemoveInstructions(3).InsertAndAdvance(instr);
|
||||
}
|
||||
|
||||
// UpdateNeedsXXXXSingle() after item count changed
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S),
|
||||
new CodeMatch(OpCodes.Ldelema, typeof(int)),
|
||||
new CodeMatch(OpCodes.Dup),
|
||||
new CodeMatch(OpCodes.Ldind_I4),
|
||||
new CodeMatch(OpCodes.Ldarg_S, (byte)5),
|
||||
new CodeMatch(OpCodes.Add),
|
||||
new CodeMatch(OpCodes.Stind_I4)
|
||||
);
|
||||
var v19 = matcher.Operand;
|
||||
matcher.Advance(7).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 5),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 19),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsAssembleSingle)))
|
||||
);
|
||||
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S, v19),
|
||||
new CodeMatch(OpCodes.Ldelema, typeof(int)),
|
||||
new CodeMatch(OpCodes.Dup),
|
||||
new CodeMatch(OpCodes.Ldind_I4),
|
||||
new CodeMatch(OpCodes.Ldc_I4, 0xE10),
|
||||
new CodeMatch(OpCodes.Ldarg_S, (byte)5),
|
||||
new CodeMatch(OpCodes.Mul),
|
||||
new CodeMatch(OpCodes.Add),
|
||||
new CodeMatch(OpCodes.Stind_I4)
|
||||
).Advance(9).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 5),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 19),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsResearchSingle)))
|
||||
);
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Fill into root lab
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.EntityFastFillIn))]
|
||||
private static IEnumerable<CodeInstruction> PlanetFactory_EntityFastFillIn_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
)
|
||||
.Advance(2)
|
||||
.InsertAndAdvance(
|
||||
// rootLabId = labPool[labId].rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 69),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 68),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 73),
|
||||
// if (rootLabId <= 0) goto label1;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 73),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
// labId = rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 73),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 68)
|
||||
// lable1:
|
||||
);
|
||||
matcher.Instruction.labels.Add(label1);
|
||||
|
||||
// Add UpdateNeedsXXXXSingle() after item count changed
|
||||
// -- Find V_76
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Sub),
|
||||
new CodeMatch(OpCodes.Stloc_S),
|
||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||
new CodeMatch(OpCodes.Stloc_S))
|
||||
.Advance(3);
|
||||
var v76 = matcher.Operand;
|
||||
// -- Patch
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S, v76),
|
||||
new CodeMatch(OpCodes.Add),
|
||||
new CodeMatch(OpCodes.Stind_I4)
|
||||
).Advance(3).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 69),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 68),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 73),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsAssembleSingle)))
|
||||
);
|
||||
// -- Find V_83
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldc_I4, 0xE10),
|
||||
new CodeMatch(OpCodes.Div),
|
||||
new CodeMatch(OpCodes.Sub),
|
||||
new CodeMatch(OpCodes.Stloc_S),
|
||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||
new CodeMatch(OpCodes.Stloc_S))
|
||||
.Advance(5);
|
||||
var v83 = matcher.Operand;
|
||||
// -- Patch
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_S, v83),
|
||||
new CodeMatch(OpCodes.Ldc_I4, 0xE10),
|
||||
new CodeMatch(OpCodes.Mul),
|
||||
new CodeMatch(OpCodes.Add),
|
||||
new CodeMatch(OpCodes.Stind_I4)
|
||||
).Advance(5).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 69),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 68),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 73),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsResearchSingle)))
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Fill into root lab
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UILabWindow), nameof(UILabWindow.OnItemButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UILabWindow_OnItemButtonClick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
var local1 = generator.DeclareLocal(typeof(int));
|
||||
var label1 = generator.DefineLabel();
|
||||
matcher
|
||||
.MatchForward(false, new CodeMatch(OpCodes.Ret))
|
||||
.Advance(1)
|
||||
.MatchForward(false, new CodeMatch(OpCodes.Ret))
|
||||
.Advance(1);
|
||||
var labels = matcher.Instruction.labels;
|
||||
matcher.InsertAndAdvance(
|
||||
// labId = this.labId;
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(UILabWindow), nameof(UILabWindow.labId))),
|
||||
new CodeInstruction(OpCodes.Stloc_S, local1),
|
||||
// rootLabId = this.factorySystem.labPool[labId].rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 27),
|
||||
// if (rootLabId <= 0) goto label1;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 27),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
// labId = rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 27),
|
||||
new CodeInstruction(OpCodes.Stloc_S, local1)
|
||||
// lable1:
|
||||
);
|
||||
matcher.Instruction.labels = new List<Label> { label1 };
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(UILabWindow), nameof(UILabWindow.labId))));
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.RemoveInstructions(2).InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, local1));
|
||||
}
|
||||
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), nameof(Player.AddHandItemCount_Unsafe)))
|
||||
).MatchBack(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsResearchSingle)))
|
||||
).Advance(10).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), nameof(Player.AddHandItemCount_Unsafe)))
|
||||
).MatchBack(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0)
|
||||
).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsAssembleSingle)))
|
||||
);
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stelem_I4),
|
||||
new CodeMatch(OpCodes.Ret)
|
||||
).Advance(1).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsResearchSingle)))
|
||||
).Advance(1).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stelem_I4),
|
||||
new CodeMatch(OpCodes.Ret)
|
||||
).Advance(1).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof (LabOptPatchFunctions), nameof(LabOptPatchFunctions.UpdateNeedsAssembleSingle)))
|
||||
);
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Add a parameter on calling LabComponent.InternalUpdateAssemble()
|
||||
// Remove call to LabComponent.InternalUpdateAssemble()
|
||||
// Redirect call of LabComponent.InternalUpdateAssemble() to InternalUpdateAssembleNew()
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTickLabProduceMode), typeof(long), typeof(bool))]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTickLabProduceMode), typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
|
||||
@@ -356,150 +159,113 @@ public class LabOptPatch : BaseUnityPlugin
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.InternalUpdateAssemble)))
|
||||
).RemoveInstructions(1).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
).SetInstruction(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.InternalUpdateAssembleNew)))
|
||||
);
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.UpdateNeedsAssemble)))
|
||||
).Advance(-4).RemoveInstructions(5);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Add a parameter on calling LabComponent.InternalUpdateResearch()
|
||||
// Remove call to LabComponent.InternalUpdateResearch()
|
||||
// Redirect call of LabComponent.SetFunction() to SetFunctionNew()
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTickLabResearchMode), typeof(long), typeof(bool))]
|
||||
private static IEnumerable<CodeInstruction> FactorySystem_GameTickLabResearchMode_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
[HarmonyPatch(typeof(BuildingParameters), nameof(BuildingParameters.ApplyPrebuildParametersToEntity))]
|
||||
private static IEnumerable<CodeInstruction> BuildingParameters_ApplyPrebuildParametersToEntity_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.InternalUpdateResearch)))
|
||||
).RemoveInstructions(1).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.InternalUpdateResearchNew)))
|
||||
);
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.UpdateNeedsResearch)))
|
||||
).Advance(-4).RemoveInstructions(5);
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.SetFunction)))
|
||||
).Repeat(codeMatcher =>
|
||||
{
|
||||
codeMatcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldloc_2),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetFunctionNew)))
|
||||
);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildingParameters), nameof(BuildingParameters.PasteToFactoryObject))]
|
||||
private static IEnumerable<CodeInstruction> BuildingParameters_PasteToFactoryObject_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.SetFunction)))
|
||||
).Repeat(codeMatcher =>
|
||||
{
|
||||
codeMatcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_2),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetFunctionNew)))
|
||||
);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.FindLabFunctionsForBuild))]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTickLabResearchMode))]
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.SyncLabFunctions))]
|
||||
// no need to patch this function, it just set everything to empty
|
||||
// [HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.TakeBackItems_Lab))]
|
||||
private static IEnumerable<CodeInstruction> FactorySystem_ReplaceLabSetFunction_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.SetFunction)))
|
||||
).Repeat(codeMatcher =>
|
||||
{
|
||||
codeMatcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetFunctionNew)))
|
||||
);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UILabWindow), nameof(UILabWindow.OnItemButtonClick))]
|
||||
[HarmonyPatch(typeof(UILabWindow), nameof(UILabWindow.OnProductButtonClick))]
|
||||
private static IEnumerable<CodeInstruction> UILabWindow_PasteToFactoryObject_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.SetFunction)))
|
||||
).Repeat(codeMatcher =>
|
||||
{
|
||||
codeMatcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool)))
|
||||
).SetInstructionAndAdvance(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetFunctionNew)))
|
||||
);
|
||||
});
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Display UI: use root lab's count
|
||||
// Do not take items back on dismantling labs
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UILabWindow), nameof(UILabWindow._OnUpdate))]
|
||||
private static IEnumerable<CodeInstruction> UILabWindow__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.TakeBackItems_Lab))]
|
||||
private static IEnumerable<CodeInstruction> FactorySystem_TakeBackItems_Lab_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var local1 = generator.DeclareLocal(typeof(LabComponent).MakeByRefType());
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.End().MatchBack(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(LabComponent), nameof(LabComponent.matrixMode)))
|
||||
).Advance(-1);
|
||||
var labels = matcher.Instruction.labels;
|
||||
var label1 = generator.DefineLabel();
|
||||
var label2 = generator.DefineLabel();
|
||||
matcher.InsertAndAdvance(
|
||||
// rootLabId = labComponent.rootLabId;
|
||||
new CodeInstruction(OpCodes.Ldloca_S, 0).WithLabels(labels),
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.SetFunction)))
|
||||
).Advance(-10);
|
||||
var label1 = matcher.Labels[0];
|
||||
matcher.Start().MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.recipeId)))
|
||||
).Insert(
|
||||
new CodeInstruction(OpCodes.Ldloc_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), "rootLabId")),
|
||||
new CodeInstruction(OpCodes.Stloc_S, 46),
|
||||
// if (rootLabId <= 0) goto label1;
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 46),
|
||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||
new CodeInstruction(OpCodes.Ble, label1),
|
||||
// labComponent2 = ref this.factorySystem.labPool[rootLabId];
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UILabWindow), nameof(UILabWindow.factorySystem))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.labPool))),
|
||||
new CodeInstruction(OpCodes.Ldloc_S, 46),
|
||||
new CodeInstruction(OpCodes.Ldelema, typeof(LabComponent)),
|
||||
new CodeInstruction(OpCodes.Stloc_S, local1),
|
||||
new CodeInstruction(OpCodes.Br, label2),
|
||||
// lable1:
|
||||
// labComponent2 = ref labComponent;
|
||||
new CodeInstruction(OpCodes.Ldloca_S, 0).WithLabels(label1),
|
||||
new CodeInstruction(OpCodes.Stloc_S, local1)
|
||||
);
|
||||
matcher.Instruction.labels = new List<Label>{label2};
|
||||
matcher.Advance(2);
|
||||
var startPos = matcher.Pos;
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.served)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.Set(OpCodes.Ldloc_S, local1).Advance(2);
|
||||
}
|
||||
|
||||
matcher.Start().Advance(startPos);
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.incServed)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.Set(OpCodes.Ldloc_S, local1).Advance(2);
|
||||
}
|
||||
|
||||
matcher.Start().Advance(startPos);
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.produced)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.Set(OpCodes.Ldloc_S, local1).Advance(2);
|
||||
}
|
||||
|
||||
matcher.Start().Advance(startPos);
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.matrixServed)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.Set(OpCodes.Ldloc_S, local1).Advance(2);
|
||||
}
|
||||
|
||||
matcher.Start().Advance(startPos);
|
||||
for (;;)
|
||||
{
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldloc_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.matrixIncServed)))
|
||||
);
|
||||
if (matcher.IsInvalid) break;
|
||||
matcher.Set(OpCodes.Ldloc_S, local1).Advance(2);
|
||||
}
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.SetFunction))]
|
||||
private static IEnumerable<CodeInstruction> LabComponent_SetFunction_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ret)
|
||||
).InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.UpdateNeedsResearch)))
|
||||
).Advance(1).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Newarr, typeof(int)),
|
||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(LabComponent), nameof(LabComponent.produced)))
|
||||
).Advance(2).Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LabComponent), nameof(LabComponent.UpdateNeedsAssemble)))
|
||||
new CodeInstruction(OpCodes.Bgt, label1)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<AssemblyName>LabOpt</AssemblyName>
|
||||
<BepInExPluginGuid>org.soardev.labopt</BepInExPluginGuid>
|
||||
<Description>DSP MOD - LabOpt</Description>
|
||||
<Version>0.2.1</Version>
|
||||
<Version>0.3.0</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "LabOpt",
|
||||
"version_number": "0.2.1",
|
||||
"version_number": "0.3.0",
|
||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LabOpt",
|
||||
"description": "Optimize Lab performance / 优化研究站性能",
|
||||
"dependencies": [
|
||||
|
||||
Reference in New Issue
Block a user