public BeatmapDifficulty ToAssets( SerializedAssets.Transaction assets, string levelFolderPath, string levelID, Characteristic characteristic ) { string beatmapFile = Path.Combine(levelFolderPath, _beatmapFilename); var beatmapData = BeatmapDataBehaviorData.FromJsonFile(beatmapFile, assets.apkVersion); string characteristicPart = ((characteristic == Characteristic.Standard) ? "" : characteristic.ToString()); string assetName = levelID + characteristicPart + _difficulty.ToString() + "BeatmapData"; MonoBehaviorAssetData monob = new MonoBehaviorAssetData() { script = assets.scriptIDToScriptPtr[BeatmapDataBehaviorData.ScriptID], name = assetName, data = beatmapData, }; AssetPtr assetPtr = assets.AppendAsset(monob); return(new BeatmapDifficulty() { difficulty = (int)_difficulty, difficultyRank = _difficultyRank, noteJumpMovementSpeed = _noteJumpMovementSpeed, noteJumpStartBeatOffset = _noteJumpStartBeatOffset, beatmapData = assetPtr, }); }
public AssetPtr AddToAssets(SerializedAssets.Transaction assets, Apk.Transaction apk, string levelID) { // var watch = System.Diagnostics.Stopwatch.StartNew(); AudioClipAssetData audioClip = CreateAudioAsset(apk, levelID); AssetPtr audioClipPtr = assets.AppendAsset(audioClip); string coverPath = Path.Combine(levelFolderPath, _coverImageFilename); Texture2DAssetData cover = Texture2DAssetData.CoverFromImageFile(coverPath, levelID); AssetPtr coverPtr = assets.AppendAsset(cover); AssetPtr environment = new AssetPtr(20, 1); // default environment switch (_environmentName) { case "NiceEnvironment": environment = new AssetPtr(38, 3); break; case "TriangleEnvironment": environment = new AssetPtr(0, 252); break; case "BigMirrorEnvironment": environment = new AssetPtr(0, 249); break; } LevelBehaviorData level = new LevelBehaviorData() { levelID = levelID, songName = _songName, songSubName = _songSubName, songAuthorName = _songAuthorName, levelAuthorName = _levelAuthorName, beatsPerMinute = _beatsPerMinute, songTimeOffset = _songTimeOffset, shuffle = _shuffle, shufflePeriod = _shufflePeriod, previewStartTime = _previewStartTime, previewDuration = _previewDuration, audioClip = audioClipPtr, coverImage = coverPtr, environment = environment, difficultyBeatmapSets = _difficultyBeatmapSets.Select(s => s.ToAssets(assets, levelFolderPath, levelID)).Where(s => s != null).ToList(), }; MonoBehaviorAssetData monob = new MonoBehaviorAssetData() { script = new AssetPtr(1, LevelBehaviorData.PathID), name = level.levelID + "Level", data = level, }; // watch.Stop(); // Console.WriteLine("song: " + watch.ElapsedMilliseconds); return(assets.AppendAsset(monob)); }
public LevelCollectionBehaviorData FindExtrasLevelCollection() { AssetObject obj = objects[235]; // the index of the extras collection in sharedassets17 if (!(obj.data is MonoBehaviorAssetData)) { throw new ParseException("Extras level collection not at normal spot"); } MonoBehaviorAssetData monob = (MonoBehaviorAssetData)obj.data; if (monob.name != "ExtrasLevelCollection") { throw new ParseException("Extras level collection not at normal spot"); } return((LevelCollectionBehaviorData)monob.data); }
public Dictionary <string, ulong> FindLevels() { var dict = new Dictionary <string, ulong>(); foreach (AssetObject obj in objects) { if (!(obj.data is MonoBehaviorAssetData)) { continue; } MonoBehaviorAssetData monob = (MonoBehaviorAssetData)obj.data; if (!(monob.data is LevelBehaviorData)) { continue; } LevelBehaviorData levelData = (LevelBehaviorData)monob.data; dict.Add(levelData.levelID, obj.pathID); } return(dict); }
public HashSet <string> ExistingLevelIDs() { var set = new HashSet <string>(); foreach (AssetObject obj in objects) { if (!(obj.data is MonoBehaviorAssetData)) { continue; } MonoBehaviorAssetData monob = (MonoBehaviorAssetData)obj.data; if (!(monob.data is LevelBehaviorData)) { continue; } LevelBehaviorData levelData = (LevelBehaviorData)monob.data; set.Add(levelData.levelID); } return(set); }
public AssetObject GetAssetObjectFromScript <T>(Predicate <MonoBehaviorAssetData> mob, Predicate <T> cond) where T : BehaviorData { foreach (AssetObject obj in objects) { if (!(obj.data is MonoBehaviorAssetData)) { continue; } MonoBehaviorAssetData monob = (MonoBehaviorAssetData)obj.data; if (!(monob.data is T) || !mob(monob)) { continue; } T behaviorData = (T)monob.data; if (cond(behaviorData)) { return(obj); } } return(null); }
public BeatmapDifficulty ToAssets( SerializedAssets assets, string levelFolderPath, string levelID, Characteristic characteristic ) { string beatmapFile = Path.Combine(levelFolderPath, _beatmapFilename); string jsonData = File.ReadAllText(beatmapFile); BeatmapSaveData saveData = JsonConvert.DeserializeObject <BeatmapSaveData>(jsonData); byte[] projectedData = saveData.SerializeToBinary(); BeatmapDataBehaviorData beatmapData = new BeatmapDataBehaviorData() { jsonData = "", signature = new byte[128], // all zeros projectedData = projectedData, }; string characteristicPart = ((characteristic == Characteristic.Standard) ? "" : characteristic.ToString()); string assetName = levelID + characteristicPart + _difficulty.ToString() + "BeatmapData"; MonoBehaviorAssetData monob = new MonoBehaviorAssetData() { script = new AssetPtr(1, BeatmapDataBehaviorData.PathID), name = assetName, data = beatmapData, }; AssetPtr assetPtr = assets.AppendAsset(monob); return(new BeatmapDifficulty() { difficulty = (int)_difficulty, difficultyRank = _difficultyRank, noteJumpMovementSpeed = _noteJumpMovementSpeed, noteJumpStartBeatOffset = _noteJumpStartBeatOffset, beatmapData = assetPtr, }); }
public SerializedAssets(Stream stream, Apk.Version v) { apkVersion = v; BinaryReader reader = new BinaryReader(stream); // ===== Parse Header int metadataSize = reader.ReadInt32BE(); int fileSize = reader.ReadInt32BE(); int generation = reader.ReadInt32BE(); if (generation != parsedGeneration) { throw new ParseException("Unsupported format version"); } int dataOffset = reader.ReadInt32BE(); int isBigEndian = reader.ReadInt32BE(); if (isBigEndian != 0) { throw new ParseException("Must be little endian"); } paddingLen = dataOffset - (metadataSize + headerLen); // ===== Parse Metadata version = reader.ReadStringToNull(); if (version != "2018.3.10f1") { throw new ParseException("Unsupported Unity version"); } targetPlatform = reader.ReadInt32(); enableTypeTree = reader.ReadBoolean(); if (enableTypeTree) { throw new ParseException("Type trees aren't supported"); } types = reader.ReadPrefixedList(r => new TypeRef(r)); objects = reader.ReadPrefixedList(r => new AssetObject(r)); scripts = reader.ReadPrefixedList(r => new Script(r)); externals = reader.ReadPrefixedList(r => new External(r)); // this is necessary to get headerLen+metadataSize to match up with offset if (reader.ReadByte() != 0) { throw new ParseException("Expected metadata to end with 0"); } if (!reader.ReadAllZeros(paddingLen)) { throw new ParseException("Expected zeros for padding"); } Debug.Assert(reader.BaseStream.Position == dataOffset, "Parsed metadata wrong"); // ===== Extra stuff scriptIDToScriptPtr = new Dictionary <byte[], AssetPtr>(new ByteArrayComparer()); environmentIDToPtr = new Dictionary <string, AssetPtr>(); assetTypeToTypeID = new Dictionary <Type, int>(); scriptTypeToTypeID = new Dictionary <Type, int>(); // ===== Parse Data for (int i = 0; i < objects.Count - 1; i++) { objects[i].paddingLen = objects[i + 1].offset - (objects[i].offset + objects[i].size); } // I've never seen any padding after the last object but handle it just in case AssetObject last = objects[objects.Count - 1]; int dataSize = fileSize - dataOffset; last.paddingLen = dataSize - (last.offset + last.size); foreach (AssetObject obj in objects) { // Console.WriteLine((reader.BaseStream.Position-dataOffset, obj.offset, obj.size)); if (reader.BaseStream.Position - dataOffset != obj.offset) { throw new ParseException("Objects aren't in order"); } long startOffset = reader.BaseStream.Position; if (types.Count <= obj.typeID) { // Console.WriteLine($"TypeID of SimpleColor: {objects[52].typeID} with type: {objects[52].data.GetType()}"); throw new ParseException($"Could not find typeID: {obj.typeID}, maximum is: {types.Count}"); } switch (types[obj.typeID].classID) { case MonoBehaviorAssetData.ClassID: byte[] scriptID = types[obj.typeID].scriptID; var monob = new MonoBehaviorAssetData(reader, obj.size, types[obj.typeID], apkVersion); scriptTypeToTypeID[monob.data.GetType()] = obj.typeID; scriptIDToScriptPtr[scriptID] = monob.script; obj.data = monob; break; case AudioClipAssetData.ClassID: obj.data = new AudioClipAssetData(reader, obj.size); break; case Texture2DAssetData.ClassID: obj.data = new Texture2DAssetData(reader, obj.size); break; case SpriteAssetData.ClassID: obj.data = new SpriteAssetData(reader, obj.size); break; case GameObjectAssetData.ClassID: obj.data = new GameObjectAssetData(reader, obj.size); break; case MeshFilterAssetData.ClassID: obj.data = new MeshFilterAssetData(reader, obj.size); break; case TextAssetData.ClassID: obj.data = new TextAssetData(reader, obj.size); break; default: obj.data = new UnknownAssetData(reader, obj.size); break; } assetTypeToTypeID[obj.data.GetType()] = obj.typeID; long bytesParsed = reader.BaseStream.Position - startOffset; if (bytesParsed != obj.size) { throw new ParseException($"Parsed {bytesParsed} bytes but expected {obj.size} for path ID {obj.pathID}"); } if (!reader.ReadAllZeros(obj.paddingLen)) { throw new ParseException("Expected zeros for padding"); } } FindEnvironmentPointers(); }