Ejemplo n.º 1
0
 public static Vector3 SnapModified(this PlanetAuxData auxData, Vector3 pos, bool onTerrain)
 {
     if (auxData.activeGridIndex < auxData.customGrids.Count)
     {
         Vector3 vector3 = auxData.customGrids[auxData.activeGridIndex].SnapModifiedInternal(pos);
         float   radius  = auxData.planet.realRadius + 0.2f;
         if (!onTerrain)
         {
             radius = Mathf.Max(auxData.planet.radius, Mathf.Floor((float)((pos.magnitude - (double)auxData.planet.radius) / 1.33333325386047)) * 1.333333f + auxData.planet.radius) + 0.2f;
         }
         pos = vector3 * radius;
     }
     return(pos);
 }
Ejemplo n.º 2
0
        public static void CalculateOffset(this PlanetAuxData auxData, Vector3 pos, GridData gridData)
        {
            if (auxData.activeGridIndex >= auxData.customGrids.Count)
            {
                return;
            }

            PlanetGrid grid = auxData.customGrids[auxData.activeGridIndex];

            pos.Normalize();
            float latitude  = BlueprintUtils.GetLatitudeRad(pos);
            float longitude = BlueprintUtils.GetLongitudeRad(pos);

            float latitudeCount         = latitude / 6.28318548202515f * grid.segment;
            float longitudeSegmentCount =
                PlanetGrid.DetermineLongitudeSegmentCount(Mathf.FloorToInt(Mathf.Max(0.0f, Mathf.Abs(latitudeCount) - 0.1f)), grid.segment);

            float longtitudeCount = longitude / 6.283185f * longitudeSegmentCount;

            float offsetLat  = Snap(latitudeCount) * 5f;
            float offsetLong = Snap(longtitudeCount) * 5f;

            gridData.snapOffset = new Vector2(offsetLong % gridData.snapGrid.x, offsetLat % gridData.snapGrid.y);
        }
        public static void AfterPrebuild_Postfix(PlayerAction_Build __instance, PlanetFactory ___factory, PlanetAuxData ___planetAux, NearColliderLogic ___nearcdLogic)
        {
            // Do we have cached inserters?
            var ci = cachedInserters;

            if (CopyInserters.copyEnabled && ci.Count > 0 && !__instance.multiLevelCovering)
            {
                foreach (var cachedInserter in ci)
                {
                    var protoId    = cachedInserter.protoId;
                    var modelIndex = (short)LDB.items.Select(cachedInserter.protoId).ModelIndex;

                    foreach (BuildPreview buildPreview in __instance.buildPreviews)
                    {
                        var positionData = GetPositions(__instance, ___factory, ___planetAux, ___nearcdLogic, buildPreview, cachedInserter);

                        if (positionData.otherId != 0)
                        {
                            // Create inserter Prebuild data
                            var pbdata = new PrebuildData
                            {
                                protoId    = (short)protoId,
                                modelIndex = modelIndex,

                                insertOffset = positionData.insertOffset,
                                pickOffset   = positionData.pickOffset,
                                filterId     = cachedInserter.filterId,

                                refCount = cachedInserter.refCount,

                                pos  = positionData.absoluteInserterPos,
                                pos2 = positionData.absoluteInserterPos2,

                                rot  = positionData.absoluteInserterRot,
                                rot2 = positionData.absoluteInserterRot2
                            };


                            // Check the player has the item in inventory, no cheating here
                            var pc        = CopyInserters.pc;
                            var itemcount = pc.player.package.GetItemCount(protoId);
                            // If player has none; skip this request, as we dont create prebuild ghosts, must avoid confusion
                            if (itemcount > 0)
                            {
                                var qty = 1;
                                pc.player.package.TakeTailItems(ref protoId, ref qty);
                                int pbCursor = ___factory.AddPrebuildDataWithComponents(pbdata); // Add the inserter request to Prebuild pool

                                if (cachedInserter.incoming)
                                {
                                    ___factory.WriteObjectConn(-pbCursor, 0, true, buildPreview.objId, positionData.endSlot);      // assembler connection
                                    ___factory.WriteObjectConn(-pbCursor, 1, false, positionData.otherId, positionData.startSlot); // other connection
                                }
                                else
                                {
                                    ___factory.WriteObjectConn(-pbCursor, 0, false, buildPreview.objId, positionData.startSlot); // assembler connection
                                    ___factory.WriteObjectConn(-pbCursor, 1, true, positionData.otherId, positionData.endSlot);  // other connection
                                }
                            }
                        }
                    }
                }
            }
        }
        private static InserterPosition GetPositions(PlayerAction_Build __instance, PlanetFactory ___factory, PlanetAuxData ___planetAux, NearColliderLogic ___nearcdLogic, BuildPreview buildPreview, CachedInserter cachedInserter)
        {
            Vector3    absoluteBuildingPos;
            Quaternion absoluteBuildingRot;

            // When using AdvancedBuildDestruct mod, all buildPreviews are positioned 'absolutely' on the planet surface.
            // In 'normal' mode the buildPreviews are relative to __instance.previewPose.
            // This means that in 'normal' mode the (only) buildPreview is always positioned at {0,0,0}

            if (buildPreview.lpos == Vector3.zero)
            {
                absoluteBuildingPos = __instance.previewPose.position;
                absoluteBuildingRot = __instance.previewPose.rotation;
            }
            else
            {
                absoluteBuildingPos = buildPreview.lpos;
                absoluteBuildingRot = buildPreview.lrot;
            }

            InserterPosition position = null;

            if (currentPositionCache.Count > 0)
            {
                position = currentPositionCache.Dequeue();
            }

            bool isCacheValid = position != null &&
                                position.cachedInserter == cachedInserter &&
                                position.absoluteBuildingPos == absoluteBuildingPos &&
                                position.absoluteBuildingRot == absoluteBuildingRot;

            if (isCacheValid)
            {
                nextPositionCache.Enqueue(position);
                return(position);
            }


            var posDelta  = cachedInserter.posDelta;
            var pos2Delta = cachedInserter.pos2Delta;

            Vector3 absoluteInserterPos  = absoluteBuildingPos + absoluteBuildingRot * cachedInserter.posDelta;
            Vector3 absoluteInserterPos2 = absoluteBuildingPos + absoluteBuildingRot * cachedInserter.pos2Delta;

            Quaternion absoluteInserterRot  = absoluteBuildingRot * cachedInserter.rot;
            Quaternion absoluteInserterRot2 = absoluteBuildingRot * cachedInserter.rot2;

            int startSlot = cachedInserter.startSlot;
            int endSlot   = cachedInserter.endSlot;

            short pickOffset   = cachedInserter.pickOffset;
            short insertOffset = cachedInserter.insertOffset;

            // Find the desired belt/building position
            // As delta doesn't work over distance, re-trace the Grid Snapped steps from the original
            // to find the target belt/building for this inserters other connection
            var testPos = absoluteBuildingPos;

            // Note: rotates each move relative to the rotation of the new building
            for (int u = 0; u < cachedInserter.snapCount; u++)
            {
                testPos = ___planetAux.Snap(testPos + absoluteBuildingRot * cachedInserter.snapMoves[u], true, false);
            }

            // Find the other entity at the target location
            int otherId = 0;

            // find building nearby
            int found = ___nearcdLogic.GetBuildingsInAreaNonAlloc(testPos, 0.2f, _nearObjectIds);

            // find nearest building
            float maxDistance = 0.2f;

            for (int x = 0; x < found; x++)
            {
                var       id = _nearObjectIds[x];
                float     distance;
                ItemProto proto;
                if (id == 0 || id == buildPreview.objId)
                {
                    continue;
                }
                else if (id > 0)
                {
                    EntityData entityData = ___factory.entityPool[id];
                    proto    = LDB.items.Select((int)entityData.protoId);
                    distance = Vector3.Distance(entityData.pos, testPos);
                }
                else
                {
                    PrebuildData prebuildData = ___factory.prebuildPool[-id];
                    proto = LDB.items.Select((int)prebuildData.protoId);
                    if (proto.prefabDesc.isBelt)
                    {
                        // ignore unbuilt belts
                        continue;
                    }
                    distance = Vector3.Distance(prebuildData.pos, testPos);
                }

                // ignore entitites that ore not (built) belts or don't have inserterPoses
                if ((proto.prefabDesc.isBelt == cachedInserter.otherIsBelt || proto.prefabDesc.insertPoses.Length > 0) && distance < maxDistance)
                {
                    otherId     = id;
                    maxDistance = distance;
                }
            }

            if (otherId != 0)
            {
                var buildingId = buildPreview.objId;

                if (buildingId == 0)
                {
                    // the original calculatePose code doesn't correctly handle calculation where one of the entity is a BuildPreview
                    // as it has objId 0 and is not registered in either the entityPool or prebuildPool
                    // To address that we override the 4 critical methods GetObjectPose/GetObjectProtoId/ObjectIsBelt/GetLocalInserts
                    // only for this specific execution of CalculatePose, by returning the expected value for the current buildPreview
                    overridePoseMethods = true;
                    overriddenProto     = buildPreview.item;
                    overriddenPose      = new Pose(absoluteBuildingPos, absoluteBuildingRot);
                }

                if (cachedInserter.incoming)
                {
                    CalculatePose(__instance, otherId, buildingId);
                }
                else
                {
                    CalculatePose(__instance, buildingId, otherId);
                }


                overridePoseMethods = false;

                bool hasNearbyPose = false;
                if (__instance.posePairs.Count > 0)
                {
                    float minDistance = 1000f;
                    PlayerAction_Build.PosePair bestFit = new PlayerAction_Build.PosePair();

                    for (int j = 0; j < __instance.posePairs.Count; ++j)
                    {
                        var posePair = __instance.posePairs[j];
                        if (
                            (cachedInserter.incoming && cachedInserter.endSlot != posePair.endSlot) ||
                            (!cachedInserter.incoming && cachedInserter.startSlot != posePair.startSlot)
                            )
                        {
                            continue;
                        }
                        float startDistance = Vector3.Distance(posePair.startPose.position, absoluteInserterPos);
                        float endDistance   = Vector3.Distance(posePair.endPose.position, absoluteInserterPos2);
                        float poseDistance  = startDistance + endDistance;

                        if (poseDistance < minDistance)
                        {
                            minDistance   = poseDistance;
                            bestFit       = posePair;
                            hasNearbyPose = true;
                        }
                    }
                    if (hasNearbyPose)
                    {
                        // if we were able to calculate a close enough sensible pose
                        // use that instead of the (visually) imprecise default

                        absoluteInserterPos  = bestFit.startPose.position;
                        absoluteInserterPos2 = bestFit.endPose.position;

                        absoluteInserterRot  = bestFit.startPose.rotation;
                        absoluteInserterRot2 = bestFit.endPose.rotation * Quaternion.Euler(0.0f, 180f, 0.0f);

                        pickOffset   = (short)bestFit.startOffset;
                        insertOffset = (short)bestFit.endOffset;

                        startSlot = bestFit.startSlot;
                        endSlot   = bestFit.endSlot;


                        posDelta  = Quaternion.Inverse(absoluteBuildingRot) * (absoluteInserterPos - absoluteBuildingPos);
                        pos2Delta = Quaternion.Inverse(absoluteBuildingRot) * (absoluteInserterPos2 - absoluteBuildingPos);
                    }
                }
            }

            position = new InserterPosition()
            {
                cachedInserter      = cachedInserter,
                absoluteBuildingPos = absoluteBuildingPos,
                absoluteBuildingRot = absoluteBuildingRot,

                otherId = otherId,

                posDelta             = posDelta,
                pos2Delta            = pos2Delta,
                absoluteInserterPos  = absoluteInserterPos,
                absoluteInserterPos2 = absoluteInserterPos2,

                absoluteInserterRot  = absoluteInserterRot,
                absoluteInserterRot2 = absoluteInserterRot2,

                pickOffset   = pickOffset,
                insertOffset = insertOffset,

                startSlot = startSlot,
                endSlot   = endSlot,
            };


            nextPositionCache.Enqueue(position);
            return(position);
        }
        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 DetermineBuildPreviews_Postfix(PlayerAction_Build __instance, PlanetFactory ___factory, PlanetAuxData ___planetAux, NearColliderLogic ___nearcdLogic, Player ___player)
        {
            // Do we have cached inserters?
            var ci = cachedInserters;

            if (CopyInserters.copyEnabled && ci.Count > 0 && !__instance.multiLevelCovering)
            {
                var bpCount = __instance.buildPreviews.Count;

                for (int i = 0; i < bpCount; i++)
                {
                    BuildPreview buildPreview = __instance.buildPreviews[i];

                    if (!buildPreview.item.prefabDesc.isInserter)
                    {
                        foreach (var cachedInserter in ci)
                        {
                            var positionData = GetPositions(__instance, ___factory, ___planetAux, ___nearcdLogic, buildPreview, cachedInserter);

                            var bp = BuildPreview.CreateSingle(LDB.items.Select(cachedInserter.protoId), LDB.items.Select(cachedInserter.protoId).prefabDesc, true);
                            bp.ResetInfos();


                            bp.lrot  = buildPreview.lrot * cachedInserter.rot;
                            bp.lrot2 = buildPreview.lrot * cachedInserter.rot2;


                            if (buildPreview.lpos == Vector3.zero)
                            {
                                bp.lpos  = buildPreview.lpos + buildPreview.lrot * positionData.posDelta;
                                bp.lpos2 = buildPreview.lpos + buildPreview.lrot * positionData.pos2Delta;
                            }
                            else
                            {
                                bp.lpos  = positionData.absoluteInserterPos;
                                bp.lpos2 = positionData.absoluteInserterPos2;
                            }



                            if (positionData.condition == null)
                            {
                                positionData.condition = EBuildCondition.Ok;

                                Vector3 lpos    = positionData.absoluteInserterPos;
                                Vector3 lpos2   = positionData.absoluteInserterPos2;
                                Vector3 forward = lpos2 - lpos;

                                Pose pose;
                                pose.position = Vector3.Lerp(lpos, lpos2, 0.5f);
                                pose.rotation = Quaternion.LookRotation(forward, lpos.normalized);


                                var colliderData = bp.desc.buildColliders[0];
                                colliderData.ext = new Vector3(colliderData.ext.x, colliderData.ext.y, Vector3.Distance(lpos2, lpos) * 0.5f + colliderData.ext.z - 0.5f);

                                if (cachedInserter.otherIsBelt)
                                {
                                    if (cachedInserter.incoming)
                                    {
                                        colliderData.pos.z -= 0.4f;
                                        colliderData.ext.z += 0.4f;
                                    }
                                    else
                                    {
                                        colliderData.pos.z += 0.4f;
                                        colliderData.ext.z += 0.4f;
                                    }
                                }

                                if (colliderData.ext.z < 0.1f)
                                {
                                    colliderData.ext.z = 0.1f;
                                }
                                colliderData.pos = pose.position + pose.rotation * colliderData.pos;
                                colliderData.q   = pose.rotation * colliderData.q;


                                //int mask = 165888;// the following is equivalent but explicitly states layers affected
                                int mask            = Convert.ToInt32(LayerMaskConstants.layer12 | LayerMaskConstants.layer16 | LayerMaskConstants.layer18);
                                int collisionsFound = Physics.OverlapBoxNonAlloc(colliderData.pos, colliderData.ext, _tmp_cols, colliderData.q, mask, QueryTriggerInteraction.Collide);

                                int collisionLimit = cachedInserter.otherIsBelt ? 0 : 1;

                                if (collisionsFound > collisionLimit)
                                {
                                    PlanetPhysics physics2 = ___player.planetData.physics;
                                    for (int j = 0; j < collisionsFound; j++)
                                    {
                                        physics2.GetColliderData(_tmp_cols[j], out ColliderData colliderData2);
                                        if (colliderData2.objId != 0)
                                        {
                                            if (colliderData2.usage == EColliderUsage.Build)
                                            {
                                                positionData.condition = EBuildCondition.Collide;
                                            }
                                        }
                                    }
                                }
                            }

                            bp.condition = (EBuildCondition)positionData.condition;

                            if (bp.condition == EBuildCondition.Ok)
                            {
                                if (cachedInserter.incoming)
                                {
                                    bp.inputObjId = positionData.otherId;
                                }
                                else
                                {
                                    bp.outputObjId = positionData.otherId;
                                }
                            }

                            __instance.AddBuildPreview(bp);
                        }
                    }
                }

                SwapPositionCache();
            }
        }
Ejemplo n.º 7
0
            public static void PlayerAction_BuildNotifyBuiltPrefix(int postObjId, PlanetAuxData ___planetAux)
            {
                var entityBuilt = pc.player.factory.entityPool[postObjId];

                ModelProto modelProto = LDB.models.Select(entityBuilt.modelIndex);
                var        prefabDesc = modelProto.prefabDesc;

                if (!prefabDesc.isInserter)
                {
                    // Check for pending inserter requests
                    if (PatchCopyInserters.pendingInserters.Count > 0)
                    {
                        var factory = pc.player.factory;
                        for (int i = pendingInserters.Count - 1; i >= 0; i--) // Reverse loop for removing found elements
                        {
                            var pi = pendingInserters[i];
                            // Is the NotifyBuilt assembler in the expected position for this pending inserter?
                            var distance = Vector3.Distance(entityBuilt.pos, pi.AssemblerPos);
                            if (distance < 0.2)
                            {
                                var assemblerId = entityBuilt.id;
                                //Debug.Log($"!!! found assembler id={assemblerId} at Pos={entityBuilt.pos} expected {pi.AssemblerPos} distance={distance}");

                                // Create inserter Prebuild data
                                var pbdata = new PrebuildData();
                                pbdata.protoId    = (short)pi.ci.protoId;
                                pbdata.modelIndex = (short)LDB.items.Select(pi.ci.protoId).ModelIndex;
                                pbdata.modelId    = factory.entityPool[pi.otherId].modelId;

                                pbdata.insertOffset = pi.ci.insertOffset;
                                pbdata.pickOffset   = pi.ci.pickOffset;
                                pbdata.filterId     = pi.ci.filterId;

                                // YukkuriC: recover absolute transforms
                                Helper.AbsTransform(entityBuilt.pos, pi.ci.posDelta, pi.ci.rot, out pbdata.pos, out pbdata.rot);
                                Helper.AbsTransform(entityBuilt.pos, pi.ci.pos2delta, pi.ci.rot2, out pbdata.pos2, out pbdata.rot2);
                                pbdata.pos  = ___planetAux.Snap(pbdata.pos, true, false);
                                pbdata.pos2 = ___planetAux.Snap(pbdata.pos2, true, false);

                                // Check the player has the item in inventory, no cheating here
                                var itemcount = pc.player.package.GetItemCount(pi.ci.protoId);
                                // If player has none; skip this request, as we dont create prebuild ghosts, must avoid confusion
                                if (itemcount > 0)
                                {
                                    var qty = 1;
                                    pc.player.package.TakeTailItems(ref pi.ci.protoId, ref qty);
                                    int pbCursor = factory.AddPrebuildData(pbdata); // Add the inserter request to Prebuild pool

                                    // Otherslot -1 will try to find one, otherwise could cache this from original assembler if it causes problems
                                    if (pi.ci.incoming)
                                    {
                                        factory.WriteObjectConn(-pbCursor, 0, true, assemblerId, -1); // assembler connection
                                        factory.WriteObjectConn(-pbCursor, 1, false, pi.otherId, -1); // other connection
                                    }
                                    else
                                    {
                                        factory.WriteObjectConn(-pbCursor, 0, false, assemblerId, -1); // assembler connection
                                        factory.WriteObjectConn(-pbCursor, 1, true, pi.otherId, -1);   // other connection
                                    }
                                }
                                pendingInserters.RemoveAt(i);
                            }
                        }
                    }
                }
            }
Ejemplo n.º 8
0
            public static void PlayerAction_BuildAfterPrebuildPostfix(PlayerAction_Build __instance, ref PlanetFactory ___factory, PlanetAuxData ___planetAux)
            {
                // Do we have cached inserters?
                var ci = PatchCopyInserters.cachedInserters;

                if (ci.Count > 0)
                {
                    var targetPos  = __instance.buildTargetPositionWanted;
                    var entityPool = ___factory.entityPool;
                    foreach (var inserter in ci)
                    {
                        // Find the desired belt/building position
                        // As delta doesn't work over distance, re-trace the Grid Snapped steps from the original
                        // to find the target belt/building for this inserters other connection
                        var currentPos = targetPos;
                        for (int u = 0; u < inserter.snapCount; u++)
                        {
                            currentPos = ___planetAux.Snap(currentPos + inserter.snapMoves[u], true, false);
                        }

                        var testPos = currentPos;

                        // Find the other entity at the target location
                        int otherId = 0;
                        for (int x = 1; x < ___factory.entityCursor; x++)
                        {
                            if (entityPool[x].id == x)
                            {
                                var distance = Vector3.Distance(entityPool[x].pos, testPos);
                                if (distance < 0.2)
                                {
                                    otherId = entityPool[x].id;
                                    break;
                                }
                            }
                        }

                        if (otherId != 0)
                        {
                            // Order an inserter
                            var pi = new PatchCopyInserters.PendingInserter();
                            pi.otherId      = otherId;
                            pi.ci           = inserter;
                            pi.AssemblerPos = targetPos;

                            PatchCopyInserters.pendingInserters.Add(pi);
                        }
                    }
                }
            }
Ejemplo n.º 9
0
            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);
                        }
                    }
                }
            }
Ejemplo n.º 10
0
        public static BPGratBox GetBoundingRange(PlanetData _planet, PlanetAuxData aux, int[] _objIds, int _objCount, List <ReformData> reforms, float _divideLongitude)
        {
            if (reforms.Count == 0 && _objCount == 0)
            {
                return(BPGratBox.zero);
            }

            float startlong = float.MaxValue;
            float startLat  = float.MaxValue;
            float endLong   = float.MinValue;
            float endLat    = float.MinValue;

            bool isPole = true;

            EntityData[]   entityPool   = _planet.factory.entityPool;
            PrebuildData[] prebuildPool = _planet.factory.prebuildPool;
            for (int i = 0; i < _objCount; i++)
            {
                int     id         = _objIds[i];
                Vector3 pos        = (id > 0) ? entityPool[id].pos.normalized : prebuildPool[-id].pos.normalized;
                Vector3 normalized = aux.Snap(pos, true).normalized;
                float   num6       = Mathf.Asin(normalized.y);
                float   num7       = Mathf.Atan2(normalized.x, -normalized.z);
                if (normalized.x * normalized.x + normalized.z * normalized.z >= 5E-07f)
                {
                    isPole = false;
                    float correctLong = num7 - _divideLongitude;
                    if (correctLong <= -1.8E-05f)
                    {
                        correctLong += 6.2831855f;
                    }
                    if (correctLong < 0f)
                    {
                        correctLong = 0f;
                    }
                    startlong = ((startlong < correctLong) ? startlong : correctLong);
                    endLong   = ((endLong > correctLong) ? endLong : correctLong);
                }
                startLat = ((startLat < num6) ? startLat : num6);
                endLat   = ((endLat > num6) ? endLat : num6);
            }

            if (BlueprintCopyExtension.isEnabled)
            {
                foreach (var data in reforms)
                {
                    if (data.longitude != 0)
                    {
                        isPole = false;
                        float correctLong = data.longitude - _divideLongitude;
                        if (correctLong <= -1.8E-05f)
                        {
                            correctLong += 6.2831855f;
                        }

                        if (correctLong < 0f)
                        {
                            correctLong = 0f;
                        }

                        startlong = startlong < correctLong ? startlong : correctLong;
                        endLong   = endLong > correctLong ? endLong : correctLong;
                    }

                    startLat = startLat < data.latitude ? startLat : data.latitude;
                    endLat   = endLat > data.latitude ? endLat : data.latitude;
                }
            }

            if (startlong < 0f)
            {
                startlong = 0f;
            }
            else if (startlong > 6.2831674f)
            {
                startlong = 6.2831674f;
            }

            if (endLong < 0f)
            {
                endLong = 0f;
            }
            else if (endLong > 6.2831674f)
            {
                endLong = 6.2831674f;
            }

            if (isPole)
            {
                startlong = 0f;
                endLong   = 6.2831674f;
            }

            startlong += _divideLongitude;
            endLong   += _divideLongitude;
            if (startlong < -3.1415927f)
            {
                startlong += 6.2831855f;
            }
            else if (startlong > 3.1415927f)
            {
                startlong -= 6.2831855f;
            }

            if (endLong < -3.1415927f)
            {
                endLong += 6.2831855f;
            }
            else if (endLong > 3.1415927f)
            {
                endLong -= 6.2831855f;
            }

            return(new BPGratBox(startlong, startLat, endLong, endLat));
        }
Ejemplo n.º 11
0
            public static void PlayerAction_BuildAfterPrebuildPostfix(PlayerAction_Build __instance, ref PlanetFactory ___factory, PlanetAuxData ___planetAux)
            {
                // Do we have cached inserters?
                var ci = PatchCopyInserters.cachedInserters;

                if (CopyInserters.copyEnabled && ci.Count > 0)
                {
                    foreach (BuildPreview buildPreview in __instance.buildPreviews)
                    {
                        Vector3    targetPos;
                        Quaternion targetRot;
                        if (__instance.buildPreviews.Count > 1)
                        {
                            targetPos = buildPreview.lpos;
                            targetRot = buildPreview.lrot;
                        }
                        else
                        {
                            targetPos = __instance.previewPose.position + __instance.previewPose.rotation * buildPreview.lpos;
                            targetRot = __instance.previewPose.rotation;
                        }

                        // ignore buildings not being built at ground level
                        if (__instance.multiLevelCovering)
                        {
                            continue;
                        }

                        var entityPool = ___factory.entityPool;
                        foreach (var inserter in ci)
                        {
                            // Find the desired belt/building position
                            // As delta doesn't work over distance, re-trace the Grid Snapped steps from the original
                            // to find the target belt/building for this inserters other connection
                            var testPos = targetPos;
                            // Note: rotates each move relative to the rotation of the new building
                            for (int u = 0; u < inserter.snapCount; u++)
                            {
                                testPos = ___planetAux.Snap(testPos + targetRot * inserter.snapMoves[u], true, false);
                            }

                            // Find the other entity at the target location
                            int otherId = 0;
                            for (int x = 1; x < ___factory.entityCursor; x++)
                            {
                                if (entityPool[x].id == x)
                                {
                                    var distance = Vector3.Distance(entityPool[x].pos, testPos);
                                    if (distance < 0.2)
                                    {
                                        otherId = entityPool[x].id;
                                        break;
                                    }
                                }
                            }

                            if (otherId != 0)
                            {
                                // Order an inserter
                                var pi = new PatchCopyInserters.PendingInserter();
                                pi.otherId      = otherId;
                                pi.ci           = inserter;
                                pi.AssemblerPos = targetPos;

                                PatchCopyInserters.pendingInserters.Add(pi);
                            }
                        }
                    }
                }
            }
Ejemplo n.º 12
0
            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);
                        }
                    }
                }
            }
Ejemplo n.º 13
0
            public static void PlayerAction_BuildNotifyBuiltPrefix(PlayerAction_Build __instance, int postObjId, PlanetAuxData ___planetAux)
            {
                var entityBuilt = pc.player.factory.entityPool[postObjId];

                ModelProto modelProto = LDB.models.Select(entityBuilt.modelIndex);
                var        prefabDesc = modelProto.prefabDesc;

                if (!prefabDesc.isInserter)
                {
                    // Check for pending inserter requests
                    if (PatchCopyInserters.pendingInserters.Count > 0)
                    {
                        var factory = pc.player.factory;
                        for (int i = pendingInserters.Count - 1; i >= 0; i--) // Reverse loop for removing found elements
                        {
                            var pi = pendingInserters[i];
                            // Is the NotifyBuilt assembler in the expected position for this pending inserter?
                            var distance = Vector3.Distance(entityBuilt.pos, pi.AssemblerPos);
                            if (distance < 0.2)
                            {
                                var assemblerId = entityBuilt.id;

                                // Create inserter Prebuild data
                                var pbdata = new PrebuildData();
                                pbdata.protoId    = (short)pi.ci.protoId;
                                pbdata.modelIndex = (short)LDB.items.Select(pi.ci.protoId).ModelIndex;

                                pbdata.insertOffset = pi.ci.insertOffset;
                                pbdata.pickOffset   = pi.ci.pickOffset;
                                pbdata.filterId     = pi.ci.filterId;

                                pbdata.refCount = pi.ci.refCount;

                                // Calculate inserter start and end positions from stored deltas and the building's rotation
                                pbdata.pos  = ___planetAux.Snap(entityBuilt.pos + entityBuilt.rot * pi.ci.posDelta, true, false);
                                pbdata.pos2 = ___planetAux.Snap(entityBuilt.pos + entityBuilt.rot * pi.ci.pos2Delta, true, false);
                                // Get inserter rotation relative to the building's
                                pbdata.rot  = entityBuilt.rot * pi.ci.rot;
                                pbdata.rot2 = entityBuilt.rot * pi.ci.rot2;

                                if (!pi.ci.incoming)
                                {
                                    CalculatePose(__instance, assemblerId, pi.otherId);
                                }
                                else
                                {
                                    CalculatePose(__instance, pi.otherId, assemblerId);
                                }
                                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)
                                    {
                                        if (__instance.posePairs[j].startSlot != pi.ci.startSlot || __instance.posePairs[j].endSlot != pi.ci.endSlot)
                                        {
                                            continue;
                                        }
                                        float startDistance = Vector3.Distance(__instance.posePairs[j].startPose.position, pbdata.pos);
                                        float endDistance   = Vector3.Distance(__instance.posePairs[j].endPose.position, pbdata.pos2);
                                        float poseDistance  = startDistance + endDistance;

                                        if (poseDistance < minDistance)
                                        {
                                            minDistance   = poseDistance;
                                            bestFit       = __instance.posePairs[j];
                                            hasNearbyPose = true;
                                        }
                                    }
                                    if (hasNearbyPose)
                                    {
                                        // if we were able to calculate a close enough sensible pose
                                        // use that instead of the (visually) ugly default

                                        pbdata.pos  = bestFit.startPose.position;
                                        pbdata.pos2 = bestFit.endPose.position;

                                        pbdata.rot  = bestFit.startPose.rotation;
                                        pbdata.rot2 = bestFit.endPose.rotation * Quaternion.Euler(0.0f, 180f, 0.0f);
                                    }
                                }

                                // Check the player has the item in inventory, no cheating here
                                var itemcount = pc.player.package.GetItemCount(pi.ci.protoId);
                                // If player has none; skip this request, as we dont create prebuild ghosts, must avoid confusion
                                if (itemcount > 0)
                                {
                                    var qty = 1;
                                    pc.player.package.TakeTailItems(ref pi.ci.protoId, ref qty);
                                    int pbCursor = factory.AddPrebuildData(pbdata); // Add the inserter request to Prebuild pool

                                    // Otherslot -1 will try to find one, otherwise could cache this from original assembler if it causes problems
                                    if (pi.ci.incoming)
                                    {
                                        factory.WriteObjectConn(-pbCursor, 0, true, assemblerId, -1); // assembler connection
                                        factory.WriteObjectConn(-pbCursor, 1, false, pi.otherId, -1); // other connection
                                    }
                                    else
                                    {
                                        factory.WriteObjectConn(-pbCursor, 0, false, assemblerId, -1); // assembler connection
                                        factory.WriteObjectConn(-pbCursor, 1, true, pi.otherId, -1);   // other connection
                                    }
                                }
                                pendingInserters.RemoveAt(i);
                            }
                        }
                    }
                }
            }
Ejemplo n.º 14
0
            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);
                        }
                    }
                }
            }