/// <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() : "")}."); }
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()}."); } }