Implement password changing

This commit is contained in:
Phillip Thelen 2019-03-27 15:09:59 +01:00
parent 121860c301
commit d7a10324f7
9 changed files with 340 additions and 276 deletions

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_medium">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/old_password"
android:layout_marginTop="@dimen/content_section_spacing"/>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/new_password"
android:layout_marginTop="@dimen/content_section_spacing"/>
<EditText
android:id="@+id/passwordEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/new_password_repeat"
android:layout_marginTop="@dimen/content_section_spacing"/>
<EditText
android:id="@+id/passwordRepeatEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -866,5 +866,8 @@
<string name="only_leader_create_challenge">Only leader can create Challenges</string>
<string name="create_party">Create Party</string>
<string name="add_local_authentication">Add Local Authentication</string>
<string name="old_password">Old Password</string>
<string name="new_password">New Password</string>
<string name="new_password_repeat">Repeat new Password</string>
</resources>

View file

@ -1,268 +1,271 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:title="@string/PS_contact_title">
<PreferenceCategory
android:title="@string/pref_account_header"
android:key="account_prefs"
android:layout="@layout/preference_category">
<PreferenceScreen android:title="@string/profile"
android:summary="@string/profile_summary"
android:key="profile"
android:layout="@layout/preference_child_summary">
<EditTextPreference android:key="display_name"
android:title="@string/display_name"
android:layout="@layout/preference_child_summary" />
<EditTextPreference android:key="photo_url"
android:title="@string/photo_url"
android:layout="@layout/preference_child_summary" />
<EditTextPreference android:key="about"
android:title="@string/about"
android:layout="@layout/preference_child_summary" />
</PreferenceScreen>
<PreferenceScreen
android:key="authentication"
android:title="@string/authentication"
android:summary="@string/authentication_summary"
app:key="authentication"
android:layout="@layout/preference_child_summary">
<Preference
android:key="login_name"
android:title="@string/login_name"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary" />
<Preference android:title="@string/confirm_username"
android:key="confirm_username"
android:layout="@layout/preference_child_summary" />
<Preference
android:key="email"
android:title="@string/email"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="add_local_auth"
android:title="@string/add_local_authentication"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="subscription_status"
android:title="@string/subscription_status"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<PreferenceCategory android:title="@string/danger_zone">
<Preference android:title="@string/reset_account"
android:key="reset_account"
android:layout="@layout/preference_child_summary" />
<Preference android:title="@string/delete_account"
android:key="delete_account"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
</PreferenceScreen>
<PreferenceScreen android:title="API"
android:key="api"
android:layout="@layout/preference_child_summary">
<Preference
android:key="@string/SP_userID"
android:title="@string/SP_userID_title"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_userID_summary"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="@string/SP_APIToken"
android:title="@string/SP_APIToken_title"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_APIToken_summary"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="SP_user_qr_code"
android:title="@string/SP_user_qr_code"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_user_qr_code"
android:layout="@layout/preference_child_summary"/>
</PreferenceScreen>
<Preference
android:key="choose_class"
tools:title="Change Class"
android:layout="@layout/preference_child_summary"/>
<Preference android:title="@string/fix_character_values"
app:key="fixCharacterValues"
android:layout="@layout/preference_child_summary"/>
<Preference android:title="@string/logout"
android:key="logout"
android:summary="@string/logout_description"
android:layout="@layout/preference_child_summary"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/app_settings"
android:layout="@layout/preference_category">
<ListPreference android:title="@string/pref_first_day_of_the_week_title"
android:key="@string/pref_first_day_of_the_week_key"
android:entries="@array/weekdays"
android:entryValues="@array/weekdayValues"
android:summary="@string/pref_first_day_of_the_week_summary"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/Language_title"
android:key="language"
android:entries="@array/Language"
android:entryValues="@array/LanguageValues"
android:summary="@string/Language_summary"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/AudioTheme_title"
android:key="audioTheme"
android:entries="@array/AudioThemes"
android:entryValues="@array/AudioValues"
android:summary="@string/AudioTheme_summary"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference android:title="@string/dailyDueDefaultView"
android:key="dailyDueDefaultView"
android:summary="@string/dailyDueDefaultViewDescription"
android:layout="@layout/preference_child_summary"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_reminder_header"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="use_reminder"
android:defaultValue="false"
android:title="@string/pref_reminder_checkbox"
android:layout="@layout/preference_child_summary"/>
<com.habitrpg.android.habitica.prefs.TimePreference
android:key="reminder_time"
android:defaultValue="19:30"
android:title="@string/pref_reminder_picker"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_cds_header"
android:layout="@layout/preference_category">
<com.habitrpg.android.habitica.prefs.TimePreference
android:key="cds_time"
android:defaultValue="00:00"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/push_notifications"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="usePushNotifications"
android:defaultValue="true"
android:title="@string/pref_push_notifications_checkbox"
android:layout="@layout/preference_child_summary"/>
<PreferenceScreen
android:key="pushNotifications"
android:title="@string/push_notifications"
android:summary="@string/push_notifications_sum"
android:layout="@layout/preference_child_summary">
<PreferenceCategory android:title="Push Notifications">
<CheckBoxPreference
android:key="preference_push_you_won_challenge"
android:defaultValue="true"
android:title="@string/preference_push_you_won_challenge"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_received_a_private_message"
android:defaultValue="true"
android:title="@string/preference_push_received_a_private_message"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_gifted_gems"
android:defaultValue="true"
android:title="@string/preference_push_gifted_gems"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_gifted_subscription"
android:defaultValue="true"
android:title="@string/preference_push_gifted_subscription"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_party"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_party"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_guild"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_guild"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_your_quest_has_begun"
android:defaultValue="true"
android:title="@string/preference_push_your_quest_has_begun"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_quest"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_quest"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_important_announcements"
android:defaultValue="true"
android:title="@string/preference_push_important_announcements"
android:layout="@layout/preference_child_summary"/>
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/maintenance"
android:layout="@layout/preference_category">
<Preference android:title="@string/reload_content"
android:key="reload_content"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/server"
android:key="server_url"
android:entries="@array/server_urls"
android:entryValues="@array/server_urls"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:title="@string/PS_contact_title">
<PreferenceCategory
android:title="@string/pref_account_header"
android:key="account_prefs"
android:layout="@layout/preference_category">
<PreferenceScreen android:title="@string/profile"
android:summary="@string/profile_summary"
android:key="profile"
android:layout="@layout/preference_child_summary">
<EditTextPreference android:key="display_name"
android:title="@string/display_name"
android:layout="@layout/preference_child_summary" />
<EditTextPreference android:key="photo_url"
android:title="@string/photo_url"
android:layout="@layout/preference_child_summary" />
<EditTextPreference android:key="about"
android:title="@string/about"
android:layout="@layout/preference_child_summary" />
</PreferenceScreen>
<PreferenceScreen
android:key="authentication"
android:title="@string/authentication"
android:summary="@string/authentication_summary"
app:key="authentication"
android:layout="@layout/preference_child_summary">
<Preference
android:key="login_name"
android:title="@string/login_name"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary" />
<Preference android:title="@string/confirm_username"
android:key="confirm_username"
android:layout="@layout/preference_child_summary" />
<Preference android:title="@string/change_password"
android:key="change_password"
android:layout="@layout/preference_child_summary" />
<Preference
android:key="email"
android:title="@string/email"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="add_local_auth"
android:title="@string/add_local_authentication"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="subscription_status"
android:title="@string/subscription_status"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:layout="@layout/preference_child_summary"/>
<PreferenceCategory android:title="@string/danger_zone">
<Preference android:title="@string/reset_account"
android:key="reset_account"
android:layout="@layout/preference_child_summary" />
<Preference android:title="@string/delete_account"
android:key="delete_account"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
</PreferenceScreen>
<PreferenceScreen android:title="API"
android:key="api"
android:layout="@layout/preference_child_summary">
<Preference
android:key="@string/SP_userID"
android:title="@string/SP_userID_title"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_userID_summary"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="@string/SP_APIToken"
android:title="@string/SP_APIToken_title"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_APIToken_summary"
android:layout="@layout/preference_child_summary"/>
<Preference
android:key="SP_user_qr_code"
android:title="@string/SP_user_qr_code"
android:selectable="true"
android:persistent="false"
android:shouldDisableView="false"
android:summary="@string/SP_user_qr_code"
android:layout="@layout/preference_child_summary"/>
</PreferenceScreen>
<Preference
android:key="choose_class"
tools:title="Change Class"
android:layout="@layout/preference_child_summary"/>
<Preference android:title="@string/fix_character_values"
app:key="fixCharacterValues"
android:layout="@layout/preference_child_summary"/>
<Preference android:title="@string/logout"
android:key="logout"
android:summary="@string/logout_description"
android:layout="@layout/preference_child_summary"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/app_settings"
android:layout="@layout/preference_category">
<ListPreference android:title="@string/pref_first_day_of_the_week_title"
android:key="@string/pref_first_day_of_the_week_key"
android:entries="@array/weekdays"
android:entryValues="@array/weekdayValues"
android:summary="@string/pref_first_day_of_the_week_summary"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/Language_title"
android:key="language"
android:entries="@array/Language"
android:entryValues="@array/LanguageValues"
android:summary="@string/Language_summary"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/AudioTheme_title"
android:key="audioTheme"
android:entries="@array/AudioThemes"
android:entryValues="@array/AudioValues"
android:summary="@string/AudioTheme_summary"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference android:title="@string/dailyDueDefaultView"
android:key="dailyDueDefaultView"
android:summary="@string/dailyDueDefaultViewDescription"
android:layout="@layout/preference_child_summary"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_reminder_header"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="use_reminder"
android:defaultValue="false"
android:title="@string/pref_reminder_checkbox"
android:layout="@layout/preference_child_summary"/>
<com.habitrpg.android.habitica.prefs.TimePreference
android:key="reminder_time"
android:defaultValue="19:30"
android:title="@string/pref_reminder_picker"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/pref_cds_header"
android:layout="@layout/preference_category">
<com.habitrpg.android.habitica.prefs.TimePreference
android:key="cds_time"
android:defaultValue="00:00"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/push_notifications"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="usePushNotifications"
android:defaultValue="true"
android:title="@string/pref_push_notifications_checkbox"
android:layout="@layout/preference_child_summary"/>
<PreferenceScreen
android:key="pushNotifications"
android:title="@string/push_notifications"
android:summary="@string/push_notifications_sum"
android:layout="@layout/preference_child_summary">
<PreferenceCategory android:title="Push Notifications">
<CheckBoxPreference
android:key="preference_push_you_won_challenge"
android:defaultValue="true"
android:title="@string/preference_push_you_won_challenge"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_received_a_private_message"
android:defaultValue="true"
android:title="@string/preference_push_received_a_private_message"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_gifted_gems"
android:defaultValue="true"
android:title="@string/preference_push_gifted_gems"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_gifted_subscription"
android:defaultValue="true"
android:title="@string/preference_push_gifted_subscription"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_party"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_party"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_guild"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_guild"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_your_quest_has_begun"
android:defaultValue="true"
android:title="@string/preference_push_your_quest_has_begun"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_invited_to_quest"
android:defaultValue="true"
android:title="@string/preference_push_invited_to_quest"
android:layout="@layout/preference_child_summary"/>
<CheckBoxPreference
android:key="preference_push_important_announcements"
android:defaultValue="true"
android:title="@string/preference_push_important_announcements"
android:layout="@layout/preference_child_summary"/>
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/maintenance"
android:layout="@layout/preference_category">
<Preference android:title="@string/reload_content"
android:key="reload_content"
android:layout="@layout/preference_child_summary"/>
<ListPreference android:title="@string/server"
android:key="server_url"
android:entries="@array/server_urls"
android:entryValues="@array/server_urls"
android:layout="@layout/preference_child_summary" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -241,7 +241,7 @@ interface ApiClient {
fun updateEmail(newEmail: String, password: String): Flowable<Void>
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void>
fun allocatePoint(stat: String): Flowable<Stats>

View file

@ -63,7 +63,7 @@ interface UserRepository : BaseRepository {
fun updateLoginName(newLoginName: String, password: String? = null): Maybe<User>
fun updateEmail(newEmail: String, password: String): Flowable<Void>
fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void>
fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void>
fun verifyUsername(username: String): Flowable<VerifyUsernameResponse>
fun allocatePoint(user: User?, stat: String): Flowable<Stats>

View file

@ -723,11 +723,11 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
return apiService.updateEmail(updateObject).compose(configureApiCallObserver())
}
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void> {
override fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void> {
val updateObject = HashMap<String, String>()
updateObject["newPassword"] = newPassword
updateObject["password"] = oldPassword
updateObject["confirmPassowrd"] = oldPasswordConfirmation
updateObject["newPassword"] = newPassword
updateObject["confirmPassword"] = newPasswordConfirmation
return apiService.updatePassword(updateObject).compose(configureApiCallObserver())
}

View file

@ -11,7 +11,6 @@ import com.habitrpg.android.habitica.models.inventory.CustomizationSet
import com.habitrpg.android.habitica.models.responses.SkillResponse
import com.habitrpg.android.habitica.models.responses.UnlockResponse
import com.habitrpg.android.habitica.models.responses.VerifyUsernameResponse
import com.habitrpg.android.habitica.models.social.ChatMessage
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.models.user.User
@ -211,8 +210,8 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun updateEmail(newEmail: String, password: String): Flowable<Void> =
apiClient.updateEmail(newEmail, password)
override fun updatePassword(newPassword: String, oldPassword: String, oldPasswordConfirmation: String): Flowable<Void> =
apiClient.updatePassword(newPassword, oldPassword, oldPasswordConfirmation)
override fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void> =
apiClient.updatePassword(oldPassword, newPassword, newPasswordConfirmation)
override fun allocatePoint(user: User?, stat: String): Flowable<Stats> {
if (user != null && user.isManaged) {

View file

@ -52,6 +52,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() {
private fun updateUserFields() {
configurePreference(findPreference("login_name"), user?.authentication?.localAuthentication?.username, false)
configurePreference(findPreference("email"), user?.authentication?.localAuthentication?.email, true)
findPreference("change_password").isVisible = user?.authentication?.localAuthentication?.email?.isNotEmpty() == true
findPreference("add_local_auth").isVisible = user?.authentication?.localAuthentication?.email?.isNotEmpty() != true
findPreference("confirm_username").isVisible = user?.flags?.isVerifiedUsername != true
}
@ -94,7 +95,25 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() {
}
private fun showChangePasswordDialog() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
val inflater = context?.layoutInflater
val view = inflater?.inflate(R.layout.dialog_edittext_change_pw, null)
val oldPasswordEditText = view?.findViewById<EditText>(R.id.editText)
val passwordEditText = view?.findViewById<EditText>(R.id.passwordEditText)
val passwordRepeatEditText = view?.findViewById<EditText>(R.id.passwordRepeatEditText)
context.notNull { context ->
val dialog = AlertDialog.Builder(context)
.setTitle(R.string.change_password)
.setPositiveButton(R.string.change) { thisDialog, _ ->
thisDialog.dismiss()
userRepository.updatePassword(oldPasswordEditText?.text.toString(), passwordEditText?.text.toString(), passwordRepeatEditText?.text.toString())
.subscribe(Consumer {
}, RxErrorHandler.handleEmptyError())
}
.setNegativeButton(R.string.action_cancel) { thisDialog, _ -> thisDialog.dismiss() }
.create()
dialog.setView(view)
dialog.show()
}
}
private fun showEmailDialog() {

View file

@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.models.inventory.Pet;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -57,11 +58,17 @@ public class ContentDeserializer implements JsonDeserializer<ContentResult> {
Map<String, Pet> premiumPets = context.deserialize(object.get("premiumPets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> questPets = context.deserialize(object.get("questPets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> whackyPets = context.deserialize(object.get("whackyPets"), new TypeToken<Map<String, Pet>>() {}.getType());
if (whackyPets == null) {
whackyPets = new HashMap<>();
}
Map<String, Mount> mounts = context.deserialize(object.get("mounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> specialMounts = context.deserialize(object.get("specialMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> premiumMounts = context.deserialize(object.get("premiumMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> questMounts = context.deserialize(object.get("questMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> whackyMounts = context.deserialize(object.get("whackyMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
if (whackyMounts == null) {
whackyMounts = new HashMap<>();
}
for (Egg egg : result.eggs) {
for (HatchingPotion potion : result.hatchingPotions) {