Skip to content

Commit

Permalink
Working on multiplayer
Browse files Browse the repository at this point in the history
  • Loading branch information
ProLoser committed Aug 19, 2024
1 parent dd306e3 commit 81f46ba
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 95 deletions.
118 changes: 93 additions & 25 deletions src/Friends/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Import FirebaseAuth and firebase.
import React, { useState, useEffect, useCallback, ChangeEvent } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import type { ChangeEventHandler, KeyboardEventHandler } from 'react';
import * as firebaseui from 'firebaseui';
import StyledFirebaseAuth from '../StyledFirebaseAuth';

Expand All @@ -25,54 +26,121 @@ const uiConfig = {
},
};


function createMatch(user1: string, user2: string) {
// Create new game record
const gameRef = firebase.database().ref('games').push();
// Point match to game
const data = {
sort: Date.now(),
game: gameRef.key,
};
firebase.database().ref(`matches/${user1}/${user2}/game`).set(data);
firebase.database().ref(`matches/${user2}/${user1}/game`).set(data);
}

type UserData = {
name: string;
photoURL: string;
language: string;
}

export default function Login({ show }: { show: boolean }) {
const [chats, setChats] = useState<firebase.database.DataSnapshot[]>([]);
const [selectedChat, setSelectedChat] = useState<firebase.database.DataSnapshot | null>(null);
const [search, setSearch] = useState<string>('');
const [matches, setMatches] = useState<firebase.database.DataSnapshot[]>([]);
const [selected, setSelected] = useState<firebase.database.DataSnapshot | null>(null);
const searchRef = useRef<HTMLInputElement>(null);
const user = useAuth(); // Local signed-in state.
const [userData, setUserData] = useState<UserData|null>(null);
const [newFriend, setNewFriend] = useState<UserData|null>(null);

// onLogin
useEffect(() => {
const fetchChats = async () => {
const chatRef = firebase.database().ref('chats');
chatRef.on('value', (snapshot) => {
const chatArray: firebase.database.DataSnapshot[] = [];
snapshot.forEach((childSnapshot) => {
chatArray.push(childSnapshot);
});
setChats(chatArray);
if (!user) return;
const matchesRef = firebase.database().ref(`matches/${user.uid}`).orderByChild('sort')
const userRef = firebase.database().ref(`users/${user.uid}`)
const subscriber = (snapshot: firebase.database.DataSnapshot) => {
const matchesArray: firebase.database.DataSnapshot[] = [];
snapshot.forEach((childSnapshot) => {
matchesArray.push(childSnapshot);
});
setMatches(matchesArray);
};
userRef.get().then(snapshot => {
let data = snapshot.val() as UserData;
if (!data) {
// Upload initial user data
data = {
name: user.displayName,
photoURL: user.photoURL,
language: navigator.language,
} as UserData;
console.log('Creating user', data);
userRef.set(data);
}
setUserData(data);
});
matchesRef.on('value', subscriber);
return () => {
matchesRef.off('value', subscriber);
}
}, [user]);

fetchChats();
}, []);
// Match Listener
useEffect(() => {
if (!user || !selected) return;
const matchesRef = firebase.database().ref(`games/${selected.val().game}`)
const subscriber = (snapshot: firebase.database.DataSnapshot) => {
const matchesArray: firebase.database.DataSnapshot[] = [];
snapshot.forEach((childSnapshot) => {
matchesArray.push(childSnapshot);
});
setMatches(matchesArray);
};
matchesRef.on('value', subscriber);
return () => matchesRef.off('value', subscriber);
}, [user, selected]);

const handleChatClick = useCallback((chat: firebase.database.DataSnapshot) => {
setSelectedChat(chat);
setSelected(chat);
}, []);

const onSearch = useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearch(event.currentTarget.value);
}, []);
const onSearch = useCallback(async event => {
if (!user || !searchRef.current?.value) return;
const search = searchRef.current.value
const friend = await firebase.database().ref(`users/${search}`).get()
if (friend.exists()) {
// user found
const match = await firebase.database().ref(`matches/${user.uid}/${friend.key}`).get()
if (!match.exists()) {
setNewFriend(friend.val() as UserData);
}
// createMatch(user.uid, snapshot.key as string);
}
}, [user]) as ChangeEventHandler<HTMLInputElement>;

const user = useAuth(); // Local signed-in state.
if (!show) return null;

return user ? (
<div id="friends" className='modal'>
<h1>Matches</h1>
<a onClick={() => firebase.auth().signOut()}>Sign-out: </a>
<span>{user.uid}</span>
<div id="chat">
<input type="search" placeholder="Search for Friends" onChange={onSearch} />
<input name="search" ref={searchRef} type="search" placeholder="Search for Friends" onChange={onSearch} />
<ul>
{chats.map((chat: firebase.database.DataSnapshot) => (
{newFriend && (
<li onClick={() => openMatch(newFriend)}>New Match: {newFriend}</li>
)}
{matches.map((chat: firebase.database.DataSnapshot) => (
<li key={chat.key} onClick={() => handleChatClick(chat)}>
{chat.val().name}
{chat.val().name}: {chat.val().messages.length} messages
</li>
))}
</ul>
{selectedChat && (
{selected && (
<div>
<h2>{selectedChat.val().name}</h2>
{selectedChat.val().messages.map((message: string, index: number) => (
<h2>{selected.val().name}</h2>
{selected.val().messages.map((message: string, index: number) => (
<p key={index}>{message}</p>
))}
</div>
Expand Down
7 changes: 0 additions & 7 deletions src/Game/Account.css

This file was deleted.

63 changes: 0 additions & 63 deletions src/Game/Account.jsx

This file was deleted.

51 changes: 51 additions & 0 deletions src/MultiplayerContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import firebase from 'firebase/compat/app';
import 'firebase/compat/database';
import { useAuth } from './AuthContext';

// React context for the auth state
export const MultiplayerContext = createContext({});

// Provider component for the auth context
export function MultiplayerProvider({ children }: { children: ReactNode}) {
const [value, setValue] = useState({});
const authUser = useAuth(); // Local signed-in state.

async function load(user: string) {
if (!authUser) return;
const database = firebase.database();
const userSnapshot = await database.ref(`users/${user}`).get();
if (!userSnapshot.exists()) {
console.error('User not found', user);
return;
}
const matchSnapshot = await database.ref(`matches/${authUser.uid}/${user}`).get();
let gameSnapshot: firebase.database.DataSnapshot;
if (!matchSnapshot.exists()) {
// Create new game record
const gameRef = firebase.database().ref('games').push();
// Point match to game
const data = {
sort: Date.now(),
game: gameRef.key,
};
firebase.database().ref(`matches/${authUser.uid}/${user}/game`).set(data);
firebase.database().ref(`matches/${user}/${authUser.uid}/game`).set(data);
gameSnapshot = await gameRef.get();
} else {
gameSnapshot = await database.ref(`games/${matchSnapshot.val().game}`).get();
}
setValue({ userSnapshot, matchSnapshot, gameSnapshot, load })
}

return (
<MultiplayerContext.Provider value={value}>
{children}
</MultiplayerContext.Provider>
);
}

// Hook to use the context
export function useMultiplayer() {
return useContext(MultiplayerContext);
}

0 comments on commit 81f46ba

Please sign in to comment.