private void ConstructionCompleted(ConstructionCompletedEvent constructionCompleted) { GameObject constructing = NitroxEntity.RequireObjectFrom(constructionCompleted.PieceId); // For bases, we need to transfer the GUID off of the ghost and onto the finished piece. // Furniture just re-uses the same piece. if (constructing.TryGetComponent(out ConstructableBase constructableBase)) { Int3 latestCell = default(Int3); Base latestBase = null; // must fetch BEFORE setState or else the BaseGhost gets destroyed BaseGhost baseGhost = constructing.GetComponentInChildren <BaseGhost>(); if (baseGhost) { latestCell = baseGhost.TargetOffset; latestBase = baseGhost.TargetBase; } constructableBase.constructedAmount = 1f; constructableBase.SetState(true, true); if (!latestBase) { Optional <object> opConstructedBase = TransientLocalObjectManager.Get(TransientObjectType.BASE_GHOST_NEWLY_CONSTRUCTED_BASE_GAMEOBJECT); latestBase = ((GameObject)opConstructedBase.Value).GetComponent <Base>(); Validate.NotNull(latestBase, "latestBase can not be null"); } Transform cellTransform = latestBase.GetCellObject(latestCell); if (latestCell == default(Int3) || !cellTransform) { latestBase.GetClosestCell(constructing.gameObject.transform.position, out latestCell, out _, out _); cellTransform = latestBase.GetCellObject(latestCell); Validate.NotNull(cellTransform, $"Must have a cell transform, one not found near {constructing.gameObject.transform.position} for latestCell {latestCell}"); } GameObject finishedPiece = null; // There can be multiple objects in a cell (such as a corridor with hatches built into it) // we look for a object that is able to be deconstructed that hasn't been tagged yet. foreach (Transform child in cellTransform) { bool isNewBasePiece = !child.GetComponent <NitroxEntity>() && child.GetComponent <BaseDeconstructable>(); if (isNewBasePiece) { finishedPiece = child.gameObject; break; } } Validate.NotNull(finishedPiece, $"Could not find finished piece in cell {latestCell} when constructing {constructionCompleted.PieceId}"); Log.Debug($"Construction completed on a base piece: {constructionCompleted.PieceId} {finishedPiece.name}"); Destroy(constructableBase.gameObject); NitroxEntity.SetNewId(finishedPiece, constructionCompleted.PieceId); BasePieceSpawnProcessor.RunSpawnProcessor(finishedPiece.GetComponent <BaseDeconstructable>(), latestBase, latestCell, finishedPiece); } else if (constructing.TryGetComponent(out Constructable constructable)) { constructable.constructedAmount = 1f; constructable.SetState(true, true); FurnitureSpawnProcessor.RunSpawnProcessor(constructable); Log.Debug($"Construction completed on a piece of furniture: {constructionCompleted.PieceId} {constructable.gameObject.name}"); } else { Log.Error($"Found ghost which is neither base piece nor a constructable: {constructing.name}"); } if (constructionCompleted.BaseId != null && !NitroxEntity.GetObjectFrom(constructionCompleted.BaseId).HasValue) { Log.Debug($"Creating base: {constructionCompleted.BaseId}"); ConfigureNewlyConstructedBase(constructionCompleted.BaseId); } }
private void ConstructionCompleted(ConstructionCompletedEvent constructionCompleted) { GameObject constructing = NitroxEntity.RequireObjectFrom(constructionCompleted.PieceId); // For bases, we need to transfer the GUID off of the ghost and onto the finished piece. // Furniture just re-uses the same piece. if (constructing.TryGetComponent(out ConstructableBase constructableBase)) { Int3 latestCell = default; Base latestBase = null; // must fetch BEFORE setState as the BaseGhost gets destroyed BaseGhost baseGhost = constructableBase.model.AliveOrNull()?.GetComponent <BaseGhost>(); if (baseGhost && baseGhost.TargetBase) { latestBase = baseGhost.TargetBase; latestCell = latestBase.WorldToGrid(baseGhost.transform.position); } constructableBase.constructedAmount = 1f; constructableBase.SetState(true); Transform cellTransform; GameObject placedPiece = null; if (!latestBase) { Optional <object> opConstructedBase = Get(TransientObjectType.BASE_GHOST_NEWLY_CONSTRUCTED_BASE_GAMEOBJECT); if (opConstructedBase.HasValue) { latestBase = ((GameObject)opConstructedBase.Value).GetComponent <Base>(); } Validate.NotNull(latestBase, "latestBase can not be null"); latestCell = latestBase !.WorldToGrid(constructing.transform.position); } if (latestCell != default(Int3)) { cellTransform = latestBase.GetCellObject(latestCell); if (cellTransform) { placedPiece = FindFinishedPiece(cellTransform); } } if (!placedPiece) { Int3 position = latestBase.WorldToGrid(constructableBase.transform.position); cellTransform = latestBase.GetCellObject(position); Validate.NotNull(cellTransform, "Unable to find cell transform at " + position); placedPiece = FindFinishedPiece(cellTransform); } Validate.NotNull(placedPiece, $"Could not find placed Piece in cell {latestCell} when constructing {constructionCompleted.PieceId}"); // This destroy instruction must be executed now, else it won't be able to happen in the case the action will have a later completion Destroy(constructableBase.gameObject); if (BuildingInitialSyncProcessor.LaterConstructionTechTypes.Contains(constructableBase.techType)) { // We need to transfer these 3 objects to the later completed event Add(TransientObjectType.LATER_CONSTRUCTED_BASE, placedPiece); Add(TransientObjectType.LATER_OBJECT_LATEST_BASE, latestBase); Add(TransientObjectType.LATER_OBJECT_LATEST_CELL, latestCell); return; } FinishConstructionCompleted(placedPiece, latestBase, latestCell, constructionCompleted.PieceId); } else if (constructing.TryGetComponent(out Constructable constructable)) { constructable.constructedAmount = 1f; constructable.SetState(true); FurnitureSpawnProcessor.RunSpawnProcessor(constructable); } else { Log.Error($"Found ghost which is neither base piece nor a constructable: {constructing.name}"); } if (constructionCompleted.BaseId != null && !NitroxEntity.GetObjectFrom(constructionCompleted.BaseId).HasValue) { ConfigureNewlyConstructedBase(constructionCompleted.BaseId); } }
public void ConstructionComplete(GameObject ghost, Optional <Base> lastTargetBase, Int3 lastTargetBaseOffset) { NitroxId baseId = null; Optional <object> opConstructedBase = TransientLocalObjectManager.Get(TransientObjectType.BASE_GHOST_NEWLY_CONSTRUCTED_BASE_GAMEOBJECT); NitroxId id = NitroxEntity.GetId(ghost); Log.Info($"Construction complete on {id} {ghost.name}"); 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 = latestBase.GetCellObject(latestCell); // 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 authoratitive due to incorrect game object positioning. if (latestCell == default(Int3) || cellTransform == null) { latestBase.GetClosestCell(ghost.transform.position, out latestCell, out Vector3 _, out float _); cellTransform = latestBase.GetCellObject(latestCell); Validate.NotNull(cellTransform, "Unable to find cell transform at " + latestCell); } GameObject finishedPiece = null; // There can be multiple objects in a cell (such as a corridor with hatches built into it) // we look for a object that is able to be deconstructed that hasn't been tagged yet. foreach (Transform child in cellTransform) { bool isNewBasePiece = !child.GetComponent <NitroxEntity>() && child.GetComponent <BaseDeconstructable>(); if (isNewBasePiece) { finishedPiece = child.gameObject; break; } } Validate.NotNull(finishedPiece, $"Could not find finished piece in cell {latestCell}"); Log.Info($"Setting id to finished piece: {finishedPiece.name} {id}"); Object.Destroy(ghost); NitroxEntity.SetNewId(finishedPiece, id); BasePieceSpawnProcessor.RunSpawnProcessor(finishedPiece.GetComponent <BaseDeconstructable>(), latestBase, latestCell, finishedPiece); } 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}"); } Log.Info($"Construction Completed {id} in base {baseId}"); ConstructionCompleted constructionCompleted = new ConstructionCompleted(id, baseId); packetSender.Send(constructionCompleted); }
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); }