public static void SetCopyInfo_Postfix(PlayerAction_Build __instance, PlanetFactory ___factory, PlanetAuxData ___planetAux, int objectId, int protoId) { cachedInserters.Clear(); // Remove previous copy info if (objectId < 0) // Copied item is a ghost, no inserters to cache { return; } var sourceEntityProto = LDB.items.Select(protoId); var sourceEntityId = objectId; var sourceEntity = ___factory.entityPool[sourceEntityId]; var sourcePos = sourceEntity.pos; var sourceRot = sourceEntity.rot; // Set the current build rotation to the copied building rotation Quaternion zeroRot = Maths.SphericalRotation(sourcePos, 0f); float yaw = Vector3.SignedAngle(zeroRot.Forward(), sourceRot.Forward(), zeroRot.Up()); if (sourceEntityProto.prefabDesc.minerType != EMinerType.Vein) { yaw = Mathf.Round(yaw / 90f) * 90f; } __instance.yaw = yaw; // Ignore building without inserter slots if (sourceEntityProto.prefabDesc.insertPoses.Length == 0) { return; } // Find connected inserters var inserterPool = ___factory.factorySystem.inserterPool; var entityPool = ___factory.entityPool; for (int i = 1; i < ___factory.factorySystem.inserterCursor; i++) { if (inserterPool[i].id == i) { var inserter = inserterPool[i]; var inserterEntity = entityPool[inserter.entityId]; var pickTarget = inserter.pickTarget; var insertTarget = inserter.insertTarget; if (pickTarget == sourceEntityId || insertTarget == sourceEntityId) { ItemProto itemProto = LDB.items.Select(inserterEntity.protoId); bool incoming = insertTarget == sourceEntityId; var otherId = incoming ? pickTarget : insertTarget; // The belt or other building this inserter is attached to Vector3 otherPos; ItemProto otherProto; if (otherId > 0) { otherPos = entityPool[otherId].pos; otherProto = LDB.items.Select((int)___factory.entityPool[otherId].protoId); } else { otherPos = ___factory.prebuildPool[-otherId].pos; otherProto = LDB.items.Select((int)___factory.prebuildPool[-otherId].protoId); } // Store the Grid-Snapped moves from assembler to belt/other int path = 0; Vector3[] snaps = new Vector3[6]; var snappedPointCount = ___planetAux.SnapLineNonAlloc(sourcePos, otherPos, ref path, snaps); Vector3 lastSnap = sourcePos; Vector3[] snapMoves = new Vector3[snappedPointCount]; for (int s = 0; s < snappedPointCount; s++) { // note: reverse rotation of the delta so that rotation works Vector3 snapMove = Quaternion.Inverse(sourceRot) * (snaps[s] - lastSnap); snapMoves[s] = snapMove; lastSnap = snaps[s]; } bool otherIsBelt = otherProto != null && otherProto.prefabDesc.isBelt; // Cache info for this inserter CachedInserter ci = new CachedInserter { incoming = incoming, protoId = inserterEntity.protoId, // rotations + deltas relative to the source building's rotation rot = Quaternion.Inverse(sourceRot) * inserterEntity.rot, rot2 = Quaternion.Inverse(sourceRot) * inserter.rot2, posDelta = Quaternion.Inverse(sourceRot) * (inserterEntity.pos - sourcePos), // Delta from copied building to inserter pos pos2Delta = Quaternion.Inverse(sourceRot) * (inserter.pos2 - sourcePos), // Delta from copied building to inserter pos2 // store to restore inserter speed refCount = Mathf.RoundToInt((float)(inserter.stt - 0.499f) / itemProto.prefabDesc.inserterSTT), // not important? pickOffset = inserter.pickOffset, insertOffset = inserter.insertOffset, // needed for pose? t1 = inserter.t1, t2 = inserter.t2, filterId = inserter.filter, snapMoves = snapMoves, snapCount = snappedPointCount, startSlot = -1, endSlot = -1, otherIsBelt = otherIsBelt }; // compute the start and end slot that the cached inserter uses CalculatePose(__instance, pickTarget, insertTarget); if (__instance.posePairs.Count > 0) { float minDistance = 1000f; for (int j = 0; j < __instance.posePairs.Count; ++j) { var posePair = __instance.posePairs[j]; float startDistance = Vector3.Distance(posePair.startPose.position, inserterEntity.pos); float endDistance = Vector3.Distance(posePair.endPose.position, inserter.pos2); float poseDistance = startDistance + endDistance; if (poseDistance < minDistance) { minDistance = poseDistance; ci.startSlot = posePair.startSlot; ci.endSlot = posePair.endSlot; } } } cachedInserters.Add(ci); } } } }
public static void PlayerAction_BuildSetCopyInfoPostfix(PlayerAction_Build __instance, ref PlanetFactory ___factory, PlanetAuxData ___planetAux, int objectId, int protoId) { cachedInserters.Clear(); // Remove previous copy info if (objectId < 0) // Copied item is a ghost, no inserters to cache { return; } var sourceEntityProto = LDB.items.Select(protoId); // Ignore building without inserter slots if (sourceEntityProto.prefabDesc.insertPoses.Length == 0) { return; } var sourceEntityId = objectId; var sourceEntity = ___factory.entityPool[sourceEntityId]; var sourcePos = sourceEntity.pos; var sourceRot = sourceEntity.rot; // Find connected inserters var inserterPool = ___factory.factorySystem.inserterPool; var entityPool = ___factory.entityPool; for (int i = 1; i < ___factory.factorySystem.inserterCursor; i++) { if (inserterPool[i].id == i) { var inserter = inserterPool[i]; var inserterEntity = entityPool[inserter.entityId]; var pickTarget = inserter.pickTarget; var insertTarget = inserter.insertTarget; if (pickTarget == sourceEntityId || insertTarget == sourceEntityId) { bool incoming = insertTarget == sourceEntityId; var otherId = incoming ? pickTarget : insertTarget; // The belt or other building this inserter is attached to var otherPos = entityPool[otherId].pos; // Store the Grid-Snapped moves from assembler to belt/other int path = 0; Vector3[] snaps = new Vector3[6]; var snappedPointCount = ___planetAux.SnapLineNonAlloc(sourcePos, otherPos, ref path, snaps); Vector3 lastSnap = sourcePos; Vector3[] snapMoves = new Vector3[snappedPointCount]; for (int s = 0; s < snappedPointCount; s++) { // note: reverse rotation of the delta so that rotation works Vector3 snapMove = Quaternion.Inverse(sourceRot) * (snaps[s] - lastSnap); snapMoves[s] = snapMove; lastSnap = snaps[s]; } // Cache info for this inserter var ci = new CachedInserter(); ci.incoming = incoming; ci.protoId = inserterEntity.protoId; // rotations + deltas relative to the source building's rotation ci.rot = Quaternion.Inverse(sourceRot) * inserterEntity.rot; ci.rot2 = Quaternion.Inverse(sourceRot) * inserter.rot2; ci.posDelta = Quaternion.Inverse(sourceRot) * (inserterEntity.pos - sourcePos); // Delta from copied building to inserter pos ci.pos2Delta = Quaternion.Inverse(sourceRot) * (inserter.pos2 - sourcePos); // Delta from copied building to inserter pos2 ItemProto itemProto = LDB.items.Select(ci.protoId); ci.refCount = Mathf.RoundToInt((float)(inserter.stt - 0.499f) / itemProto.prefabDesc.inserterSTT); // compute the start and end slot that the cached inserter uses if (!incoming) { CalculatePose(__instance, sourceEntityId, otherId); } else { CalculatePose(__instance, otherId, sourceEntityId); } if (__instance.posePairs.Count > 0) { float minDistance = 1000f; PlayerAction_Build.PosePair bestFit = new PlayerAction_Build.PosePair(); bool hasNearbyPose = false; for (int j = 0; j < __instance.posePairs.Count; ++j) { float startDistance = Vector3.Distance(__instance.posePairs[j].startPose.position, inserterEntity.pos); float endDistance = Vector3.Distance(__instance.posePairs[j].endPose.position, inserter.pos2); float poseDistance = startDistance + endDistance; if (poseDistance < minDistance) { minDistance = poseDistance; bestFit = __instance.posePairs[j]; hasNearbyPose = true; } } if (hasNearbyPose) { ci.startSlot = bestFit.startSlot; ci.endSlot = bestFit.endSlot; } } // not important? ci.pickOffset = inserter.pickOffset; ci.insertOffset = inserter.insertOffset; // needed for pose? ci.t1 = inserter.t1; ci.t2 = inserter.t2; ci.filterId = inserter.filter; ci.snapMoves = snapMoves; ci.snapCount = snappedPointCount; cachedInserters.Add(ci); } } } }
public static void PlayerAction_BuildSetCopyInfoPostfix(ref PlanetFactory ___factory, int objectId, PlanetAuxData ___planetAux) { cachedInserters.Clear(); // Remove previous copy info var sourceEntity = objectId; var sourcePos = ___factory.entityPool[objectId].pos; var sourceRot = ___factory.entityPool[objectId].rot; // Find connected inserters int matches = 0; var inserterPool = ___factory.factorySystem.inserterPool; var entityPool = ___factory.entityPool; for (int i = 1; i < ___factory.factorySystem.inserterCursor; i++) { if (inserterPool[i].id == i) { var inserter = inserterPool[i]; var pickTarget = inserter.pickTarget; var insertTarget = inserter.insertTarget; if (pickTarget == sourceEntity || insertTarget == sourceEntity) { matches++; var inserterType = ___factory.entityPool[inserter.entityId].protoId; bool incoming = insertTarget == sourceEntity; var otherId = incoming ? pickTarget : insertTarget; // The belt or other building this inserter is attached to var otherPos = ___factory.entityPool[otherId].pos; // Store the Grid-Snapped moves from assembler to belt/other Vector3 begin = sourcePos; Vector3 end = otherPos; int path = 0; Vector3[] snaps = new Vector3[6]; var snappedPointCount = ___planetAux.SnapLineNonAlloc(begin, end, ref path, snaps); Vector3 lastSnap = begin; Vector3[] snapMoves = new Vector3[snappedPointCount]; for (int s = 0; s < snappedPointCount; s++) { Vector3 snapMove = snaps[s] - lastSnap; snapMoves[s] = snapMove; lastSnap = snaps[s]; } // Cache info for this inserter var ci = new CachedInserter(); ci.incoming = incoming; ci.protoId = inserterType; ci.rot = ___factory.entityPool[inserter.entityId].rot; ci.rot2 = inserter.rot2; ci.pos2delta = inserter.pos2; // YukkuriC: record abs pos first ci.posDelta = entityPool[inserter.entityId].pos; // YukkuriC: dump relative transforms Helper.RelTransform(sourcePos, entityPool[inserter.entityId].pos, ___factory.entityPool[inserter.entityId].rot, out ci.posDelta, out ci.rot); Helper.RelTransform(sourcePos, inserter.pos2, inserter.rot2, out ci.pos2delta, out ci.rot2); // not important? ci.pickOffset = inserter.pickOffset; ci.insertOffset = inserter.insertOffset; // needed for pose? ci.t1 = inserter.t1; ci.t2 = inserter.t2; ci.filterId = inserter.filter; ci.snapMoves = snapMoves; ci.snapCount = snappedPointCount; cachedInserters.Add(ci); } } } }
public static void PlayerAction_BuildSetCopyInfoPostfix(PlayerAction_Build __instance, ref PlanetFactory ___factory, int objectId, PlanetAuxData ___planetAux) { cachedInserters.Clear(); // Remove previous copy info if (objectId < 0) // Copied item is a ghost, no inserters to cache { return; } var sourceEntity = objectId; var sourcePos = ___factory.entityPool[objectId].pos; // Find connected inserters int matches = 0; var inserterPool = ___factory.factorySystem.inserterPool; var entityPool = ___factory.entityPool; for (int i = 1; i < ___factory.factorySystem.inserterCursor; i++) { if (inserterPool[i].id == i) { var inserter = inserterPool[i]; var pickTarget = inserter.pickTarget; var insertTarget = inserter.insertTarget; if (pickTarget == sourceEntity || insertTarget == sourceEntity) { matches++; var inserterType = ___factory.entityPool[inserter.entityId].protoId; bool incoming = insertTarget == sourceEntity; var otherId = incoming ? pickTarget : insertTarget; // The belt or other building this inserter is attached to var otherPos = ___factory.entityPool[otherId].pos; // Store the Grid-Snapped moves from assembler to belt/other Vector3 begin = sourcePos; Vector3 end = otherPos; int path = 0; Vector3[] snaps = new Vector3[6]; var snappedPointCount = ___planetAux.SnapLineNonAlloc(begin, end, ref path, snaps); Vector3 lastSnap = begin; Vector3[] snapMoves = new Vector3[snappedPointCount]; for (int s = 0; s < snappedPointCount; s++) { Vector3 snapMove = snaps[s] - lastSnap; snapMoves[s] = snapMove; lastSnap = snaps[s]; } // Cache info for this inserter var ci = new CachedInserter(); ci.otherDelta = (otherPos - sourcePos); // Delta from copied building to other belt/building ci.incoming = incoming; ci.protoId = inserterType; ci.rot = ___factory.entityPool[inserter.entityId].rot; ci.rot2 = inserter.rot2; ci.pos2delta = (inserter.pos2 - entityPool[inserter.entityId].pos); // Delta from inserter pos2 to copied building var posDelta = entityPool[inserter.entityId].pos - sourcePos; // Delta from copied building to inserter pos if (!incoming) { posDelta = sourcePos - entityPool[inserter.entityId].pos; // Reverse for outgoing inserters } ci.posDelta = posDelta; // compute the start and end slot that the cached inserter uses if (!incoming) { CalculatePose(__instance, sourceEntity, otherId); } else { CalculatePose(__instance, otherId, sourceEntity); } if (__instance.posePairs.Count > 0) { float minDistance = 1000f; PlayerAction_Build.PosePair bestFit = new PlayerAction_Build.PosePair(); bool hasNearbyPose = false; for (int j = 0; j < __instance.posePairs.Count; ++j) { float startDistance = Vector3.Distance(__instance.posePairs[j].startPose.position, entityPool[inserter.entityId].pos); float endDistance = Vector3.Distance(__instance.posePairs[j].endPose.position, inserter.pos2); float poseDistance = startDistance + endDistance; if (poseDistance < minDistance) { minDistance = poseDistance; bestFit = __instance.posePairs[j]; hasNearbyPose = true; } } if (hasNearbyPose) { ci.startSlot = bestFit.startSlot; ci.endSlot = bestFit.endSlot; } } // not important? ci.pickOffset = inserter.pickOffset; ci.insertOffset = inserter.insertOffset; // needed for pose? ci.t1 = inserter.t1; ci.t2 = inserter.t2; ci.filterId = inserter.filter; ci.snapMoves = snapMoves; ci.snapCount = snappedPointCount; cachedInserters.Add(ci); } } } }