Skip to content

Commit d1c3775

Browse files
author
Ookiineko
committed
Add other source files
Signed-off-by: Ookiineko <chiisaineko@protonmail.com>
1 parent 2138e28 commit d1c3775

5 files changed

Lines changed: 218 additions & 0 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/bin/
2+
/obj/
3+
/packages/
4+
/riderModule.iml
5+
/_ReSharper.Caches/
6+
/FodyWeavers*
7+
/collection.db

CollectionDowngrader.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using Realms;
2+
using Realms.Exceptions;
3+
using CollectionDowngrader.LazerSchema;
4+
5+
namespace CollectionDowngrader
6+
{
7+
class CollectionDowngrader
8+
{
9+
const int LazerSchemaVersion = 26;
10+
11+
private static int Main(string[] args)
12+
{
13+
String realmFile, outputFile;
14+
FileStream outStream;
15+
BinaryWriter binWriter;
16+
Realm db;
17+
DateTimeOffset lastMod;
18+
BeatmapCollection? lastModCollection;
19+
20+
if (args.Length != 2)
21+
{
22+
Console.Error.WriteLine("Usage: CollectionDowngrader <path to osu! (lazer) client.realm> " +
23+
"<output osu! (stable) collection.db path>");
24+
25+
return 1;
26+
}
27+
28+
realmFile = args[0];
29+
outputFile = args[1];
30+
31+
if (File.Exists(realmFile)) {
32+
Console.WriteLine("Found realm file.");
33+
} else {
34+
Console.Error.WriteLine("Realm file does not exist, stop.");
35+
36+
return 1;
37+
}
38+
39+
if (File.Exists(outputFile))
40+
{
41+
Console.Error.WriteLine("Output file already exists, aborting.");
42+
43+
return 1;
44+
}
45+
46+
RealmConfiguration config = new(realmFile)
47+
{
48+
IsReadOnly = true,
49+
SchemaVersion = LazerSchemaVersion
50+
};
51+
52+
config.Schema = new[] {
53+
typeof(Beatmap),
54+
typeof(BeatmapCollection),
55+
typeof(BeatmapDifficulty),
56+
typeof(BeatmapMetadata),
57+
typeof(BeatmapSet),
58+
typeof(BeatmapUserSettings),
59+
typeof(RealmFile),
60+
typeof(RealmNamedFileUsage),
61+
typeof(RealmUser),
62+
typeof(Ruleset),
63+
typeof(ModPreset)
64+
};
65+
66+
try
67+
{
68+
db = Realm.GetInstance(config);
69+
}
70+
catch (RealmException re)
71+
{
72+
Console.Error.WriteLine($"Error opening database:\n\n{re.Message}");
73+
if (re.Message.Contains("is less than last set version"))
74+
{
75+
Console.Error.WriteLine("It seemed like the specified osu! (lazer) database is in a new format " +
76+
"which is not compatible with this version of CollectionDowngrader.");
77+
Console.Error.WriteLine("\nYou can go check the project page to see if there's a new release, " +
78+
"or file an Issue on GitHub to let me know it needs updating.");
79+
}
80+
81+
return 1;
82+
}
83+
84+
Console.WriteLine("The specified osu! (lazer) database is loaded successfully.");
85+
86+
List<BeatmapCollection> collections = db.All<BeatmapCollection>().ToList();
87+
int collectionCount = collections.Count;
88+
89+
Console.WriteLine($"Found {collectionCount} collections in the database.");
90+
91+
try
92+
{
93+
outStream = File.Open(outputFile, FileMode.CreateNew, FileAccess.Write);
94+
}
95+
catch (IOException ioe)
96+
{
97+
Console.Error.WriteLine($"Cannot create output file for writing: {ioe.Message}");
98+
99+
return 1;
100+
}
101+
102+
Console.WriteLine("Output file is created successfully, now start writing data.");
103+
104+
binWriter = new BinaryWriter(outStream);
105+
106+
// find the last modified collection and its modification date
107+
lastModCollection = collections.MaxBy(i => i.LastModified.Ticks);
108+
lastMod = lastModCollection is null ? DateTimeOffset.Now : lastModCollection.LastModified;
109+
110+
binWriter.Write((int) lastMod.Ticks); // last modification date
111+
binWriter.Write(collectionCount); // collection count
112+
113+
foreach (BeatmapCollection collection in collections)
114+
{
115+
binWriter.Write((byte) 0x0b);
116+
binWriter.Write(collection.Name); // collection name
117+
binWriter.Write(collection.BeatmapMD5Hashes.Count); // beatmap count
118+
119+
foreach (string hash in collection.BeatmapMD5Hashes)
120+
{
121+
binWriter.Write((byte) 0x0b);
122+
binWriter.Write(hash); // beatmap MD5 hash
123+
}
124+
}
125+
126+
binWriter.Close();
127+
outStream.Close();
128+
129+
Console.WriteLine("Everything is OK.");
130+
131+
return 0;
132+
}
133+
}
134+
}

CollectionDowngrader.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Realm" Version="10.20.0" />
12+
</ItemGroup>
13+
14+
</Project>

CollectionDowngrader.sln

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CollectionDowngrader", "CollectionDowngrader.csproj", "{F97772E9-AF01-45FB-928D-8A1F7B7A828D}"
4+
EndProject
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Debug|Any CPU = Debug|Any CPU
8+
Release|Any CPU = Release|Any CPU
9+
EndGlobalSection
10+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
11+
{F97772E9-AF01-45FB-928D-8A1F7B7A828D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12+
{F97772E9-AF01-45FB-928D-8A1F7B7A828D}.Debug|Any CPU.Build.0 = Debug|Any CPU
13+
{F97772E9-AF01-45FB-928D-8A1F7B7A828D}.Release|Any CPU.ActiveCfg = Release|Any CPU
14+
{F97772E9-AF01-45FB-928D-8A1F7B7A828D}.Release|Any CPU.Build.0 = Release|Any CPU
15+
EndGlobalSection
16+
EndGlobal

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
CollectionDowngrader
2+
=========================
3+
4+
> **Warning**
5+
>
6+
> This operation (Importing data from lazer to stable) is not officially supported by osu!, so use this at your own risk and don't forget to backup your data before downgrading!
7+
8+
A very simple and tiny program that converts osu! (lazer) collection data to osu! (stable) collection.db format.
9+
10+
## Usage
11+
12+
> **Note**
13+
>
14+
> You should already know where your osu! installations are located and what you are trying to do.
15+
16+
`CollectionDowngrader.exe <path to osu! (lazer) client.realm> <output osu! (stable) collection.db path>`
17+
18+
### Example
19+
20+
This command reads the collection data from osu! (lazer) at the default installation path and creates a collection.db
21+
that can be used in osu! (stable).
22+
23+
````shell
24+
CollectionDowngrader.exe %APPDATA%/osu/client.realm collection.db
25+
````
26+
27+
> **Warning**
28+
>
29+
> If you already have some collections in your osu! (stable) installation, then you should ***NEVER*** directly overwrite
30+
the existing collection.db with a new one. Instead, use [CollectionManager][CollectionManager] for merging data in multiple collection databases.
31+
32+
## Downloads
33+
34+
[GitHub Releases](../../releases)
35+
36+
## How to build
37+
38+
Just utilize your IDEs.
39+
40+
## Credits / See also
41+
42+
* [kabiiQ/BeatmapExporter][BeatmapExporter]: Inspiration of this project, all code for osu! (lazer) realm schema and
43+
the database parsing.
44+
* [Piotrekol/CollectionManager][CollectionManager]: Code for creating osu! (stable) collection.db files.
45+
46+
[BeatmapExporter]: https://github.com/kabiiQ/BeatmapExporter.git
47+
[CollectionManager]: https://github.com/Piotrekol/CollectionManager.git

0 commit comments

Comments
 (0)