From 671f1564bb78e931fab4ea3ba0c57e76d8ef36fa Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Sat, 29 Jun 2024 01:18:31 +0800 Subject: [PATCH 01/17] =?UTF-8?q?=E5=9C=A8into=E3=80=81textbox=E4=B8=8A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=E5=B8=B8=E7=94=A8=E7=9A=84=E7=AC=A6?= =?UTF-8?q?=E5=8F=B7=E8=BD=AC=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/src/scriptParser/contentParser.ts | 6 ++-- .../src/Core/gameScripts/choose/index.tsx | 10 +++--- .../webgal/src/Core/gameScripts/intro.tsx | 4 ++- packages/webgal/src/Stage/TextBox/TextBox.tsx | 3 +- packages/webgal/src/hooks/useEscape.ts | 34 +++++++++++++++++++ 5 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 packages/webgal/src/hooks/useEscape.ts diff --git a/packages/parser/src/scriptParser/contentParser.ts b/packages/parser/src/scriptParser/contentParser.ts index fce148224..cbb6fd161 100644 --- a/packages/parser/src/scriptParser/contentParser.ts +++ b/packages/parser/src/scriptParser/contentParser.ts @@ -45,12 +45,12 @@ export const contentParser = ( }; function getChooseContent(contentRaw: string, assetSetter: any): string { - const chooseList = contentRaw.split('|'); + const chooseList = contentRaw.split(/(? = []; const chooseValueList: Array = []; for (const e of chooseList) { - chooseKeyList.push(e.split(':')[0] ?? ''); - chooseValueList.push(e.split(':')[1] ?? ''); + chooseKeyList.push(e.split(/(? { if (e.match(/\./)) { diff --git a/packages/webgal/src/Core/gameScripts/choose/index.tsx b/packages/webgal/src/Core/gameScripts/choose/index.tsx index 326a548b8..a1cb1ae58 100644 --- a/packages/webgal/src/Core/gameScripts/choose/index.tsx +++ b/packages/webgal/src/Core/gameScripts/choose/index.tsx @@ -11,6 +11,7 @@ import { PerformController } from '@/Core/Modules/perform/performController'; import { useSEByWebgalStore } from '@/hooks/useSoundEffect'; import { WebGAL } from '@/Core/WebGAL'; import { whenChecker } from '@/Core/controller/gamePlay/scriptExecutor'; +import useEscape from '@/hooks/useEscape'; class ChooseOption { /** @@ -21,8 +22,7 @@ class ChooseOption { const parts = script.split('->'); const conditonPart = parts.length > 1 ? parts[0] : null; const mainPart = parts.length > 1 ? parts[1] : parts[0]; - const mainPartNodes = mainPart.split(':'); - + const mainPartNodes = mainPart.split(/(? { - const chooseOptionScripts = sentence.content.split('|'); + const chooseOptionScripts = sentence.content.split(/(? ChooseOption.parse(e)); // eslint-disable-next-line react/no-deprecated diff --git a/packages/webgal/src/Core/gameScripts/intro.tsx b/packages/webgal/src/Core/gameScripts/intro.tsx index 294526f8f..18fab8657 100644 --- a/packages/webgal/src/Core/gameScripts/intro.tsx +++ b/packages/webgal/src/Core/gameScripts/intro.tsx @@ -7,6 +7,8 @@ import { nextSentence } from '@/Core/controller/gamePlay/nextSentence'; import { PerformController } from '@/Core/Modules/perform/performController'; import { logger } from '@/Core/util/logger'; import { WebGAL } from '@/Core/WebGAL'; +import { replace } from 'lodash'; +import useEscape from '@/hooks/useEscape'; /** * 显示一小段黑屏演示 * @param sentence @@ -81,7 +83,7 @@ export const intro = (sentence: ISentence): IPerform => { width: '100%', height: '100%', }; - const introArray: Array = sentence.content.split(/\|/); + const introArray: Array = sentence.content.split(/[^\\]\|/).map((val: string) => useEscape(val)); let endWait = 1000; let baseDuration = endWait + delayTime * introArray.length; diff --git a/packages/webgal/src/Stage/TextBox/TextBox.tsx b/packages/webgal/src/Stage/TextBox/TextBox.tsx index f833fddec..8381b23d9 100644 --- a/packages/webgal/src/Stage/TextBox/TextBox.tsx +++ b/packages/webgal/src/Stage/TextBox/TextBox.tsx @@ -8,6 +8,7 @@ import { match } from '@/Core/util/match'; import { textSize } from '@/store/userDataInterface'; import IMSSTextbox from '@/Stage/TextBox/IMSSTextbox'; import { SCREEN_CONSTANTS } from '@/Core/util/constants'; +import useEscape from '@/hooks/useEscape'; const userAgent = navigator.userAgent; const isFirefox = /firefox/i.test(userAgent); @@ -100,7 +101,7 @@ function isCJK(character: string) { export function compileSentence(sentence: string, lineLimit: number, ignoreLineLimit?: boolean): EnhancedNode[][] { // 先拆行 - const lines = sentence.split('|'); + const lines = sentence.split(/[^\\]\|/).map((val: string) => useEscape(val)); // 对每一行进行注音处理 const rubyLines = lines.map((line) => parseString(line)); const nodeLines = rubyLines.map((line) => { diff --git a/packages/webgal/src/hooks/useEscape.ts b/packages/webgal/src/hooks/useEscape.ts new file mode 100644 index 000000000..3e54c99ef --- /dev/null +++ b/packages/webgal/src/hooks/useEscape.ts @@ -0,0 +1,34 @@ +const escapeMap = [ + { + reg: /\\\\/g, + val: '\\', + }, + { + reg: /\\\|/g, + val: '|', + }, + { + reg: /\\:/g, + val: ':', + }, + { + reg: /\\,/g, + val: ',', + }, + { + reg: /\\;/g, + val: ';', + }, + { + reg: /\\./g, + val: '.', + }, +]; +const useEscape = (val: string): string => { + let _res = val; + for (let i of escapeMap) { + _res = _res.replaceAll(i.reg, i.val); + } + return _res; +}; +export default useEscape; From 74a31c76a4c4982c8f8a625f65346385085b618a Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Sat, 29 Jun 2024 15:03:06 +0800 Subject: [PATCH 02/17] =?UTF-8?q?setVar=E5=A2=9E=E5=8A=A0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=B8=B8=E6=88=8F=E8=BF=90=E8=A1=8C=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E7=94=A8=E4=BA=8E=E8=B0=83=E8=AF=95=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E7=AD=89=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webgal/src/Core/gameScripts/setVar.ts | 35 +++++++++++++++---- .../webgal/src/types/angular-expressions.d.ts | 3 +- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index 7a2e736ba..48789d663 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -8,7 +8,7 @@ import { setGlobalVar } from '@/store/userDataReducer'; import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; import { ISetGameVar } from '@/store/stageInterface'; import { dumpToStorageFast } from '@/Core/controller/storage/storageController'; - +import { WebGAL } from '@/Core/WebGAL'; /** * 设置变量 * @param sentence @@ -32,6 +32,8 @@ export const setVar = (sentence: ISentence): IPerform => { const valExp = sentence.content.split(/=/)[1]; if (valExp === 'random()') { webgalStore.dispatch(targetReducerFunction({ key, value: Math.random() })); + } else if (valExp.match(/\$[.a-zA-Z]/)) { + webgalStore.dispatch(targetReducerFunction({ key, value: String(getValueFromState(valExp.trim())) })); } else if (valExp.match(/[+\-*\/()]/)) { // 如果包含加减乘除号,则运算 // 先取出运算表达式中的变量 @@ -39,8 +41,8 @@ export const setVar = (sentence: ISentence): IPerform => { // 将变量替换为变量的值,然后合成表达式字符串 const valExp2 = valExpArr .map((e) => { - if (e.match(/[a-zA-Z]/)) { - return getValueFromState(e).toString(); + if (e.match(/\$?[.a-zA-Z]/)) { + return String(getValueFromState(e.trim())); } else return e; }) .reduce((pre, curr) => pre + curr, ''); @@ -77,12 +79,31 @@ export const setVar = (sentence: ISentence): IPerform => { }; }; +type BaseVal = string | number | boolean; + export function getValueFromState(key: string) { let ret: number | string | boolean = 0; - if (webgalStore.getState().stage.GameVar.hasOwnProperty(key)) { - ret = webgalStore.getState().stage.GameVar[key]; - } else if (webgalStore.getState().userData.globalGameVar.hasOwnProperty(key)) { - ret = webgalStore.getState().userData.globalGameVar[key]; + const stage = webgalStore.getState().stage; + const GUI = webgalStore.getState().GUI; + const userData = webgalStore.getState().userData; + const _Merge = { ...GUI, ...stage, ...userData, gameName: WebGAL.gameName, gameKey: WebGAL.gameKey }; + const is_baseVal = (_obj: object, _val: string) => + ['string', 'number', 'boolean'].includes(typeof Reflect.get(_obj, _val)); + let _all: { [key: PropertyKey]: any } = {}; + // 排除GameVar和globalGameVar,因为这两个本来就可以获取 + for (let i in _Merge) { + if (i === 'GameVar') continue; + if (i === 'globalGameVar') continue; + if (i) { + Reflect.set(_all, '$' + i, Reflect.get(_Merge, i) as BaseVal); + } + } + if (stage.GameVar.hasOwnProperty(key)) { + ret = stage.GameVar[key]; + } else if (userData.globalGameVar.hasOwnProperty(key)) { + ret = userData.globalGameVar[key]; + } else if (key.startsWith('$') && is_baseVal(_all, key)) { + ret = compile(key)(_all) as BaseVal; } return ret; } diff --git a/packages/webgal/src/types/angular-expressions.d.ts b/packages/webgal/src/types/angular-expressions.d.ts index f18dcb1c1..b5518d2a3 100644 --- a/packages/webgal/src/types/angular-expressions.d.ts +++ b/packages/webgal/src/types/angular-expressions.d.ts @@ -1,3 +1,4 @@ +import { EvaluatorFunc } from 'angular-expressions'; declare module 'angular-expressions' { - export function compile(src: string, lexerOptions?: any): () => number | boolean; + export function compile(src: string, lexerOptions?: any): () => number | boolean | EvaluatorFunc; } From 06b972840cd609237426ef58dd38453749e3fc2a Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Mon, 1 Jul 2024 23:24:37 +0800 Subject: [PATCH 03/17] add test txt file --- packages/webgal/public/game/scene/demo_escape.txt | 3 +++ packages/webgal/public/game/scene/start.txt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 packages/webgal/public/game/scene/demo_escape.txt diff --git a/packages/webgal/public/game/scene/demo_escape.txt b/packages/webgal/public/game/scene/demo_escape.txt new file mode 100644 index 000000000..f0f4cd023 --- /dev/null +++ b/packages/webgal/public/game/scene/demo_escape.txt @@ -0,0 +1,3 @@ +intro:我会显示出来:\:\,\.\;不信你看看 -hold; +WebGal:我会显示出来:\:\,\.\;不信你看看; +choose:我会显示出来:\:\,\.\;不信你看看; diff --git a/packages/webgal/public/game/scene/start.txt b/packages/webgal/public/game/scene/start.txt index 642f0a686..321b6e0a9 100644 --- a/packages/webgal/public/game/scene/start.txt +++ b/packages/webgal/public/game/scene/start.txt @@ -1,3 +1,3 @@ setVar:heroine=WebGAL; setVar:egine=WebGAL; -choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt; +choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Escape test:demo_escape.txt; From 8feddc623068305e795021d2f7d6c891125a0d77 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Tue, 2 Jul 2024 20:58:03 +0800 Subject: [PATCH 04/17] split test files --- packages/webgal/public/game/scene/function_test.txt | 1 + packages/webgal/public/game/scene/start.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 packages/webgal/public/game/scene/function_test.txt diff --git a/packages/webgal/public/game/scene/function_test.txt b/packages/webgal/public/game/scene/function_test.txt new file mode 100644 index 000000000..aef71b384 --- /dev/null +++ b/packages/webgal/public/game/scene/function_test.txt @@ -0,0 +1 @@ +choose:Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Escape test:demo_escape.txt; diff --git a/packages/webgal/public/game/scene/start.txt b/packages/webgal/public/game/scene/start.txt index 321b6e0a9..b536aea89 100644 --- a/packages/webgal/public/game/scene/start.txt +++ b/packages/webgal/public/game/scene/start.txt @@ -1,3 +1,3 @@ setVar:heroine=WebGAL; setVar:egine=WebGAL; -choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Escape test:demo_escape.txt; +choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Function Test:function_test.txt From d4e737b549b8aa7efd73b8fa2bf50519364b2319 Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Tue, 2 Jul 2024 22:27:44 +0800 Subject: [PATCH 05/17] =?UTF-8?q?=E4=BF=AE=E5=A4=8DuseEscape=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/webgal/src/Core/gameScripts/intro.tsx | 2 +- packages/webgal/src/Stage/TextBox/TextBox.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webgal/src/Core/gameScripts/intro.tsx b/packages/webgal/src/Core/gameScripts/intro.tsx index 18fab8657..cdbf65e23 100644 --- a/packages/webgal/src/Core/gameScripts/intro.tsx +++ b/packages/webgal/src/Core/gameScripts/intro.tsx @@ -83,7 +83,7 @@ export const intro = (sentence: ISentence): IPerform => { width: '100%', height: '100%', }; - const introArray: Array = sentence.content.split(/[^\\]\|/).map((val: string) => useEscape(val)); + const introArray: Array = sentence.content.split(/(? useEscape(val)); let endWait = 1000; let baseDuration = endWait + delayTime * introArray.length; diff --git a/packages/webgal/src/Stage/TextBox/TextBox.tsx b/packages/webgal/src/Stage/TextBox/TextBox.tsx index 8381b23d9..cdfaad11c 100644 --- a/packages/webgal/src/Stage/TextBox/TextBox.tsx +++ b/packages/webgal/src/Stage/TextBox/TextBox.tsx @@ -101,7 +101,7 @@ function isCJK(character: string) { export function compileSentence(sentence: string, lineLimit: number, ignoreLineLimit?: boolean): EnhancedNode[][] { // 先拆行 - const lines = sentence.split(/[^\\]\|/).map((val: string) => useEscape(val)); + const lines = sentence.split(/(? useEscape(val)); // 对每一行进行注音处理 const rubyLines = lines.map((line) => parseString(line)); const nodeLines = rubyLines.map((line) => { From de4458c7da08dad8053317f090689e2aa9d90223 Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Fri, 5 Jul 2024 23:23:05 +0800 Subject: [PATCH 06/17] =?UTF-8?q?=E5=A2=9E=E5=8A=A0ConfigData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/parser/src/configParser/configParser.ts | 2 +- packages/webgal/public/game/config.txt | 2 ++ packages/webgal/public/game/scene/start.txt | 2 ++ packages/webgal/src/Core/gameScripts/setVar.ts | 2 +- .../src/Core/util/coreInitialFunction/infoFetcher.ts | 8 ++++++++ packages/webgal/src/Core/webgalCore.ts | 8 ++++++++ 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/parser/src/configParser/configParser.ts b/packages/parser/src/configParser/configParser.ts index 12b686b30..cca9e66ec 100644 --- a/packages/parser/src/configParser/configParser.ts +++ b/packages/parser/src/configParser/configParser.ts @@ -26,7 +26,7 @@ function configLineParser(inputLine: string): IConfigItem { }; } // 截取命令 - const getCommandResult = /:/.exec(newSentenceRaw); + const getCommandResult = /\s*:\s*/.exec(newSentenceRaw); // 没有command if (getCommandResult === null) { diff --git a/packages/webgal/public/game/config.txt b/packages/webgal/public/game/config.txt index 3bc42af83..8de560adb 100644 --- a/packages/webgal/public/game/config.txt +++ b/packages/webgal/public/game/config.txt @@ -3,3 +3,5 @@ Game_key:0f87dstRg; Title_img:WebGAL_New_Enter_Image.png; Title_bgm:s_Title.mp3; Game_Logo:WebGalEnter.png; +Debug:true; +GameNum:10; diff --git a/packages/webgal/public/game/scene/start.txt b/packages/webgal/public/game/scene/start.txt index 642f0a686..45b94d686 100644 --- a/packages/webgal/public/game/scene/start.txt +++ b/packages/webgal/public/game/scene/start.txt @@ -1,3 +1,5 @@ setVar:heroine=WebGAL; setVar:egine=WebGAL; +WebGAL:Debug变量为{$GameNum}真 -when=$Debug==true; +:; choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt; diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index 48789d663..3b3d7a59e 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -86,7 +86,7 @@ export function getValueFromState(key: string) { const stage = webgalStore.getState().stage; const GUI = webgalStore.getState().GUI; const userData = webgalStore.getState().userData; - const _Merge = { ...GUI, ...stage, ...userData, gameName: WebGAL.gameName, gameKey: WebGAL.gameKey }; + const _Merge = { ...GUI, ...stage, ...userData, ...WebGAL.ConfigData }; const is_baseVal = (_obj: object, _val: string) => ['string', 'number', 'boolean'].includes(typeof Reflect.get(_obj, _val)); let _all: { [key: PropertyKey]: any } = {}; diff --git a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts index 04bf6492e..c425f109e 100644 --- a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts +++ b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts @@ -65,8 +65,16 @@ export const infoFetcher = (url: string) => { break; } } + let res: any = args[0].trim(); + if (/^(true|false)$/g.test(args[0])) { + res = res === 'true' ? true : false; + } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { + res = Number(res); + } + Reflect.set(WebGAL.ConfigData, command, res); // 保存全部configData }); } + Object.freeze(WebGAL.ConfigData); // 冻结configData变量,因为它不应该被修改 window?.renderPromise?.(); delete window.renderPromise; initKey(); diff --git a/packages/webgal/src/Core/webgalCore.ts b/packages/webgal/src/Core/webgalCore.ts index f1becd487..8ecd4058d 100644 --- a/packages/webgal/src/Core/webgalCore.ts +++ b/packages/webgal/src/Core/webgalCore.ts @@ -1,3 +1,10 @@ +/* + * @Author: xuranXYS + * @LastEditTime: 2024-07-05 22:55:40 + * @GitHub: www.github.com/xiaoxustudio + * @WebSite: www.xiaoxustudio.top + * @Description: By xuranXYS + */ import { BacklogManager } from '@/Core/Modules/backlog'; import mitt from 'mitt'; import { SceneManager } from '@/Core/Modules/scene'; @@ -13,4 +20,5 @@ export class WebgalCore { public gameName = ''; public gameKey = ''; public events = new Events(); + public ConfigData: { [key: string]: string | boolean | number } = {}; // 存放在config中定义的静态全局变量 } From 4314a6ce0deeceaa55b39739859da6a6d6c5a75f Mon Sep 17 00:00:00 2001 From: Mahiru Date: Sat, 6 Jul 2024 08:10:17 +0800 Subject: [PATCH 07/17] use record as the type of ConfigData --- packages/webgal/src/Core/webgalCore.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/webgal/src/Core/webgalCore.ts b/packages/webgal/src/Core/webgalCore.ts index 8ecd4058d..2e60cbce9 100644 --- a/packages/webgal/src/Core/webgalCore.ts +++ b/packages/webgal/src/Core/webgalCore.ts @@ -1,10 +1,3 @@ -/* - * @Author: xuranXYS - * @LastEditTime: 2024-07-05 22:55:40 - * @GitHub: www.github.com/xiaoxustudio - * @WebSite: www.xiaoxustudio.top - * @Description: By xuranXYS - */ import { BacklogManager } from '@/Core/Modules/backlog'; import mitt from 'mitt'; import { SceneManager } from '@/Core/Modules/scene'; @@ -20,5 +13,5 @@ export class WebgalCore { public gameName = ''; public gameKey = ''; public events = new Events(); - public ConfigData: { [key: string]: string | boolean | number } = {}; // 存放在config中定义的静态全局变量 + public ConfigData: Record = {}; // 存放在config中定义的静态全局变量 } From 90094778c7d321b1290fdfa334ce7620e72f8b71 Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Sun, 7 Jul 2024 17:46:45 +0800 Subject: [PATCH 08/17] Reference PR 510 --- .../public/game/scene/demo_changeConfig.txt | 10 ++++ packages/webgal/public/game/scene/start.txt | 4 +- .../Core/controller/gamePlay/nextSentence.ts | 9 ++++ .../controller/gamePlay/scriptExecutor.ts | 2 +- .../webgal/src/Core/gameScripts/setVar.ts | 35 +++++++++---- .../util/coreInitialFunction/infoFetcher.ts | 25 ++++++--- packages/webgal/src/Core/webgalCore.ts | 9 +--- packages/webgal/src/UI/Title/Title.tsx | 51 ++++++++++++++++++- .../webgal/src/store/userDataInterface.ts | 17 +++++++ packages/webgal/src/store/userDataReducer.ts | 7 +++ 10 files changed, 138 insertions(+), 31 deletions(-) create mode 100644 packages/webgal/public/game/scene/demo_changeConfig.txt diff --git a/packages/webgal/public/game/scene/demo_changeConfig.txt b/packages/webgal/public/game/scene/demo_changeConfig.txt new file mode 100644 index 000000000..fee4a267d --- /dev/null +++ b/packages/webgal/public/game/scene/demo_changeConfig.txt @@ -0,0 +1,10 @@ +webgal:我会修改标题 -hold; +setVar:Game_name=WebGal_Change +webgal:游戏标题已经被我修改为{Game_name} -hold; +webgal:我会修改游戏背景 -hold; +setVar:Title_img=bg.png; +webgal:游戏背景已经被我修改为{Title_img} -hold; +webgal:获取bgm声音:{$bgm.volume} -hold; +setVar:bgm_calc= $bgm.volume * 2 ; +webgal:获取bgm声音的两倍是{bgm_calc} -hold; +end; diff --git a/packages/webgal/public/game/scene/start.txt b/packages/webgal/public/game/scene/start.txt index f4bdcc77f..e3cb98592 100644 --- a/packages/webgal/public/game/scene/start.txt +++ b/packages/webgal/public/game/scene/start.txt @@ -1,5 +1,3 @@ setVar:heroine=WebGAL; setVar:egine=WebGAL; -WebGAL:Debug变量为{$GameNum}真 -when=$Debug==true; -:; -choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Function Test:function_test.txt; +choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Change Config:demo_changeConfig.txt; diff --git a/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts b/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts index 2699ef181..188d23668 100644 --- a/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts +++ b/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts @@ -8,6 +8,7 @@ import { IBacklogItem } from '@/Core/Modules/backlog'; import { SYSTEM_CONFIG } from '@/config'; import { WebGAL } from '@/Core/WebGAL'; import { IRunPerform } from '@/store/stageInterface'; +import { setConfigData } from '@/store/userDataReducer'; /** * 进行下一句 @@ -18,6 +19,14 @@ export const nextSentence = () => { */ WebGAL.events.userInteractNext.emit(); + // 保存当前更改ConfigData数据(如果它更改了的话) + const ConfigDataState = webgalStore.getState().userData.configData; + const process_change = (prop: any, val: any) => { + webgalStore.dispatch(setConfigData({ key: prop, value: val })); + }; + for (let i in ConfigDataState) { + if (ConfigDataState[i] !== WebGAL.ConfigData[i]) process_change(i, ConfigDataState[i]); + } // 如果当前显示标题,那么不进行下一句 const GUIState = webgalStore.getState().GUI; if (GUIState.showTitle) { diff --git a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts index eb07f7684..75108d7ba 100644 --- a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts +++ b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts @@ -60,7 +60,7 @@ export const scriptExecutor = () => { if (contentExp !== null) { contentExp.forEach((e) => { const contentVarValue = getValueFromState(e.replace(/(? { } }); let targetReducerFunction: ActionCreatorWithPayload; + const configData = webgalStore.getState().userData.configData; if (setGlobal) { targetReducerFunction = setGlobalVar; } else { targetReducerFunction = setStageVar; } // 先把表达式拆分为变量名和赋值语句 - if (sentence.content.match(/=/)) { - const key = sentence.content.split(/=/)[0]; - const valExp = sentence.content.split(/=/)[1]; + if (sentence.content.match(/\s*=\s*/)) { + const key = sentence.content.split(/\s*=\s*/)[0]; + const valExp = sentence.content.split(/\s*=\s*/)[1]; if (valExp === 'random()') { webgalStore.dispatch(targetReducerFunction({ key, value: Math.random() })); } else if (valExp.match(/\$[.a-zA-Z]/)) { @@ -59,11 +60,18 @@ export const setVar = (sentence: ISentence): IPerform => { } else { if (!isNaN(Number(valExp))) { webgalStore.dispatch(targetReducerFunction({ key, value: Number(valExp) })); - } else webgalStore.dispatch(targetReducerFunction({ key, value: valExp })); + } else if (configData[key]) { + webgalStore.dispatch(setConfigData({ key, value: valExp })); + } else { + webgalStore.dispatch(targetReducerFunction({ key, value: valExp })); + } } if (setGlobal) { logger.debug('设置全局变量:', { key, value: webgalStore.getState().userData.globalGameVar[key] }); dumpToStorageFast(); + } else if (configData[key]) { + logger.debug('设置配置变量:', { key, value: webgalStore.getState().userData.configData[key] }); + dumpToStorageFast(); } else { logger.debug('设置变量:', { key, value: webgalStore.getState().stage.GameVar[key] }); } @@ -82,18 +90,19 @@ export const setVar = (sentence: ISentence): IPerform => { type BaseVal = string | number | boolean; export function getValueFromState(key: string) { - let ret: number | string | boolean = 0; + let ret: any; const stage = webgalStore.getState().stage; const GUI = webgalStore.getState().GUI; const userData = webgalStore.getState().userData; - const _Merge = { ...GUI, ...stage, ...userData, ...WebGAL.ConfigData }; - const is_baseVal = (_obj: object, _val: string) => - ['string', 'number', 'boolean'].includes(typeof Reflect.get(_obj, _val)); + const _Merge = { ...GUI, ...stage, ...userData }; + const is_baseVal = (_obj: object, _val: any, no_get = false) => + ['string', 'number', 'boolean'].includes(typeof (no_get ? _val : Reflect.get(_obj, _val))); let _all: { [key: PropertyKey]: any } = {}; - // 排除GameVar和globalGameVar,因为这两个本来就可以获取 + // 排除GameVar、globalGameVar、configData因为这几个本来就可以获取 for (let i in _Merge) { if (i === 'GameVar') continue; if (i === 'globalGameVar') continue; + if (i === 'configData') continue; if (i) { Reflect.set(_all, '$' + i, Reflect.get(_Merge, i) as BaseVal); } @@ -102,8 +111,12 @@ export function getValueFromState(key: string) { ret = stage.GameVar[key]; } else if (userData.globalGameVar.hasOwnProperty(key)) { ret = userData.globalGameVar[key]; - } else if (key.startsWith('$') && is_baseVal(_all, key)) { + } else if (is_baseVal(userData.configData, key)) { + ret = compile(key)(userData.configData) as BaseVal; + } else if (key.startsWith('$') && is_baseVal(_all, compile(key)(_all), true)) { ret = compile(key)(_all) as BaseVal; + } else { + ret = key; } return ret; } diff --git a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts index c425f109e..b115f376d 100644 --- a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts +++ b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { logger } from '../logger'; import { assetSetter, fileType } from '../gameAssetsAccess/assetSetter'; -import { getStorage } from '../../controller/storage/storageController'; +import { getStorage, setStorage } from '../../controller/storage/storageController'; import { webgalStore } from '@/store/store'; import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; import { setEbg } from '@/Core/gameScripts/changeBg/setEbg'; @@ -9,6 +9,8 @@ import { initKey } from '@/Core/controller/storage/fastSaveLoad'; import { WebgalParser } from '@/Core/parser/sceneParser'; import { WebGAL } from '@/Core/WebGAL'; import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; +import { setConfigData, setUserData } from '@/store/userDataReducer'; +import { saveGame } from '@/Core/controller/storage/saveGame'; declare global { interface Window { @@ -23,14 +25,14 @@ export const infoFetcher = (url: string) => { const GUIState = webgalStore.getState().GUI; const dispatch = webgalStore.dispatch; axios.get(url).then((r) => { + let _GameData = {}; let gameConfigRaw: string = r.data; - const gameConfig = WebgalParser.parseConfig(gameConfigRaw); + let gameConfig = WebgalParser.parseConfig(gameConfigRaw); logger.info('获取到游戏信息', gameConfig); // 按照游戏的配置开始设置对应的状态 if (GUIState) { gameConfig.forEach((e) => { const { command, args } = e; - switch (command) { case 'Title_img': { const titleUrl = assetSetter(args.join(''), fileType.background); @@ -67,16 +69,27 @@ export const infoFetcher = (url: string) => { } let res: any = args[0].trim(); if (/^(true|false)$/g.test(args[0])) { - res = res === 'true' ? true : false; + res = !!(res === 'true'); } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { res = Number(res); } - Reflect.set(WebGAL.ConfigData, command, res); // 保存全部configData + Reflect.set(_GameData, command, res); // 保存全部configData }); } - Object.freeze(WebGAL.ConfigData); // 冻结configData变量,因为它不应该被修改 window?.renderPromise?.(); delete window.renderPromise; initKey(); + getStorage(); + const configData = webgalStore.getState().userData.configData; + if (Object.keys(configData).length === 0) { + webgalStore.dispatch( + setUserData({ + key: 'configData', + value: _GameData, + }), + ); + Reflect.set(WebGAL, 'ConfigData', _GameData); + setStorage(); + } }); }; diff --git a/packages/webgal/src/Core/webgalCore.ts b/packages/webgal/src/Core/webgalCore.ts index 8ecd4058d..7697cdb74 100644 --- a/packages/webgal/src/Core/webgalCore.ts +++ b/packages/webgal/src/Core/webgalCore.ts @@ -1,10 +1,3 @@ -/* - * @Author: xuranXYS - * @LastEditTime: 2024-07-05 22:55:40 - * @GitHub: www.github.com/xiaoxustudio - * @WebSite: www.xiaoxustudio.top - * @Description: By xuranXYS - */ import { BacklogManager } from '@/Core/Modules/backlog'; import mitt from 'mitt'; import { SceneManager } from '@/Core/Modules/scene'; @@ -20,5 +13,5 @@ export class WebgalCore { public gameName = ''; public gameKey = ''; public events = new Events(); - public ConfigData: { [key: string]: string | boolean | number } = {}; // 存放在config中定义的静态全局变量 + public ConfigData: Record = {}; // 存放在config中定义的静态全局变量备份(用于比较更新) } diff --git a/packages/webgal/src/UI/Title/Title.tsx b/packages/webgal/src/UI/Title/Title.tsx index 1026e4379..ca2a42ec4 100644 --- a/packages/webgal/src/UI/Title/Title.tsx +++ b/packages/webgal/src/UI/Title/Title.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useEffect } from 'react'; import styles from './title.module.scss'; import { playBgm } from '@/Core/controller/stage/playBgm'; import { continueGame, startGame } from '@/Core/controller/gamePlay/startContinueGame'; @@ -17,7 +17,12 @@ import { WebGAL } from '@/Core/WebGAL'; import useApplyStyle from '@/hooks/useApplyStyle'; import { fullScreenOption } from '@/store/userDataInterface'; import { keyboard } from '@/hooks/useHotkey'; - +import { logger } from '@/Core/util/logger'; +import { assetSetter, fileType } from '@/Core/util/gameAssetsAccess/assetSetter'; +import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; +import { getStorage, setStorage } from '@/Core/controller/storage/storageController'; +import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; +import { setUserData } from '@/store/userDataReducer'; /** * 标题页 * @constructor @@ -33,7 +38,49 @@ const Title: FC = () => { const { playSeEnter, playSeClick } = useSoundEffect(); const applyStyle = useApplyStyle('UI/Title/title.scss'); + useEffect(() => { + // configData发生变化 + const configData = webgalStore.getState().userData.configData; + for (let i in configData) { + if ((configData[i] as string) !== WebGAL.ConfigData[i]) { + const val = configData[i] as string; + switch (i) { + case 'Title_img': { + const titleUrl = assetSetter(val, fileType.background); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); + setEbg(titleUrl); + break; + } + case 'Game_Logo': { + const logoUrlList = [assetSetter(val, fileType.background)]; + webgalStore.dispatch(setLogoImage(logoUrlList)); + break; + } + + case 'Title_bgm': { + const bgmUrl = assetSetter(val, fileType.bgm); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); + break; + } + + case 'Game_name': { + WebGAL.gameName = val; + document.title = val; + break; + } + + case 'Game_key': { + WebGAL.gameKey = val; + getStorage(); + getFastSaveFromStorage(); + getSavesFromStorage(0, 0); + break; + } + } + } + } + }, [webgalStore.getState().userData.configData]); return ( <> {GUIState.showTitle &&
} diff --git a/packages/webgal/src/store/userDataInterface.ts b/packages/webgal/src/store/userDataInterface.ts index 585568406..a01b8fc90 100644 --- a/packages/webgal/src/store/userDataInterface.ts +++ b/packages/webgal/src/store/userDataInterface.ts @@ -94,14 +94,31 @@ export interface IAppreciation { export interface IUserData { globalGameVar: IGameVar; // 不跟随存档的全局变量 optionData: IOptionData; // 用户设置选项数据 + configData: Record; // 存放在config中定义的全局变量 appreciationData: IAppreciation; } +/** + * @interface IUserData 配置数据接口 + */ +export interface IConfigData { + Game_name: string; + Game_key: string; + Title_img: string; + Title_bgm: string; + Game_Logo: string; + [key: string]: any; +} export interface ISetUserDataPayload { key: keyof IUserData; value: any; } +export interface ISetConfigDataPayload { + key: keyof IConfigData; + value: any; +} + export interface ISetOptionDataPayload { key: keyof IOptionData; value: any; diff --git a/packages/webgal/src/store/userDataReducer.ts b/packages/webgal/src/store/userDataReducer.ts index 7efc5b8de..4f3d0d160 100644 --- a/packages/webgal/src/store/userDataReducer.ts +++ b/packages/webgal/src/store/userDataReducer.ts @@ -8,6 +8,7 @@ import { IAppreciationAsset, IOptionData, ISaveData, + ISetConfigDataPayload, ISetOptionDataPayload, ISetUserDataPayload, IUserData, @@ -46,6 +47,7 @@ export const initState: IUserData = { bgm: [], cg: [], }, + configData: {}, // 存放在config中定义的全局变量 }; const userDataSlice = createSlice({ @@ -61,6 +63,10 @@ const userDataSlice = createSlice({ const { key, value } = action.payload; state[key] = value; }, + setConfigData: (state, action: PayloadAction) => { + const { key, value } = action.payload; + state.configData[key] = value; + }, unlockCgInUserData: (state, action: PayloadAction) => { const { name, url, series } = action.payload; // 检查是否存在 @@ -135,6 +141,7 @@ const userDataSlice = createSlice({ export const { setUserData, + setConfigData, resetUserData, setOptionData, setGlobalVar, From 99e42d20a2112e0e42b1d08229dafd87ba09fac3 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Sun, 7 Jul 2024 19:57:29 +0800 Subject: [PATCH 09/17] move test script entry --- packages/webgal/public/game/scene/function_test.txt | 2 +- packages/webgal/public/game/scene/start.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webgal/public/game/scene/function_test.txt b/packages/webgal/public/game/scene/function_test.txt index aef71b384..8514bd9d0 100644 --- a/packages/webgal/public/game/scene/function_test.txt +++ b/packages/webgal/public/game/scene/function_test.txt @@ -1 +1 @@ -choose:Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Escape test:demo_escape.txt; +choose:Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Change Config:demo_changeConfig.txt; diff --git a/packages/webgal/public/game/scene/start.txt b/packages/webgal/public/game/scene/start.txt index e3cb98592..1e072c7c3 100644 --- a/packages/webgal/public/game/scene/start.txt +++ b/packages/webgal/public/game/scene/start.txt @@ -1,3 +1,3 @@ setVar:heroine=WebGAL; setVar:egine=WebGAL; -choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Lip Sync Animation Test:demo_animation.txt | Variable interpolation test:demo_var.txt | Change Config:demo_changeConfig.txt; +choose:简体中文:demo_zh_cn.txt|日本語:demo_ja.txt|English:demo_en.txt|Test:function_test.txt; From c81a09b517370b7ce0e3f09dcca16737d6ceb537 Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Sun, 7 Jul 2024 22:47:19 +0800 Subject: [PATCH 10/17] Reference PR 510 (2) --- packages/webgal/public/game/config.txt | 1 + .../public/game/scene/demo_changeConfig.txt | 9 ++- .../Core/controller/gamePlay/nextSentence.ts | 9 --- .../webgal/src/Core/gameScripts/setVar.ts | 19 ++---- .../util/coreInitialFunction/infoFetcher.ts | 29 +++++----- packages/webgal/src/Core/webgalCore.ts | 1 - packages/webgal/src/UI/Title/Title.tsx | 58 ++----------------- packages/webgal/src/hooks/useConfigData.ts | 57 ++++++++++++++++++ .../webgal/src/store/userDataInterface.ts | 6 +- packages/webgal/src/store/userDataReducer.ts | 7 --- 10 files changed, 89 insertions(+), 107 deletions(-) create mode 100644 packages/webgal/src/hooks/useConfigData.ts diff --git a/packages/webgal/public/game/config.txt b/packages/webgal/public/game/config.txt index 8de560adb..6b1274182 100644 --- a/packages/webgal/public/game/config.txt +++ b/packages/webgal/public/game/config.txt @@ -5,3 +5,4 @@ Title_bgm:s_Title.mp3; Game_Logo:WebGalEnter.png; Debug:true; GameNum:10; +GameNum_Double:20; diff --git a/packages/webgal/public/game/scene/demo_changeConfig.txt b/packages/webgal/public/game/scene/demo_changeConfig.txt index fee4a267d..13a276619 100644 --- a/packages/webgal/public/game/scene/demo_changeConfig.txt +++ b/packages/webgal/public/game/scene/demo_changeConfig.txt @@ -1,9 +1,14 @@ webgal:我会修改标题 -hold; -setVar:Game_name=WebGal_Change +setVar:Game_name=WebGal_Change -global; webgal:游戏标题已经被我修改为{Game_name} -hold; webgal:我会修改游戏背景 -hold; -setVar:Title_img=bg.png; +setVar:Title_img=bg.png -global; webgal:游戏背景已经被我修改为{Title_img} -hold; +webgal:获取Debug值:{Debug} -hold; +setVar:GameNum=15 -global; +webgal:获取并修改GameNum的值:{GameNum} -hold; +setVar:GameNum_Double=GameNum_Double + 5; +webgal:获取GameNum_Double的值,但我不会修改它原本的值:{GameNum_Double} -hold; webgal:获取bgm声音:{$bgm.volume} -hold; setVar:bgm_calc= $bgm.volume * 2 ; webgal:获取bgm声音的两倍是{bgm_calc} -hold; diff --git a/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts b/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts index 188d23668..2699ef181 100644 --- a/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts +++ b/packages/webgal/src/Core/controller/gamePlay/nextSentence.ts @@ -8,7 +8,6 @@ import { IBacklogItem } from '@/Core/Modules/backlog'; import { SYSTEM_CONFIG } from '@/config'; import { WebGAL } from '@/Core/WebGAL'; import { IRunPerform } from '@/store/stageInterface'; -import { setConfigData } from '@/store/userDataReducer'; /** * 进行下一句 @@ -19,14 +18,6 @@ export const nextSentence = () => { */ WebGAL.events.userInteractNext.emit(); - // 保存当前更改ConfigData数据(如果它更改了的话) - const ConfigDataState = webgalStore.getState().userData.configData; - const process_change = (prop: any, val: any) => { - webgalStore.dispatch(setConfigData({ key: prop, value: val })); - }; - for (let i in ConfigDataState) { - if (ConfigDataState[i] !== WebGAL.ConfigData[i]) process_change(i, ConfigDataState[i]); - } // 如果当前显示标题,那么不进行下一句 const GUIState = webgalStore.getState().GUI; if (GUIState.showTitle) { diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index 4c437e3db..d55d79808 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -4,11 +4,10 @@ import { webgalStore } from '@/store/store'; import { setStageVar } from '@/store/stageReducer'; import { logger } from '@/Core/util/logger'; import { compile } from 'angular-expressions'; -import { setConfigData, setGlobalVar } from '@/store/userDataReducer'; +import { setGlobalVar } from '@/store/userDataReducer'; import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; import { ISetGameVar } from '@/store/stageInterface'; import { dumpToStorageFast } from '@/Core/controller/storage/storageController'; -import { WebGAL } from '@/Core/WebGAL'; /** * 设置变量 * @param sentence @@ -21,7 +20,6 @@ export const setVar = (sentence: ISentence): IPerform => { } }); let targetReducerFunction: ActionCreatorWithPayload; - const configData = webgalStore.getState().userData.configData; if (setGlobal) { targetReducerFunction = setGlobalVar; } else { @@ -60,8 +58,6 @@ export const setVar = (sentence: ISentence): IPerform => { } else { if (!isNaN(Number(valExp))) { webgalStore.dispatch(targetReducerFunction({ key, value: Number(valExp) })); - } else if (configData[key]) { - webgalStore.dispatch(setConfigData({ key, value: valExp })); } else { webgalStore.dispatch(targetReducerFunction({ key, value: valExp })); } @@ -69,9 +65,6 @@ export const setVar = (sentence: ISentence): IPerform => { if (setGlobal) { logger.debug('设置全局变量:', { key, value: webgalStore.getState().userData.globalGameVar[key] }); dumpToStorageFast(); - } else if (configData[key]) { - logger.debug('设置配置变量:', { key, value: webgalStore.getState().userData.configData[key] }); - dumpToStorageFast(); } else { logger.debug('设置变量:', { key, value: webgalStore.getState().stage.GameVar[key] }); } @@ -92,27 +85,23 @@ type BaseVal = string | number | boolean; export function getValueFromState(key: string) { let ret: any; const stage = webgalStore.getState().stage; - const GUI = webgalStore.getState().GUI; const userData = webgalStore.getState().userData; - const _Merge = { ...GUI, ...stage, ...userData }; + const _Merge = { ...stage, ...userData }; const is_baseVal = (_obj: object, _val: any, no_get = false) => ['string', 'number', 'boolean'].includes(typeof (no_get ? _val : Reflect.get(_obj, _val))); let _all: { [key: PropertyKey]: any } = {}; - // 排除GameVar、globalGameVar、configData因为这几个本来就可以获取 + // 排除GameVar、globalGameVar因为这几个本来就可以获取 for (let i in _Merge) { if (i === 'GameVar') continue; if (i === 'globalGameVar') continue; - if (i === 'configData') continue; if (i) { - Reflect.set(_all, '$' + i, Reflect.get(_Merge, i) as BaseVal); + _all['$' + i] = Reflect.get(_Merge, i) as BaseVal; } } if (stage.GameVar.hasOwnProperty(key)) { ret = stage.GameVar[key]; } else if (userData.globalGameVar.hasOwnProperty(key)) { ret = userData.globalGameVar[key]; - } else if (is_baseVal(userData.configData, key)) { - ret = compile(key)(userData.configData) as BaseVal; } else if (key.startsWith('$') && is_baseVal(_all, compile(key)(_all), true)) { ret = compile(key)(_all) as BaseVal; } else { diff --git a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts index b115f376d..1568809b2 100644 --- a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts +++ b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts @@ -9,8 +9,7 @@ import { initKey } from '@/Core/controller/storage/fastSaveLoad'; import { WebgalParser } from '@/Core/parser/sceneParser'; import { WebGAL } from '@/Core/WebGAL'; import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; -import { setConfigData, setUserData } from '@/store/userDataReducer'; -import { saveGame } from '@/Core/controller/storage/saveGame'; +import { setGlobalVar } from '@/store/userDataReducer'; declare global { interface Window { @@ -23,9 +22,10 @@ declare global { */ export const infoFetcher = (url: string) => { const GUIState = webgalStore.getState().GUI; + const ConfigState = webgalStore.getState().userData.globalGameVar; const dispatch = webgalStore.dispatch; + getStorage(); axios.get(url).then((r) => { - let _GameData = {}; let gameConfigRaw: string = r.data; let gameConfig = WebgalParser.parseConfig(gameConfigRaw); logger.info('获取到游戏信息', gameConfig); @@ -73,23 +73,20 @@ export const infoFetcher = (url: string) => { } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { res = Number(res); } - Reflect.set(_GameData, command, res); // 保存全部configData + // 添加不存在的值 + if (!ConfigState[command]) { + dispatch( + setGlobalVar({ + key: command, + value: res, + }), + ); + } + setStorage(); }); } window?.renderPromise?.(); delete window.renderPromise; initKey(); - getStorage(); - const configData = webgalStore.getState().userData.configData; - if (Object.keys(configData).length === 0) { - webgalStore.dispatch( - setUserData({ - key: 'configData', - value: _GameData, - }), - ); - Reflect.set(WebGAL, 'ConfigData', _GameData); - setStorage(); - } }); }; diff --git a/packages/webgal/src/Core/webgalCore.ts b/packages/webgal/src/Core/webgalCore.ts index 7697cdb74..f1becd487 100644 --- a/packages/webgal/src/Core/webgalCore.ts +++ b/packages/webgal/src/Core/webgalCore.ts @@ -13,5 +13,4 @@ export class WebgalCore { public gameName = ''; public gameKey = ''; public events = new Events(); - public ConfigData: Record = {}; // 存放在config中定义的静态全局变量备份(用于比较更新) } diff --git a/packages/webgal/src/UI/Title/Title.tsx b/packages/webgal/src/UI/Title/Title.tsx index ca2a42ec4..6af1e7605 100644 --- a/packages/webgal/src/UI/Title/Title.tsx +++ b/packages/webgal/src/UI/Title/Title.tsx @@ -6,23 +6,14 @@ import { useDispatch, useSelector } from 'react-redux'; import { RootState, webgalStore } from '@/store/store'; import { setMenuPanelTag, setVisibility } from '@/store/GUIReducer'; import { MenuPanelTag } from '@/store/guiInterface'; -import { nextSentence } from '@/Core/controller/gamePlay/nextSentence'; -import { restorePerform } from '@/Core/controller/storage/jumpFromBacklog'; -import { setEbg } from '@/Core/gameScripts/changeBg/setEbg'; import useTrans from '@/hooks/useTrans'; // import { resize } from '@/Core/util/resize'; import { hasFastSaveRecord, loadFastSaveGame } from '@/Core/controller/storage/fastSaveLoad'; import useSoundEffect from '@/hooks/useSoundEffect'; -import { WebGAL } from '@/Core/WebGAL'; import useApplyStyle from '@/hooks/useApplyStyle'; -import { fullScreenOption } from '@/store/userDataInterface'; +import { fullScreenOption, IConfigData } from '@/store/userDataInterface'; import { keyboard } from '@/hooks/useHotkey'; -import { logger } from '@/Core/util/logger'; -import { assetSetter, fileType } from '@/Core/util/gameAssetsAccess/assetSetter'; -import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; -import { getStorage, setStorage } from '@/Core/controller/storage/storageController'; -import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; -import { setUserData } from '@/store/userDataReducer'; +import useConfigData from '@/hooks/useConfigData'; /** * 标题页 * @constructor @@ -36,51 +27,10 @@ const Title: FC = () => { const showBackground = background === '' ? 'rgba(0,0,0,1)' : `url("${background}")`; const t = useTrans('title.'); const { playSeEnter, playSeClick } = useSoundEffect(); + const configData = useSelector((state: RootState) => state.userData.globalGameVar) as IConfigData; const applyStyle = useApplyStyle('UI/Title/title.scss'); - useEffect(() => { - // configData发生变化 - const configData = webgalStore.getState().userData.configData; - for (let i in configData) { - if ((configData[i] as string) !== WebGAL.ConfigData[i]) { - const val = configData[i] as string; - switch (i) { - case 'Title_img': { - const titleUrl = assetSetter(val, fileType.background); - webgalStore.dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); - setEbg(titleUrl); - break; - } - - case 'Game_Logo': { - const logoUrlList = [assetSetter(val, fileType.background)]; - webgalStore.dispatch(setLogoImage(logoUrlList)); - break; - } - - case 'Title_bgm': { - const bgmUrl = assetSetter(val, fileType.bgm); - webgalStore.dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); - break; - } - - case 'Game_name': { - WebGAL.gameName = val; - document.title = val; - break; - } - - case 'Game_key': { - WebGAL.gameKey = val; - getStorage(); - getFastSaveFromStorage(); - getSavesFromStorage(0, 0); - break; - } - } - } - } - }, [webgalStore.getState().userData.configData]); + useConfigData(configData); // 监听基础ConfigData变化 return ( <> {GUIState.showTitle &&
} diff --git a/packages/webgal/src/hooks/useConfigData.ts b/packages/webgal/src/hooks/useConfigData.ts new file mode 100644 index 000000000..f54931203 --- /dev/null +++ b/packages/webgal/src/hooks/useConfigData.ts @@ -0,0 +1,57 @@ +import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; +import { getStorage } from '@/Core/controller/storage/storageController'; +import { setEbg } from '@/Core/gameScripts/changeBg/setEbg'; +import { assetSetter, fileType } from '@/Core/util/gameAssetsAccess/assetSetter'; +import { WebGAL } from '@/Core/WebGAL'; +import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; +import { webgalStore } from '@/store/store'; +import { IConfigData } from '@/store/userDataInterface'; +import { useEffect } from 'react'; + +const useConfigData = (configData: IConfigData) => { + const _map = ['Title_img', 'Game_Logo', 'Title_bgm', 'Game_name', 'Game_key']; + return useEffect(() => { + // configData发生变化 + for (let i in configData) { + if (_map.includes(i)) { + const val = configData[i] as string; + switch (i) { + case 'Title_img': { + const titleUrl = assetSetter(val, fileType.background); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); + setEbg(titleUrl); + break; + } + + case 'Game_Logo': { + const logoUrlList = [assetSetter(val, fileType.background)]; + webgalStore.dispatch(setLogoImage(logoUrlList)); + break; + } + + case 'Title_bgm': { + const bgmUrl = assetSetter(val, fileType.bgm); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); + break; + } + + case 'Game_name': { + WebGAL.gameName = val; + document.title = val; + break; + } + + case 'Game_key': { + WebGAL.gameKey = val; + getStorage(); + getFastSaveFromStorage(); + getSavesFromStorage(0, 0); + break; + } + } + } + } + return () => {}; + }, [configData.Game_Logo, configData.Game_key, configData.Game_name, configData.Title_bgm, configData.Title_img]); +}; +export default useConfigData; diff --git a/packages/webgal/src/store/userDataInterface.ts b/packages/webgal/src/store/userDataInterface.ts index a01b8fc90..982b514c6 100644 --- a/packages/webgal/src/store/userDataInterface.ts +++ b/packages/webgal/src/store/userDataInterface.ts @@ -94,11 +94,11 @@ export interface IAppreciation { export interface IUserData { globalGameVar: IGameVar; // 不跟随存档的全局变量 optionData: IOptionData; // 用户设置选项数据 - configData: Record; // 存放在config中定义的全局变量 appreciationData: IAppreciation; } + /** - * @interface IUserData 配置数据接口 + * @interface IConfigData 配置数据接口 */ export interface IConfigData { Game_name: string; @@ -116,7 +116,7 @@ export interface ISetUserDataPayload { export interface ISetConfigDataPayload { key: keyof IConfigData; - value: any; + value: string | boolean | number; } export interface ISetOptionDataPayload { diff --git a/packages/webgal/src/store/userDataReducer.ts b/packages/webgal/src/store/userDataReducer.ts index 4f3d0d160..7efc5b8de 100644 --- a/packages/webgal/src/store/userDataReducer.ts +++ b/packages/webgal/src/store/userDataReducer.ts @@ -8,7 +8,6 @@ import { IAppreciationAsset, IOptionData, ISaveData, - ISetConfigDataPayload, ISetOptionDataPayload, ISetUserDataPayload, IUserData, @@ -47,7 +46,6 @@ export const initState: IUserData = { bgm: [], cg: [], }, - configData: {}, // 存放在config中定义的全局变量 }; const userDataSlice = createSlice({ @@ -63,10 +61,6 @@ const userDataSlice = createSlice({ const { key, value } = action.payload; state[key] = value; }, - setConfigData: (state, action: PayloadAction) => { - const { key, value } = action.payload; - state.configData[key] = value; - }, unlockCgInUserData: (state, action: PayloadAction) => { const { name, url, series } = action.payload; // 检查是否存在 @@ -141,7 +135,6 @@ const userDataSlice = createSlice({ export const { setUserData, - setConfigData, resetUserData, setOptionData, setGlobalVar, From b10cff55f345a034267bf5a631230b3d7d20bc38 Mon Sep 17 00:00:00 2001 From: xiaoxustudio <1783558957@qq.com> Date: Mon, 8 Jul 2024 00:17:37 +0800 Subject: [PATCH 11/17] Fixed bug where globalVariable is empty --- .../util/coreInitialFunction/infoFetcher.ts | 27 ++++---- packages/webgal/src/hooks/useConfigData.ts | 63 ++++++++++--------- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts index 1568809b2..75b5c5288 100644 --- a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts +++ b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts @@ -9,7 +9,9 @@ import { initKey } from '@/Core/controller/storage/fastSaveLoad'; import { WebgalParser } from '@/Core/parser/sceneParser'; import { WebGAL } from '@/Core/WebGAL'; import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; -import { setGlobalVar } from '@/store/userDataReducer'; +import { resetUserData, setGlobalVar } from '@/store/userDataReducer'; +import localforage from 'localforage'; +import { IUserData } from '@/store/userDataInterface'; declare global { interface Window { @@ -21,10 +23,9 @@ declare global { * @param url 游戏信息路径 */ export const infoFetcher = (url: string) => { + getStorage(); const GUIState = webgalStore.getState().GUI; - const ConfigState = webgalStore.getState().userData.globalGameVar; const dispatch = webgalStore.dispatch; - getStorage(); axios.get(url).then((r) => { let gameConfigRaw: string = r.data; let gameConfig = WebgalParser.parseConfig(gameConfigRaw); @@ -42,6 +43,7 @@ export const infoFetcher = (url: string) => { } case 'Game_Logo': { + // eslint-disable-next-line max-nested-callbacks const logoUrlList = args.map((url) => assetSetter(url, fileType.background)); dispatch(setLogoImage(logoUrlList)); break; @@ -73,20 +75,19 @@ export const infoFetcher = (url: string) => { } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { res = Number(res); } - // 添加不存在的值 - if (!ConfigState[command]) { - dispatch( - setGlobalVar({ - key: command, - value: res, - }), - ); - } - setStorage(); + dispatch( + setGlobalVar({ + key: command, + value: res, + }), + ); }); } window?.renderPromise?.(); delete window.renderPromise; initKey(); + setTimeout(() => { + setStorage(); + }, 200); }); }; diff --git a/packages/webgal/src/hooks/useConfigData.ts b/packages/webgal/src/hooks/useConfigData.ts index f54931203..6ed8553f7 100644 --- a/packages/webgal/src/hooks/useConfigData.ts +++ b/packages/webgal/src/hooks/useConfigData.ts @@ -13,41 +13,42 @@ const useConfigData = (configData: IConfigData) => { return useEffect(() => { // configData发生变化 for (let i in configData) { - if (_map.includes(i)) { - const val = configData[i] as string; - switch (i) { - case 'Title_img': { - const titleUrl = assetSetter(val, fileType.background); - webgalStore.dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); - setEbg(titleUrl); - break; - } + if (!_map.includes(i)) { + continue; + } + const val = configData[i] as string; + switch (i) { + case 'Title_img': { + const titleUrl = assetSetter(val, fileType.background); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); + setEbg(titleUrl); + break; + } - case 'Game_Logo': { - const logoUrlList = [assetSetter(val, fileType.background)]; - webgalStore.dispatch(setLogoImage(logoUrlList)); - break; - } + case 'Game_Logo': { + const logoUrlList = [assetSetter(val, fileType.background)]; + webgalStore.dispatch(setLogoImage(logoUrlList)); + break; + } - case 'Title_bgm': { - const bgmUrl = assetSetter(val, fileType.bgm); - webgalStore.dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); - break; - } + case 'Title_bgm': { + const bgmUrl = assetSetter(val, fileType.bgm); + webgalStore.dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); + break; + } - case 'Game_name': { - WebGAL.gameName = val; - document.title = val; - break; - } + case 'Game_name': { + WebGAL.gameName = val; + document.title = val; + break; + } - case 'Game_key': { - WebGAL.gameKey = val; - getStorage(); - getFastSaveFromStorage(); - getSavesFromStorage(0, 0); - break; - } + case 'Game_key': { + WebGAL.gameKey = val; + getStorage(); + getFastSaveFromStorage(); + getSavesFromStorage(0, 0); + break; } } } From e7fbcc500b4b8e6690a045d42383b5501ff11b37 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Mon, 8 Jul 2024 20:11:21 +0800 Subject: [PATCH 12/17] fix: game config handler --- .../controller/gamePlay/scriptExecutor.ts | 2 +- .../util/coreInitialFunction/infoFetcher.ts | 64 ++++++------------- packages/webgal/src/UI/Title/Title.tsx | 5 +- packages/webgal/src/hooks/useConfigData.ts | 7 +- .../webgal/src/store/userDataInterface.ts | 17 ----- 5 files changed, 25 insertions(+), 70 deletions(-) diff --git a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts index 75108d7ba..eb07f7684 100644 --- a/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts +++ b/packages/webgal/src/Core/controller/gamePlay/scriptExecutor.ts @@ -60,7 +60,7 @@ export const scriptExecutor = () => { if (contentExp !== null) { contentExp.forEach((e) => { const contentVarValue = getValueFromState(e.replace(/(? { let gameConfigRaw: string = r.data; let gameConfig = WebgalParser.parseConfig(gameConfigRaw); logger.info('获取到游戏信息', gameConfig); + // 先把 key 找到并设置了 + const keyItem = gameConfig.find((e) => e.command === 'Game_key'); + const key = (keyItem?.options?.[0].value as string) ?? ''; + WebGAL.gameKey = key; + initKey(); + getStorage(); + getFastSaveFromStorage(); + getSavesFromStorage(0, 0); // 按照游戏的配置开始设置对应的状态 if (GUIState) { gameConfig.forEach((e) => { const { command, args } = e; - switch (command) { - case 'Title_img': { - const titleUrl = assetSetter(args.join(''), fileType.background); - dispatch(setGuiAsset({ asset: 'titleBg', value: titleUrl })); - setEbg(titleUrl); - break; - } - - case 'Game_Logo': { - // eslint-disable-next-line max-nested-callbacks - const logoUrlList = args.map((url) => assetSetter(url, fileType.background)); - dispatch(setLogoImage(logoUrlList)); - break; - } - - case 'Title_bgm': { - const bgmUrl = assetSetter(args[0], fileType.bgm); - dispatch(setGuiAsset({ asset: 'titleBgm', value: bgmUrl })); - break; - } - - case 'Game_name': { - WebGAL.gameName = args[0]; - document.title = args[0]; - break; - } - - case 'Game_key': { - WebGAL.gameKey = args[0]; - getStorage(); - getFastSaveFromStorage(); - getSavesFromStorage(0, 0); - break; - } - } let res: any = args[0].trim(); if (/^(true|false)$/g.test(args[0])) { - res = !!(res === 'true'); + res = !!res; } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { res = Number(res); } - dispatch( - setGlobalVar({ - key: command, - value: res, - }), - ); + if (webgalStore.getState().userData.globalGameVar?.[command] === undefined) { + dispatch( + setGlobalVar({ + key: command, + value: res, + }), + ); + } }); } window?.renderPromise?.(); delete window.renderPromise; - initKey(); - setTimeout(() => { - setStorage(); - }, 200); + setStorage(); }); }; diff --git a/packages/webgal/src/UI/Title/Title.tsx b/packages/webgal/src/UI/Title/Title.tsx index 6af1e7605..15bc0eb4f 100644 --- a/packages/webgal/src/UI/Title/Title.tsx +++ b/packages/webgal/src/UI/Title/Title.tsx @@ -11,7 +11,7 @@ import useTrans from '@/hooks/useTrans'; import { hasFastSaveRecord, loadFastSaveGame } from '@/Core/controller/storage/fastSaveLoad'; import useSoundEffect from '@/hooks/useSoundEffect'; import useApplyStyle from '@/hooks/useApplyStyle'; -import { fullScreenOption, IConfigData } from '@/store/userDataInterface'; +import { fullScreenOption } from '@/store/userDataInterface'; import { keyboard } from '@/hooks/useHotkey'; import useConfigData from '@/hooks/useConfigData'; /** @@ -27,10 +27,9 @@ const Title: FC = () => { const showBackground = background === '' ? 'rgba(0,0,0,1)' : `url("${background}")`; const t = useTrans('title.'); const { playSeEnter, playSeClick } = useSoundEffect(); - const configData = useSelector((state: RootState) => state.userData.globalGameVar) as IConfigData; const applyStyle = useApplyStyle('UI/Title/title.scss'); - useConfigData(configData); // 监听基础ConfigData变化 + useConfigData(); // 监听基础ConfigData变化 return ( <> {GUIState.showTitle &&
} diff --git a/packages/webgal/src/hooks/useConfigData.ts b/packages/webgal/src/hooks/useConfigData.ts index 6ed8553f7..c9f6c10c6 100644 --- a/packages/webgal/src/hooks/useConfigData.ts +++ b/packages/webgal/src/hooks/useConfigData.ts @@ -4,12 +4,13 @@ import { setEbg } from '@/Core/gameScripts/changeBg/setEbg'; import { assetSetter, fileType } from '@/Core/util/gameAssetsAccess/assetSetter'; import { WebGAL } from '@/Core/WebGAL'; import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; -import { webgalStore } from '@/store/store'; -import { IConfigData } from '@/store/userDataInterface'; +import { RootState, webgalStore } from '@/store/store'; import { useEffect } from 'react'; +import { useSelector } from 'react-redux'; -const useConfigData = (configData: IConfigData) => { +const useConfigData = () => { const _map = ['Title_img', 'Game_Logo', 'Title_bgm', 'Game_name', 'Game_key']; + const configData = useSelector((state: RootState) => state.userData.globalGameVar); return useEffect(() => { // configData发生变化 for (let i in configData) { diff --git a/packages/webgal/src/store/userDataInterface.ts b/packages/webgal/src/store/userDataInterface.ts index 982b514c6..585568406 100644 --- a/packages/webgal/src/store/userDataInterface.ts +++ b/packages/webgal/src/store/userDataInterface.ts @@ -97,28 +97,11 @@ export interface IUserData { appreciationData: IAppreciation; } -/** - * @interface IConfigData 配置数据接口 - */ -export interface IConfigData { - Game_name: string; - Game_key: string; - Title_img: string; - Title_bgm: string; - Game_Logo: string; - [key: string]: any; -} - export interface ISetUserDataPayload { key: keyof IUserData; value: any; } -export interface ISetConfigDataPayload { - key: keyof IConfigData; - value: string | boolean | number; -} - export interface ISetOptionDataPayload { key: keyof IOptionData; value: any; From cd6180944f75819c15b347b2cbee8a41e6d48b0b Mon Sep 17 00:00:00 2001 From: Mahiru Date: Mon, 8 Jul 2024 21:00:02 +0800 Subject: [PATCH 13/17] fix: lint, setVar, infoFetcher --- .../webgal/src/Core/gameScripts/setVar.ts | 16 +++--- .../util/coreInitialFunction/infoFetcher.ts | 56 ++++++++----------- .../webgal/src/Stage/MainStage/useSetBg.ts | 2 +- packages/webgal/src/hooks/useConfigData.ts | 14 +++-- packages/webgal/src/hooks/useFullScreen.ts | 7 +-- packages/webgal/src/hooks/useHotkey.tsx | 10 ++-- packages/webgal/src/store/stageInterface.ts | 2 +- 7 files changed, 50 insertions(+), 57 deletions(-) diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index d55d79808..4451717a3 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -8,6 +8,7 @@ import { setGlobalVar } from '@/store/userDataReducer'; import { ActionCreatorWithPayload } from '@reduxjs/toolkit'; import { ISetGameVar } from '@/store/stageInterface'; import { dumpToStorageFast } from '@/Core/controller/storage/storageController'; +import get from 'lodash/get'; /** * 设置变量 * @param sentence @@ -83,7 +84,7 @@ export const setVar = (sentence: ISentence): IPerform => { type BaseVal = string | number | boolean; export function getValueFromState(key: string) { - let ret: any; + let ret: any = 0; const stage = webgalStore.getState().stage; const userData = webgalStore.getState().userData; const _Merge = { ...stage, ...userData }; @@ -91,11 +92,12 @@ export function getValueFromState(key: string) { ['string', 'number', 'boolean'].includes(typeof (no_get ? _val : Reflect.get(_obj, _val))); let _all: { [key: PropertyKey]: any } = {}; // 排除GameVar、globalGameVar因为这几个本来就可以获取 - for (let i in _Merge) { - if (i === 'GameVar') continue; - if (i === 'globalGameVar') continue; - if (i) { - _all['$' + i] = Reflect.get(_Merge, i) as BaseVal; + for (let propertyName in _Merge) { + if (propertyName === 'GameVar') continue; + if (propertyName === 'globalGameVar') continue; + if (propertyName) { + // @ts-ignore + _all['$' + propertyName] = get(_Merge, propertyName) as BaseVal; } } if (stage.GameVar.hasOwnProperty(key)) { @@ -104,8 +106,6 @@ export function getValueFromState(key: string) { ret = userData.globalGameVar[key]; } else if (key.startsWith('$') && is_baseVal(_all, compile(key)(_all), true)) { ret = compile(key)(_all) as BaseVal; - } else { - ret = key; } return ret; } diff --git a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts index d021d4f89..10af13945 100644 --- a/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts +++ b/packages/webgal/src/Core/util/coreInitialFunction/infoFetcher.ts @@ -1,17 +1,12 @@ import axios from 'axios'; import { logger } from '../logger'; -import { assetSetter, fileType } from '../gameAssetsAccess/assetSetter'; -import { getStorage, setStorage } from '../../controller/storage/storageController'; +import { getStorage, getStorageAsync, setStorage } from '../../controller/storage/storageController'; import { webgalStore } from '@/store/store'; -import { setGuiAsset, setLogoImage } from '@/store/GUIReducer'; -import { setEbg } from '@/Core/gameScripts/changeBg/setEbg'; import { initKey } from '@/Core/controller/storage/fastSaveLoad'; import { WebgalParser } from '@/Core/parser/sceneParser'; import { WebGAL } from '@/Core/WebGAL'; import { getFastSaveFromStorage, getSavesFromStorage } from '@/Core/controller/storage/savesController'; -import { resetUserData, setGlobalVar } from '@/store/userDataReducer'; -import localforage from 'localforage'; -import { IUserData } from '@/store/userDataInterface'; +import { setGlobalVar } from '@/store/userDataReducer'; declare global { interface Window { @@ -23,41 +18,38 @@ declare global { * @param url 游戏信息路径 */ export const infoFetcher = (url: string) => { - getStorage(); - const GUIState = webgalStore.getState().GUI; const dispatch = webgalStore.dispatch; - axios.get(url).then((r) => { + axios.get(url).then(async (r) => { let gameConfigRaw: string = r.data; let gameConfig = WebgalParser.parseConfig(gameConfigRaw); logger.info('获取到游戏信息', gameConfig); // 先把 key 找到并设置了 const keyItem = gameConfig.find((e) => e.command === 'Game_key'); - const key = (keyItem?.options?.[0].value as string) ?? ''; - WebGAL.gameKey = key; + WebGAL.gameKey = (keyItem?.args?.[0] as string) ?? ''; initKey(); - getStorage(); + await getStorageAsync(); getFastSaveFromStorage(); getSavesFromStorage(0, 0); // 按照游戏的配置开始设置对应的状态 - if (GUIState) { - gameConfig.forEach((e) => { - const { command, args } = e; - let res: any = args[0].trim(); - if (/^(true|false)$/g.test(args[0])) { - res = !!res; - } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { - res = Number(res); - } - if (webgalStore.getState().userData.globalGameVar?.[command] === undefined) { - dispatch( - setGlobalVar({ - key: command, - value: res, - }), - ); - } - }); - } + gameConfig.forEach((e) => { + const { command, args } = e; + let res: any = args[0].trim(); + if (/^(true|false)$/g.test(args[0])) { + res = !!res; + } else if (/^[0-9]+\.?[0-9]+$/g.test(args[0])) { + res = Number(res); + } + if (!webgalStore.getState().userData.globalGameVar?.[command]) { + logger.info('首次写入 Game Config'); + dispatch( + setGlobalVar({ + key: command, + value: res, + }), + ); + } + }); + window?.renderPromise?.(); delete window.renderPromise; setStorage(); diff --git a/packages/webgal/src/Stage/MainStage/useSetBg.ts b/packages/webgal/src/Stage/MainStage/useSetBg.ts index 83f270f70..542ea447a 100644 --- a/packages/webgal/src/Stage/MainStage/useSetBg.ts +++ b/packages/webgal/src/Stage/MainStage/useSetBg.ts @@ -59,4 +59,4 @@ function addBg(type?: 'image' | 'spine', ...args: any[]) { // @ts-ignore return WebGAL.gameplay.pixiStage?.addBg(...args); } -} \ No newline at end of file +} diff --git a/packages/webgal/src/hooks/useConfigData.ts b/packages/webgal/src/hooks/useConfigData.ts index c9f6c10c6..be2a23b41 100644 --- a/packages/webgal/src/hooks/useConfigData.ts +++ b/packages/webgal/src/hooks/useConfigData.ts @@ -25,12 +25,14 @@ const useConfigData = () => { setEbg(titleUrl); break; } - - case 'Game_Logo': { - const logoUrlList = [assetSetter(val, fileType.background)]; - webgalStore.dispatch(setLogoImage(logoUrlList)); - break; - } + /** + * TODO:Game_Logo 是个数组,并且改变后会造成进入游戏界面重新渲染,以后再考虑如何处理 + */ + // case 'Game_Logo': { + // const logoUrlList = [assetSetter(val, fileType.background)]; + // webgalStore.dispatch(setLogoImage(logoUrlList)); + // break; + // } case 'Title_bgm': { const bgmUrl = assetSetter(val, fileType.bgm); diff --git a/packages/webgal/src/hooks/useFullScreen.ts b/packages/webgal/src/hooks/useFullScreen.ts index 3dcad037e..228ce4fb3 100644 --- a/packages/webgal/src/hooks/useFullScreen.ts +++ b/packages/webgal/src/hooks/useFullScreen.ts @@ -19,17 +19,16 @@ export function useFullScreen() { if (isEnterGame) { document.documentElement.requestFullscreen(); if (keyboard) keyboard.lock(['Escape', 'F11']); - }; + } break; } case fullScreenOption.off: { if (document.fullscreenElement) { document.exitFullscreen(); if (keyboard) keyboard.unlock(); - }; + } break; } } }, [fullScreen]); - -}; +} diff --git a/packages/webgal/src/hooks/useHotkey.tsx b/packages/webgal/src/hooks/useHotkey.tsx index a08bbdfc5..2e8ebb41f 100644 --- a/packages/webgal/src/hooks/useHotkey.tsx +++ b/packages/webgal/src/hooks/useHotkey.tsx @@ -21,11 +21,11 @@ export interface HotKeyType { MouseWheel: {} | boolean; Ctrl: boolean; Esc: - | { - href: string; - nav: 'replace' | 'push'; - } - | boolean; + | { + href: string; + nav: 'replace' | 'push'; + } + | boolean; AutoSave: {} | boolean; } diff --git a/packages/webgal/src/store/stageInterface.ts b/packages/webgal/src/store/stageInterface.ts index 04e9ee1ff..51273975c 100644 --- a/packages/webgal/src/store/stageInterface.ts +++ b/packages/webgal/src/store/stageInterface.ts @@ -5,7 +5,7 @@ import { ISentence } from '@/Core/controller/scene/sceneInterface'; * @interface IGameVar */ export interface IGameVar { - [propName: string]: string | boolean | number; + [propName: string]: string | boolean | number | Array; } export interface ISetGameVar { From a6794f050d8eba775afd13835e1c32f5aa8ecc8f Mon Sep 17 00:00:00 2001 From: Mahiru Date: Mon, 8 Jul 2024 21:06:47 +0800 Subject: [PATCH 14/17] fix: optimize setVar --- .../webgal/src/Core/gameScripts/setVar.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index 4451717a3..95fd4cecd 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -32,8 +32,6 @@ export const setVar = (sentence: ISentence): IPerform => { const valExp = sentence.content.split(/\s*=\s*/)[1]; if (valExp === 'random()') { webgalStore.dispatch(targetReducerFunction({ key, value: Math.random() })); - } else if (valExp.match(/\$[.a-zA-Z]/)) { - webgalStore.dispatch(targetReducerFunction({ key, value: String(getValueFromState(valExp.trim())) })); } else if (valExp.match(/[+\-*\/()]/)) { // 如果包含加减乘除号,则运算 // 先取出运算表达式中的变量 @@ -88,24 +86,13 @@ export function getValueFromState(key: string) { const stage = webgalStore.getState().stage; const userData = webgalStore.getState().userData; const _Merge = { ...stage, ...userData }; - const is_baseVal = (_obj: object, _val: any, no_get = false) => - ['string', 'number', 'boolean'].includes(typeof (no_get ? _val : Reflect.get(_obj, _val))); - let _all: { [key: PropertyKey]: any } = {}; - // 排除GameVar、globalGameVar因为这几个本来就可以获取 - for (let propertyName in _Merge) { - if (propertyName === 'GameVar') continue; - if (propertyName === 'globalGameVar') continue; - if (propertyName) { - // @ts-ignore - _all['$' + propertyName] = get(_Merge, propertyName) as BaseVal; - } - } if (stage.GameVar.hasOwnProperty(key)) { ret = stage.GameVar[key]; } else if (userData.globalGameVar.hasOwnProperty(key)) { ret = userData.globalGameVar[key]; - } else if (key.startsWith('$') && is_baseVal(_all, compile(key)(_all), true)) { - ret = compile(key)(_all) as BaseVal; + } else if (key.startsWith('$')) { + const propertyKey = key.replace('$', ''); + ret = get(_Merge, propertyKey, 0) as BaseVal; } return ret; } From c238449bb205187ebccc4804fcf36094162a4617 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Mon, 8 Jul 2024 21:17:06 +0800 Subject: [PATCH 15/17] fix: sperate stage and userData when get sys vars --- packages/webgal/public/game/scene/demo_changeConfig.txt | 4 ++-- packages/webgal/src/Core/gameScripts/setVar.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/webgal/public/game/scene/demo_changeConfig.txt b/packages/webgal/public/game/scene/demo_changeConfig.txt index 13a276619..8666897a8 100644 --- a/packages/webgal/public/game/scene/demo_changeConfig.txt +++ b/packages/webgal/public/game/scene/demo_changeConfig.txt @@ -9,7 +9,7 @@ setVar:GameNum=15 -global; webgal:获取并修改GameNum的值:{GameNum} -hold; setVar:GameNum_Double=GameNum_Double + 5; webgal:获取GameNum_Double的值,但我不会修改它原本的值:{GameNum_Double} -hold; -webgal:获取bgm声音:{$bgm.volume} -hold; -setVar:bgm_calc= $bgm.volume * 2 ; +webgal:获取bgm声音:{$stage.bgm.volume} -hold; +setVar:bgm_calc= $stage.bgm.volume * 2 ; webgal:获取bgm声音的两倍是{bgm_calc} -hold; end; diff --git a/packages/webgal/src/Core/gameScripts/setVar.ts b/packages/webgal/src/Core/gameScripts/setVar.ts index 95fd4cecd..e42780ab4 100644 --- a/packages/webgal/src/Core/gameScripts/setVar.ts +++ b/packages/webgal/src/Core/gameScripts/setVar.ts @@ -85,7 +85,7 @@ export function getValueFromState(key: string) { let ret: any = 0; const stage = webgalStore.getState().stage; const userData = webgalStore.getState().userData; - const _Merge = { ...stage, ...userData }; + const _Merge = { stage, userData }; // 不要直接合并到一起,防止可能的键冲突 if (stage.GameVar.hasOwnProperty(key)) { ret = stage.GameVar[key]; } else if (userData.globalGameVar.hasOwnProperty(key)) { From 17f7a989cb835b79019d09619e6797f765221e1c Mon Sep 17 00:00:00 2001 From: Mahiru Date: Mon, 8 Jul 2024 21:19:11 +0800 Subject: [PATCH 16/17] fix: demo var script --- packages/webgal/public/game/scene/demo_var.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webgal/public/game/scene/demo_var.txt b/packages/webgal/public/game/scene/demo_var.txt index dd8a6351a..9b31b80f5 100644 --- a/packages/webgal/public/game/scene/demo_var.txt +++ b/packages/webgal/public/game/scene/demo_var.txt @@ -4,7 +4,7 @@ setVar:speaker=WebGAL; {speaker}:Background now is {bg}.; {speaker}:\{bg\} is not use interpolation.; setVar:a=3; -setVar:bg=bg1.png -when=a>2; +setVar:bg=WebGalEnter.png -when=a>2; changeBg:{bg} -next; setVar:func=variable interpolation; {speaker}:Bg changed! Welcome to {speaker} {func}!; From dbd00b93b0aaa5ceef290b49792f6c5638cf3104 Mon Sep 17 00:00:00 2001 From: Mahiru Date: Sat, 20 Jul 2024 08:21:12 +0800 Subject: [PATCH 17/17] update version --- packages/webgal/package.json | 2 +- .../webgal/public/game/template/template.json | 2 +- packages/webgal/src/config/info.ts | 2 +- releasenote.md | 55 +++++++++++-------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/packages/webgal/package.json b/packages/webgal/package.json index 077558189..29290e283 100644 --- a/packages/webgal/package.json +++ b/packages/webgal/package.json @@ -1,7 +1,7 @@ { "name": "webgal", "private": true, - "version": "4.5.3", + "version": "4.5.4", "scripts": { "dev": "vite --host --port 3000", "build": "cross-env NODE_ENV=production tsc && vite build --base=./", diff --git a/packages/webgal/public/game/template/template.json b/packages/webgal/public/game/template/template.json index 3a596b65c..58e0b8552 100644 --- a/packages/webgal/public/game/template/template.json +++ b/packages/webgal/public/game/template/template.json @@ -1,4 +1,4 @@ { "name":"Default Template", - "webgal-version":"4.5.3" + "webgal-version":"4.5.4" } diff --git a/packages/webgal/src/config/info.ts b/packages/webgal/src/config/info.ts index 1c705a9d3..9edbbfe1e 100644 --- a/packages/webgal/src/config/info.ts +++ b/packages/webgal/src/config/info.ts @@ -1,5 +1,5 @@ export const __INFO = { - version: 'WebGAL 4.5.3', + version: 'WebGAL 4.5.4', contributors: [ { username: 'Mahiru', link: 'https://github.com/MakinoharaShoko' }, { username: 'Hoshinokinya', link: 'https://github.com/hshqwq' }, diff --git a/releasenote.md b/releasenote.md index c2d22a975..e4a4f65fd 100644 --- a/releasenote.md +++ b/releasenote.md @@ -8,15 +8,13 @@ #### 新功能 -为对话框中文本提供部分应用样式的支持 +允许使用脚本修改标题画面等游戏配置选项 -支持了选项界面的自定义 +允许使用变量获取一部分引擎状态 #### 修复 -下雨特效的内存泄露 - -同时调用多个 callScene 或 changeScene 的冲突问题 +为部分字符添加转义 ## Release Notes @@ -29,39 +27,52 @@ #### New Features -Added support for partial style application for text in dialog boxes. +Allow using scripts to modify game configuration options such as title screen -Added support for custom option interfaces. +Allow using variables to get some engine states -#### Fixes +#### Bug Fixes -Fixed a memory leak in the rain effect. +Added escaping for some characters -Fixed a conflict issue when calling multiple callScene or changeScene simultaneously. + +## リリースノート +**このリポジトリはソースコードのみを公開しています** + +**もしあなたが使いやすいグラフィカルエディタでWebGALゲームを作成、制作、リアルタイムプレビューしたい場合は、[WebGALグラフィカルエディタをダウンロードしてください](https://github.com/MakinoharaShoko/WebGAL_Terre/releases)** + +### このバージョンについて - #### 新機能 -対話ボックスで一部のスタイルを適用できるようになった +スクリプトを使用してタイトル画面などのゲーム設定オプションを変更できるようになりました -オプション画面のカスタマイズに対応した +変数を使用して一部のエンジン状態を取得できるようになりました #### 修正 -雨エフェクトのメモリリークを修正 +一部の文字のエスケープを追加しました + + + + -複数の callScene または changeScene を同時に呼び出した際の競合の問題を修正 +[//]: # () - -#### Nouvelles fonctionnalités +[//]: # (#### Nouvelles fonctionnalités) -Prise en charge partielle des styles CSS pour le texte des boîtes de dialogue +[//]: # () +[//]: # (Prise en charge partielle des styles CSS pour le texte des boîtes de dialogue) -Personnalisation de l'interface des choix +[//]: # () +[//]: # (Personnalisation de l'interface des choix) -#### Corrections +[//]: # () +[//]: # (#### Corrections) -Fuite de mémoire avec l'effet de pluie +[//]: # () +[//]: # (Fuite de mémoire avec l'effet de pluie) -Conflit lors de l'appel simultané de plusieurs callScene ou changeScene +[//]: # () +[//]: # (Conflit lors de l'appel simultané de plusieurs callScene ou changeScene)