/// <summary>
        /// Deletes the given tile entity from it's chunk and creates a new one based on the tile entity type
        /// </summary>
        private void RecreateTileEntity([NotNull] TileEntity tileEntity)
        {
            var chunk = tileEntity.GetChunk();

            // Prevent further errors on client updates; crucial when removing power item!
            tileEntity.SetDisableModifiedCheck(true);

            // Remove corrupt tile entity
            chunk.RemoveTileEntity(World, tileEntity);

            // Remove power item
            var tePowered = tileEntity as TileEntityPowered;
            var powerItem = tePowered?.GetPowerItem();

            if (powerItem != null)
            {
                PowerManager.Instance.RemovePowerNode(powerItem);
            }

            // Create new tile entity
            var newTileEntity = TileEntity.Instantiate(tileEntity.GetTileEntityType(), chunk);

            newTileEntity.localChunkPos = tileEntity.localChunkPos;
            chunk.AddTileEntity(newTileEntity);

            // Recreate power item if necessary
            var newPowered = newTileEntity as TileEntityPowered;

            if (newPowered != null)
            {
                // Restore old PowerItemType and TriggerType values
                if (tePowered != null)
                {
                    newPowered.PowerItemType = tePowered.PowerItemType;
                }

                // fancy new C#7 syntax, isn't it? :)
                if (tileEntity is TileEntityPoweredTrigger teTrigger && newPowered is TileEntityPoweredTrigger newTrigger)
                {
                    newTrigger.TriggerType = teTrigger.TriggerType;
                }

                // Create power item according to PowerItemType and TriggerType
                newPowered.InitializePowerData();

                // Wires to the corrupt block are cut and not restored. We could try to reattach everything, but meh...
            }

            var newPowerItem = newPowered?.GetPowerItem();

            Log.Debug($"[{tileEntity.ToWorldPos()}] Replaced old {tileEntity.GetType()} with new {newTileEntity.GetType()}" +
                      $"{(newPowerItem != null ? " and new power item " + newPowerItem.GetType() : "")}.");
        }
Пример #2
0
        private static void LoadTileEntity(BinaryReader _br, [NotNull] TileEntity tileEntity, Vector3i posDelta)
        {
            // TileEntityPowered needs to be read manually because TileEntityPowered.read destroys wires
            // of the original position (where prefab originates) when it's loadedat new position.
            var tileEntityPowered = tileEntity as TileEntityPowered;

            if (tileEntityPowered != null)
            {
                LoadTileEntityPowered(_br, tileEntityPowered, posDelta);
            }
            else
            {
                tileEntity.read(_br, TileEntity.StreamModeRead.Persistency);

                // Adjust localChunkPos afterwards
                var localChunkPos = tileEntity.localChunkPos;
                localChunkPos            = World.toBlock(tileEntity.GetChunk().ToWorldPos(localChunkPos) + posDelta);
                tileEntity.localChunkPos = localChunkPos;
            }

            Log.Debug($"Loaded tile entity {tileEntity.ToStringBetter()}.");
        }
        /// <summary>
        /// Find/fix problems with TileEntityPowered objects and their PowerItems,
        /// which may caus NRE at TileEntityPoweredTrigger.write and other problems
        /// </summary>
        /// <param name="tileEntity">Tile entity to repair; currently only TileEntityPowered type is scanned/repaired</param>
        private void RepairTileEntity([NotNull] TileEntity tileEntity)
        {
            if (tileEntity is TileEntityPowered powered && !IsValidTileEntityPowered(powered))
            {
                _problemsFound++;

                if (!_simulate)
                {
                    RecreateTileEntity(tileEntity);
                }

                LogAndOutput($"{(_simulate ? "Found" : "Repaired")} corrupt power block at {tileEntity.ToWorldPos()} in {tileEntity.GetChunk()}.");
            }
        }