/**
         * This function is called directly after spawning a new BasePiece to add BaseDeconstructable.
         * If we are in the middle of a geometry rebuild, we want to make sure the object keeps its id.
         */
        public static void Postfix(Transform geometry, Base.Face face)
        {
            if (!geometry || !geometry.gameObject)
            {
                return;
            }

            Resolve <GeometryRespawnManager>().BaseFaceRespawned(geometry.gameObject, face.cell, face.direction);
        }
            [HarmonyPrefix] // We're attempting to replace the geometry building method
            public static bool Prefix(ref Base __instance, Int3 cell)
            {
                Int3 v = Base.CellSize[7];

                Int3.Bounds         bounds = new Int3.Bounds(cell, cell + v - 1);
                BaseDeconstructable parent = null;

                if (__instance.GetCellMask(cell))
                {
                    Transform transform = __instance.SpawnPiece(Base.Piece.Moonpool, cell);
                    parent        = BaseDeconstructable.MakeCellDeconstructable(transform, bounds, TechType.BaseMoonpool);
                    transform.tag = "MainPieceGeometry";
                }
                for (int i = 0; i < Base.moonpoolFaces.Length; i++)
                {
                    Base.RoomFace roomFace = Base.moonpoolFaces[i];
                    Base.Face     face     = new Base.Face(cell + roomFace.offset, roomFace.direction);
                    if (__instance.GetFaceMask(face))
                    {
                        Base.FaceType face2         = __instance.GetFace(face);
                        Base.Piece    moonpoolPiece = __instance.GetMoonpoolPiece(face, face2);
                        if (moonpoolPiece != Base.Piece.Invalid)
                        {
                            Transform transform2 = __instance.SpawnPiece(moonpoolPiece, cell, roomFace.rotation, null);
                            transform2.localPosition = Int3.Scale(roomFace.offset, Base.cellSize) + roomFace.localOffset;
                            if (face2 != Base.FaceType.Solid)
                            {
                                TechType            recipe = Base.FaceToRecipe[(int)face2];
                                BaseDeconstructable baseDeconstructable = BaseDeconstructable.MakeFaceDeconstructable(transform2, bounds, face, face2, recipe);
                                if (!__instance.isGhost)
                                {
                                    transform2.GetComponentsInChildren <IBaseModuleGeometry>(true, Base.sBaseModulesGeometry);
                                    int j     = 0;
                                    int count = Base.sBaseModulesGeometry.Count;
                                    while (j < count)
                                    {
                                        IBaseModuleGeometry baseModuleGeometry = Base.sBaseModulesGeometry[j];
                                        baseModuleGeometry.geometryFace = face;
                                        j++;
                                    }
                                    Base.sBaseModulesGeometry.Clear();
                                    if (face2 == Base.FaceType.UpgradeConsole)
                                    {
                                        baseDeconstructable.LinkModule(new Base.Face?(new Base.Face(face.cell - __instance.anchor, face.direction)));
                                    }
                                }
                            }
                            else if (!__instance.isGhost)
                            {
                                BaseExplicitFace.MakeFaceDeconstructable(transform2, face, parent);
                            }
                        }
                    }
                }
                return(false);
            }
Beispiel #3
0
        private string getObjectKey(GameObject gameObject)
        {
            BaseDeconstructable deconstructable = gameObject.GetComponentInChildren <BaseDeconstructable>();

            Int3 faceCell = default(Int3);

            Base.Direction?faceDirection = null;

            if (deconstructable && deconstructable.face.HasValue)
            {
                Base.Face face = deconstructable.face.Value;
                faceCell      = face.cell;
                faceDirection = face.direction;
            }

            return(getObjectKey(gameObject.name, gameObject.transform.position, faceCell, faceDirection));
        }
        public static bool Prefix(ref Base.Face __result, Base.Face face)
        {
            if (MultiplayerBuilder.RotationMetadata.HasValue)
            {
                switch (MultiplayerBuilder.RotationMetadata.Value)
                {
                case AnchoredFaceBuilderMetadata anchoredFaceRotationMetadata:
                    __result = new Base.Face(anchoredFaceRotationMetadata.Cell.ToUnity(), (Base.Direction)anchoredFaceRotationMetadata.Direction);
                    return(false);

                case BaseModuleBuilderMetadata baseModuleRotationMetadata:
                    __result = new Base.Face(baseModuleRotationMetadata.Cell.ToUnity(), (Base.Direction)baseModuleRotationMetadata.Direction);
                    return(false);
                }
            }

            return(true);
        }
Beispiel #5
0
        public Optional <BuilderMetadata> From(object baseGhost)
        {
            BuilderMetadata builderMetadata = null;

            switch (baseGhost)
            {
            case BaseAddCorridorGhost corridorGhost:
            {
                int     rotation      = corridorGhost.rotation;
                Vector3 position      = corridorGhost.GetComponentInParent <ConstructableBase>().transform.position;
                bool    hasTargetBase = corridorGhost.targetBase != null;
                Int3    targetCell    = hasTargetBase ? corridorGhost.targetBase.WorldToGrid(position): default;
                builderMetadata = new CorridorBuilderMetadata(position.ToDto(), rotation, hasTargetBase, targetCell.ToDto());
                break;
            }

            case BaseAddMapRoomGhost mapRoomGhost:
            {
                Base.CellType cellType       = mapRoomGhost.cellType;
                int           connectionMask = mapRoomGhost.connectionMask;
                builderMetadata = new MapRoomBuilderMetadata((byte)cellType, connectionMask);
                break;
            }

            case BaseAddModuleGhost module:
            {
                Int3 cell      = module.anchoredFace !.Value.cell;
                int  direction = (int)module.anchoredFace.Value.direction;

                builderMetadata = new BaseModuleBuilderMetadata(cell.ToDto(), direction);
                break;
            }

            case BaseAddFaceGhost faceGhost:
            {
                Base.Face anchoredFace = faceGhost.anchoredFace !.Value;
                builderMetadata = new AnchoredFaceBuilderMetadata(anchoredFace.cell.ToDto(), (int)anchoredFace.direction, (int)faceGhost.faceType);
                break;
            }
            }

            return(Optional.OfNullable(builderMetadata));
        }
Beispiel #6
0
        public Optional <RotationMetadata> From(object baseGhost)
        {
            RotationMetadata rotationMetadata = null;

            if (baseGhost is BaseAddCorridorGhost)
            {
                BaseAddCorridorGhost corridorGhost = baseGhost as BaseAddCorridorGhost;
                int rotation = (int)corridorGhost.ReflectionGet("rotation");
                rotationMetadata = new CorridorRotationMetadata(rotation);
            }
            else if (baseGhost is BaseAddMapRoomGhost)
            {
                BaseAddMapRoomGhost mapRoomGhost = baseGhost as BaseAddMapRoomGhost;
                Base.CellType       cellType     = (Base.CellType)mapRoomGhost.ReflectionGet("cellType");
                int connectionMask = (int)mapRoomGhost.ReflectionGet("connectionMask");
                rotationMetadata = new MapRoomRotationMetadata((byte)cellType, connectionMask);
            }
            else if (baseGhost is BaseAddModuleGhost)
            {
                BaseAddModuleGhost module = baseGhost as BaseAddModuleGhost;

                Int3 cell      = module.anchoredFace.Value.cell;
                int  direction = (int)module.anchoredFace.Value.direction;

                rotationMetadata = new BaseModuleRotationMetadata(cell, direction);
            }
            else if (baseGhost is BaseAddFaceGhost)
            {
                BaseAddFaceGhost faceGhost = baseGhost as BaseAddFaceGhost;

                if (faceGhost.anchoredFace.HasValue)
                {
                    Base.Face anchoredFace = faceGhost.anchoredFace.Value;

                    rotationMetadata = new AnchoredFaceRotationMetadata(anchoredFace.cell, (int)anchoredFace.direction, (int)faceGhost.faceType);
                }
            }

            return(Optional.OfNullable(rotationMetadata));
        }
Beispiel #7
0
        public static bool Prefix(Constructable __instance)
        {
            if (__instance.constructed)
            {
                return(true);
            }

            // If we are constructing a base piece then we'll want to store all of the BaseGhost information
            // as it will not be available when the construction hits 100%
            if (__instance is ConstructableBase constructableBase)
            {
                BaseGhost baseGhost = constructableBase.gameObject.GetComponentInChildren <BaseGhost>();
                if (baseGhost != null)
                {
                    lastTargetBase       = baseGhost.TargetBase;
                    lastTargetBaseOffset = baseGhost.TargetOffset;
                }

                lastFace = baseGhost switch
                {
                    BaseAddFaceGhost {
                        anchoredFace : { }
                    } baseAddFaceGhost => baseAddFaceGhost.anchoredFace.Value,
                    BaseAddModuleGhost {
                        anchoredFace : { }
                    } baseAddModuleGhost => baseAddModuleGhost.anchoredFace.Value,
                    _ => lastFace
                };
            }
            else
            {
                lastTargetBase       = null;
                lastTargetBaseOffset = default(Int3);
            }

            return(true);
        }
Beispiel #8
0
        private static void ApplyRotationMetadata(GameObject ghostModel, RotationMetadata rotationMetadata)
        {
            BaseGhost component = ghostModel.GetComponent <BaseGhost>();

            if (component == null)
            {
                Log.Error("Was unable to apply rotation metadata - no BaseGhost found");
            }
            else if (component.GetType() != rotationMetadata.GhostType)
            {
                Log.Error("Was unable to apply rotation metadata - " + component.GetType() + " did not match " + rotationMetadata.GhostType);
            }
            else if (component is BaseAddCorridorGhost)
            {
                Log.Info("Placing BaseAddCorridorGhost Rotation Metadata");

                CorridorRotationMetadata corridorRotationMetadata = (rotationMetadata as CorridorRotationMetadata);
                BaseAddCorridorGhost     corridor = (component as BaseAddCorridorGhost);
                corridor.ReflectionSet("rotation", corridorRotationMetadata.Rotation);

                int  corridorType = (int)corridor.ReflectionCall("CalculateCorridorType");
                Base ghostBase    = (Base)corridor.ReflectionGet("ghostBase");
                ghostBase.SetCorridor(Int3.zero, corridorType, corridor.isGlass);
                corridor.ReflectionCall("RebuildGhostGeometry");
            }
            else if (component is BaseAddMapRoomGhost)
            {
                Log.Info("Placing MapRoomRotationMetadata Rotation Metadata");

                MapRoomRotationMetadata mapRoomRotationMetadata = (rotationMetadata as MapRoomRotationMetadata);
                BaseAddMapRoomGhost     mapRoom = (component as BaseAddMapRoomGhost);
                mapRoom.ReflectionSet("cellType", mapRoomRotationMetadata.CellType);
                mapRoom.ReflectionSet("connectionMask", mapRoomRotationMetadata.ConnectionMask);

                Base ghostBase = (Base)mapRoom.ReflectionGet("ghostBase");

                ghostBase.SetCell(Int3.zero, (Base.CellType)mapRoomRotationMetadata.CellType);
                mapRoom.ReflectionCall("RebuildGhostGeometry");
            }
            else if (component is BaseAddModuleGhost)
            {
                BaseModuleRotationMetadata baseModuleRotationMetadata = (rotationMetadata as BaseModuleRotationMetadata);
                BaseAddModuleGhost         module = (component as BaseAddModuleGhost);

                module.anchoredFace = new Base.Face(baseModuleRotationMetadata.Cell.ToUnity(), (Base.Direction)baseModuleRotationMetadata.Direction);
                module.ReflectionCall("RebuildGhostGeometry");
            }
            else if (component is BaseAddFaceGhost)
            {
                AnchoredFaceRotationMetadata baseModuleRotationMetadata = (rotationMetadata as AnchoredFaceRotationMetadata);
                BaseAddFaceGhost             faceGhost = (component as BaseAddFaceGhost);
                Log.Info("Applying BaseAddFaceGhost " + baseModuleRotationMetadata);


                Base.Face face = new Base.Face(baseModuleRotationMetadata.Cell.ToUnity(), (Base.Direction)baseModuleRotationMetadata.Direction);
                faceGhost.anchoredFace = face;

                Base          ghostBase = (Base)faceGhost.ReflectionGet("ghostBase");
                Base.FaceType faceType  = (Base.FaceType)baseModuleRotationMetadata.FaceType;
                ghostBase.SetFace(face, faceType);

                faceGhost.ReflectionCall("RebuildGhostGeometry");
            }
        }
Beispiel #9
0
 public static void Put(this NetDataWriter writer, Base.Face face)
 {
     writer.Put((byte)face.direction);
     writer.Put(face.cell);
 }
Beispiel #10
0
        private static BaseDeconstructable FindBaseDeconstructable(string guid, string baseGuid, Base.FaceType faceType, Base.Face face, Int3.Bounds bounds)
        {
            var baseObject = GuidHelper.Find(baseGuid);

            if (baseObject != null)
            {
                foreach (var item in baseObject.GetAllComponentsInChildren <BaseDeconstructable>())
                {
                    if (item.faceType != faceType)
                    {
                        continue;
                    }

                    if (item.bounds != bounds)
                    {
                        continue;
                    }

                    if (item.face.GetValueOrDefault() != face)
                    {
                        continue;
                    }

                    GuidHelper.Set(item.gameObject, guid);
                    return(item);
                }
            }

            if (string.IsNullOrEmpty(guid) == false)
            {
                Log.Warn("Couldn't find base deconstructable: " + guid);
            }

            return(null);
        }
Beispiel #11
0
        public void ConstructionComplete(GameObject ghost, Optional <Base> lastTargetBase, Int3 lastTargetBaseOffset, Base.Face lastTargetFace = default(Base.Face))
        {
            NitroxId          baseId            = null;
            Optional <object> opConstructedBase = TransientLocalObjectManager.Get(TransientObjectType.BASE_GHOST_NEWLY_CONSTRUCTED_BASE_GAMEOBJECT);

            NitroxId id = NitroxEntity.GetId(ghost);

            if (opConstructedBase.HasValue)
            {
                GameObject constructedBase = (GameObject)opConstructedBase.Value;
                baseId = NitroxEntity.GetId(constructedBase);
            }

            // For base pieces, we must switch the id from the ghost to the newly constructed piece.
            // Furniture just uses the same game object as the ghost for the final product.
            if (ghost.GetComponent <ConstructableBase>())
            {
                Int3 latestCell = lastTargetBaseOffset;
                Base latestBase = lastTargetBase.HasValue ? lastTargetBase.Value : ((GameObject)opConstructedBase.Value).GetComponent <Base>();
                baseId = NitroxEntity.GetId(latestBase.gameObject);

                Transform  cellTransform;
                GameObject placedPiece = null;

                if (!latestBase)
                {
                    if (opConstructedBase.HasValue)
                    {
                        latestBase = ((GameObject)opConstructedBase.Value).GetComponent <Base>();
                    }

                    Validate.NotNull(latestBase, "latestBase can not be null");
                    latestCell = latestBase.WorldToGrid(ghost.transform.position);
                }

                if (latestCell != default(Int3))
                {
                    cellTransform = latestBase.GetCellObject(latestCell);
                    if (cellTransform != null)
                    {
                        placedPiece = FindFinishedPiece(cellTransform);
                    }
                }

                // This check ensures that the latestCell actually leads us to the correct entity.  The lastTargetBaseOffset is unreliable as the base shape
                // can change which makes the target offset change. It may be possible to fully deprecate lastTargetBaseOffset and only rely on GetClosestCell;
                // however, there may still be pieces were the ghost base's target offset is authoritative due to incorrect game object positioning.
                if (placedPiece == null)
                {
                    Int3 position = latestBase.WorldToGrid(ghost.gameObject.transform.position);
                    cellTransform = latestBase.GetCellObject(position);

                    Validate.NotNull(cellTransform, "Unable to find cell transform at " + latestCell);
                    placedPiece = FindFinishedPiece(cellTransform);
                }

                Validate.NotNull(placedPiece, $"Could not find finished piece in cell {latestCell}");

                Object.Destroy(ghost);
                NitroxEntity.SetNewId(placedPiece, id);

                BasePieceSpawnProcessor.RunSpawnProcessor(placedPiece.GetComponent <BaseDeconstructable>(), latestBase, latestCell, placedPiece);
            }
            else if (ghost.TryGetComponent(out Constructable constructable))
            {
                FurnitureSpawnProcessor.RunSpawnProcessor(constructable);
            }
            else
            {
                Log.Error($"Found ghost which is neither base piece nor a constructable: {ghost.name}");
            }

            ConstructionCompleted constructionCompleted = new ConstructionCompleted(id, baseId);

            packetSender.Send(constructionCompleted);
        }