public static void UpdateCommandState_Prefix(PlayerController __instance) { if (__instance.cmd.type != ECommand.None && __instance.cmd.type != ECommand.Follow && (__instance.cmd.mode != lastCmdMode || __instance.cmd.type != lastCmdType)) { if (__instance.cmd.type != ECommand.Build || __instance.cmd.mode != 1) { BuildLogic.ResetMultiBuild(); } if (__instance.cmd.type != ECommand.Build || __instance.cmd.mode != 0) { BlueprintCreator.EndBpMode(); } // the preivous command might force us to stau in BuildMode (Even though we were leaving) if (__instance.cmd.type == ECommand.Build && lastCmdMode == 1 && __instance.cmd.mode != 1) { BlueprintManager.PrepareNew(); } if (__instance.cmd.type != ECommand.Build) { BlueprintManager.PrepareNew(); } lastCmdMode = __instance.cmd.mode; lastCmdType = __instance.cmd.type; } }
internal void Update() { if (!isValidInstallation) { return; } BuildLogic.OnUpdate(); BlueprintCreator.OnUpdate(); }
public static void UIGeneralTips__OnUpdate_Postfix(ref Text ___modeText) { if (BuildLogic.IsMultiBuildAvailable() && BuildLogic.multiBuildEnabled) { ___modeText.text += $"\nMultiBuild [{(BuildLogic.startPos == Vector3.zero ? "START" : "END")}]"; if (BuildLogic.spacingStore[BuildLogic.spacingIndex] > 0) { ___modeText.text += $" - Spacing {BuildLogic.spacingStore[BuildLogic.spacingIndex]}"; if (BuildLogic.spacingPeriod > 1) { ___modeText.text += $" every {BuildLogic.spacingPeriod} copies"; } } } if (BlueprintCreator.bpMode) { ___modeText.text = "Blueprint Mode"; } }
public static void PasteInsertersOnly(BlueprintData data, Vector3 targetPos, float yaw, int pasteIndex = 0, bool connectToPasted = false) { PlayerAction_Build actionBuild = GameMain.data.mainPlayer.controller.actionBuild; var backupMechaBuildArea = actionBuild.player.mecha.buildArea; actionBuild.player.mecha.buildArea = 10000f; Vector2 targetSpr = targetPos.ToSpherical(); ConcurrentQueue <InserterCopy> inserterQueue = new ConcurrentQueue <InserterCopy>(data.copiedInserters); Util.Parallelize((threadIndex) => { while (inserterQueue.TryDequeue(out InserterCopy inserter)) { var pastedEntity = ConcurrentPasteInserter(threadIndex, inserter, yaw, pasteIndex, connectToPasted); BuildLogic.CheckBuildConditionsWorker(_abs[threadIndex], pastedEntity.buildPreview); } }); actionBuild.player.mecha.buildArea = backupMechaBuildArea; }
public static void UIKeyTips_UpdateTipDesiredState_Prefix(ref UIKeyTips __instance, ref List <UIKeyTipNode> ___allTips) { if (tooltips.Count == 0) { allTips = ___allTips; tooltips.Add("toggle-build", __instance.RegisterTip("L-ALT", "Toggle multiBuild mode")); tooltips.Add("toggle-inserters", __instance.RegisterTip("TAB", "Toggle inserters copy")); tooltips.Add("increase-spacing", __instance.RegisterTip("+", "Increase space between copies")); tooltips.Add("decrease-spacing", __instance.RegisterTip("-", "Decrease space between copies")); tooltips.Add("increase-period", __instance.RegisterTip("CTRL", "+", "Increase spacing period")); tooltips.Add("decrease-period", __instance.RegisterTip("CTRL", "-", "Decrease spacing period")); tooltips.Add("zero-spacing", __instance.RegisterTip("0", "Reset space between copies")); tooltips.Add("rotate-path", __instance.RegisterTip("Z", "Rotate build path")); tooltips.Add("increase-radius", __instance.RegisterTip("+", "Increase selection area")); tooltips.Add("decrease-radius", __instance.RegisterTip("-", "Decrease selection area")); tooltips.Add("bp-select", __instance.RegisterTip(0, "Add building to blueprint")); tooltips.Add("bp-deselect", __instance.RegisterTip("CTRL", 0, "Remove building from blueprint")); tooltips.Add("bp-reference", __instance.RegisterTip("ALT", 0, "Select reference building")); } tooltips["toggle-build"].desired = tooltips["toggle-inserters"].desired = BuildLogic.IsMultiBuildAvailable(); tooltips["rotate-path"].desired = tooltips["zero-spacing"].desired = tooltips["decrease-spacing"].desired = tooltips["increase-spacing"].desired = tooltips["decrease-period"].desired = tooltips["increase-period"].desired = BuildLogic.IsMultiBuildRunning(); tooltips["increase-radius"].desired = tooltips["decrease-radius"].desired = tooltips["bp-select"].desired = tooltips["bp-deselect"].desired = tooltips["bp-reference"].desired = BlueprintCreator.bpMode; }
public static List <BuildPreview> Paste(Vector3 targetPos, float yaw, bool pasteInserters = true) { PlayerAction_Build actionBuild = GameMain.data.mainPlayer.controller.actionBuild; pastedEntities.Clear(); parallelPastedEntities.Clear(); previews.Clear(); InserterPoses.ResetOverrides(); Vector2 targetSpr = targetPos.ToSpherical(); float yawRad = yaw * Mathf.Deg2Rad; for (int i = 0; i < data.copiedBuildings.Count; i++) { PasteBuilding(i, data.copiedBuildings[i], targetSpr, yaw); } for (int i = 0; i < data.copiedBelts.Count; i++) { PasteBelt(i, data.copiedBelts[i], targetSpr, yaw); } if (pasteInserters && data.copiedInserters.Count > 16) { var maxThreads = Environment.ProcessorCount - 1; var runningThreads = 0; var next = -1; ManualResetEvent done = new ManualResetEvent(false); for (int i = 0; i < maxThreads; i++) { ThreadPool.QueueUserWorkItem(_ => { int item; Interlocked.Increment(ref runningThreads); try { PlayerAction_Build ab = BuildLogic.ClonePlayerAction_Build(actionBuild); while ((item = Interlocked.Increment(ref next)) < data.copiedInserters.Count) { PasteInserter(ab, item, data.copiedInserters[item], yaw); } } catch (Exception e) { Console.WriteLine(e.ToString()); } finally { if (Interlocked.Decrement(ref runningThreads) == 0) { done.Set(); } } }); } done.WaitOne(); } else if (pasteInserters) { for (var i = 0; i < data.copiedInserters.Count; i++) { PasteInserter(actionBuild, i, data.copiedInserters[i], yaw); } } // merge the inserter pastedEntities in the main dictionaries foreach (var item in parallelPastedEntities) { previews.Add(item.Value.buildPreview); pastedEntities.Add(item.Key, item.Value); } // after creating the belt previews this restore the correct connection to other belts and buildings foreach (BeltCopy belt in data.copiedBelts) { BuildPreview preview = pastedEntities[belt.originalId].buildPreview; if (belt.outputId != 0 && pastedEntities.TryGetValue(belt.outputId, out PastedEntity otherEntity) && Vector3.Distance(preview.lpos, otherEntity.buildPreview.lpos) < 10) // if the belts are too far apart ignore connection { preview.output = otherEntity.buildPreview; var otherBelt = data.copiedBelts[otherEntity.index]; if (otherBelt.backInputId == belt.originalId) { preview.outputToSlot = 1; } if (otherBelt.leftInputId == belt.originalId) { preview.outputToSlot = 2; } if (otherBelt.rightInputId == belt.originalId) { preview.outputToSlot = 3; } } if (belt.connectedBuildingId != 0 && pastedEntities.TryGetValue(belt.connectedBuildingId, out PastedEntity otherBuilding)) { if (belt.connectedBuildingIsOutput) { preview.output = otherBuilding.buildPreview; preview.outputToSlot = belt.connectedBuildingSlot; } else { preview.input = otherBuilding.buildPreview; preview.inputFromSlot = belt.connectedBuildingSlot; } } bool beltHasInput = pastedEntities.ContainsKey(belt.backInputId) || pastedEntities.ContainsKey(belt.leftInputId) || pastedEntities.ContainsKey(belt.rightInputId); bool beltHasOutput = pastedEntities.ContainsKey(belt.outputId); if (!beltHasInput || !beltHasOutput) { int found = actionBuild.nearcdLogic.GetBuildingsInAreaNonAlloc(preview.lpos, 0.34f, _nearObjectIds, false); for (int x = 0; x < found; x++) { int overlappingEntityId = _nearObjectIds[x]; if (overlappingEntityId <= 0) { continue; } EntityData overlappingEntityData = actionBuild.factory.entityPool[overlappingEntityId]; if (overlappingEntityData.beltId <= 0) { continue; } BeltComponent overlappingBelt = actionBuild.factory.cargoTraffic.beltPool[overlappingEntityData.beltId]; bool overlappingBeltHasInput = (overlappingBelt.backInputId + overlappingBelt.leftInputId + overlappingBelt.rightInputId) != 0; bool overlappingBeltHasOutput = overlappingBelt.outputId != 0; if ((beltHasOutput && !overlappingBeltHasOutput) || (beltHasInput && !overlappingBeltHasInput)) { // found overlapping belt that can be 'replaced' to connect to existing belts preview.coverObjId = overlappingEntityId; preview.ignoreCollider = true; preview.willCover = true; } } } } return(previews); }
public static void Paste(BlueprintData data, Vector3 targetPos, float yaw, bool pasteInserters = true, int pasteIndex = 0) { PlayerAction_Build actionBuild = GameMain.data.mainPlayer.controller.actionBuild; var backupMechaBuildArea = actionBuild.player.mecha.buildArea; actionBuild.player.mecha.buildArea = 10000f; Vector2 targetSpr = targetPos.ToSpherical(); ConcurrentQueue <BuildingCopy> buildingsQueue = new ConcurrentQueue <BuildingCopy>(data.copiedBuildings); Util.Parallelize((int threadIndex) => { while (buildingsQueue.TryDequeue(out BuildingCopy building)) { var pastedEntity = ConcurrentPasteBuilding(threadIndex, building, targetSpr, yaw, pasteIndex); lock (actionBuild.nearcdLogic) { actionBuild.nearcdLogic.ActiveEntityBuildCollidersInArea(pastedEntity.pose.position, 5f); } } }); buildingsQueue = new ConcurrentQueue <BuildingCopy>(data.copiedBuildings); Util.Parallelize((int threadIndex) => { while (buildingsQueue.TryDequeue(out BuildingCopy building)) { int pasteId = PASTE_INDEX_MULTIPLIER * pasteIndex + building.originalId; var pastedEntity = BlueprintManager.pastedEntities[pasteId]; ConcurrentConnectBuildings(threadIndex, pastedEntity); BuildLogic.CheckBuildConditionsWorker(_abs[threadIndex], pastedEntity.buildPreview); } }); ConcurrentQueue <BeltCopy> beltsQueue = new ConcurrentQueue <BeltCopy>(data.copiedBelts); Util.Parallelize((int threadIndex) => { while (beltsQueue.TryDequeue(out BeltCopy belt)) { var pastedEntity = ConcurrentPasteBelt(threadIndex, belt, targetSpr, yaw, pasteIndex); } }); // after creating the belt previews this restore the correct connection to other belts and buildings beltsQueue = new ConcurrentQueue <BeltCopy>(data.copiedBelts); Util.Parallelize((int threadIndex) => { while (beltsQueue.TryDequeue(out BeltCopy belt)) { int pasteId = PASTE_INDEX_MULTIPLIER * pasteIndex + belt.originalId; var pastedEntity = BlueprintManager.pastedEntities[pasteId]; ConcurrentConnectBelt(threadIndex, pastedEntity); BuildLogic.CheckBuildConditionsWorker(_abs[threadIndex], pastedEntity.buildPreview); } }); if (pasteInserters) { ConcurrentQueue <InserterCopy> inserterQueue = new ConcurrentQueue <InserterCopy>(data.copiedInserters); Util.Parallelize((threadIndex) => { while (inserterQueue.TryDequeue(out InserterCopy inserter)) { var pastedEntity = ConcurrentPasteInserter(threadIndex, inserter, yaw, pasteIndex); BuildLogic.CheckBuildConditionsWorker(_abs[threadIndex], pastedEntity.buildPreview); } }); } actionBuild.player.mecha.buildArea = backupMechaBuildArea; }