Archipelago/worlds/musedash/MuseDashCollection.py

145 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from .Items import SongData, AlbumData
from typing import Dict, List, Optional
from collections import ChainMap
def load_text_file(name: str) -> str:
import pkgutil
return pkgutil.get_data(__name__, name).decode()
class MuseDashCollections:
"""Contains all the data of Muse Dash, loaded from MuseDashData.txt."""
STARTING_CODE = 2900000
MUSIC_SHEET_NAME: str = "Music Sheet"
MUSIC_SHEET_CODE: int = STARTING_CODE
FREE_ALBUMS = [
"Default Music",
"Budget Is Burning: Nano Core",
"Budget Is Burning Vol.1",
]
DIFF_OVERRIDES = [
"MuseDash ka nanika hi",
"Rush-Hour",
"Find this Month's Featured Playlist",
"PeroPero in the Universe",
]
album_items: Dict[str, AlbumData] = {}
album_locations: Dict[str, int] = {}
song_items: Dict[str, SongData] = {}
song_locations: Dict[str, int] = {}
vfx_trap_items: Dict[str, int] = {
"Bad Apple Trap": STARTING_CODE + 1,
"Pixelate Trap": STARTING_CODE + 2,
"Random Wave Trap": STARTING_CODE + 3,
"Shadow Edge Trap": STARTING_CODE + 4,
"Chromatic Aberration Trap": STARTING_CODE + 5,
"Background Freeze Trap": STARTING_CODE + 6,
"Gray Scale Trap": STARTING_CODE + 7,
}
sfx_trap_items: Dict[str, int] = {
"Nyaa SFX Trap": STARTING_CODE + 8,
"Error SFX Trap": STARTING_CODE + 9,
}
item_names_to_id = ChainMap({}, sfx_trap_items, vfx_trap_items)
location_names_to_id = ChainMap(song_locations, album_locations)
def __init__(self) -> None:
self.item_names_to_id[self.MUSIC_SHEET_NAME] = self.MUSIC_SHEET_CODE
item_id_index = self.STARTING_CODE + 50
full_file = load_text_file("MuseDashData.txt")
seen_albums = set()
for line in full_file.splitlines():
line = line.strip()
sections = line.split("|")
album = sections[2]
if album not in seen_albums:
seen_albums.add(album)
self.album_items[album] = AlbumData(item_id_index)
item_id_index += 1
# Data is in the format 'Song|UID|Album|StreamerMode|EasyDiff|HardDiff|MasterDiff|SecretDiff'
song_name = sections[0]
# [1] is used in the client copy to make sure item id's match.
song_is_free = album in self.FREE_ALBUMS
steamer_mode = sections[3] == "True"
if song_name in self.DIFF_OVERRIDES:
# Note: These difficulties may not actually be representative of these songs.
# The game does not provide these difficulties so they have to be filled in.
diff_of_easy = 4
diff_of_hard = 7
diff_of_master = 10
else:
diff_of_easy = self.parse_song_difficulty(sections[4])
diff_of_hard = self.parse_song_difficulty(sections[5])
diff_of_master = self.parse_song_difficulty(sections[6])
self.song_items[song_name] = SongData(item_id_index, song_is_free, steamer_mode,
diff_of_easy, diff_of_hard, diff_of_master)
item_id_index += 1
self.item_names_to_id.update({name: data.code for name, data in self.song_items.items()})
self.item_names_to_id.update({name: data.code for name, data in self.album_items.items()})
location_id_index = self.STARTING_CODE
for name in self.album_items.keys():
self.album_locations[f"{name}-0"] = location_id_index
self.album_locations[f"{name}-1"] = location_id_index + 1
location_id_index += 2
for name in self.song_items.keys():
self.song_locations[f"{name}-0"] = location_id_index
self.song_locations[f"{name}-1"] = location_id_index + 1
location_id_index += 2
def get_songs_with_settings(self, dlc_songs: bool, streamer_mode_active: bool,
diff_lower: int, diff_higher: int) -> List[str]:
"""Gets a list of all songs that match the filter settings. Difficulty thresholds are inclusive."""
filtered_list = []
for songKey, songData in self.song_items.items():
if not dlc_songs and not songData.song_is_free:
continue
if streamer_mode_active and not songData.streamer_mode:
continue
if songData.easy is not None and diff_lower <= songData.easy <= diff_higher:
filtered_list.append(songKey)
continue
if songData.hard is not None and diff_lower <= songData.hard <= diff_higher:
filtered_list.append(songKey)
continue
if songData.master is not None and diff_lower <= songData.master <= diff_higher:
filtered_list.append(songKey)
continue
return filtered_list
def parse_song_difficulty(self, difficulty: str) -> Optional[int]:
"""Attempts to parse the song difficulty."""
if len(difficulty) <= 0 or difficulty == "?" or difficulty == "¿":
return None
# 0 is used as a filler and no songs actually have a 0 difficulty song.
if difficulty == "0":
return None
# Curse the 2023 april fools update. Used on 3rd Avenue.
if difficulty == "":
return 10
return int(difficulty)