/** * 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); }
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); }
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)); }
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)); }
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); }
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"); } }
public static void Put(this NetDataWriter writer, Base.Face face) { writer.Put((byte)face.direction); writer.Put(face.cell); }
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); }
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); }