#if UNITY_EDITOR using System.Collections.Generic; using BlockOutReplica.Domain; using BlockOutReplica.Infrastructure; using UnityEngine; namespace BlockOutReplica.Gameplay { public sealed partial class BlockOutGameController { public bool IsFirstTwentyPreview { get; private set; } public void BeginFirstTwentyPreview() { if (IsFullLoopSandbox) RestoreFullLoopSandbox(); BeginFullLoopSandbox(); var ids = new List(); for (int i=0;i<20;i++) ids.Add(OriginalLevelSettings.All[i].seedId); progress = new BlockOutProgress(new BlockOutFlowDefinition(ids,4,10),false,1); economy = BlockOutEconomy.Load(); player = new BlockOutPlayerState(economy,"",_=>{}); journey = new BlockOutJourney(BlockOutJourneyConfig.Load(),"",_=>{}); IsFirstTwentyPreview = true; InitializeInteractions(); LoadCurrentLevel(); Debug.Log("BLOCKOUT_FIRST20_PREVIEW: started, level=1, isolatedSaves=True, sourceDurations=True"); } public void SelectFirstTwentyPreviewLevel(int number) { if(!IsFirstTwentyPreview) BeginFirstTwentyPreview(); progress.MoveBy(Mathf.Clamp(number,1,20)-LevelNumber); LoadCurrentLevel(); } public System.Collections.IEnumerator ReviewFirstTwentyPreview() { int savedLevel=PlayerPrefs.GetInt("BlockOutReplica.PlayerLevel.v2",1); string savedWallet=PlayerPrefs.GetString("BlockOutReplica.PlayerState.v1",""); string savedJourney=PlayerPrefs.GetString("BlockOutReplica.Journey.v1",""); BeginFirstTwentyPreview(); int checks=0; try { for(int n=1;n<=20;n++) { SelectFirstTwentyPreviewLevel(n); yield return null; if(CurrentLevelId!=$"t238-level-{n}"||TimeLeft!=OriginalLevelSettings.All[n-1].levelDuration) throw new System.InvalidOperationException("Wrong loaded level/time at "+n); if(pieces.Count!=level.Pieces.Count||doors.Count!=level.Doors.Count) throw new System.InvalidOperationException("Missing live views at "+n); foreach(var piece in pieces) { if(!movementRules.IsAllowed(piece,piece.transform.position,pieces)) throw new System.InvalidOperationException($"Illegal initial pose: level {n}, {piece.name}"); foreach(var renderer in piece.GetComponentsInChildren()) foreach(var material in renderer.sharedMaterials) if(material!=null&&(material.shader==null||!material.shader.isSupported||material.shader.name=="Hidden/InternalErrorShader")) throw new System.InvalidOperationException($"Unsupported piece material: level {n}, {renderer.name}"); } checks+=3; if(n==6||n==10||n==15||n==17||n==19||n==20) { ScreenCapture.CaptureScreenshot($"Docs/iterations/2026-10-20-first20-level-{n}.png"); yield return null; } } if(PlayerPrefs.GetInt("BlockOutReplica.PlayerLevel.v2",1)!=savedLevel||PlayerPrefs.GetString("BlockOutReplica.PlayerState.v1","")!=savedWallet||PlayerPrefs.GetString("BlockOutReplica.Journey.v1","")!=savedJourney) throw new System.InvalidOperationException("Preview modified formal saves"); Debug.Log($"BLOCKOUT_FIRST20_RUNTIME: passed=True, checks={checks+1}, allLevelsInstantiated=True, initialPosesLegal=True, persistentSavesUntouched=True, manuallyWonAll=False"); } finally { SelectFirstTwentyPreviewLevel(1); } } } } #endif