diff --git a/KeyCtrl/src/components/MultiplayerPage/Modal.js b/KeyCtrl/src/components/MultiplayerPage/Modal.js index 9bf5058..76019a3 100644 --- a/KeyCtrl/src/components/MultiplayerPage/Modal.js +++ b/KeyCtrl/src/components/MultiplayerPage/Modal.js @@ -33,7 +33,7 @@ const MyTextField = styled((props) => ( }, })); -export const Modal = ({ setShowModal, setJoinLobby, setLobbyID, setName, name, isFindMatch, cancelFindMatch }) => { +export const Modal = ({ setShowModal, setJoinLobby, setLobbyID, setName, name, isFindMatch, cancelFindMatch, isRanked, cancelFindRanked }) => { // close the modal when clicking outside the modal. const modalRef = useRef(); @@ -70,6 +70,16 @@ export const Modal = ({ setShowModal, setJoinLobby, setLobbyID, setName, name, i , document.getElementById("portal") ); + } else if (isRanked) { + return ReactDom.createPortal( +
+
+

Finding a Match...

+ +
+
, + document.getElementById("portal") + ); } else { return ReactDom.createPortal(
diff --git a/KeyCtrl/src/components/MultiplayerPage/Multiplayer.js b/KeyCtrl/src/components/MultiplayerPage/Multiplayer.js index 1aeb609..daadf78 100644 --- a/KeyCtrl/src/components/MultiplayerPage/Multiplayer.js +++ b/KeyCtrl/src/components/MultiplayerPage/Multiplayer.js @@ -36,6 +36,7 @@ const Multiplayer = ({loggedIn, accountInfo}) => { const [lobbyID, setLobbyID] = useState(0) const [name, setName] = useState('guest' + Math.floor(Math.random() * 1000)) const [isFindMatch, setFindMatch] = useState(false) + const [isRanked, setRanked] = useState(false) const socketRef = useRef() @@ -44,16 +45,24 @@ const Multiplayer = ({loggedIn, accountInfo}) => { determineName() if (socketRef.current == null) { console.log("creating new connection") - socketRef.current = io.connect("https://generated-respected-python.glitch.me") + //socketRef.current = io.connect("https://generated-respected-python.glitch.me") + socketRef.current = io.connect("http://localhost:4000") } //Finding Match code... socketRef.current.on('findMatchSuccess', (lobby) => { console.log(socketRef.current.id + " found a match") - //socketRef.current.disconnect() setLobbyID(lobby) setShowModal(false) setJoinLobby(true) }) + + socketRef.current.on('findRankedMatchSuccess', (rankedLobby) => { + console.log(socketRef.current.id + " found a ranked match") + setLobbyID(rankedLobby) + setShowModal(false) + setRanked(true) + setJoinLobby(true) + }) }) //Enter lobby modal @@ -80,10 +89,22 @@ const Multiplayer = ({loggedIn, accountInfo}) => { setShowModal(true) } + function findRanked() { + setRanked(true) + setShowModal(true) + socketRef.current.emit('findRanked', {username: name, mmr: 5}) + } + + function cancelFindRanked() { + socketRef.current.emit('cancelFindRanked') + setRanked(false) + setShowModal(false) + } + return (
- {showModal ? : null} + {showModal ? : null} {joinLobby ? null :
@@ -116,7 +137,7 @@ const Multiplayer = ({loggedIn, accountInfo}) => { {joinLobby || !loggedIn ? null :
-
+
Ranked
@@ -142,7 +163,9 @@ const Multiplayer = ({loggedIn, accountInfo}) => { lobbyID={lobbyID} username={name} isFindMatch={isFindMatch} + isRanked={isRanked} setFindMatch={setFindMatch} + setRanked={setRanked} setJoinLobby={setJoinLobby} setShowModal={setShowModal} setLobbyID={setLobbyID} diff --git a/KeyCtrl/src/components/MultiplayerPage/MultiplayerGame.js b/KeyCtrl/src/components/MultiplayerPage/MultiplayerGame.js index e89905f..e77728f 100644 --- a/KeyCtrl/src/components/MultiplayerPage/MultiplayerGame.js +++ b/KeyCtrl/src/components/MultiplayerPage/MultiplayerGame.js @@ -48,7 +48,8 @@ const MultiplayerGame = (props) => { useEffect( () => { - socketRef.current = io.connect("https://generated-respected-python.glitch.me") //LOCALHOST for local testing + //socketRef.current = io.connect("https://generated-respected-python.glitch.me") + socketRef.current = io.connect("http://localhost:4000") console.log(lobbyID, username) socketRef.current.emit('switchLobby', { lobbyID }, username) @@ -69,6 +70,15 @@ const MultiplayerGame = (props) => { props.setJoinLobby(true) }) + socketRef.current.on('findRankedMatchSuccess', (rankedLobby) => { + console.log(socketRef.current.id + " found a ranked match") + socketRef.current.disconnect() + props.setLobbyID(rankedLobby) + props.setShowModal(false) + props.setJoinLobby(false) + props.setJoinLobby(true) + }) + socketRef.current.on("gameStart", () => { console.log("Game Start") setInCountdown(true) @@ -280,7 +290,11 @@ const MultiplayerGame = (props) => { // --------------------------------------------------- function readyUp() { - if(props.isFindMatch) { + if(props.isRanked) { + console.log("Requeue for Ranked") + props.setShowModal(true) + socketRef.current.emit('findRanked', {username, mmr: 5}) + } else if(props.isFindMatch) { //get back in Find Match queue props.setShowModal(true) socketRef.current.emit('findMatch') @@ -293,11 +307,17 @@ const MultiplayerGame = (props) => { function leaveRoom() { //back to mp menu + props.setRanked(false) props.setJoinLobby(false) props.setFindMatch(false) } - + var readyRequeueBtn + if(props.isRanked || props.isFindMatch) { + readyRequeueBtn = + } else { + readyRequeueBtn = + } return (
@@ -349,7 +369,7 @@ const MultiplayerGame = (props) => {
- + {readyRequeueBtn}
diff --git a/KeyCtrl/src/components/MultiplayerPage/matchmaker.js b/KeyCtrl/src/components/MultiplayerPage/matchmaker.js new file mode 100644 index 0000000..de50ae0 --- /dev/null +++ b/KeyCtrl/src/components/MultiplayerPage/matchmaker.js @@ -0,0 +1,73 @@ +const app = require('express')() +const http = require('http').createServer(app) +const io = require('socket.io')(http, { + cors: { + origin: ["http://localhost:3000", "https://generated-respected-python.glitch.me", "https://keyctrl.net"], //CHANGE TO HOST URL + methods: ["GET", "POST"], + credentials: true, + transports: ['websocket', 'polling'] + }, + allowEIO3: true +}); + +//Initialize Ranked Queue with MMR buckets +var rankedQueue = [] +rankedQueue[0] = new Array() //0-299 +rankedQueue[1] = new Array() //300-599 +rankedQueue[2] = new Array() //600-899 +rankedQueue[3] = new Array() //900+ + +var bucketBracketOne = 300 +var bucketBracketTwo = 600 +var bucketBracketThree = 900 + +var foundPlayers = [] //WARNING: CURRENTLY ALL LOGIC INVOLVING FOUNDPLAYERS WILL FAIL + //AS IT WILL OVERLAP WITH OTHER GAMES. NEEDS TO BE MADE GAME SPECIFIC SOMEHOW + +io.on('connection', (socket) => { + console.log(socket.id + " connected") + socket.on('addToRankedQueue', function({socketID, username, mmr}) { + console.log("ADDED TO QUEUE - socket: " + socketID + " user: " + username + " mmr: " + mmr) + var queuingPlayer = {socketID, username, mmr} + //Place user in their bucket + if(queuingPlayer.mmr < bucketBracketOne) { + console.log("Player dropped in bucket one") + rankedQueue[0].push(queuingPlayer) + } else if(queuingPlayer.mmr < bucketBracketTwo) { + console.log("Player dropped in bucket two") + rankedQueue[1].push(queuingPlayer) + } else if(queuingPlayer.mmr < bucketBracketThree) { + console.log("Player dropped in bucket three") + rankedQueue[2].push(queuingPlayer) + } else { + console.log("Player dropped in bucket four") + rankedQueue[3].push(queuingPlayer) + } + + if(rankedQueue[0].length >= 4) { + console.log("Match Found") + for(var i=0; i<4; i++) { + foundPlayers.push(rankedQueue[0].shift()) + } + socket.emit('rankedGameMatched', (foundPlayers)) + foundPlayers = [] + } + }) + socket.on('cancelFindRanked', function(socketID) { + rankedQueue.forEach(list => { + list.splice(list.indexOf(socketID), 1) + console.log(socketID + " left the queue") + }) + }) +}) + +// if(rankedQueue[3].length >= 4) { +// for(var i=0; i<3; i++) { +// foundPlayers.push(rankedQueue[3].shift()) +// } +// } + + +http.listen(4001, () => { + console.log('listening on *:4001'); + }); \ No newline at end of file diff --git a/KeyCtrl/src/components/MultiplayerPage/index.js b/KeyCtrl/src/components/MultiplayerPage/server.js similarity index 78% rename from KeyCtrl/src/components/MultiplayerPage/index.js rename to KeyCtrl/src/components/MultiplayerPage/server.js index 3112b5d..51996ef 100644 --- a/KeyCtrl/src/components/MultiplayerPage/index.js +++ b/KeyCtrl/src/components/MultiplayerPage/server.js @@ -1,8 +1,9 @@ +const ioclient = require('socket.io-client') const app = require('express')() const http = require('http').createServer(app) const io = require('socket.io')(http, { cors: { - origin: ["https://capstone-projects-2022-spring.github.io", "http://localhost:3000" ,"https://keyctrl.net"], //CHANGE TO HOST URL + origin: ["https://capstone-projects-2022-spring.github.io", "http://localhost:3000", "https://keyctrl.net"], //CHANGE TO HOST URL methods: ["GET", "POST"], credentials: true, transports: ['websocket', 'polling'] @@ -15,9 +16,12 @@ var wordsArray = {}; var roomWordsArray = {}; var matchResultsArray = {}; var findMatchPlayers = []; - +var findRankedMatchPlayers = []; var gameStartPlayers = 4; +//Matchmaking server connection +var mmServerSocket = ioclient.connect("http://localhost:4001") + //Generate lines to send to players var randWordsFunc = require('random-words'); @@ -78,7 +82,13 @@ io.on('connection', (socket) => { console.log(socket.id + " stopped looking for a match") }) - //Custom Lobby code + socket.on('cancelFindRanked', function() { + console.log("Canceling ranked search") + var socketID = socket.id + mmServerSocket.emit('cancelFindRanked', (socketID)) + }) + + //Join Lobby socket.on('switchLobby', function(newRoom, username) { socket.join(newRoom.lobbyID); socket.emit('updateLobby', newRoom); @@ -150,6 +160,24 @@ io.on('connection', (socket) => { socket.on('message', ({ name, message }, room) => { io.in(room).emit('message', { name, message }); }); + + //Ranked Queue + socket.on('findRanked', function({username, mmr}) { + var socketID = socket.id + console.log("sending " + socketID + " " + username + " " + mmr + " to matchmaker") + mmServerSocket.emit('addToRankedQueue', ({socketID, username, mmr: 5})) + }) + + mmServerSocket.on('rankedGameMatched', function(foundPlayers) { + console.log("Ranked Match Found! Connecting") + //Create random lobby ID + var rankedLobby = 'rankedLobby' + Math.random() * 10000 + foundPlayers.forEach(player => { + var socketID = player.socketID + console.log(" - " + player.username + "id: " + socketID) + io.to(socketID).emit('findRankedMatchSuccess', rankedLobby) + }) + }) }); http.listen(4000, () => {