mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-26 19:49:22 +01:00
Hotfix 1.11.5 to main
Hotfix 1.11.5 to main
This commit is contained in:
commit
235991e51d
2
assets
2
assets
@ -1 +1 @@
|
||||
Subproject commit a36741a2112217eaf067248d7d1917266339a56d
|
||||
Subproject commit 9398703b8f0e437ef6d5212373e2ae8465b3bfda
|
||||
2
locales
2
locales
@ -1 +1 @@
|
||||
Subproject commit 6b5e2130256dd521908f15a485d045fb36baca41
|
||||
Subproject commit fe7025942cf5ad1391380cc4e52695535c56c986
|
||||
@ -79,51 +79,14 @@ export class LoginPhase extends Phase {
|
||||
}
|
||||
|
||||
private showLoginRegister(): void {
|
||||
const { gameData, phaseManager, ui } = globalScene;
|
||||
|
||||
const backButton = () => {
|
||||
phaseManager.unshiftNew("LoginPhase", false);
|
||||
this.end();
|
||||
};
|
||||
|
||||
const checkUserInfo = async (): Promise<boolean> => {
|
||||
ui.playSelect();
|
||||
const success = await updateUserInfo();
|
||||
if (!success[0]) {
|
||||
removeCookie(sessionIdKey);
|
||||
globalScene.reset(true, true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const loginButton = async () => {
|
||||
const success = await checkUserInfo();
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
await gameData.loadSystem();
|
||||
this.end();
|
||||
};
|
||||
|
||||
const registerButton = async () => {
|
||||
const success = await checkUserInfo();
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
this.end();
|
||||
};
|
||||
const { ui } = globalScene;
|
||||
|
||||
const goToLoginButton = () => {
|
||||
globalScene.playSound("ui/menu_open");
|
||||
|
||||
ui.setMode(UiMode.LOGIN_FORM, { buttonActions: [loginButton, backButton] });
|
||||
this.goToLogin();
|
||||
};
|
||||
|
||||
const goToRegistrationButton = () => {
|
||||
globalScene.playSound("ui/menu_open");
|
||||
|
||||
ui.setMode(UiMode.REGISTRATION_FORM, { buttonActions: [registerButton, backButton] });
|
||||
this.goToRegister();
|
||||
};
|
||||
|
||||
if (this.showText) {
|
||||
@ -134,4 +97,56 @@ export class LoginPhase extends Phase {
|
||||
|
||||
ui.setMode(UiMode.LOGIN_OR_REGISTER, { buttonActions: [goToLoginButton, goToRegistrationButton] });
|
||||
}
|
||||
|
||||
private async checkUserInfo(): Promise<boolean> {
|
||||
globalScene.ui.playSelect();
|
||||
const success = await updateUserInfo();
|
||||
if (!success[0]) {
|
||||
removeCookie(sessionIdKey);
|
||||
globalScene.reset(true, true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public goToLogin(): void {
|
||||
const { gameData, ui, phaseManager } = globalScene;
|
||||
|
||||
const backButton = () => {
|
||||
phaseManager.unshiftNew("LoginPhase", false);
|
||||
this.end();
|
||||
};
|
||||
|
||||
const loginButton = async () => {
|
||||
const success = await this.checkUserInfo();
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
await gameData.loadSystem();
|
||||
this.end();
|
||||
};
|
||||
globalScene.playSound("ui/menu_open");
|
||||
|
||||
ui.setMode(UiMode.LOGIN_FORM, { buttonActions: [loginButton, backButton] });
|
||||
}
|
||||
|
||||
public goToRegister(): void {
|
||||
const { phaseManager, ui } = globalScene;
|
||||
|
||||
const backButton = () => {
|
||||
phaseManager.unshiftNew("LoginPhase", false);
|
||||
this.end();
|
||||
};
|
||||
|
||||
const registerButton = async () => {
|
||||
const success = await this.checkUserInfo();
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
this.end();
|
||||
};
|
||||
globalScene.playSound("ui/menu_open");
|
||||
|
||||
ui.setMode(UiMode.REGISTRATION_FORM, { buttonActions: [registerButton, backButton] });
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ export abstract class ApiBase {
|
||||
console.log(`Sending ${config.method ?? "GET"} request to: `, this.base + path, config);
|
||||
}
|
||||
|
||||
// TODO: need some sort of error handling here?
|
||||
return await fetch(this.base + path, config);
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ export class PokerogueAccountApi extends ApiBase {
|
||||
console.warn("Register failed!", err);
|
||||
}
|
||||
|
||||
return "Unknown error!";
|
||||
return "Unknown registration error!";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +76,7 @@ export class PokerogueAccountApi extends ApiBase {
|
||||
console.warn("Login failed!", err);
|
||||
}
|
||||
|
||||
return "Unknown error!";
|
||||
return "Unknown login error!";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { LoginRegisterInfoContainerUiHandler } from "#ui/login-register-info-container-ui-handler";
|
||||
import type { SettingsDisplayUiHandler } from "#ui/settings-display-ui-handler";
|
||||
import i18next from "i18next";
|
||||
|
||||
@ -8,6 +9,8 @@ const cancelHandler = () => {
|
||||
// Reset the cursor to the current language, if in the settings menu
|
||||
if (handler && typeof (handler as SettingsDisplayUiHandler).setOptionCursor === "function") {
|
||||
(handler as SettingsDisplayUiHandler).setOptionCursor(-1, 0, true);
|
||||
} else if (handler && typeof (handler as LoginRegisterInfoContainerUiHandler).setInteractive === "function") {
|
||||
(handler as LoginRegisterInfoContainerUiHandler).setInteractive(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -708,7 +708,7 @@ export class TimedEventManager {
|
||||
}
|
||||
|
||||
export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
private event: TimedEvent | nil;
|
||||
private readonly event: TimedEvent | nil;
|
||||
private eventTimerText: Phaser.GameObjects.Text;
|
||||
private banner: Phaser.GameObjects.Image;
|
||||
private availableWidth: number;
|
||||
@ -725,7 +725,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
* Set the width that can be used to display the event timer and banner. By default
|
||||
* these elements get centered horizontally in that space, in the bottom left of the screen
|
||||
*/
|
||||
setWidth(width: number) {
|
||||
public setWidth(width: number): void {
|
||||
if (width !== this.availableWidth) {
|
||||
this.availableWidth = width;
|
||||
const xPosition = this.availableWidth / 2 + (this.event?.xOffset ?? 0);
|
||||
@ -738,7 +738,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
setup() {
|
||||
public setup(): void {
|
||||
const lang = i18next.resolvedLanguage;
|
||||
if (this.event?.bannerKey) {
|
||||
let key = this.event.bannerKey;
|
||||
@ -775,7 +775,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
public show(): void {
|
||||
this.setVisible(true);
|
||||
this.updateCountdown();
|
||||
|
||||
@ -784,13 +784,13 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
clear() {
|
||||
public clear(): void {
|
||||
this.setVisible(false);
|
||||
this.eventTimer && clearInterval(this.eventTimer);
|
||||
this.eventTimer = null;
|
||||
}
|
||||
|
||||
private timeToGo(date: Date) {
|
||||
private timeToGo(date: Date): string {
|
||||
// Utility to add leading zero
|
||||
function z(n) {
|
||||
return (n < 10 ? "0" : "") + n;
|
||||
@ -816,8 +816,8 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||
});
|
||||
}
|
||||
|
||||
updateCountdown() {
|
||||
if (this.event && this.event.eventType !== EventType.NO_TIMER_DISPLAY) {
|
||||
private updateCountdown(): void {
|
||||
if (this.event && this.event.eventType !== EventType.NO_TIMER_DISPLAY && this.eventTimerText.visible) {
|
||||
this.eventTimerText.setText(this.timeToGo(this.event.endDate));
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@ export class LoginOrRegisterUiHandler extends LoginRegisterInfoContainerUiHandle
|
||||
return [i18next.t("menu:login"), i18next.t("menu:register")];
|
||||
}
|
||||
|
||||
// TODO: use mixins so it's not necessary to inherit from `FormModalUiHandler`
|
||||
public override getInputFieldConfigs(): InputFieldConfig[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||
import { fixedInt } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
import JSZip from "jszip";
|
||||
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
||||
|
||||
interface BuildInteractableImageOpts {
|
||||
scale?: number;
|
||||
@ -30,12 +31,12 @@ const MAX_SAVES_FOR_USERNAME_PANEL = 7;
|
||||
const ERR_NO_SAVES: string = "No save files found";
|
||||
const ERR_TOO_MANY_SAVES: string = "Too many save files found";
|
||||
|
||||
// TODO: use mixins
|
||||
export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHandler {
|
||||
private usernameInfoImage: Phaser.GameObjects.Image;
|
||||
private saveDownloadImage: Phaser.GameObjects.Image;
|
||||
private changeLanguageImage: Phaser.GameObjects.Image;
|
||||
private infoContainer: Phaser.GameObjects.Container;
|
||||
private lastFocusedInput: InputText | null = null;
|
||||
|
||||
public override getReadableErrorMessage(error: string): string {
|
||||
if (!error) {
|
||||
@ -109,6 +110,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan
|
||||
this.changeLanguageImage //
|
||||
.setPositionRelative(this.infoContainer, 40, 0)
|
||||
.on("pointerdown", () => {
|
||||
this.setInteractive(false);
|
||||
globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, {
|
||||
options: languageOptions,
|
||||
maxOptions: 7,
|
||||
@ -154,6 +156,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan
|
||||
const handler = () => {
|
||||
globalScene.ui.revertMode();
|
||||
this.infoContainer.disableInteractive();
|
||||
this.setInteractive(true);
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -162,6 +165,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan
|
||||
}
|
||||
|
||||
globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { options, delay: 1000 });
|
||||
this.setInteractive(false);
|
||||
this.infoContainer.setInteractive(
|
||||
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width, globalScene.game.canvas.height),
|
||||
Phaser.Geom.Rectangle.Contains,
|
||||
@ -230,4 +234,45 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable interactivity on all interactive objects.
|
||||
* @param active - Whether to enable or disable interactivity
|
||||
*/
|
||||
public setInteractive(active: boolean): void {
|
||||
const objects = [...this.buttonBgs, this.usernameInfoImage, this.saveDownloadImage, this.changeLanguageImage];
|
||||
|
||||
for (const obj of objects) {
|
||||
if (active) {
|
||||
obj.setInteractive();
|
||||
} else {
|
||||
obj.disableInteractive();
|
||||
if (obj instanceof Phaser.GameObjects.Image) {
|
||||
obj.clearTint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setInteractiveInputs(active);
|
||||
this.setMouseCursorStyle("default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable interactivity on all input fields.
|
||||
* @param active - Whether to enable or disable interactivity
|
||||
*/
|
||||
private setInteractiveInputs(active: boolean): void {
|
||||
if (active) {
|
||||
// `setFocus` doesn't focus without a timeout
|
||||
setTimeout(() => {
|
||||
this.lastFocusedInput?.setFocus();
|
||||
this.lastFocusedInput = null;
|
||||
}, 50);
|
||||
} else {
|
||||
this.lastFocusedInput = this.inputs.find(input => input.isFocused) ?? null;
|
||||
}
|
||||
for (const input of this.inputs) {
|
||||
(input.node as HTMLInputElement).disabled = !active;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ import { addWindow } from "#ui/ui-theme";
|
||||
import { fixedInt } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
// TODO: use mixins
|
||||
export abstract class OAuthProvidersUiHandler extends LoginRegisterInfoContainerUiHandler {
|
||||
private discordImage: Phaser.GameObjects.Image;
|
||||
private googleImage: Phaser.GameObjects.Image;
|
||||
@ -56,6 +55,18 @@ export abstract class OAuthProvidersUiHandler extends LoginRegisterInfoContainer
|
||||
this.getUi().add(this.externalPartyContainer);
|
||||
}
|
||||
|
||||
public override setInteractive(active: boolean): void {
|
||||
super.setInteractive(active);
|
||||
const externalPartyIcons = this.externalPartyContainer.list.filter(obj => obj instanceof Phaser.GameObjects.Image);
|
||||
for (const obj of externalPartyIcons) {
|
||||
if (active) {
|
||||
obj.setInteractive();
|
||||
} else {
|
||||
obj.disableInteractive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected processExternalProvider(): void {
|
||||
const titleX = 22;
|
||||
this.externalPartyTitle
|
||||
|
||||
@ -1515,9 +1515,6 @@ export class PartyUiHandler extends MessageUiHandler {
|
||||
);
|
||||
}
|
||||
this.addCommonOptions(pokemon);
|
||||
if (this.partyUiMode === PartyUiMode.SWITCH && pokemon.isFusion()) {
|
||||
this.options.push(PartyOption.UNSPLICE);
|
||||
}
|
||||
break;
|
||||
case PartyUiMode.REVIVAL_BLESSING:
|
||||
this.options.push(PartyOption.REVIVE);
|
||||
@ -1551,6 +1548,9 @@ export class PartyUiHandler extends MessageUiHandler {
|
||||
case PartyUiMode.CHECK:
|
||||
this.addCommonOptions(pokemon);
|
||||
if (globalScene.phaseManager.getCurrentPhase().is("SelectModifierPhase")) {
|
||||
if (pokemon.isFusion()) {
|
||||
this.options.push(PartyOption.UNSPLICE);
|
||||
}
|
||||
this.options.push(PartyOption.RELEASE);
|
||||
const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon);
|
||||
for (let i = 0; i < formChangeItemModifiers.length; i++) {
|
||||
|
||||
@ -2,9 +2,11 @@ import { pokerogueApi } from "#api/pokerogue-api";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { TextStyle } from "#enums/text-style";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import type { LoginPhase } from "#phases/login-phase";
|
||||
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||
import { addTextObject } from "#ui/text";
|
||||
import { fixedInt } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
import { LoginRegisterInfoContainerUiHandler } from "./login-register-info-container-ui-handler";
|
||||
|
||||
@ -86,7 +88,7 @@ export class RegistrationFormUiHandler extends LoginRegisterInfoContainerUiHandl
|
||||
this.submitAction = originalRegistrationAction;
|
||||
this.sanitizeInputs();
|
||||
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
|
||||
const onFail = error => {
|
||||
const onFail = (error: string) => {
|
||||
globalScene.ui.setMode(UiMode.REGISTRATION_FORM, Object.assign(config, { errorMessage: error?.trim() }));
|
||||
globalScene.ui.playError();
|
||||
};
|
||||
@ -109,18 +111,25 @@ export class RegistrationFormUiHandler extends LoginRegisterInfoContainerUiHandl
|
||||
if (registerError) {
|
||||
onFail(registerError);
|
||||
} else {
|
||||
pokerogueApi.account
|
||||
.login({
|
||||
username: usernameInput.text,
|
||||
password: passwordInput.text,
|
||||
})
|
||||
.then(loginError => {
|
||||
if (loginError) {
|
||||
onFail(loginError);
|
||||
} else {
|
||||
originalRegistrationAction?.();
|
||||
}
|
||||
});
|
||||
const username = usernameInput.text;
|
||||
const password = passwordInput.text;
|
||||
pokerogueApi.account.login({ username, password }).then(loginError => {
|
||||
if (loginError) {
|
||||
// retry once if the first attempt fails
|
||||
const retryLogin = () => {
|
||||
pokerogueApi.account.login({ username, password }).then(error => {
|
||||
if (error) {
|
||||
(globalScene.phaseManager.getCurrentPhase() as LoginPhase).goToLogin();
|
||||
} else {
|
||||
originalRegistrationAction?.();
|
||||
}
|
||||
});
|
||||
};
|
||||
globalScene.time.delayedCall(fixedInt(2000), retryLogin);
|
||||
} else {
|
||||
originalRegistrationAction?.();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -261,6 +261,7 @@ export class TitleUiHandler extends OptionSelectUiHandler {
|
||||
private getSnow(): void {
|
||||
const width = globalScene.scaledCanvas.width;
|
||||
const height = globalScene.scaledCanvas.height;
|
||||
this.snow?.destroy(); // Ensures no duplicate snow layers
|
||||
this.snow = globalScene.add.tileSprite(width, height, width, height, "snow");
|
||||
this.snow.setOrigin(1, 1);
|
||||
|
||||
|
||||
@ -85,12 +85,12 @@ describe("Pokerogue Account API", () => {
|
||||
expect(error).toBe("Username is already taken");
|
||||
});
|
||||
|
||||
it('should return "Unknown error" and report a warning on ERROR', async () => {
|
||||
it('should return "Unknown registration error!" and report a warning on ERROR', async () => {
|
||||
server.use(http.post(`${apiBase}/account/register`, () => HttpResponse.error()));
|
||||
|
||||
const error = await accountApi.register(registerParams);
|
||||
|
||||
expect(error).toBe("Unknown error!");
|
||||
expect(error).toBe("Unknown registration error!");
|
||||
expect(console.warn).toHaveBeenCalledWith("Register failed!", expect.any(Error));
|
||||
});
|
||||
});
|
||||
@ -119,12 +119,12 @@ describe("Pokerogue Account API", () => {
|
||||
expect(console.warn).toHaveBeenCalledWith("Login failed!", 401, "Unauthorized");
|
||||
});
|
||||
|
||||
it('should return "Unknown error" and report a warning on ERROR', async () => {
|
||||
it('should return "Unknown login error!" and report a warning on ERROR', async () => {
|
||||
server.use(http.post(`${apiBase}/account/login`, () => HttpResponse.error()));
|
||||
|
||||
const error = await accountApi.login(loginParams);
|
||||
|
||||
expect(error).toBe("Unknown error!");
|
||||
expect(error).toBe("Unknown login error!");
|
||||
expect(console.warn).toHaveBeenCalledWith("Login failed!", expect.any(Error));
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user