From e654773b81bee02d1259ff03c33e8ca4cdb7979d Mon Sep 17 00:00:00 2001 From: Filip Pajic Date: Fri, 5 Jul 2024 16:29:01 +0200 Subject: [PATCH] feature: implement chatting functionality on react client --- packages/webcave-client/src/renderer.ts | 2 +- .../src/multiplayer/WebCaveMultiplayer.tsx | 56 ++++++++++++++----- .../webcave-react/src/styles/Inputs.styles.ts | 13 +++-- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/packages/webcave-client/src/renderer.ts b/packages/webcave-client/src/renderer.ts index 253e2e3..db1f481 100644 --- a/packages/webcave-client/src/renderer.ts +++ b/packages/webcave-client/src/renderer.ts @@ -141,7 +141,7 @@ class Renderer implements IRenderer { let ctx = this.textContext = this.textCanvas.getContext( "2d" ); ctx.textAlign = "left"; ctx.textBaseline = "middle"; - ctx.font = "24px Minecraftia"; + ctx.font = "24px"; } public draw() { diff --git a/packages/webcave-react/src/multiplayer/WebCaveMultiplayer.tsx b/packages/webcave-react/src/multiplayer/WebCaveMultiplayer.tsx index 6b14417..8cbd7b7 100644 --- a/packages/webcave-react/src/multiplayer/WebCaveMultiplayer.tsx +++ b/packages/webcave-react/src/multiplayer/WebCaveMultiplayer.tsx @@ -14,10 +14,11 @@ import { PayloadBySocketEvent } from '@acid-info/webcave-core/src' import { MultiplayerClient, Player, Renderer } from '@acid-info/webcave-client/src' import { HandlerByMultiplayerEvent } from '@acid-info/webcave-client/src/types/multiplayer.ts' import { EChatActions } from '@acid-info/webcave-client/src/shared/controls.ts' +import { DEFAULT_SELECTOR_WIDTH_PX } from '@acid-info/webcave-client/src' const WebCaveMultiplayer: React.FC = (props) => { const { - selectorWidthPx, + selectorWidthPx = DEFAULT_SELECTOR_WIDTH_PX, chunkSize, serverUrl } = props; @@ -62,7 +63,7 @@ const WebCaveMultiplayer: React.FC = (props) => { if (isReady) { intervalId = setInterval(() => { const currentTime = +new Date / 1000; - renderWorld(lastUpdate); // Update local + renderWorld(); // Update local if (currentTime - lastUpdate > 0.033 && !renderer.shouldSkipRender()) { client.updatePlayer() @@ -78,7 +79,7 @@ const WebCaveMultiplayer: React.FC = (props) => { } }, [isReady]) - const renderWorld = (lastUpdate: number) => { + const renderWorld = () => { if (client) { const player = client.world.localPlayer @@ -110,11 +111,11 @@ const WebCaveMultiplayer: React.FC = (props) => { return; } - addMessageToChat({ - type: 'chat', - user: "pajicf", - msg - }) + chatBoxInputRef.current.blur() + + client.sendMessage(msg); + + chatBoxInputRef.current.value = ""; } } @@ -145,6 +146,8 @@ const WebCaveMultiplayer: React.FC = (props) => { client.on("connect", onConnectionHandler) client.on("world", onWorldHandler) client.on("spawn", onSpawnHandler) + client.on("message", onMessageHandler) + client.on("chat", onChatMessageHandler) client.connect(serverUrl, nickname) } @@ -173,9 +176,34 @@ const WebCaveMultiplayer: React.FC = (props) => { setIsReady(true) setStatusMessage(undefined) - player.on(EChatActions.OPEN_CHAT, () => { - setIsChatOpen(true) - chatBoxInputRef.current.focus() + player.on(EChatActions.OPEN_CHAT, handleOpenChat) + } + + const onMessageHandler: HandlerByMultiplayerEvent<"message"> = (msg) => { + addMessageToChat({ + type: 'generic', + msg + }) + } + + const onChatMessageHandler: HandlerByMultiplayerEvent<"chat"> = (user, msg) => { + addMessageToChat({ + type: 'chat', + user, + msg + }) + return false; + } + + const handleOpenChat = (state?: boolean) => { + setIsChatOpen(prevState => { + const newState = state != undefined ? state : !prevState; + + if (prevState === false) { + chatBoxInputRef.current.focus() + } + + return newState; }) } @@ -191,13 +219,13 @@ const WebCaveMultiplayer: React.FC = (props) => { selectorWidthPx={selectorWidthPx} > - + - + handleOpenChat(true)}> {messages.map((m, index) => ( @@ -221,6 +249,8 @@ const WebCaveMultiplayer: React.FC = (props) => { maxLength={60} spellCheck={false} onKeyDown={onChatboxEntry} + isChatOpen={isChatOpen} + placeholder={"Enter message or close the chat by pressing 't'"} /> diff --git a/packages/webcave-react/src/styles/Inputs.styles.ts b/packages/webcave-react/src/styles/Inputs.styles.ts index 5ea9adc..cd71e7f 100644 --- a/packages/webcave-react/src/styles/Inputs.styles.ts +++ b/packages/webcave-react/src/styles/Inputs.styles.ts @@ -4,13 +4,13 @@ export const ChatContainer = styled.div<{isChatOpen: boolean}>` position: absolute; left: 20px; bottom: 18px; - opacity: ${props => props.isChatOpen ? '1' : '0'}; - height: ${props => props.isChatOpen ? 'initial' : '0'}; + opacity: ${props => props.isChatOpen ? '1' : '0.2'}; + height: ${props => props.isChatOpen ? 'initial' : '100px'}; overflow: hidden; ` export const ChatBox = styled.div` - width: 600px; + width: 400px; height: 195px; overflow: hidden; overflow-y: scroll; @@ -32,9 +32,10 @@ export const ChatBoxText = styled.div` align-items: start; ` -export const ChatBoxEntry = styled.input` - width: 610px; - height: 30px; +export const ChatBoxEntry = styled.input<{isChatOpen: boolean}>` + opacity: ${props => props.isChatOpen ? '1' : '0'}; + height: ${props => props.isChatOpen ? '30px' : '0'}; + width: 400px; padding-left: 10px; padding-bottom: 2px; background: rgba(0, 0, 0, 0.6);