public void ReadAll() { CustomPostprocessor.DoImports = false; try { BinaryReader reader = new BinaryReader(new MemoryStream(data)); reader.SkipBytes(16); reader.SkipBytes(12); Archive arc = null; while (reader.BaseStream.Position <= 90000) { short entryType = reader.ReadInt16(); short subType = reader.ReadInt16(); short entryCount = reader.ReadInt16(); short entryIndex = reader.ReadInt16(); string name = reader.ReadNullTerminatedString(); if (reader.PeekChar() == 0) { reader.SkipByte(); } if (entryType == 2) { arc = new Archive(name, AssetDatabase.LoadAssetAtPath("Assets/SilentHill3/Archives/" + name + ".arc", typeof(UnityEngine.Object))); arc.OpenArchive(); } if (entryType == 3) { try { name = name.Replace("tmp", arc.NameAsPath()); string path = "Assets/SilentHill3/Resources/" + name; path = Path.GetDirectoryName(path); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.WriteAllBytes("Assets/SilentHill3/Resources/" + name, arc.AllFiles[entryCount].data); } catch (Exception) { Debug.LogError("Problem at " + name + " [" + entryIndex + "](" + arc.AllFiles.Count + ") sub " + subType.ToString("X")); } } } AssetDatabase.Refresh(); } catch (Exception e) { Debug.LogException(e); } CustomPostprocessor.DoImports = true; }
public static Texture2D[] ReadTex32(string baseName, BinaryReader reader) { reader.SkipBytes(12); //Skips -1 0 32 /*int texGroupLength = */reader.ReadInt32(); reader.SkipBytes(4); //Skips 0 int texCount = reader.ReadInt32(); reader.SkipBytes(8); //Skips 0 0 List<Texture2D> textures = new List<Texture2D>(texCount); for (int i = 0; i != texCount; i++) { reader.SkipBytes(8); //Skips -1 0 short width = reader.ReadInt16(); short height = reader.ReadInt16(); byte bits = reader.ReadByte(); byte buffer = reader.ReadByte(); reader.SkipBytes(2); //skips 0x0000 int lengthOfTex = reader.ReadInt32(); /*int nextDataRelativeOffset = */reader.ReadInt32(); reader.SkipBytes(24 + buffer); //skips -1 0 0 0 0 0 + buffer Color32[] _pixels = null; if (bits == 32) { _pixels = new Color32[lengthOfTex / 4]; for (int j = 0; j != lengthOfTex / 4; j++) { _pixels[j] = reader.ReadBGRA(); } } else if (bits == 16) { _pixels = new Color32[lengthOfTex / 2]; for (int j = 0; j != lengthOfTex / 2; j ++) { _pixels[j] = reader.ReadRGBA5551(); } } Texture2D text = new Texture2D(width, height, TextureFormat.RGBA32, false); text.SetPixels32(_pixels); text.Apply(); text.alphaIsTransparency = true; text.name = baseName + i; textures.Add(text); } return textures.ToArray(); }
public static int Deserialise(BinaryReader reader, GameObject parent) { GameObject go = new GameObject("Mesh Group"); go.isStatic = true; MeshGroup group = go.AddComponent<MeshGroup>(); go.transform.SetParent(parent.transform); int NextOffset = reader.ReadInt32(); reader.SkipInt32(48); reader.SkipInt32(); // Length reader.SkipInt32(0); group.TextureGroup = reader.ReadInt32(); group.TextureIndex = reader.ReadInt32(); group.Unknown1 = reader.ReadInt32(); reader.SkipInt32(0); reader.SkipBytes(16, 0); int next; do { next = SubMeshGroup.Deserialise(reader, go); } while (next != 0); return NextOffset; }
public int MeshFlags; // 60 is normal, 124 is decal public static int Deserialise(BinaryReader reader, GameObject parent) { GameObject go = new GameObject("Mesh Part"); MeshPart part = go.AddComponent<MeshPart>(); part.transform.SetParent(parent.transform); long offset = reader.BaseStream.Position; int NextOffset = reader.ReadInt32(); reader.SkipInt32(64); reader.SkipInt32();//Length reader.SkipInt32(0); int VertexCount = reader.ReadInt32(); part.ObjectType = reader.ReadInt32(); //1 = static, 2 = can be or not there, 3 = can move int val = reader.ReadInt32(); part.OcclusionGroup = "0x" + val.ToString("X") + " 0b" + Convert.ToString(val, 2); part.MeshFlags = reader.ReadInt32(); reader.SkipBytes(32, 0); go.isStatic = part.ObjectType != 3; Matrix4x4 matrix = part.GetComponentInParent<Scene>().GetSH3ToUnityMatrix(); List<Vector3> _verts = new List<Vector3>(); List<Vector3> _norms = new List<Vector3>(); List<Vector2> _uvs = new List<Vector2>(); List<Color32> _colors = new List<Color32>(); for (int i = 0; i != VertexCount; i++) { Vector3 temp = reader.ReadVector3(); temp.y = -temp.y; _verts.Add(matrix.MultiplyPoint(temp)); temp = reader.ReadVector3(); temp.x = -temp.x; temp.z = -temp.z; _norms.Add(temp); _uvs.Add(reader.ReadVector2()); _colors.Add(reader.ReadBGRA()); } Mesh mesh = MeshUtils.MakeStripped(_verts, _norms, _uvs, _colors); mesh.name = "mesh_" + offset; go.AddComponent<MeshFilter>().sharedMesh = mesh; go.AddComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; return NextOffset; }
public static MapShadows ReadShadowCasters(string path) { string assetPath = path.Replace(".kg2", ".asset"); GameObject subGO = Scene.BeginEditingPrefab(path, "Shadows"); try { MapShadows casters = subGO.AddComponent<MapShadows>(); BinaryReader reader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)); if (reader.BaseStream.Length != 0) { //Master header reader.SkipInt32(); short casterCount = reader.ReadInt16(); reader.SkipBytes(10, 0); Matrix4x4 transMat = casters.GetComponentInParent<Scene>().GetSH3ToUnityMatrix(); //Reading casters for (int i = 0; i != casterCount; i++) { //Caster header reader.SkipInt32(0); /*short index = */reader.ReadInt16(); short shapeCounts = reader.ReadInt16(); reader.SkipBytes(16, 0); /*Vector3 mainPivot = */reader.ReadShortVector3(); /*short casterGroup = */reader.ReadInt16(); Matrix4x4 mainMatrix = reader.ReadMatrix4x4(); Vector3 debugPosition = Matrix4x4Utils.ExtractTranslationFromMatrix(ref mainMatrix); debugPosition.y = -debugPosition.y; Vector3 currentNormal = Vector3.zero; //reading shapes for (int j = 0; j != shapeCounts; j++) { short countOfPoints = reader.ReadInt16(); short UnknownS1 = reader.ReadInt16(); /*short UnknownS2 = */reader.ReadInt16(); reader.SkipInt16(countOfPoints); /*Vector3 pivot = */reader.ReadShortVector3(); short shapeGroup = reader.ReadInt16(); List<Vector3> _verts = new List<Vector3>(); List<Vector3> _norms = new List<Vector3>(); for (int k = 0; k != countOfPoints; ) { Vector3 v = reader.ReadShortVector3(); short flag = reader.ReadInt16(); if (flag == 0) { currentNormal = Vector3.Normalize(v); } else { _verts.Add(transMat.MultiplyPoint(v + debugPosition)); _norms.Add(currentNormal); k++; } } Mesh mesh = null; if (UnknownS1 == 6) { mesh = MeshUtils.MakeStripped(_verts, _norms, null, null, true); } else if (UnknownS1 == 5) { mesh = MeshUtils.MakeStrippedInverted(_verts, _norms); } else { mesh = MeshUtils.MakeSquare(_verts, _norms, null, null, true); } mesh.name = "shadowMesh_" + shapeGroup; GameObject go = new GameObject("Shadow mesh"); go.transform.SetParent(subGO.transform); go.AddComponent<MeshFilter>().sharedMesh = mesh; MeshRenderer mr = go.AddComponent<MeshRenderer>(); mr.sharedMaterial = MaterialRolodex.defaultDiffuse; mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; if (reader.BaseStream.Position % 16 != 0) { reader.SkipBytes(8, 0); } } } } reader.Close(); foreach (MeshFilter mf in subGO.GetComponentsInChildren<MeshFilter>()) { AssetDatabase.AddObjectToAsset(mf.sharedMesh, assetPath); } Scene.FinishEditingPrefab(path, subGO); return casters; } catch (Exception e) { Debug.LogException(e); } return null; }
public static MapLights ReadLights(string path) { /*string assetPath = path.Replace(".ded", ".asset");*/ GameObject subGO = Scene.BeginEditingPrefab(path, "Lights"); try { MapLights lights = subGO.AddComponent<MapLights>(); BinaryReader reader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)); reader.SkipInt16(); //Usually the area's code reader.SkipInt16(); //Usually 1, saw a 20 short globalLightsCount = reader.ReadInt16(); reader.SkipInt16(0); short globalLightsOffset = reader.ReadInt16(); reader.SkipInt16(0); reader.SkipBytes(8, 0); short weirdLightsCount = reader.ReadInt16(); reader.SkipInt16(0); short weirdLightsOffset = reader.ReadInt16(); reader.SkipInt16(0); reader.SkipBytes(8, 0); short lightsCount = reader.ReadInt16(); reader.SkipInt16(0); short lightsOffset = reader.ReadInt16(); reader.SkipInt16(0); reader.SkipBytes(40, 0); short ambientOffset = reader.ReadInt16(); reader.SkipBytes(24, 0); Matrix4x4 transMat = lights.GetComponentInParent<Scene>().GetSH3ToUnityMatrix(); reader.BaseStream.Position = globalLightsOffset; for (int i = 0; i != globalLightsCount; i++) { GlobalLight gl = new GlobalLight(); gl.rotation = reader.ReadQuaternion(); gl.Unknown1 = reader.ReadVector3(); reader.SkipInt16(0); gl.Unknown2 = reader.ReadInt16(); lights.globalLights.Add(gl); } reader.BaseStream.Position = weirdLightsOffset; for (int i = 0; i != weirdLightsCount; i++) { LocalLight ll = new LocalLight(); ll.color = reader.ReadColor(); ll.Unknown1 = reader.ReadSingle(); ll.Range = reader.ReadSingle(); reader.SkipBytes(8, 0); ll.position = reader.ReadVector3YInverted(); reader.SkipInt16(0x0); ll.Unknown2 = reader.ReadInt16(); lights.weirdLights.Add(ll); } reader.BaseStream.Position = lightsOffset; for (int i = 0; i != lightsCount; i++) { LocalLight ll = new LocalLight(); ll.color = reader.ReadColor(); ll.Unknown1 = reader.ReadSingle(); ll.Range = reader.ReadSingle(); reader.SkipBytes(8, 0); ll.position = reader.ReadVector3YInverted(); reader.SkipInt16(0x0); ll.Unknown2 = reader.ReadInt16(); lights.localLights.Add(ll); GameObject lightGO = new GameObject("Light " + i); lightGO.transform.SetParent(subGO.transform); lightGO.transform.localPosition = transMat.MultiplyPoint(ll.position); Light light = lightGO.AddComponent<Light>(); light.type = LightType.Point; light.range = ll.Range * Scene.GLOBAL_SCALE; light.color = ll.color; light.intensity = 8.0f; light.bounceIntensity = 1.0f; } reader.BaseStream.Position = ambientOffset; lights.Unknown1 = reader.ReadVector4(); lights.Unknown2 = reader.ReadVector4(); lights.ambientColor = reader.ReadColor(); lights.Unknown3 = reader.ReadVector4(); reader.Close(); Scene.FinishEditingPrefab(path, subGO); return lights; } catch (Exception e) { Debug.LogException(e); } return null; }
public static Texture2D[] ReadDDS(string baseName, BinaryReader reader) { reader.SkipInt32(2); int texturesSize = reader.ReadInt32(); reader.SkipInt32(0); reader.SkipInt32(0); reader.SkipInt32(0x19990901); //magic reader.SkipInt32(0); reader.SkipInt32(0); reader.SkipInt32(1); List<Texture2D> textures = new List<Texture2D>(); int i = 0; while (reader.BaseStream.Position < texturesSize) { short textureID = reader.ReadInt16(); reader.SkipInt16(0); short width = reader.ReadInt16(); short height = reader.ReadInt16(); reader.SkipInt16(512); reader.SkipInt16(512); int subgroupsCount = reader.ReadInt32(); //1 more? reader.SkipInt16(); reader.SkipInt16(); reader.SkipBytes(12); //Skips 0 0 0 int texLength = 0; for (int j = 0; j != subgroupsCount; j++) { //Subgroup thingie /*short subgroupID = */ reader.SkipInt16(); reader.SkipInt16(); reader.SkipInt16(0); reader.SkipInt16(0); reader.SkipInt16(512); reader.SkipInt16(512); reader.SkipInt16(256); reader.SkipInt16(0); texLength = reader.ReadInt32(); /*int texAndHeaderLength = */ reader.SkipInt32(); reader.SkipInt32(0); reader.SkipUInt32(0x99000000); } Texture2D text = new Texture2D(width, height, TextureFormat.DXT1, false); text.LoadRawTextureData(reader.ReadBytes(texLength)); text.Apply(); text.alphaIsTransparency = true; text.name = baseName + textureID.ToString("0000"); textures.Add(text); i++; } reader.SkipBytes(0x10); return textures.ToArray(); }
public CollisionPane(BinaryReader reader, Matrix4x4 transMat) { type = reader.ReadInt32(); int vectorsToRead = reader.ReadInt32(); //Not neccessarely group = reader.ReadInt32(); //More like group reader.SkipInt32(0); if (type == 769) { Vector3 vertex = reader.ReadVector3YInverted(); vectors = new Vector3[] { transMat.MultiplyPoint(vertex) }; reader.SkipSingle(1.0f); offset = transMat.MultiplyPoint(reader.ReadVector3YInverted()); radius = reader.ReadSingle() * Scene.GLOBAL_SCALE; } else if (type == 257 || type == 1) { List<Vector3> v3s = new List<Vector3>(); for (int i = 0; i != vectorsToRead; i++) { if (type == 1 && i != 0 && i % 3 == 0) { reader.SkipBytes(16); continue; } Vector3 vertex = reader.ReadVector3YInverted(); v3s.Add(transMat.MultiplyPoint(vertex)); reader.SkipSingle(1.0f); } vectors = v3s.ToArray(); offset = Vector3.zero; radius = 0.0f; } else { Debug.LogWarning("UNHANDLED COLLIDER TYPE " + type + " FIX IT"); } }
static void ReadSH2Map(BinaryReader reader, Map scene, string path) { GameObject subGO = scene.gameObject; string assetPath = path.Replace(".map", ".asset"); int fileID = reader.ReadInt32(); int fileSize = reader.ReadInt32(); int Unknown1 = reader.ReadInt32(); reader.SkipInt32(0); //Textures Texture[] textures = TextureUtils.ReadDDS(Path.GetFileName(path).Replace(".map", "_tex"), reader); //Meshes reader.SkipInt32(1); reader.SkipInt32(); //Length from magic to bottom reader.SkipInt32(0); reader.SkipInt32(0); long magicPosition = reader.BaseStream.Position; reader.SkipInt32(0x20010730); //Magic number? reader.SkipInt32(1); int materialsOffset = reader.ReadInt32() + (int)magicPosition; int meshCount = reader.ReadInt32(); reader.SkipInt32(0); reader.SkipInt32(); // Length of elements from 0^ reader.SkipInt32(20); reader.SkipInt32(0); reader.SkipInt32(0); reader.SkipInt32(1); reader.SkipInt32(8); long v1offset = reader.BaseStream.Position; reader.ReadVector3YInverted(); //V1 reader.SkipInt32(0); reader.ReadVector3YInverted(); //V2 reader.SkipInt32(0); int headerLength = reader.ReadInt32(); //From v1 to vertexLength int indicesOffset = reader.ReadInt32() + (int)v1offset; int indicesLength = reader.ReadInt32(); int Unknown = reader.ReadInt32(); reader.SkipInt32(meshCount); List<MeshGroupSH2> groups = new List<MeshGroupSH2>(); for (int i = 0; i != meshCount; i++) { groups.Add(MeshGroupSH2.Initialise(reader, subGO)); } int vertexLength = reader.ReadInt32(); reader.SkipInt32(1); reader.SkipInt32(0); int elementLength = reader.ReadInt32(); reader.SkipInt32(vertexLength); int vertexElementsCount = vertexLength / elementLength; List<Vector3> verts = new List<Vector3>(); List<Vector3> norms = new List<Vector3>(); List<Color32> colors = new List<Color32>(); List<Vector2> uvs = new List<Vector2>(); for (int i = 0; i != vertexElementsCount; i++) { verts.Add(reader.ReadVector3YInverted() * Scene.GLOBAL_SCALE); norms.Add(reader.ReadVector3YInverted()); if (elementLength == 36) { colors.Add(reader.ReadBGRA()); } uvs.Add(reader.ReadVector2()); } reader.BaseStream.Position = indicesOffset; List<short[]> indices = new List<short[]>(groups.Count); //stupid for (int i = 0; i != groups.Count; i++) { indices.Add(null); } for(int i = 0; i != groups.Count; i++) { MeshGroupSH2 group = groups[i]; indices[group.MainID] = new short[group.indexCount]; for (int j = 0; j != group.indexCount ; j++) { indices[group.MainID][j] = reader.ReadInt16(); } Debug.Log("End of i = " + reader.BaseStream.Position.ToString("X")); } reader.BaseStream.Position = materialsOffset; //Mesh renderer MaterialRolodex rolodex = MaterialRolodex.GetOrCreateAt(assetPath); rolodex.AddTextures(textures); MeshRenderer mr = subGO.AddComponent<MeshRenderer>(); Material[] mats = new Material[groups.Count]; for (int i = 0; i != groups.Count; i++) { reader.SkipInt16(); MaterialRolodex.TexMatsPair tmp = rolodex.GetWithSH2ID(reader.ReadInt16()); mats[i] = tmp.GetOrCreateDiffuse(); reader.SkipBytes(12); } mr.sharedMaterials = mats; reader.Close(); //Mesh filter subGO.AddComponent<MeshFilter>().sharedMesh = MeshUtils.MakeIndexedStrip(verts, indices, norms, uvs, colors); foreach (MeshFilter mf in subGO.GetComponentsInChildren<MeshFilter>()) { AssetDatabase.AddObjectToAsset(mf.sharedMesh, assetPath); } }
public static Camera TryMakeCamera(BinaryReader reader, Matrix4x4 transMat) { Vector2 zoneA = reader.ReadVector2(); reader.SkipBytes(8); Vector2 zoneB = reader.ReadVector2(); Vector2 zoneHeights = reader.ReadVector2(); Vector2 constraintA = reader.ReadVector2(); reader.SkipBytes(8); Vector2 constraintB = reader.ReadVector2(); Vector2 constraintHeights = reader.ReadVector2(); reader.SkipInt32(0); int type = reader.ReadInt32(); reader.SkipInt32(0); int Unknown1 = reader.ReadInt32(); Vector4 Unknown2 = reader.ReadVector4(); Vector2 Unknown3 = reader.ReadVector2(); reader.SkipInt32(0); int Unknown4 = reader.ReadInt32(); Vector2 Unknown5 = reader.ReadVector2(); Vector2 Unknown6 = reader.ReadVector2(); if (type != 1) { Camera cam = new Camera(); Vector3 activeMin = new Vector3(zoneA.x, -zoneHeights.x, zoneA.y); Vector3 activeMax = new Vector3(zoneB.x, -zoneHeights.y, zoneB.y); cam.activeArea = new Bounds(); cam.activeArea.SetMinMax(transMat.MultiplyPoint(activeMin), transMat.MultiplyPoint(activeMax)); Vector3 constraintMin = new Vector3(constraintA.x, -constraintHeights.x, constraintA.y); Vector3 constraintMax = new Vector3(constraintB.x, -constraintHeights.y, constraintB.y); cam.constraintsArea = new Bounds(); cam.constraintsArea.SetMinMax(transMat.MultiplyPoint(constraintMin), transMat.MultiplyPoint(constraintMax)); cam.type = type; cam.Unknown1 = Unknown1; cam.Unknown2 = Unknown2; cam.Unknown3 = Unknown3; cam.Unknown4 = Unknown4; cam.Unknown5 = Unknown5; cam.Unknown6 = Unknown6; return cam; } return null; }
/// <summary> /// /// </summary> /// <param name="stageFileName"></param> /// <param name="mapChipImageFileName"></param> /// <param name="objectFileName"></param> /// <param name="town"></param> /// <param name="wall"></param> /// <param name="road"></param> /// <param name="directionsToWarArea">攻め込む方向のリスト。昇順にソートされているのが前提</param> /// <returns></returns> public WarMap Load(string stageFileName, int town, int wall, int road, IEnumerable<int> directionsToWarArea) { const int NUMOFMAPCHIP = 32; const int DEPLOY_CANDIDATE_NUM = 20; const int ENDCITY = 15, ENDWALL = 24, ENDSTREET = 39; string gameDataPath = Path.Combine(_scenarioPath, "Data"); var mapchipID = new int[NUMOFMAPCHIP,NUMOFMAPCHIP]; var objectID = new int[NUMOFMAPCHIP,NUMOFMAPCHIP]; var height = new int[NUMOFMAPCHIP,NUMOFMAPCHIP]; var initDeployCandidates = new List<List<Point2>>(); using (var filestream = new FileStream(Path.Combine(gameDataPath, stageFileName), FileMode.Open)) using (var reader = new BinaryReader(filestream)) { // (x,y) = (0,0), (0,1), ..., (0,MAX), (1,0) という順序でチップが記述されている // マップチップID for (int x = 0; x < NUMOFMAPCHIP; x++) { for (int y = 0; y < NUMOFMAPCHIP; y++) { mapchipID[x, y] = reader.ReadByte(); } } // オブジェクトID(0は移動不可(ダミー), 1はオブジェクトなし) for (int x = 0; x < NUMOFMAPCHIP; x++) { for (int y = 0; y < NUMOFMAPCHIP; y++) { objectID[x, y] = reader.ReadByte() + 1; } } // 半分しか表示されないチップを移動不可に設定 for (int y = 0; y < NUMOFMAPCHIP; y++) { objectID[0, y] = 0; if (!(++y < NUMOFMAPCHIP)) break; objectID[NUMOFMAPCHIP - 1, y] = 0; } // オブジェクトの生成順序 for (int x = 0; x < NUMOFMAPCHIP; x++) { for (int y = 0; y < NUMOFMAPCHIP; y++) { int rankOrder = reader.ReadByte(); int id = objectID[x, y] - 1; if (id <= 0) continue; // 指定した個数以上の順序を持つオブジェクトを削除 if (id <= ENDCITY) { // 都市 if (rankOrder > town) objectID[x, y] = 1; } else if (id <= ENDWALL) { // 壁 if (rankOrder > wall) objectID[x, y] = 1; } else if (id <= ENDSTREET) { // 道 if (rankOrder > road) objectID[x, y] = 1; } } } // 高さの読み込み for (int x = 0; x < NUMOFMAPCHIP; x++) { for (int y = 0; y < NUMOFMAPCHIP; y++) { height[x, y] = reader.ReadByte(); } } // 座標(x, y)をそれぞれ1+1=2バイトで表現。20組の座標で1エリアからの初期配置候補 // 攻め込む方向により初期配置候補が異なるので、実際に攻め込んだ方向になるまで読み飛ばす。 directionsToWarArea.ConcatFirst(0) .Zip2Chain() .ForEach(t => { var list = new List<Point2>(); reader.SkipBytes((t.Item2 - t.Item1) * 2 * DEPLOY_CANDIDATE_NUM); for (int i = 0; i < DEPLOY_CANDIDATE_NUM; i++) { int x = reader.ReadByte(), y = reader.ReadByte(); list.Add(AtatCoordToGameCoord(new Point2(x, y))); } initDeployCandidates.Add(list); }); } // 各チップの生成 var lands = new Land[NUMOFMAPCHIP,NUMOFMAPCHIP]; for (int x = 0; x < lands.GetLength(0); x++) { for (int y = 0; y < lands.GetLength(1); y++) { lands[x, y] = new Land(height[x, y], WarGlobal.Landforms[mapchipID[x, y]], objectID[x, y] == 0 ? null : WarGlobal.Constructs[objectID[x, y]]); } } return new WarMap(lands, lands[0, 0], new FarenMoveCalculator(), initDeployCandidates); }