MirrorMoon EP — в поисках заветной планеты
Осторожно, спойлеры! Если вы в тупике и отчаянии, то эта статья должна помочь вам пройти игру. Плюс, технические подробности.
Предисловие
Это была самая странная, долгая и познавательная охота за ачивкой. Был изучен код игры, воссоздан API и реализован звездный навигатор для этой бесконечной космической одиссеи. Весь путь я проклинал разработчиков. Ведь, по сути, игра длится всего 10 минут. А дальше, дальше только пустота и надежда. Но как я рад теперь! Благодаря разработчикам и моему стремлению я многое узнал. Далее само прохождение.
Обсерватория
Перейдя на сторону B, мы начинаем путешествие. Поначалу, кажется, оно не имеет цели, но найдя первую обсерваторию, мы видим кружок. Это наша цель. В обсерватории мы наблюдаем созвездия. Выбрав ближайшие звезды, начинаем на них охоту. Если эти звезды уже открыты, то мы можем запускать навигатор и вычислять цель.
Звезды
Названия звезд генерируются из трех букв и двух случайных чисел. Буквы привязаны к координатам. Найдите любую звезду, где первые две буквы будут совпадать с искомой звездой. Прыгайте туда и ищите, непосредственно, нужную вам звезду. Она должна быть рядом. Пометив нужные звезды, идем в навигатор.
Финал
Выбираем сезон. Помечаем все нужные звезды. Находясь на планете с обсерваторией, включаем режим OBS. Просчитываем расположение звезд, перекрестие должно указывать на загадочную планету. Выходим из режима OBS. Включаем ортогональную проекцию. Теперь мы видим карту как в игре. Идем в игру и подгоняем вид. Где-то в центре мы найдем далекую звезду и прыгнем туда, в надежде…
Реализация
MirrorMoon EP создан на Unity 3D. Поэтому было не сложно декомпилировать код. Алгоритм следующий. Открываем урл — http://www.santaragione.com/NTF/MMEP/notification_1_1.php. Нас интересует последняя строчка. В ней находится кол-во сезонов. Это число используется для генерации хэша. Также нам потребуется секретный ключ thankyouforhackingmysecretkey1234568
. О нет, нас раскусили :)
string getHash(string text) {
MD5 md5Hash = MD5.Create ();
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(text));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
return sBuilder.ToString();
}
string availableSeasons = urlopen("http://www.santaragione.com/NTF/MMEP/notification_1_1.php").Split('\n')[6];
string hash = getHash (availableSeasons + secretKey);
Теперь мы можем получить список сезонов: 1_000022,2_000077,3_000100,4_000099
… Пары из номера и сида, разделенные запятыми.
string baseUrl = "http://www.mirrormoongame.com/mmphp/";
string url = string.Format ("seasons.php?Seasons={0}&hash={1}", availableSeasons, hash);
string data = Utils.urlopen (baseUrl + url);
Похожим образом получаем звезды в выбранном сезоне:
string hash = Utils.getHash (seed + secretKey);
string url = string.Format ("full_star.php?Seed={0}&hash={1}", seed, hash);
string data = Utils.urlopen(baseUrl + url);
foreach (string pair in data.Split(',')) {
string name = pair.Substring(16, 6).Trim();
string pos = pair.Substring(22);
float x = Convert.ToSingle(pos.Substring(0, 3));
float y = Convert.ToSingle(pos.Substring(3, 3));
float z = Convert.ToSingle(pos.Substring(6));
GameObject star = Instantiate(starPrefab) as GameObject;
star.GetComponent().title = name;
star.transform.position = new Vector3(x, y, z);
stars.Add(star);
}
Это пары из координат и название звезды — 000022349205629_LIAMD 349205629,000022490453661_PAX4 490453661,000022570586427_RHUMB 570586427
…
Пожалуй, это всё… или нет? За кулисами остался алгоритм добавления звезд. Это я оставлю истинным ценителям цифрового творчества. Не хулиганьте.
P.S.: Прохождение актуально только для онлайнового режима. Навигатор можно скачать здесь, исходники там же.
P.P. S.: Описанные события произошли в марте 2014 года. Больше двух лет пост лежал в черновиках, потому что не было технической части в рассказе. Теперь это исправлено.