From 336ec04f6615e17ac3824a1e02f2e43bb906ea69 Mon Sep 17 00:00:00 2001 From: cha0s Date: Sat, 7 Sep 2024 12:07:05 -0500 Subject: [PATCH] feat: dialogue pages --- app/react/components/dom/dialogue.jsx | 51 ++++++++++++++++++++------- app/react/components/dom/entities.jsx | 1 + app/server/create/homestead.js | 6 +--- app/util/dialogue.js | 12 ++++++- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/app/react/components/dom/dialogue.jsx b/app/react/components/dom/dialogue.jsx index d024f8c..f783495 100644 --- a/app/react/components/dom/dialogue.jsx +++ b/app/react/components/dom/dialogue.jsx @@ -18,36 +18,63 @@ export default function Dialogue({ const ref = useRef(); const [dimensions, setDimensions] = useState({h: 0, w: 0}); const [caret, setCaret] = useState(0); + const [page, setPage] = useState(0); const radians = useRadians(); + const [pageLetters, setPageLetters] = useState([]); useEffect(() => { + setCaret(0); + setPageLetters(dialogue.letters.filter((letter) => letter.page === page)); + }, [dialogue, page]); + useEffect(() => { + if (0 === pageLetters.length) { + return; + } return dialogue.addSkipListener(() => { - if (caret >= dialogue.letters.length - 1) { - dialogue.onClose(); + // at end + if (caret >= pageLetters.length - 1) { + if (page < dialogue.pages - 1) { + setPage((page) => page + 1); + } + else { + dialogue.onClose(); + } } + // skip to end else { - setCaret(dialogue.letters.length - 1); + setCaret(pageLetters.length - 1); } }); - }, [caret, dialogue]); + }, [caret, dialogue, page, pageLetters]); useEffect(() => { - const {params} = dialogue.letters[caret]; + if (0 === pageLetters.length) { + return; + } + const {params} = pageLetters[caret]; let handle; - if (caret >= dialogue.letters.length - 1) { + // start lingering timeout + if (caret >= pageLetters.length - 1) { const {linger} = dialogue; if (!linger) { return; } handle = setTimeout(() => { - dialogue.onClose(); + if (page < dialogue.pages - 1) { + setPage((page) => page + 1); + } + else { + dialogue.onClose(); + } }, linger * 1000); } else { + // jump to next caret spot let jump = caret; - while (0 === dialogue.letters[jump].params.rate.frequency && jump < dialogue.letters.length - 1) { + while (0 === pageLetters[jump].params.rate.frequency && jump < pageLetters.length - 1) { jump += 1; } setCaret(jump); - if (jump < dialogue.letters.length - 1) { + if (jump < pageLetters.length - 1) { + // wait for next jump handle = setTimeout(() => { setCaret(caret + 1); }, params.rate.frequency * 1000) @@ -56,7 +83,7 @@ export default function Dialogue({ return () => { clearTimeout(handle); } - }, [caret, dialogue]); + }, [caret, dialogue, page, pageLetters]); const updateDimensions = useCallback(() => { if (ref.current) { const {height, width} = ref.current.getBoundingClientRect(); @@ -65,8 +92,8 @@ export default function Dialogue({ }, [domScale]); useAnimationFrame(updateDimensions); const localRender = useMemo( - () => render(dialogue.letters, styles.letter), - [dialogue.letters], + () => render(pageLetters, styles.letter), + [pageLetters], ); let position = 'function' === typeof dialogue.position ? dialogue.position() diff --git a/app/react/components/dom/entities.jsx b/app/react/components/dom/entities.jsx index ca05ee4..51a78bd 100644 --- a/app/react/components/dom/entities.jsx +++ b/app/react/components/dom/entities.jsx @@ -45,6 +45,7 @@ export default function Entities({ dialogues[key].position = () => updating[id].Position; } dialogues[key].letters = parseLetters(dialogues[key].body); + dialogues[key].pages = 1 + dialogues[key].letters.at(-1).page; setChatMessages((chatMessages) => ({ [[id, key].join('-')]: dialogues[key].letters, ...chatMessages, diff --git a/app/server/create/homestead.js b/app/server/create/homestead.js index cbc1257..d7b439f 100644 --- a/app/server/create/homestead.js +++ b/app/server/create/homestead.js @@ -289,11 +289,7 @@ export default async function createHomestead(id) { interacting: 1, interactScript: ` const lines = [ - 'mrowwr', - 'prrrowwwww', - 'mew mew!', - 'mewwwww', - '\\\\*purrrrr\\\\*', + 'Mind your own business, buddy.\\n\\ner, I mean, MEEHHHHHH', ]; const line = lines[Math.floor(Math.random() * lines.length)]; subject.Interlocutor.dialogue({ diff --git a/app/util/dialogue.js b/app/util/dialogue.js index 5b9b176..e3a48ac 100644 --- a/app/util/dialogue.js +++ b/app/util/dialogue.js @@ -27,6 +27,7 @@ function computeParams(ancestors) { export function parseLetters(source) { let letters = []; + let page = 0; try { const tree = parser.parse(source); tree.dialogue = { @@ -43,6 +44,10 @@ export function parseLetters(source) { } break; } + case 'paragraph': { + page += 1; + break; + } case 'text': { const params = computeParams(ancestors); const split = node.value.split(''); @@ -51,7 +56,12 @@ export function parseLetters(source) { for (const name in params) { indices[name] = i + params[name].length; } - letters.push({character: split[i], indices, params}); + letters.push({ + character: split[i], + indices, + page: page - 1, + params, + }); } for (const name in params) { params[name].length += split.length;