diff --git a/.env b/.env index 6ac42ba97b4..7d21f7d3208 100644 --- a/.env +++ b/.env @@ -1,3 +1,5 @@ VITE_BYPASS_LOGIN=0 VITE_BYPASS_TUTORIAL=0 -VITE_SERVER_URL=http://localhost:8001 \ No newline at end of file +VITE_SERVER_URL=http://localhost:8001 +VITE_DISCORD_CLIENT_ID=1248062921129459756 +VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com diff --git a/.env.beta b/.env.beta index 8d1e93b3277..3f23d53ea3e 100644 --- a/.env.beta +++ b/.env.beta @@ -1,3 +1,5 @@ VITE_BYPASS_LOGIN=0 VITE_BYPASS_TUTORIAL=0 -VITE_SERVER_URL=https://api.beta.pokerogue.net \ No newline at end of file +VITE_SERVER_URL=https://api.beta.pokerogue.net +VITE_DISCORD_CLIENT_ID=1248062921129459756 +VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com \ No newline at end of file diff --git a/.env.development b/.env.development index e9180f0875d..eaf1d1403f2 100644 --- a/.env.development +++ b/.env.development @@ -1,3 +1,5 @@ VITE_BYPASS_LOGIN=1 VITE_BYPASS_TUTORIAL=0 -VITE_SERVER_URL=http://localhost:8001 \ No newline at end of file +VITE_SERVER_URL=http://localhost:8001 +VITE_DISCORD_CLIENT_ID=1234567890 +VITE_GOOGLE_CLIENT_ID=1234567890 diff --git a/.env.production b/.env.production index 74818d41a12..4d4d8a3aaf3 100644 --- a/.env.production +++ b/.env.production @@ -1,3 +1,5 @@ VITE_BYPASS_LOGIN=0 VITE_BYPASS_TUTORIAL=0 -VITE_SERVER_URL=https://api.pokerogue.net \ No newline at end of file +VITE_SERVER_URL=https://api.pokerogue.net +VITE_DISCORD_CLIENT_ID=1248062921129459756 +VITE_GOOGLE_CLIENT_ID=955345393540-2k6lfftf0fdnb0krqmpthjnqavfvvf73.apps.googleusercontent.com \ No newline at end of file diff --git a/public/images/ui/discord.png b/public/images/ui/discord.png new file mode 100644 index 00000000000..1cd833854b0 Binary files /dev/null and b/public/images/ui/discord.png differ diff --git a/public/images/ui/google.png b/public/images/ui/google.png new file mode 100644 index 00000000000..82760552886 Binary files /dev/null and b/public/images/ui/google.png differ diff --git a/public/images/ui/legacy/discord.png b/public/images/ui/legacy/discord.png new file mode 100644 index 00000000000..eac801cdd9d Binary files /dev/null and b/public/images/ui/legacy/discord.png differ diff --git a/public/images/ui/legacy/google.png b/public/images/ui/legacy/google.png new file mode 100644 index 00000000000..82760552886 Binary files /dev/null and b/public/images/ui/legacy/google.png differ diff --git a/src/account.ts b/src/account.ts index 4d19513908f..7fd1d208496 100644 --- a/src/account.ts +++ b/src/account.ts @@ -4,6 +4,8 @@ import * as Utils from "./utils"; export interface UserInfo { username: string; lastSessionSlot: integer; + discordId: string; + googleId: string; } export let loggedInUser: UserInfo = null; @@ -11,13 +13,13 @@ export let loggedInUser: UserInfo = null; export const clientSessionId = Utils.randomString(32); export function initLoggedInUser(): void { - loggedInUser = { username: "Guest", lastSessionSlot: -1 }; + loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: ""}; } export function updateUserInfo(): Promise<[boolean, integer]> { return new Promise<[boolean, integer]>(resolve => { if (bypassLogin) { - loggedInUser = { username: "Guest", lastSessionSlot: -1 }; + loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "" }; let lastSessionSlot = -1; for (let s = 0; s < 5; s++) { if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) { diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 15cd295d23c..aca2d5e6c41 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -154,6 +154,8 @@ export class LoadingScene extends SceneBase { this.loadImage("select_gen_cursor_highlight", "ui"); this.loadImage("saving_icon", "ui"); + this.loadImage("discord", "ui"); + this.loadImage("google", "ui"); this.loadImage("default_bg", "arenas"); // Load arena images diff --git a/src/locales/de/menu-ui-handler.ts b/src/locales/de/menu-ui-handler.ts index 0338ba6f399..6d461d286af 100644 --- a/src/locales/de/menu-ui-handler.ts +++ b/src/locales/de/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "Wähle einen Slot zum Exportieren.", "importData": "Daten importieren", "exportData": "Daten exportieren", + "linkDiscord": "Discord verbinden", + "unlinkDiscord": "Discord trennen", + "linkGoogle": "Google verbinden", + "unlinkGoogle": "Google trennen", "cancel": "Abbrechen", "losingProgressionWarning": "Du wirst jeglichen Fortschritt seit Anfang dieses Kampfes verlieren. Fortfahren?", "noEggs": "Du brütest aktuell keine Eier aus!" diff --git a/src/locales/de/menu.ts b/src/locales/de/menu.ts index cb8cf9a318a..bd0173a3383 100644 --- a/src/locales/de/menu.ts +++ b/src/locales/de/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Benutzername", "password": "Passwort", "login": "Anmelden", + "orUse": "Or use", "register": "Registrieren", "emptyUsername": "Benutzername darf nicht leer sein.", "invalidLoginUsername": "Der eingegebene Benutzername ist ungültig.", diff --git a/src/locales/en/menu-ui-handler.ts b/src/locales/en/menu-ui-handler.ts index 97d6e38a099..6eb680544ed 100644 --- a/src/locales/en/menu-ui-handler.ts +++ b/src/locales/en/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "Select a slot to export from.", "importData": "Import Data", "exportData": "Export Data", + "linkDiscord": "Link Discord", + "unlinkDiscord": "Unlink Discord", + "linkGoogle": "Link Google", + "unlinkGoogle": "Unlink Google", "cancel": "Cancel", "losingProgressionWarning": "You will lose any progress since the beginning of the battle. Proceed?", "noEggs": "You are not hatching\nany eggs at the moment!" diff --git a/src/locales/en/menu.ts b/src/locales/en/menu.ts index 542399fee51..c6a767def50 100644 --- a/src/locales/en/menu.ts +++ b/src/locales/en/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Username", "password": "Password", "login": "Login", + "orUse": "Or use", "register": "Register", "emptyUsername": "Username must not be empty", "invalidLoginUsername": "The provided username is invalid", diff --git a/src/locales/es/menu-ui-handler.ts b/src/locales/es/menu-ui-handler.ts index bf71c2b390b..e38ac4eab3d 100644 --- a/src/locales/es/menu-ui-handler.ts +++ b/src/locales/es/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "Selecciona una ranura para exportar.", "importData": "Importar Datos", "exportData": "Exportar Datos", + "linkDiscord": "Conectar Discord", + "unlinkDiscord": "Desconectar Discord", + "linkGoogle": "Conectar Google", + "unlinkGoogle": "Desconectar Google", "cancel": "Cancelar", "losingProgressionWarning": "Perderás cualquier progreso desde el inicio de la batalla. ¿Continuar?", "noEggs": "You are not hatching\nany eggs at the moment!" diff --git a/src/locales/es/menu.ts b/src/locales/es/menu.ts index 85d9d50f015..524464f32f7 100644 --- a/src/locales/es/menu.ts +++ b/src/locales/es/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Usuario", "password": "Contraseña", "login": "Iniciar Sesión", + "orUse": "O usa", "register": "Registrarse", "emptyUsername": "El usuario no puede estar vacío", "invalidLoginUsername": "El usuario no es válido", diff --git a/src/locales/fr/menu-ui-handler.ts b/src/locales/fr/menu-ui-handler.ts index 3eabc132f6b..70cf05fe984 100644 --- a/src/locales/fr/menu-ui-handler.ts +++ b/src/locales/fr/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "Sélectionnez l’emplacement depuis lequel exporter les données.", "importData": "Importer données", "exportData": "Exporter données", + "linkDiscord": "Link Discord", + "unlinkDiscord": "Unlink Discord", + "linkGoogle": "Link Google", + "unlinkGoogle": "Unlink Google", "cancel": "Retour", "losingProgressionWarning": "Vous allez perdre votre progression depuis le début du combat. Continuer ?", "noEggs": "Vous ne faites actuellement\néclore aucun Œuf !" diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index 3aee5c42103..aeb6ad9ed7e 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -12,6 +12,7 @@ export const menu: SimpleTranslationEntries = { "username": "Nom d’utilisateur", "password": "Mot de passe", "login": "Connexion", + "orUse": "Ou utilisez", "register": "S’inscrire", "emptyUsername": "Le nom d’utilisateur est manquant", "invalidLoginUsername": "Le nom d’utilisateur n’est pas valide", diff --git a/src/locales/it/menu-ui-handler.ts b/src/locales/it/menu-ui-handler.ts index 5bd845448aa..58e48574476 100644 --- a/src/locales/it/menu-ui-handler.ts +++ b/src/locales/it/menu-ui-handler.ts @@ -16,6 +16,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "importSlotSelect": "Seleziona uno slot in cui importare.", "exportSession": "Esporta sessione", "exportSlotSelect": "Seleziona uno slot da cui esportare.", + "linkDiscord": "Link Discord", + "unlinkDiscord": "Unlink Discord", + "linkGoogle": "Link Google", + "unlinkGoogle": "Unlink Google", "importData": "Importa dati", "exportData": "Esporta dati", "cancel": "Annulla", diff --git a/src/locales/it/menu.ts b/src/locales/it/menu.ts index 3e083d3d374..8df8c2db9b3 100644 --- a/src/locales/it/menu.ts +++ b/src/locales/it/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Nome utente", "password": "Password", "login": "Accedi", + "orUse": "Or use", "register": "Registrati", "emptyUsername": "Nome utente mancante!", "invalidLoginUsername": "Nome utente non valido!", diff --git a/src/locales/ko/menu-ui-handler.ts b/src/locales/ko/menu-ui-handler.ts index 3bd412bc5ea..2e036f49b4d 100644 --- a/src/locales/ko/menu-ui-handler.ts +++ b/src/locales/ko/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "내보낼 슬롯을 골라주세요.", "importData": "데이터 불러오기", "exportData": "데이터 내보내기", + "linkDiscord": "디스코드 연동", + "unlinkDiscord": "디스코드 연동해제", + "linkGoogle": "구글 연동", + "unlinkGoogle": "구글 연동해제", "cancel": "취소", "losingProgressionWarning": "전투 시작으로부터의 진행 상황을 잃게 됩니다. 계속하시겠습니까?", "noEggs": "부화중인 알이 없습니다!" diff --git a/src/locales/ko/menu.ts b/src/locales/ko/menu.ts index 0e12b3bd15e..1025ccff5c5 100644 --- a/src/locales/ko/menu.ts +++ b/src/locales/ko/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "이름", "password": "비밀번호", "login": "로그인", + "orUse": "혹은", "register": "등록", "emptyUsername": "이름은 비워둘 수 없습니다", "invalidLoginUsername": "사용할 수 없는 이름입니다", diff --git a/src/locales/pt_BR/bgm-name.ts b/src/locales/pt_BR/bgm-name.ts index 87d90dabc9d..a31dd458374 100644 --- a/src/locales/pt_BR/bgm-name.ts +++ b/src/locales/pt_BR/bgm-name.ts @@ -1,89 +1,89 @@ import { SimpleTranslationEntries } from "#app/interfaces/locales"; export const bgmName: SimpleTranslationEntries = { - "music": "Music: ", - "missing_entries" : "{{name}}", - "battle_kanto_champion": "B2W2 Kanto Champion Battle", - "battle_johto_champion": "B2W2 Johto Champion Battle", - "battle_hoenn_champion": "B2W2 Hoenn Champion Battle", - "battle_sinnoh_champion": "B2W2 Sinnoh Champion Battle", - "battle_champion_alder": "BW Unova Champion Battle", - "battle_champion_iris": "B2W2 Unova Champion Battle", - "battle_kalos_champion": "XY Kalos Champion Battle", - "battle_alola_champion": "USUM Alola Champion Battle", - "battle_galar_champion": "SWSH Galar Champion Battle", - "battle_champion_geeta": "SV Champion Geeta Battle", - "battle_champion_nemona": "SV Champion Nemona Battle", - "battle_champion_kieran": "SV Champion Kieran Battle", - "battle_hoenn_elite": "ORAS Elite Four Battle", - "battle_unova_elite": "BW Elite Four Battle", - "battle_kalos_elite": "XY Elite Four Battle", - "battle_alola_elite": "SM Elite Four Battle", - "battle_galar_elite": "SWSH League Tournament Battle", - "battle_paldea_elite": "SV Elite Four Battle", - "battle_bb_elite": "SV BB League Elite Four Battle", - "battle_final_encounter": "PMD RTDX Rayquaza's Domain", - "battle_final": "BW Ghetsis Battle", - "battle_kanto_gym": "B2W2 Kanto Gym Battle", - "battle_johto_gym": "B2W2 Johto Gym Battle", - "battle_hoenn_gym": "B2W2 Hoenn Gym Battle", - "battle_sinnoh_gym": "B2W2 Sinnoh Gym Battle", - "battle_unova_gym": "BW Unova Gym Battle", - "battle_kalos_gym": "XY Kalos Gym Battle", - "battle_galar_gym": "SWSH Galar Gym Battle", - "battle_paldea_gym": "SV Paldea Gym Battle", - "battle_legendary_kanto": "XY Kanto Legendary Battle", - "battle_legendary_raikou": "HGSS Raikou Battle", - "battle_legendary_entei": "HGSS Entei Battle", - "battle_legendary_suicune": "HGSS Suicune Battle", - "battle_legendary_lugia": "HGSS Lugia Battle", - "battle_legendary_ho_oh": "HGSS Ho-oh Battle", - "battle_legendary_regis_g5": "B2W2 Legendary Titan Battle", - "battle_legendary_regis_g6": "ORAS Legendary Titan Battle", - "battle_legendary_gro_kyo": "ORAS Groudon & Kyogre Battle", - "battle_legendary_rayquaza": "ORAS Rayquaza Battle", - "battle_legendary_deoxys": "ORAS Deoxys Battle", - "battle_legendary_lake_trio": "ORAS Lake Guardians Battle", - "battle_legendary_sinnoh": "ORAS Sinnoh Legendary Battle", - "battle_legendary_dia_pal": "ORAS Dialga & Palkia Battle", - "battle_legendary_giratina": "ORAS Giratina Battle", - "battle_legendary_arceus": "HGSS Arceus Battle", - "battle_legendary_unova": "BW Unova Legendary Battle", - "battle_legendary_kyurem": "BW Kyurem Battle", - "battle_legendary_res_zek": "BW Reshiram & Zekrom Battle", - "battle_legendary_xern_yvel": "XY Xerneas & Yveltal Battle", - "battle_legendary_tapu": "SM Tapu Battle", - "battle_legendary_sol_lun": "SM Solgaleo & Lunala Battle", - "battle_legendary_ub": "SM Ultra Beast Battle", - "battle_legendary_dusk_dawn": "USUM Dusk Mane & Dawn Wings Necrozma Battle", - "battle_legendary_ultra_nec": "USUM Ultra Necrozma Battle", - "battle_legendary_zac_zam": "SWSH Zacian & Zamazenta Battle", - "battle_legendary_glas_spec": "SWSH Glastrier & Spectrier Battle", - "battle_legendary_calyrex": "SWSH Calyrex Battle", - "battle_legendary_birds_galar": "SWSH Galarian Legendary Birds Battle", - "battle_legendary_ruinous": "SV Treasures of Ruin Battle", - "battle_legendary_kor_mir": "SV Depths of Area Zero Battle", - "battle_legendary_loyal_three": "SV Loyal Three Battle", - "battle_legendary_ogerpon": "SV Ogerpon Battle", - "battle_legendary_terapagos": "SV Terapagos Battle", - "battle_legendary_pecharunt": "SV Pecharunt Battle", - "battle_rival": "BW Rival Battle", - "battle_rival_2": "BW N Battle", - "battle_rival_3": "BW Final N Battle", - "battle_trainer": "BW Trainer Battle", - "battle_wild": "BW Wild Battle", - "battle_wild_strong": "BW Strong Wild Battle", - "end_summit": "PMD RTDX Sky Tower Summit", - "battle_rocket_grunt": "HGSS Team Rocket Battle", - "battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle", - "battle_galactic_grunt": "BDSP Team Galactic Battle", - "battle_plasma_grunt": "BW Team Plasma Battle", - "battle_flare_grunt": "XY Team Flare Battle", - "battle_rocket_boss": "USUM Giovanni Battle", - "battle_aqua_magma_boss": "ORAS Archie & Maxie Battle", - "battle_galactic_boss": "BDSP Cyrus Battle", - "battle_plasma_boss": "B2W2 Ghetsis Battle", - "battle_flare_boss": "XY Lysandre Battle", + "music": "Música: ", + "missing_entries": "{{name}}", + "battle_kanto_champion": "B2W2 Batalha do Campeão de Kanto", + "battle_johto_champion": "B2W2 Batalha do Campeão de Johto", + "battle_hoenn_champion": "B2W2 Batalha do Campeão de Hoenn", + "battle_sinnoh_champion": "B2W2 Batalha do Campeão de Sinnoh", + "battle_champion_alder": "BW Batalha do Campeão de Unova", + "battle_champion_iris": "B2W2 Batalha do Campeão de Unova", + "battle_kalos_champion": "XY Batalha do Campeão de Kalos", + "battle_alola_champion": "USUM Batalha do Campeão de Alola", + "battle_galar_champion": "SWSH Batalha do Campeão de Galar", + "battle_champion_geeta": "SV Batalha da Campeã Geeta", + "battle_champion_nemona": "SV Batalha da Campeã Nemona", + "battle_champion_kieran": "SV Batalha do Campeão Kieran", + "battle_hoenn_elite": "ORAS Batalha da Elite dos Quatro", + "battle_unova_elite": "BW Batalha da Elite dos Quatro", + "battle_kalos_elite": "XY Batalha da Elite dos Quatro", + "battle_alola_elite": "SM Batalha da Elite dos Quatro", + "battle_galar_elite": "SWSH Batalha da Liga Pokémon", + "battle_paldea_elite": "SV Batalha da Elite dos Quatro", + "battle_bb_elite": "SV Liga BB Batalha da Elite dos Quatro", + "battle_final_encounter": "PMD RTDX Domínio do Rayquaza", + "battle_final": "BW Batalha do Ghetsis", + "battle_kanto_gym": "B2W2 Batalha de Ginásio de Kanto", + "battle_johto_gym": "B2W2 Batalha de Ginásio de Johto", + "battle_hoenn_gym": "B2W2 Batalha de Ginásio de Hoenn", + "battle_sinnoh_gym": "B2W2 Batalha de Ginásio de Sinnoh", + "battle_unova_gym": "BW Batalha de Ginásio de Unova", + "battle_kalos_gym": "XY Batalha de Ginásio de Kalos", + "battle_galar_gym": "SWSH Batalha de Ginásio de Galar", + "battle_paldea_gym": "SV Batalha de Ginásio de Paldea", + "battle_legendary_kanto": "XY Batalha dos Lendários de Kanto", + "battle_legendary_raikou": "HGSS Batalha do Raikou", + "battle_legendary_entei": "HGSS Batalha do Entei", + "battle_legendary_suicune": "HGSS Batalha do Suicune", + "battle_legendary_lugia": "HGSS Batalha do Lugia", + "battle_legendary_ho_oh": "HGSS Batalha do Ho-Oh", + "battle_legendary_regis_g5": "B2W2 Batalha dos Titãs Lendários", + "battle_legendary_regis_g6": "ORAS Batalha dos Titãs Lendários", + "battle_legendary_gro_kyo": "ORAS Batalha do Groudon & Kyogre", + "battle_legendary_rayquaza": "ORAS Batalha do Rayquaza", + "battle_legendary_deoxys": "ORAS Batalha do Deoxys", + "battle_legendary_lake_trio": "ORAS Batalha do Trio dos Lagos", + "battle_legendary_sinnoh": "ORAS Batalha dos Lendários de Sinnoh", + "battle_legendary_dia_pal": "ORAS Batalha do Dialga & Palkia", + "battle_legendary_giratina": "ORAS Batalha do Giratina", + "battle_legendary_arceus": "HGSS Batalha do Arceus", + "battle_legendary_unova": "BW Batalha dos Lendários de Unova", + "battle_legendary_kyurem": "BW Batalha do Kyurem", + "battle_legendary_res_zek": "BW Batalha do Reshiram & Zekrom", + "battle_legendary_xern_yvel": "XY Batalha do Xerneas & Yveltal", + "battle_legendary_tapu": "SM Batalha dos Guardiões de Alola", + "battle_legendary_sol_lun": "SM Batalha do Solgaleo & Lunala", + "battle_legendary_ub": "SM Batalha das Ultracriaturas", + "battle_legendary_dusk_dawn": "USUM Batalha do Necrozma Crepúsculo & Alvorada", + "battle_legendary_ultra_nec": "USUM Batalha do Necrozma Ultra", + "battle_legendary_zac_zam": "SWSH Batalha do Zacian & Zamazenta", + "battle_legendary_glas_spec": "SWSH Batalha do Glastrier & Spectrier", + "battle_legendary_calyrex": "SWSH Batalha do Calyrex", + "battle_legendary_birds_galar": "SWSH Batalha dos Pássaros Lendários de Galar", + "battle_legendary_ruinous": "SV Batalha dos Lendários Ruinosos", + "battle_legendary_kor_mir": "SV Batalha das Cavernas da Área Zero", + "battle_legendary_loyal_three": "SV Batalha dos Três Leais", + "battle_legendary_ogerpon": "SV Batalha do Ogerpon", + "battle_legendary_terapagos": "SV Batalha do Terapagos", + "battle_legendary_pecharunt": "SV Batalha do Pecharunt", + "battle_rival": "BW Batalha do Rival", + "battle_rival_2": "BW Batalha do N", + "battle_rival_3": "BW Batalha Final do N", + "battle_trainer": "BW Batalha de Treinador", + "battle_wild": "BW Batalha de Pokémon Selvagem", + "battle_wild_strong": "BW Batalha de Pokémon Selvagem Forte", + "end_summit": "PMD RTDX Cume da Torre do Céu", + "battle_rocket_grunt": "HGSS Batalha da Equipe Rocket", + "battle_aqua_magma_grunt": "ORAS Batalha da Equipe Aqua & Magma", + "battle_galactic_grunt": "BDSP Batalha da Equipe Galáctica", + "battle_plasma_grunt": "BW Batalha da Equipe Plasma", + "battle_flare_grunt": "XY Batalha da Equipe Flare", + "battle_rocket_boss": "USUM Batalha do Giovanni", + "battle_aqua_magma_boss": "ORAS Batalha do Maxie & Archie", + "battle_galactic_boss": "BDSP Batalha do Cyrus", + "battle_plasma_boss": "B2W2 Batalha do Ghetsis", + "battle_flare_boss": "XY Batalha do Lysandre", // Biome Music "abyss": "PMD EoS Dark Crater", @@ -123,23 +123,23 @@ export const bgmName: SimpleTranslationEntries = { "wasteland": "PMD EoS Hidden Highland", // Encounter - "encounter_ace_trainer": "BW Trainers' Eyes Meet (Ace Trainer)", - "encounter_backpacker": "BW Trainers' Eyes Meet (Backpacker)", - "encounter_clerk": "BW Trainers' Eyes Meet (Clerk)", - "encounter_cyclist": "BW Trainers' Eyes Meet (Cyclist)", - "encounter_lass": "BW Trainers' Eyes Meet (Lass)", - "encounter_parasol_lady": "BW Trainers' Eyes Meet (Parasol Lady)", - "encounter_pokefan": "BW Trainers' Eyes Meet (Poke Fan)", - "encounter_psychic": "BW Trainers' Eyes Meet (Psychic)", - "encounter_rich": "BW Trainers' Eyes Meet (Gentleman)", + "encounter_ace_trainer": "BW Encontro com Treinador (Treinador Ás)", + "encounter_backpacker": "BW Encontro com Treinador (Mochileiro)", + "encounter_clerk": "BW Encontro com Treinador (Funcionário)", + "encounter_cyclist": "BW Encontro com Treinador (Ciclista)", + "encounter_lass": "BW Encontro com Treinador (Senhorita)", + "encounter_parasol_lady": "BW Encontro com Treinador (Moça de Sombrinha)", + "encounter_pokefan": "BW Encontro com Treinador (Pokéfã)", + "encounter_psychic": "BW Encontro com Treinador (Médium)", + "encounter_rich": "BW Encontro com Treinador (Cavalheiro)", "encounter_rival": "BW Cheren", - "encounter_roughneck": "BW Trainers' Eyes Meet (Roughneck)", - "encounter_scientist": "BW Trainers' Eyes Meet (Scientist)", - "encounter_twins": "BW Trainers' Eyes Meet (Twins)", - "encounter_youngster": "BW Trainers' Eyes Meet (Youngster)", + "encounter_roughneck": "BW Encontro com Treinador (Arruaceiro)", + "encounter_scientist": "BW Encontro com Treinador (Cientista)", + "encounter_twins": "BW Encontro com Treinador (Gêmeos)", + "encounter_youngster": "BW Encontro com Treinador (Jovem)", // Other - "heal": "BW Pokémon Heal", - "menu": "PMD EoS Welcome to the World of Pokémon!", - "title": "PMD EoS Top Menu Theme", + "heal": "BW Centro Pokémon", + "menu": "PMD EoS Bem-vindo ao Mundo dos Pokémon!", + "title": "PMD EoS Menu Principal", } as const; diff --git a/src/locales/pt_BR/menu-ui-handler.ts b/src/locales/pt_BR/menu-ui-handler.ts index 75e5adcfd87..b874df7e23b 100644 --- a/src/locales/pt_BR/menu-ui-handler.ts +++ b/src/locales/pt_BR/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "Selecione um slot para exportar.", "importData": "Importar dados", "exportData": "Exportar dados", + "linkDiscord": "Conectar Discord", + "unlinkDiscord": "Desconectar Discord", + "linkGoogle": "Conectar Google", + "unlinkGoogle": "Desconectar Google", "cancel": "Cancelar", "losingProgressionWarning": "Você vai perder todo o progresso desde o início da batalha. Confirmar?", "noEggs": "Você não está chocando\nnenhum ovo no momento!" diff --git a/src/locales/pt_BR/menu.ts b/src/locales/pt_BR/menu.ts index 1e097737b69..aca16b6b511 100644 --- a/src/locales/pt_BR/menu.ts +++ b/src/locales/pt_BR/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "Nome de Usuário", "password": "Senha", "login": "Iniciar sessão", + "orUse": "Ou use", "register": "Registrar-se", "emptyUsername": "Nome de usuário vazio", "invalidLoginUsername": "Nome de usuário inválido", diff --git a/src/locales/zh_CN/menu-ui-handler.ts b/src/locales/zh_CN/menu-ui-handler.ts index 71d79472a45..461f5bb9956 100644 --- a/src/locales/zh_CN/menu-ui-handler.ts +++ b/src/locales/zh_CN/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "选择要导出的存档位。", "importData": "导入数据", "exportData": "导出数据", + "linkDiscord": "Link Discord", + "unlinkDiscord": "Unlink Discord", + "linkGoogle": "Link Google", + "unlinkGoogle": "Unlink Google", "cancel": "取消", "losingProgressionWarning": "你将失去自战斗开始以来的所有进度。\n是否继续?", "noEggs": "当前没有任何蛋\n正在孵化中!" diff --git a/src/locales/zh_CN/menu.ts b/src/locales/zh_CN/menu.ts index 92a9d1bfbf4..b1b5b00d554 100644 --- a/src/locales/zh_CN/menu.ts +++ b/src/locales/zh_CN/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "用户名", "password": "密码", "login": "登录", + "Or use": "Or use", "register": "注册", "emptyUsername": "用户名不能为空", "invalidLoginUsername": "输入的用户名无效", diff --git a/src/locales/zh_TW/menu-ui-handler.ts b/src/locales/zh_TW/menu-ui-handler.ts index 21ba10ba30e..e3675b0571e 100644 --- a/src/locales/zh_TW/menu-ui-handler.ts +++ b/src/locales/zh_TW/menu-ui-handler.ts @@ -18,6 +18,10 @@ export const menuUiHandler: SimpleTranslationEntries = { "exportSlotSelect": "選擇要導出的存檔位。", "importData": "導入數據", "exportData": "導出數據", + "linkDiscord": "Link Discord", + "unlinkDiscord": "Unlink Discord", + "linkGoogle": "Link Google", + "unlinkGoogle": "Unlink Google", "cancel": "取消", "losingProgressionWarning": "你將失去自戰鬥開始以來的所有進度。是否\n繼續?", "noEggs": "You are not hatching\nany eggs at the moment!" diff --git a/src/locales/zh_TW/menu.ts b/src/locales/zh_TW/menu.ts index 564c20d5791..e43264de2f6 100644 --- a/src/locales/zh_TW/menu.ts +++ b/src/locales/zh_TW/menu.ts @@ -17,6 +17,7 @@ export const menu: SimpleTranslationEntries = { "username": "用戶名", "password": "密碼", "login": "登入", + "orUse": "Or use", "register": "注冊", "emptyUsername": "用戶名不能為空", "invalidLoginUsername": "提供的用戶名無效", diff --git a/src/phases.ts b/src/phases.ts index 51391971308..c9f9c3c31b2 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -130,6 +130,16 @@ export class LoginPhase extends Phase { } ] }); + }, () => { + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); + const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify`; + window.open(discordUrl, "_self"); + }, () => { + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); + const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; + const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&redirect_uri=${redirectUri}&response_type=code&scope=openid`; + window.open(googleUrl, "_self"); } ] }); diff --git a/src/test/utils/mocks/mocksContainer/mockText.ts b/src/test/utils/mocks/mocksContainer/mockText.ts index 1dd440fde7c..f4513e20926 100644 --- a/src/test/utils/mocks/mocksContainer/mockText.ts +++ b/src/test/utils/mocks/mocksContainer/mockText.ts @@ -8,6 +8,7 @@ export default class MockText { private textureManager; public list = []; public style; + public text = ""; constructor(textureManager, x, y, content, styleOptions) { this.scene = textureManager.scene; @@ -17,6 +18,8 @@ export default class MockText { // Phaser.GameObjects.Text.prototype.updateText = () => null; // Phaser.Textures.TextureManager.prototype.addCanvas = () => {}; UI.prototype.showText = this.showText; + this.text = ""; + this.phaserText = ""; // super(scene, x, y); // this.phaserText = new Phaser.GameObjects.Text(scene, x, y, content, styleOptions); } @@ -150,7 +153,8 @@ export default class MockText { setText(text) { // Sets the text this Game Object will display. - // return this.phaserText.setText(text); + // return this.phaserText.setText\(text); + this.text = text; } setAngle(angle) { diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 3b75c6f7c13..2a4f419cbbc 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -3,8 +3,65 @@ import { ModalConfig } from "./modal-ui-handler"; import * as Utils from "../utils"; import { Mode } from "./ui"; import i18next from "i18next"; +import BattleScene from "#app/battle-scene.js"; +import { addTextObject, TextStyle } from "./text"; +import { addWindow } from "./ui-theme"; export default class LoginFormUiHandler extends FormModalUiHandler { + private googleImage: Phaser.GameObjects.Image; + private discordImage: Phaser.GameObjects.Image; + private externalPartyContainer: Phaser.GameObjects.Container; + private externalPartyBg: Phaser.GameObjects.NineSlice; + private externalPartyTitle: Phaser.GameObjects.Text; + constructor(scene: BattleScene, mode?: Mode) { + super(scene, mode); + } + + setup(): void { + + super.setup(); + this.externalPartyContainer = this.scene.add.container(0, 0); + this.externalPartyContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 12, this.scene.game.canvas.height / 12), Phaser.Geom.Rectangle.Contains); + this.externalPartyTitle = addTextObject(this.scene, 0, 4, "", TextStyle.SETTINGS_LABEL); + this.externalPartyTitle.setOrigin(0.5, 0); + this.externalPartyBg = addWindow(this.scene, 0, 0, 0, 0); + this.externalPartyContainer.add(this.externalPartyBg); + this.externalPartyContainer.add(this.externalPartyTitle); + + const googleImage = this.scene.add.image(0, 0, "google"); + googleImage.setOrigin(0, 0); + googleImage.setScale(0.07); + googleImage.setInteractive(); + googleImage.setName("google-icon"); + googleImage.on("pointerdown", () => { + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); + const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; + const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&redirect_uri=${redirectUri}&response_type=code&scope=openid`; + window.open(googleUrl, "_self"); + }); + this.googleImage = googleImage; + + const discordImage = this.scene.add.image(20, 0, "discord"); + discordImage.setOrigin(0, 0); + discordImage.setScale(0.07); + discordImage.setInteractive(); + discordImage.setName("discord-icon"); + discordImage.on("pointerdown", () => { + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); + const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify`; + window.open(discordUrl, "_self"); + }); + this.discordImage = discordImage; + + this.externalPartyContainer.add(this.googleImage); + this.externalPartyContainer.add(this.discordImage); + this.getUi().add(this.externalPartyContainer); + this.externalPartyContainer.add(this.googleImage); + this.externalPartyContainer.add(this.discordImage); + this.externalPartyContainer.setVisible(false); + } + getModalTitle(config?: ModalConfig): string { return i18next.t("menu:login"); } @@ -22,7 +79,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { } getButtonLabels(config?: ModalConfig): string[] { - return [ i18next.t("menu:login"), i18next.t("menu:register") ]; + return [ i18next.t("menu:login"), i18next.t("menu:register")]; } getReadableErrorMessage(error: string): string { @@ -46,8 +103,10 @@ export default class LoginFormUiHandler extends FormModalUiHandler { show(args: any[]): boolean { if (super.show(args)) { - const config = args[0] as ModalConfig; + this.processExternalProvider(); + + const config = args[0] as ModalConfig; const originalLoginAction = this.submitAction; this.submitAction = (_) => { // Prevent overlapping overrides on action modification @@ -83,4 +142,33 @@ export default class LoginFormUiHandler extends FormModalUiHandler { return false; } + + clear() { + super.clear(); + this.externalPartyContainer.setVisible(false); + + this.discordImage.off("pointerdown"); + this.googleImage.off("pointerdown"); + } + + processExternalProvider() : void { + this.externalPartyTitle.setText(i18next.t("menu:orUse") ?? ""); + this.externalPartyTitle.setX(20+this.externalPartyTitle.text.length); + this.externalPartyTitle.setVisible(true); + this.externalPartyContainer.setPositionRelative(this.modalContainer, 175, 0); + this.externalPartyContainer.setVisible(true); + this.externalPartyBg.setSize(this.externalPartyTitle.text.length+50, this.modalBg.height); + this.getUi().moveTo(this.externalPartyContainer, this.getUi().length - 1); + this.googleImage.setPosition(this.externalPartyBg.width/3.1,this.externalPartyBg.height-60); + this.discordImage.setPosition(this.externalPartyBg.width/3.1, this.externalPartyBg.height-40); + + this.externalPartyContainer.setAlpha(0); + this.scene.tweens.add({ + targets: this.externalPartyContainer, + duration: Utils.fixedInt(1000), + ease: "Sine.easeInOut", + y: "-=24", + alpha: 1 + }); + } } diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 571a09f3b37..3bfbb3576cc 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -6,7 +6,7 @@ import { addWindow } from "./ui-theme"; import MessageUiHandler from "./message-ui-handler"; import { OptionSelectConfig, OptionSelectItem } from "./abstact-option-select-ui-handler"; import { Tutorial, handleTutorial } from "../tutorial"; -import { updateUserInfo } from "../account"; +import { loggedInUser, updateUserInfo } from "../account"; import i18next from "i18next"; import {Button} from "#enums/buttons"; import { GameDataType } from "#enums/game-data-type"; @@ -22,7 +22,7 @@ enum MenuOptions { MANAGE_DATA, COMMUNITY, SAVE_AND_QUIT, - LOG_OUT + LOG_OUT, } let wikiUrl = "https://wiki.pokerogue.net/start"; @@ -332,6 +332,51 @@ export default class MenuUiHandler extends MessageUiHandler { success = true; break; case MenuOptions.MANAGE_DATA: + if (!bypassLogin && !this.manageDataConfig.options.some(o => o.label === i18next.t("menuUiHandler:linkDiscord") || o.label === i18next.t("menuUiHandler:unlinkDiscord"))) { + this.manageDataConfig.options.splice(this.manageDataConfig.options.length-1,0, + { + label: loggedInUser.discordId === "" ? i18next.t("menuUiHandler:linkDiscord") : i18next.t("menuUiHandler:unlinkDiscord"), + handler: () => { + if (loggedInUser?.discordId === "") { + const token = Utils.getCookie(Utils.sessionIdKey); + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); + const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}`; + window.open(discordUrl, "_self"); + return true; + } else { + Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => { + if (!res.ok) { + console.error(`Unlink failed (${res.status}: ${res.statusText})`); + } + updateUserInfo().then(() => this.scene.reset(true, true)); + }); + return true; + } + } + }, + { + label: loggedInUser?.googleId === "" ? i18next.t("menuUiHandler:linkGoogle") : i18next.t("menuUiHandler:unlinkGoogle"), + handler: () => { + if (loggedInUser?.googleId === "") { + const token = Utils.getCookie(Utils.sessionIdKey); + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); + const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; + const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&response_type=code&redirect_uri=${redirectUri}&scope=openid&state=${token}`; + window.open(googleUrl, "_self"); + return true; + } else { + Utils.apiPost("/auth/google/logout", undefined, undefined, true).then(res => { + if (!res.ok) { + console.error(`Unlink failed (${res.status}: ${res.statusText})`); + } + updateUserInfo().then(() => this.scene.reset(true, true)); + }); + return true; + } + } + }); + } ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.manageDataConfig); success = true; break; diff --git a/src/vite.env.d.ts b/src/vite.env.d.ts index b588b5b1145..ba466ecb27c 100644 --- a/src/vite.env.d.ts +++ b/src/vite.env.d.ts @@ -5,6 +5,8 @@ interface ImportMetaEnv { readonly VITE_BYPASS_TUTORIAL?: string; readonly VITE_API_BASE_URL?: string; readonly VITE_SERVER_URL?: string; + readonly VITE_DISCORD_CLIENT_ID?: string; + readonly VITE_GOOGLE_CLIENT_ID?: string; } interface ImportMeta {