public static bool Read(RAFFileListEntry file, ref InibinFile data, Logger logger) { bool result = true; logger.Event("Reading inibin: " + file.FileName); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); result = ReadCharacterInibin(myInput, ref data, logger); int end = file.FileName.LastIndexOf("/"); String directory = file.FileName.Substring(0, end); String archive = file.RAFArchive.RAFFilePath; archive = archive.Replace("\\", "/"); end = archive.LastIndexOf("/"); archive = archive.Substring(0, end); data.directory = new DirectoryInfo(archive + "/" + directory); myInput.Close(); } catch(Exception e) { logger.Error("Unable to open memory stream: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
public static bool Read(int skin, IFileEntry file, ref Dictionary<String, String> animations, Logger logger) { bool result = true; logger.Event("Parsing animation list: " + file.FileName ); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); StreamReader reader = new StreamReader(myInput); ParseAnimations(skin, reader, ref animations); reader.Close(); myInput.Close(); } catch { logger.Error("Failed to parse animation list: " + file.FileName); result = false; animations.Clear(); } return result; }
//Helper Functions. //(Because nested Try/Catch looks nasty in one function block.) private static bool ReadBinary(MemoryStream input, ref SKLFile data, Logger logger) { bool result = true; try { BinaryReader myFile = new BinaryReader(input, Encoding.ASCII); result = ReadData(myFile, ref data, logger); myFile.Close(); } catch (Exception e) { logger.Error("Unable to open binary reader."); logger.Error(e.Message); result = false; } return result; }
/// <summary> /// Read in binary .anm file from RAF. /// </summary> /// <param name="file">The file.</param> /// <param name="data">The contents of the file are stored in here.</param> /// <returns></returns> public static bool Read(RAFFileListEntry file, ref ANMFile data, Logger logger) { bool result = true; logger.Event("Reading anm: " + file.FileName); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); result = ReadBinary(myInput, ref data, logger); myInput.Close(); } catch(Exception e) { logger.Error("Unable to open memory stream: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
// // Helper creation function. // private bool Create(List<float> vertexPositions, List<float> vertexNormals, List<float> vertexTextureCoordinates, List<uint> indices, Logger logger) { bool result = true; logger.Event("Creating OpenGL static model."); numIndices = indices.Count; // Create Vertex Array Object if (result == true) { GL.GenVertexArrays(1, out vao); } ErrorCode error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Bind VAO if (result == true) { GL.BindVertexArray(vao); } // Create the VBOs int[] buffers = new int[4]; if (result == true) { GL.GenBuffers(4, buffers); } // Check for errors error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Store data and bind vertex buffer. if (result == true) { vertexPositionBuffer = buffers[0]; vertexNormalBuffer = buffers[1]; vertexTextureCoordinateBuffer = buffers[2]; indexBuffer = buffers[3]; GL.BindBuffer(BufferTarget.ArrayBuffer, vertexPositionBuffer); } // // // Set vertex data. // // if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexPositions.Count * sizeof(float)), vertexPositions.ToArray(), BufferUsageHint.StaticDraw); } // Check for errors. error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put vertices into attribute slot 0. if (result == true) { GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(0); } // // // Bind normal buffer. // // if (result == true) { GL.BindBuffer(BufferTarget.ArrayBuffer, vertexNormalBuffer); } // Set normal data. if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexNormals.Count * sizeof(float)), vertexNormals.ToArray(), BufferUsageHint.StaticDraw); } // Check for errors. error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put normals into attribute slot 1. if (result == true) { GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(1); } // // // Bind texture cordinates buffer. // // if (result == true) { GL.BindBuffer(BufferTarget.ArrayBuffer, vertexTextureCoordinateBuffer); } // Set Texture Coordinate Data if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexTextureCoordinates.Count * sizeof(float)), vertexTextureCoordinates.ToArray(), BufferUsageHint.StaticDraw); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put texture coords into attribute slot 2. if (result == true) { GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(2); } // Bind index buffer. if (result == true) { GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer); } // Set index data. if (result == true) { GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Count * sizeof(uint)), indices.ToArray(), BufferUsageHint.StaticDraw); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Unbind VAO from pipeline. if (result == true) { GL.BindVertexArray(0); } else { logger.Error("Failed to create OpenGL static model."); } return result; }
private static bool ReadData(BinaryReader file, ref ANMFile data, Logger logger) { bool result = true; try { // File Header Information. data.id = new String(file.ReadChars(ANMFile.ID_SIZE)); data.version = file.ReadUInt32(); // Version 0, 1, 2, 3 Code if (data.version == 0 || data.version == 1 || data.version == 2 || data.version == 3) { // // Header information specific to these versions. // data.magic = file.ReadUInt32(); data.numberOfBones = file.ReadUInt32(); data.numberOfFrames = file.ReadUInt32(); data.playbackFPS = file.ReadUInt32(); // Read in all the bones for (UInt32 i = 0; i < data.numberOfBones; ++i) { ANMBone bone = new ANMBone(); bone.name = new String(file.ReadChars(ANMBone.BONE_NAME_LENGTH)); bone.name = RemoveAnimationNamePadding(bone.name); bone.name = bone.name.ToLower(); // Unknown file.ReadUInt32(); // For each bone, read in its value at each frame in the animation. for (UInt32 j = 0; j < data.numberOfFrames; ++j) { ANMFrame frame = new ANMFrame(); // Read in the frame's quaternion. frame.orientation[0] = file.ReadSingle(); // x frame.orientation[1] = file.ReadSingle(); // y frame.orientation[2] = file.ReadSingle(); // z frame.orientation[3] = file.ReadSingle(); // w // Read in the frame's position. frame.position[0] = file.ReadSingle(); // x frame.position[1] = file.ReadSingle(); // y frame.position[2] = file.ReadSingle(); // z bone.frames.Add(frame); } data.bones.Add(bone); } } // Version 4 Code else if (data.version == 4) { // // Based on the reverse engineering work of Hossein Ahmadi. // // In this version, position vectors and orientation quaternions are // stored separately in sorted, keyed blocks. The assumption is Riot // is removing duplicate vectors and quaternions by using an indexing scheme // to look up values. // // So, after the header, there are three data sections: a vector section, a quaternion // section, and a look up section. The number of vectors and quaternions // may not match the expected value based on the number of frames and bones. However, // the number of look ups should match this value and can be used to create the animation. // // Header information specific to version 4. // data.magic = file.ReadUInt32(); // Not sure what any of these mean. float unknown = file.ReadSingle(); unknown = file.ReadSingle(); unknown = file.ReadSingle(); data.numberOfBones = file.ReadUInt32(); data.numberOfFrames = file.ReadUInt32(); // Time per frame is stored in this file type. Need to invert it into FPS. data.playbackFPS = (UInt32) Math.Round(1.0f / file.ReadSingle()); // These are offsets to specific data sections in the file. UInt32 unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); UInt32 positionOffset = file.ReadUInt32(); UInt32 orientationOffset = file.ReadUInt32(); UInt32 indexOffset = file.ReadUInt32(); // These last three values are confusing. // They aren't a vector and they throw off the offset values // by 12 bytes. Just ignore them and keep reading. unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); // // Vector section. // List<float> positions = new List<float>(); UInt32 numberOfPositions = (orientationOffset - positionOffset) / sizeof(float); for (UInt32 i = 0; i < numberOfPositions; ++i) { positions.Add(file.ReadSingle()); } // // Quaternion section. // List<float> orientations = new List<float>(); UInt32 numberOfOrientations = (indexOffset - orientationOffset) / sizeof(float); for (UInt32 i = 0; i < numberOfOrientations; ++i) { orientations.Add(file.ReadSingle()); } // // Offset section. // // Note: Unlike versions 0-3, data in this version is // Frame 1: // Bone 1: // Bone 2: // ... // Frame 2: // Bone 1: // ... // Dictionary<UInt32, ANMBone> boneMap = new Dictionary<UInt32, ANMBone>(); for (Int32 i = 0; i < data.numberOfBones; ++i) { // // The first frame is a special case since we are allocating bones // as we read them in. // // Read in the offset data. UInt32 boneID = file.ReadUInt32(); UInt16 positionID = file.ReadUInt16(); UInt16 unknownIndex = file.ReadUInt16(); // Unknown. UInt16 orientationID = file.ReadUInt16(); unknownIndex = file.ReadUInt16(); // Unknown. Seems to always be zero. // Allocate the bone. ANMBone bone = new ANMBone(); bone.id = boneID; // Allocate all the frames for the bone. for (int j = 0; j < data.numberOfFrames; ++j) { bone.frames.Add(new ANMFrame()); } // Retrieve the data for the first frame. ANMFrame frame = bone.frames[0]; frame.position = LookUpVector(positionID, positions); frame.orientation = LookUpQuaternion(orientationID, orientations); // Store the bone in the dictionary by bone ID. boneMap[boneID] = bone; } Int32 currentFrame = 1; Int32 currentBone = 0; UInt32 numberOfLookUps = (data.numberOfFrames - 1) * data.numberOfBones; for (UInt32 i = 0; i < numberOfLookUps; ++i) { // // Normal case for all frames after the first. // // Read in the offset data. UInt32 boneID = file.ReadUInt32(); UInt16 positionID = file.ReadUInt16(); UInt16 unknownIndex = file.ReadUInt16(); // Unknown. UInt16 orientationID = file.ReadUInt16(); unknownIndex = file.ReadUInt16(); // Unknown. Seems to always be zero. // Retrieve the bone from the dictionary. // Note: The bones appear to be in the same order in every frame. So, a dictionary // isn't exactly needed and you could probably get away with a list. However, this way // feels safer just in case something ends up being out of order. ANMBone bone = boneMap[boneID]; ANMFrame frame = bone.frames[currentFrame]; frame.position = LookUpVector(positionID, positions); frame.orientation = LookUpQuaternion(orientationID, orientations); // This loop is slightly ambiguous. // // The problem is previous .anm versions contain data like: // foreach bone // foreach frame // // However, this version contains data like: // foreach frame // foreach bone // // So, reading one version is going to be a little goofy. currentBone++; if (currentBone >= data.numberOfBones) { currentBone = 0; currentFrame++; } } // Finally, we need to move all the data from the dictionary into the ANMFile. foreach(var bone in boneMap) { data.bones.Add(bone.Value); } // Currently returning false for this version. We can not render this version correctly yet. // So, we need to tell the viewer not to try and load it. result = false; } // Unknown version else { logger.Error("Unknown anm version: " + data.version); result = false; } } catch(Exception e) { logger.Error("Anm reading error."); logger.Error(e.Message); result = false; } logger.Event("File ID: " + data.id); logger.Event("Magic: " + data.magic); logger.Event("Version: " + data.version); logger.Event("Number of Bones: " + data.numberOfBones); logger.Event("Number of Frames: " + data.numberOfFrames); logger.Event("Playback FPS: " + data.playbackFPS); return result; }
private static bool ReadData(BinaryReader file, ref SKNFile data, Logger logger) { bool result = true; try { // File Header Information. data.magic = file.ReadInt32(); data.version = file.ReadInt16(); data.numObjects = file.ReadInt16(); if (data.version == 1 || data.version == 2) { // Contains material headers. data.numMaterialHeaders = file.ReadInt32(); for (int i = 0; i < data.numMaterialHeaders; ++i) { // Read in the headers. SKNMaterial header = new SKNMaterial(); header.name = new String(file.ReadChars(SKNMaterial.MATERIAL_NAME_SIZE)); header.startVertex = file.ReadInt32(); header.numVertices = file.ReadInt32(); header.startIndex = file.ReadInt32(); header.numIndices = file.ReadInt32(); data.materialHeaders.Add(header); } // Read in model data. data.numIndices = file.ReadInt32(); data.numVertices = file.ReadInt32(); for (int i = 0; i < data.numIndices; ++i) { data.indices.Add(file.ReadInt16()); } for (int i = 0; i < data.numVertices; ++i) { SKNVertex vertex = new SKNVertex(); vertex.position[0] = file.ReadSingle(); // x vertex.position[1] = file.ReadSingle(); // y vertex.position[2] = file.ReadSingle(); // z for (int j = 0; j < SKNVertex.BONE_INDEX_SIZE; ++j) { int bone = (int)file.ReadByte(); vertex.boneIndex[j] = bone; } vertex.weights[0] = file.ReadSingle(); vertex.weights[1] = file.ReadSingle(); vertex.weights[2] = file.ReadSingle(); vertex.weights[3] = file.ReadSingle(); vertex.normal[0] = file.ReadSingle(); // x vertex.normal[1] = file.ReadSingle(); // y vertex.normal[2] = file.ReadSingle(); // z vertex.texCoords[0] = file.ReadSingle(); // u vertex.texCoords[1] = file.ReadSingle(); // v data.vertices.Add(vertex); } // Data exclusive to version two. if (data.version == 2) { data.endTab.Add(file.ReadInt32()); data.endTab.Add(file.ReadInt32()); data.endTab.Add(file.ReadInt32()); } } // Unknown Version else { logger.Error("Unknown skn version: " + data.version); result = false; } } catch(Exception e) { logger.Error("Skn reading error."); logger.Error(e.Message); result = false; } logger.Event("Magic: " + data.magic); logger.Event("Version: " + data.version); logger.Event("Number of Objects: " + data.numObjects); logger.Event("Number of Material Headers: " + data.numMaterialHeaders); logger.Event("Number of Vertices: " + data.numVertices); logger.Event("Number of Indices: " + data.numIndices); return result; }
private static bool ReadData(BinaryReader file, ref SKLFile data, Logger logger) { bool result = true; try { // File Header Information. data.id = new String(file.ReadChars(SKLFile.ID_SIZE)); data.version = file.ReadUInt32(); if (data.version == 1 || data.version == 2) { data.designerID = file.ReadUInt32(); // Read in the bones. data.numBones = file.ReadUInt32(); for (int i = 0; i < data.numBones; ++i) { SKLBone bone = new SKLBone(); bone.name = new String( file.ReadChars(SKLBone.BONE_NAME_SIZE)); bone.name = RemoveBoneNamePadding(bone.name); bone.name = bone.name.ToLower(); bone.ID = i; bone.parentID = file.ReadInt32(); bone.scale = file.ReadSingle(); // Read in transform matrix. float[] orientation = new float[SKLBone.ORIENTATION_SIZE]; for (int j = 0; j < SKLBone.ORIENTATION_SIZE; ++j) { orientation[j] = file.ReadSingle(); } bone.orientation = orientation; // Position from matrix. bone.position[0] = orientation[3]; bone.position[1] = orientation[7]; bone.position[2] = orientation[11]; data.bones.Add(bone); } // Version two contains bone IDs. if (data.version == 2) { data.numBoneIDs = file.ReadUInt32(); for (uint i = 0; i < data.numBoneIDs; ++i) { data.boneIDs.Add(file.ReadUInt32()); } } } // Newest version so far. else if (data.version == 0) { // Header Int16 zero = file.ReadInt16(); // ? data.numBones = (uint)file.ReadInt16(); data.numBoneIDs = file.ReadUInt32(); Int16 offsetToVertexData = file.ReadInt16(); // Should be 64. int unknown = file.ReadInt16(); // ? int offset1 = file.ReadInt32(); int offsetToAnimationIndices = file.ReadInt32(); int offset2 = file.ReadInt32(); int offset3 = file.ReadInt32(); int offsetToStrings = file.ReadInt32(); // Not sure what this data represents. // I think it's padding incase more header data is required later. file.BaseStream.Position += 20; file.BaseStream.Position = offsetToVertexData; for (int i = 0; i < data.numBones; ++i) { SKLBone bone = new SKLBone(); // The old scale was always 0.1. // For now, just go with it. bone.scale = 0.1f; zero = file.ReadInt16(); // ? bone.ID = file.ReadInt16(); bone.parentID = file.ReadInt16(); unknown = file.ReadInt16(); // ? int namehash = file.ReadInt32(); float twoPointOne = file.ReadSingle(); bone.position[0] = file.ReadSingle(); bone.position[1] = file.ReadSingle(); bone.position[2] = file.ReadSingle(); float one = file.ReadSingle(); // ? Maybe scales for X, Y, and Z one = file.ReadSingle(); one = file.ReadSingle(); bone.orientation[0] = file.ReadSingle(); bone.orientation[1] = file.ReadSingle(); bone.orientation[2] = file.ReadSingle(); bone.orientation[3] = file.ReadSingle(); float ctx = file.ReadSingle(); // ctx float cty = file.ReadSingle(); // cty float ctz = file.ReadSingle(); // ctz data.bones.Add(bone); // The rest of the bone data is unknown. Maybe padding? file.BaseStream.Position += 32; } file.BaseStream.Position = offset1; for (int i = 0; i < data.numBones; ++i) // Inds for version 4 animation. { // 8 bytes uint sklID = file.ReadUInt32(); uint anmID = file.ReadUInt32(); data.boneIDMap[anmID] = sklID; } file.BaseStream.Position = offsetToAnimationIndices; for (int i = 0; i < data.numBoneIDs; ++i) // Inds for animation { // 2 bytes UInt16 boneID = file.ReadUInt16(); data.boneIDs.Add(boneID); } file.BaseStream.Position = offsetToStrings; for (int i = 0; i < data.numBones; ++i) { // bone names string name = ""; while (name.Contains('\0') == false) { name += new string(file.ReadChars(4)); } name = RemoveBoneNamePadding(name); name = name.ToLower(); data.bones[i].name = name; } } // Unknown Version else { logger.Error("Unknown skl version: " + data.version); result = false; } } catch (Exception e) { logger.Error("Skl reading error."); logger.Error(e.Message); result = false; } logger.Event("File ID: " + data.id); logger.Event("Version: " + data.version); logger.Event("Designer ID: " + data.designerID); logger.Event("Number of Bones: " + data.numBones); logger.Event("Number of Bone IDs: " + data.numBoneIDs); return result; }
/// <summary> /// Read in binary .dds file from RAF. /// </summary> /// <param name="file">The file.</param> /// <param name="data">The contents of the file are stored in here.</param> /// <returns></returns> public static bool Read(RAFFileListEntry file, ref Bitmap bitmap, Logger logger) { bool result = true; logger.Event("Reading dds: " + file.FileName); try { // Create image. int[] images = new int[1]; Il.ilGenImages(1, images); // Bind image. Il.ilBindImage(images[0]); // Load the image data into DevIL. byte[] data = file.GetContent(); result = Il.ilLoadL(Il.IL_DDS, data, data.Length); if (result == true) { int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); ; // Create the bitmap. bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); Rectangle rect = new Rectangle(0, 0, width, height); // Store the DevIL image data into the bitmap. BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); Il.ilCopyPixels(0, 0, 0, width, height, 1, Il.IL_BGRA, Il.IL_UNSIGNED_BYTE, bitmapData.Scan0); bitmap.UnlockBits(bitmapData); } // Free image. Il.ilDeleteImages(1, images); if (result == false) { throw new System.Exception("Unable to load image data."); } } catch(Exception e) { logger.Error("Unable to open dds file: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
private bool StoreModel(ModelDefinition def, out LOLModel model, Logger logger) { model = new LOLModel(); model.skinNumber = def.skin; model.animationList = def.anmListKey.ToLower(); // Find the skn. if (skns.ContainsKey(def.skn)) { model.skn = skns[def.skn]; } else { logger.Error("Unable to find skn file: " + def.skn); return false; } // Find the skl. if (skls.ContainsKey(def.skl)) { model.skl = skls[def.skl]; } else { logger.Error("Unable to find skl file: " + def.skl); return false; } // Find the texture. if (textures.ContainsKey(def.tex)) { model.texture = textures[def.tex]; } else { logger.Error("Unable to find texture file: " + def.tex); return false; } return true; }
private bool StoreAnimations(ref LOLModel model, Logger logger) { bool result = true; Dictionary<String, String> animationStrings = new Dictionary<String, String>(); // Sanity if (animationLists.ContainsKey(model.animationList) == true) { result = ANMListReader.Read(model.skinNumber - 1, // indexing in animations.list assumes the original skin to be -1 animationLists[model.animationList], ref animationStrings, logger); } else { logger.Error("Unable to find animation list: " + model.animationList); } if (result == true) { // Store the animations in the model. foreach (var a in animationStrings) { if (animations.ContainsKey(a.Value) == true) { if (model.animations.ContainsKey(a.Key) == false) { model.animations.Add(a.Key, animations[a.Value]); } else { logger.Error("Duplicate animation: " + a.Key); } } else { logger.Error("Unable to find animation: " + a.Value); } } } return result; }
// Replacement for individual raf reading and individual filetype searching // Provide the directory of RADS\projects\lol_game_client\filearchives or the equivalent private bool ReadRAFs(DirectoryInfo dir, Logger logger) { try { RAFMasterFileList rafFiles = new RAFMasterFileList(dir.FullName); logger.Event("Opening the 'filearchives' directory: " + dir.FullName); foreach (RAFMasterFileList.RAFSearchResult result in rafFiles.SearchFileEntries(new string[] { ".dds", ".skn", ".skl", ".inibin", "animations.list", ".anm" }, RAFMasterFileList.RAFSearchType.All)) { RAFFileListEntry e = result.value; // Split off the actual file name from the full path String name = e.FileName.Substring(e.FileName.LastIndexOf('/') + 1).ToLower(); switch (result.searchPhrase) { case ".dds": // Try to parse out unwanted textures. if (!e.FileName.ToLower().Contains("loadscreen") && !e.FileName.ToLower().Contains("circle") && !e.FileName.ToLower().Contains("square") && e.FileName.ToLower().Contains("data") && e.FileName.ToLower().Contains("characters")) { // Check that the file isn't already in the dictionary if (!textures.ContainsKey(name)) { textures.Add(name, e); } else { logger.Warning("Duplicate texture " + name + ": " + e.FileName); } } break; case ".skn": if (!skns.ContainsKey(name)) { skns.Add(name, e); } else { logger.Warning("Duplicate skn " + name + ": " + e.FileName); } break; case ".skl": if (!skls.ContainsKey(name)) { skls.Add(name, e); } else { logger.Warning("Duplicate skn " + name + ": " + e.FileName); } break; case ".inibin": // Try to only read champion inibins if (e.FileName.ToLower().Contains("data") && e.FileName.ToLower().Contains("characters")) { inibins.Add(e); } else { logger.Warning("Excluding inibin " + name + ": " + e.FileName); } break; case "animations.list": // Riot changed their directory structure for some skins. // Originally, champion Animation.list files were stored in a directory structure like // "*/ChampionName/Animation.list". Now, some are stored like // "*/ChampionName/Skins/Skin01/Animation.list". if (e.FileName.ToLower().Contains("skin") == false && e.FileName.ToLower().Contains("base") == false) { // Original Case. // Remove the file name. name = e.FileName.Remove(e.FileName.LastIndexOf('/')); // Remove proceeding directories to get the parent directory name = name.Substring(name.LastIndexOf('/') + 1).ToLower(); } else { // Newer Case. string path = e.FileName.ToString(); string[] splitPath = path.Split('/'); // Sanity if (splitPath.Length > 3) { name = splitPath[splitPath.Length - 4].ToLower(); } } // Store. if (!animationLists.ContainsKey(name)) { animationLists.Add(name, e); } else { logger.Warning("Duplicate animation list " + name + ": " + e.FileName); } break; case ".anm": // Remove the .anm extension. name = name.Remove(name.Length - 4); if (!animations.ContainsKey(name)) { animations.Add(name, e); } else { logger.Warning("Duplicate anm " + name + ": " + e.FileName); } break; } } } catch (Exception e) { // Something went wrong. Most likely the RAF read failed due to a bad directory. logger.Error("Failed to open RAFs"); logger.Error(e.Message); return false; } return true; }
private void GenerateModelDefinitions(Logger logger) { foreach (RAFFileListEntry f in inibins) { InibinFile iniFile = new InibinFile(); bool readResult = InibinReader.Read(f, ref iniFile, logger); if (readResult == true) { // Add the models from this .inibin file List<ModelDefinition> modelDefs = iniFile.GetModelStrings(); for (int j = 0; j < modelDefs.Count; ++j) { // Name the model after the parent directory // of the .inibin plus the name from the .inibin. // Some things overlap without both. string path = f.FileName; string[] splitPath = path.Split('/'); string directoryName = splitPath[splitPath.Length - 2]; if (directoryName.Contains("Base") == true || directoryName.Contains("Skin") == true) { // The directory structure for this case will be something like // "*/ChampionName/Skins/Base/". // We just want the "ChampionName". directoryName = splitPath[splitPath.Length - 4]; } // Sometimes the name from the .inibin file is "". // So, just name it after the directory String name = modelDefs[j].name; if (name == "") { name = directoryName + "/" + directoryName; } else { name = directoryName + "/" + name; } try { LOLModel model; bool storeResult = StoreModel(modelDefs[j], out model, logger); if (storeResult == true) { // Try to store animations for model as well storeResult = StoreAnimations(ref model, logger); } if (storeResult == true) { if (models.ContainsKey(name) == false) { logger.Event("Adding model definition: " + name); models.Add(name, model); } else { logger.Warning("Duplicate model definition: " + name); } } } catch (Exception e) { logger.Error("Unable to store model definition: " + name); logger.Error(e.Message); } } } } }
public bool Read(Logger logger) { bool result = true; // Clear old data. models.Clear(); skls.Clear(); skns.Clear(); textures.Clear(); inibins.Clear(); animationLists.Clear(); animations.Clear(); DirectoryInfo rootDir = null; try { logger.Event("Reading models from: " + Root); rootDir = new DirectoryInfo(Root); } catch { logger.Error("Unable to get the directory information: " + Root); result = false; } // // Try to find the raf files and read them. // if (result == true) { try { result = GetRAFFiles(rootDir, logger); // If the finding or reading fails, bail. if (!result) { logger.Error("Unable to find the 'filearchives' directory: " + Root); } } catch (Exception e) { logger.Error("Unable to open directory: " + Root); logger.Error(e.Message); result = false; } } // Sanity if (result == true) { GenerateModelDefinitions(logger); } return result; }