From 132ba814228356f8f84d7078f05a57d866bc0b60 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Emmanuel Zorg <zorgjeanbe@proton.me> Date: Sat, 23 Jul 2022 16:34:27 +0200 Subject: [PATCH 1/4] Refactor how nicknames are set This turns the nickname setting into a helper function in Character.js, and extends it so it returns validation failures, and updates Title.js so any issue is made clear to the user. --- .../Screens/Character/Title/Text_Title.csv | 2 ++ BondageClub/Screens/Character/Title/Title.js | 24 +++++++++------ BondageClub/Scripts/Character.js | 29 +++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/BondageClub/Screens/Character/Title/Text_Title.csv b/BondageClub/Screens/Character/Title/Text_Title.csv index 4a09112acc..cfae60a456 100644 --- a/BondageClub/Screens/Character/Title/Text_Title.csv +++ b/BondageClub/Screens/Character/Title/Text_Title.csv @@ -2,6 +2,8 @@ SelectTitle,Select your displayed name and title CurrentTitle,Current title: TITLE Nickname,Nickname (letters and spaces) NicknameLocked,Nickname locked by your owner +NicknameTooLong,Nickname is too long (max. 20 characters) +NicknameInvalidChars,Nickname contains invalid characters TitleNone,None TitleMistress,Mistress TitleClubSlave,Club Slave diff --git a/BondageClub/Screens/Character/Title/Title.js b/BondageClub/Screens/Character/Title/Title.js index b6a0b55d9e..20d6887e3d 100644 --- a/BondageClub/Screens/Character/Title/Title.js +++ b/BondageClub/Screens/Character/Title/Title.js @@ -61,6 +61,8 @@ var TitleList = [ { Name: "Drone", Requirement: function () { return (AsylumGGTSGetLevel(Player) >= 6); }, Earned: true } ]; var TitleCanEditNickname = true; +/** @type {string} */ +var TitleNicknameStatus = null; let TitleOffset = 0; let TitleListFiltered = []; const TitlePerPage = 28; @@ -145,6 +147,7 @@ function TitleLoad() { E.removeAttribute("onfocus"); E.setAttribute("readonly", "readonly"); } + TitleNicknameStatus = null; } /** @@ -159,8 +162,10 @@ function TitleRun() { DrawText(TextGet("CurrentTitle").replace("TITLE", TextGet("Title" + (Player.Title || "None"))), 300, 100, "Black", "Gray"); DrawText(TextGet(TitleCanEditNickname ? "Nickname" : "NicknameLocked"), 750, 180, "Black", "Gray"); ElementPosition("InputNickname", 1300, 175, 500, 60); + if (TitleNicknameStatus) + DrawText(TextGet(TitleNicknameStatus), 1000, 250, "red"); let X = 130; - let Y = 250; + let Y = 325; for (let T = TitleOffset; T < TitleOffset + TitlePerPage && T < TitleListFiltered.length; T++) { DrawButton(X, Y, 400, 65, TextGet("Title" + TitleListFiltered[T].Name), 'White', undefined, undefined, Player.Title == TitleListFiltered[T].Name); X = X + 450; @@ -191,7 +196,7 @@ function TitleClick() { // When the user selects a title let X = 130; - let Y = 250; + let Y = 325; for (let T = TitleOffset; T < TitleOffset + TitlePerPage && T < TitleListFiltered.length; T++) { if (MouseIn(X, Y, 400, 65)) { TitleSet(TitleListFiltered[T].Name); @@ -211,14 +216,15 @@ function TitleClick() { * @returns {void} - Nothing */ function TitleExit() { - let Regex = /^[a-zA-Z\s]*$/; let Nick = ElementValue("InputNickname"); if (Nick == null) Nick = ""; - Nick = Nick.trim().substring(0, 20); - if (Regex.test(Nick)) { - Player.Nickname = Nick; - ServerAccountUpdate.QueueData({ Nickname: Nick }); - ElementRemove("InputNickname"); - CommonSetScreen("Character", "InformationSheet"); + const status = CharacterSetNickname(Player, Nick); + if (status) { + TitleNicknameStatus = status; + return; } + + // Nickname was fine, return to the Info sheet + ElementRemove("InputNickname"); + CommonSetScreen("Character", "InformationSheet"); } diff --git a/BondageClub/Scripts/Character.js b/BondageClub/Scripts/Character.js index fad22e4e68..6909fac7c5 100644 --- a/BondageClub/Scripts/Character.js +++ b/BondageClub/Scripts/Character.js @@ -1784,3 +1784,32 @@ function CharacterNickname(C) { if ((Nick == "") || !Regex.test(Nick)) Nick = C.Name; return AsylumGGTSCharacterName(C, Nick); } + +/** + * Update the given character's nickname. + * + * Note that changing any nickname but yours (ie. Player) is not supported. + * + * @param {Character} C - The character to change the nickname of. + * @param {string} Nick - The name to use as the new nickname. + * @return {string} null if the nickname was valid, or an explanation for why the nickname was rejected. + */ +function CharacterSetNickname(C, Nick) { + if (!C.IsPlayer()) return null; + + let Regex = /^[a-zA-Z\s]*$/; + + Nick = Nick.trim(); + if (Nick.length > 20) return "NicknameTooLong"; + + if (!Regex.test(Nick)) return "NicknameInvalidChars"; + + if (C.Nickname != Nick) { + C.Nickname = Nick; + if (C.IsPlayer()) { + ServerAccountUpdate.QueueData({ Nickname: Nick }); + } + } + + return null; +} -- GitLab From b52512a8d083c83e7c2c84f345e0b416407ebdcf Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Emmanuel Zorg <zorgjeanbe@proton.me> Date: Sat, 23 Jul 2022 16:41:36 +0200 Subject: [PATCH 2/4] A few QoL changes to the title screen itself This: - stops changing the title from exiting the screen automatically - makes the currently set title obvious by drawing it in yellow - aligns the current title label with the title selector itself - only update the title on screen close, like the nickname --- BondageClub/Screens/Character/Title/Title.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/BondageClub/Screens/Character/Title/Title.js b/BondageClub/Screens/Character/Title/Title.js index 20d6887e3d..ab7ef570f7 100644 --- a/BondageClub/Screens/Character/Title/Title.js +++ b/BondageClub/Screens/Character/Title/Title.js @@ -60,6 +60,7 @@ var TitleList = [ { Name: "GoodSlave", Requirement: function () { return (AsylumGGTSGetLevel(Player) >= 6); }, Earned: true }, { Name: "Drone", Requirement: function () { return (AsylumGGTSGetLevel(Player) >= 6); }, Earned: true } ]; +var TitleSelectedTitle = null; var TitleCanEditNickname = true; /** @type {string} */ var TitleNicknameStatus = null; @@ -139,6 +140,7 @@ function TitleIsEarned(Title) { * @returns {void} - Nothing */ function TitleLoad() { + TitleSelectedTitle = TitleGet(Player); TitleListFiltered = TitleList.filter(T => T.Requirement()); TitleCanEditNickname = (!LogQuery("BlockNickname", "OwnerRule") || (Player.Ownership == null) || (Player.Ownership.Stage !== 1)); let E = ElementCreateInput("InputNickname", "text", Player.Nickname, "20"); @@ -157,17 +159,24 @@ function TitleLoad() { */ function TitleRun() { - // List all the available titles DrawText(TextGet("SelectTitle"), 1000, 100, "Black", "Gray"); - DrawText(TextGet("CurrentTitle").replace("TITLE", TextGet("Title" + (Player.Title || "None"))), 300, 100, "Black", "Gray"); + + // Draw nickname field DrawText(TextGet(TitleCanEditNickname ? "Nickname" : "NicknameLocked"), 750, 180, "Black", "Gray"); ElementPosition("InputNickname", 1300, 175, 500, 60); if (TitleNicknameStatus) DrawText(TextGet(TitleNicknameStatus), 1000, 250, "red"); + + MainCanvas.textAlign = "left"; + DrawText(TextGet("CurrentTitle").replace("TITLE", TextGet("Title" + (Player.Title || "None"))), 130, 285, "Black", "Gray"); + MainCanvas.textAlign = "center"; + + // List all the available titles let X = 130; let Y = 325; for (let T = TitleOffset; T < TitleOffset + TitlePerPage && T < TitleListFiltered.length; T++) { - DrawButton(X, Y, 400, 65, TextGet("Title" + TitleListFiltered[T].Name), 'White', undefined, undefined, Player.Title == TitleListFiltered[T].Name); + const isCurrentTitle = TitleSelectedTitle == TitleListFiltered[T].Name; + DrawButton(X, Y, 400, 65, TextGet("Title" + TitleListFiltered[T].Name), isCurrentTitle ? "yellow" : 'White', undefined, undefined, isCurrentTitle); X = X + 450; if (X > 1500) { X = 130; @@ -199,8 +208,7 @@ function TitleClick() { let Y = 325; for (let T = TitleOffset; T < TitleOffset + TitlePerPage && T < TitleListFiltered.length; T++) { if (MouseIn(X, Y, 400, 65)) { - TitleSet(TitleListFiltered[T].Name); - TitleExit(); + TitleSelectedTitle = TitleListFiltered[T].Name; } X = X + 450; if (X > 1500) { @@ -224,6 +232,8 @@ function TitleExit() { return; } + TitleSet(TitleSelectedTitle); + // Nickname was fine, return to the Info sheet ElementRemove("InputNickname"); CommonSetScreen("Character", "InformationSheet"); -- GitLab From d45a540759ade4e1f76b2f5722c1fc836ffb5cb7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Emmanuel Zorg <zorgjeanbe@proton.me> Date: Sat, 23 Jul 2022 16:43:32 +0200 Subject: [PATCH 3/4] Move the nickname validation regex to a global under Server.js --- BondageClub/Scripts/Character.js | 4 +--- BondageClub/Scripts/Server.js | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/BondageClub/Scripts/Character.js b/BondageClub/Scripts/Character.js index 6909fac7c5..21e103410d 100644 --- a/BondageClub/Scripts/Character.js +++ b/BondageClub/Scripts/Character.js @@ -1797,12 +1797,10 @@ function CharacterNickname(C) { function CharacterSetNickname(C, Nick) { if (!C.IsPlayer()) return null; - let Regex = /^[a-zA-Z\s]*$/; - Nick = Nick.trim(); if (Nick.length > 20) return "NicknameTooLong"; - if (!Regex.test(Nick)) return "NicknameInvalidChars"; + if (!ServerCharacterNicknameRegex.test(Nick)) return "NicknameInvalidChars"; if (C.Nickname != Nick) { C.Nickname = Nick; diff --git a/BondageClub/Scripts/Server.js b/BondageClub/Scripts/Server.js index e5833a7ea8..dc91082699 100644 --- a/BondageClub/Scripts/Server.js +++ b/BondageClub/Scripts/Server.js @@ -13,6 +13,7 @@ var ServerURL = "http://localhost:4288"; var ServerBeep = { Message: "", Timer: 0 }; var ServerIsConnected = false; var ServerReconnectCount = 0; +var ServerCharacterNicknameRegex = /^[a-zA-Z\s]*$/; const ServerScriptMessage = "WARNING! Console scripts can break your account or steal your data. Only run scripts if " + "you know what you're doing and you trust the source. See " + -- GitLab From 3838c9c2202f9d3e63e796db283f3f774372cbfd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Emmanuel Zorg <zorgjeanbe@proton.me> Date: Sat, 23 Jul 2022 16:54:18 +0200 Subject: [PATCH 4/4] Notify the chatroom that the character changed their nickname This is inspired by !3445 --- .../Screens/Character/Player/Dialog_Player.csv | 1 + BondageClub/Scripts/Character.js | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/BondageClub/Screens/Character/Player/Dialog_Player.csv b/BondageClub/Screens/Character/Player/Dialog_Player.csv index afd333a9d4..a9dafc7931 100644 --- a/BondageClub/Screens/Character/Player/Dialog_Player.csv +++ b/BondageClub/Screens/Character/Player/Dialog_Player.csv @@ -3466,3 +3466,4 @@ ChainClapNipplesChain,,,Style 1,, ChainClapNipplesChain2,,,Style 2,, ChainClampSetChain,,,SourceCharacter changes the chain style on DestinationCharacter chest.,, ChainClampSetChain2,,,SourceCharacter changes the chain style on DestinationCharacter chest.,, +CharacterNicknameUpdated,,,OldNick is now known as NewNick.,, diff --git a/BondageClub/Scripts/Character.js b/BondageClub/Scripts/Character.js index 21e103410d..99ea3991ad 100644 --- a/BondageClub/Scripts/Character.js +++ b/BondageClub/Scripts/Character.js @@ -1803,10 +1803,23 @@ function CharacterSetNickname(C, Nick) { if (!ServerCharacterNicknameRegex.test(Nick)) return "NicknameInvalidChars"; if (C.Nickname != Nick) { + const oldNick = C.Nickname || C.Name; C.Nickname = Nick; if (C.IsPlayer()) { ServerAccountUpdate.QueueData({ Nickname: Nick }); } + + if (ServerPlayerIsInChatRoom()) { + // When in a chatroom, send a notification that the player updated their nick + const Dictionary = [ + { Tag: "SourceCharacter", Text: CharacterNickname(C), MemberNumber: C.MemberNumber }, + { Tag: "DestinationCharacter", Text: CharacterNickname(C), MemberNumber: C.MemberNumber }, + { Tag: "OldNick", Text: oldNick }, + { Tag: "NewNick", Text: CharacterNickname(C) }, + ]; + + ServerSend("ChatRoomChat", { Content: "CharacterNicknameUpdated", Type: "Action", Dictionary: Dictionary }); + } } return null; -- GitLab