Beispiel #1
0
        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,
            });
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 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);
 }
Beispiel #7
0
        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,
            });
        }
Beispiel #8
0
        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();
        }