115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
from objects import glob
|
|
from common.ripple import userUtils
|
|
from os.path import dirname, basename, isfile
|
|
import glob as _glob
|
|
import importlib
|
|
import json
|
|
from secret.achievements import common
|
|
|
|
def load_achievements():
|
|
"""Load all the achievements from handler list into glob.achievementClasses,
|
|
and sets glob.ACHIEVEMENTS_VERSION to the highest version number in our achievement list.
|
|
"""
|
|
|
|
modules = _glob.glob("secret/achievements/handlers/*.py")
|
|
modules = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith("__init__.py")]
|
|
# ^ cat face
|
|
|
|
for module in modules:
|
|
module = importlib.import_module("secret.achievements.handlers." + module)
|
|
module.load()
|
|
if module.ORDER in glob.achievementClasses:
|
|
print("\n!!! FOUND OVERLAPPING ACHIEVEMENT ORDER FOR {}!!!".format(module.ORDER))
|
|
print("Unable to load {} due to {} already loaded in slot {}\n".format(module.__name__, glob.achievementClasses[module.ORDER].__name__, module.ORDER))
|
|
continue
|
|
glob.achievementClasses[module.ORDER] = module
|
|
glob.ACHIEVEMENTS_VERSION = max(glob.ACHIEVEMENTS_VERSION, module.VERSION)
|
|
|
|
print("Loaded {} achievement classes!".format(len(glob.achievementClasses)), end=" ")
|
|
|
|
def unlock_achievements_update(userID, version):
|
|
"""Scans the user for past achievements they should have unlocked
|
|
|
|
Arguments:
|
|
userID {int} -- User id of a player
|
|
version {int} -- Last achivement version the player had
|
|
|
|
Returns:
|
|
Array -- List of achievements
|
|
"""
|
|
achievements = []
|
|
|
|
# Scan all past achivement versions from the user's achivement version to the latest
|
|
index = 1
|
|
for handler in glob.achievementClasses.values():
|
|
if handler.VERSION > version:
|
|
achievements += [x + index for x in handler.update(userID)]
|
|
index += handler.LENGTH
|
|
|
|
# Update achivement version for user
|
|
userUtils.updateAchievementsVersion(userID)
|
|
|
|
return achievements
|
|
|
|
def unlock_achievements(score, beatmap, user_data):
|
|
"""Return array of achievements the current play recived
|
|
|
|
Arguments:
|
|
score {Score} -- Score data recived from replay
|
|
beatmap {Beatmap} -- Played beatmap
|
|
user_data {dict} -- Info about the current player
|
|
|
|
Returns:
|
|
Array -- List of achievements for the current play
|
|
"""
|
|
achievements = []
|
|
|
|
userID = userUtils.getID(score.playerName)
|
|
user_cache = common.get_usercache(userID)
|
|
|
|
# Get current gamemode and change value std to osu
|
|
gamemode_index = score.gameMode
|
|
|
|
# Check if user should run achivement recheck
|
|
if user_cache["version"] < glob.ACHIEVEMENTS_VERSION:
|
|
achievements += unlock_achievements_update(userID, user_cache["version"])
|
|
|
|
# Check if gameplay should get new achivement
|
|
index = 1
|
|
for handler in glob.achievementClasses.values():
|
|
achievements += [x + index for x in handler.handle(gamemode_index, score, beatmap, user_data)]
|
|
index += handler.LENGTH
|
|
|
|
# Add pending achievements that were added though redis or mysql
|
|
achievements += [-x for x in user_cache["achievements"] if x < 0] # Negative achievements id's means its pending
|
|
|
|
# Remove pending achievements from redis object since we added it to the post achievements
|
|
user_cache["achievements"] = [x for x in user_cache["achievements"] if x > 0]
|
|
|
|
# Remove duplicated achievements (incase of unlock_achievements_update adding stuff)
|
|
achievements = list(set(achievements))
|
|
|
|
# Remove already achived achievements from list
|
|
achievements = [x for x in achievements if x not in user_cache["achievements"]]
|
|
|
|
user_cache["achievements"] += achievements
|
|
glob.redis.set("lets:user_achievement_cache:{}".format(userID), json.dumps(user_cache), 1800)
|
|
|
|
for achievement in achievements:
|
|
userUtils.unlockAchievement(userID, achievement)
|
|
|
|
return achievements
|
|
|
|
def achievements_response(achievements):
|
|
achievement_objects = []
|
|
|
|
index = 1
|
|
for handler in glob.achievementClasses.values():
|
|
achievement_objects += [handler.ACHIEVEMENTS[x - index] for x in achievements if len(handler.ACHIEVEMENTS) > x - index and x - index >= 0]
|
|
index += handler.LENGTH
|
|
|
|
achievements_packed = []
|
|
for achievement_object in achievement_objects:
|
|
achievements_packed.append("+".join([achievement_object["icon"], achievement_object["name"], achievement_object["description"]]))
|
|
|
|
return "/".join(achievements_packed) |