From dffc9a57f09314eb37594be1d6d2d9f7d374fe51 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jun 2020 13:07:40 -0700 Subject: [PATCH 1/3] p2p --- .gitignore | 1 + src/maze_assets/index.js | 57 +++++++++++++++++++++++++++++++++++----- src/maze_assets/maze.css | 1 - 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 2c405a2..cd8d535 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ canisters/ .dfx/ # frontend code +package-lock.json node_modules/ diff --git a/src/maze_assets/index.js b/src/maze_assets/index.js index f4fa4b9..8d1f0af 100644 --- a/src/maze_assets/index.js +++ b/src/maze_assets/index.js @@ -8,7 +8,6 @@ const N = 10; const symbols = [ "", "wall", "hero" ]; async function generateMaze(dom) { - console.log("generateMaze"); let f = await canister.getMap(); // First create the empty map for (let i = 0; i < N; i++) { @@ -64,6 +63,23 @@ async function mazeKeyPressHandler(e) { tmpState.update(tmp); // Remove processed moves pendingMoves = pendingMoves.filter(m => m.seq >= processedSeq); + // send p2p msgs + const others = state.getOtherPlayers(); + others.forEach(id => { + const conn = peer.connect(id, { debug: 2 }); + conn.send(pendingMoves); + conn.on('data', data => { + console.log(data); + }); + //console.log(conn); + /*conn.on('open', () => { + console.log(id, pendingMoves); + conn.send(pendingMoves); + });*/ + //conn.close(); + }); + + await render(); e.preventDefault(); } @@ -104,24 +120,37 @@ class Map { } else return "" } + getOtherPlayers() { + const list = []; + for (const pos in this._grids) { + const person = this._grids[pos].person; + if (typeof person !== 'undefined') { + const id = person.toText().slice(3); + if (id != myid) { + list.push(id); + } + } + } + return list; + } // update map and draw the diff update(g) { processedSeq = g[1]; const new_grids = []; g[0].forEach(grid => { const pos = Pos.fromPos(grid._0_); - new_grids[pos] = Map.getGridType(grid._1_); + new_grids[pos] = grid._1_; }); for (const pos in this._grids) { - const type = this._grids[pos]; + const type = Map.getGridType(this._grids[pos]); grids[pos].classList.remove(type); if (!this._isFinal) { grids[pos].classList.remove("temp"); } } for (const pos in new_grids) { - const type = new_grids[pos]; + const type = Map.getGridType(new_grids[pos]); grids[pos].classList.add(type); if (!this._isFinal) { grids[pos].classList.add("temp"); @@ -143,11 +172,17 @@ let tmpState = new Map(false); let myid; let myseq; let processedSeq; +let peer; const score = document.createElement('div'); score.id = "maze_score"; -async function init() { +function init() { + const link = document.createElement('script'); + link.setAttribute('src', 'https://cdn.jsdelivr.net/npm/peerjs@1.2.0/dist/peerjs.min.js'); + link.setAttribute('type', 'text/javascript'); + document.getElementsByTagName("head")[0].appendChild(link); + const container = document.createElement('div'); container.id = "maze_container"; const maze = document.createElement('div'); @@ -160,7 +195,7 @@ async function init() { let div = document.createElement('div'); div.id = "maze_message"; - document.body.appendChild(div); + document.body.appendChild(div); document.addEventListener("keydown", mazeKeyPressHandler, false); @@ -171,8 +206,16 @@ async function init() { join.addEventListener('click', () => { (async () => { const res = await canister.join(); - myid = res[0]; + myid = res[0].toText().slice(3); myseq = res[1].toNumber(); + // create p2p object + peer = new Peer(myid, { + host: 'localhost', + port: 9000, + path: '/myapp', + debug: 2 + }); + // set timer setInterval(render, 200); })(); }); diff --git a/src/maze_assets/maze.css b/src/maze_assets/maze.css index 89333b6..5e41bd2 100644 --- a/src/maze_assets/maze.css +++ b/src/maze_assets/maze.css @@ -45,7 +45,6 @@ content: "\1F381"; } #maze div.temp::after { - background-color: #45aa45; opacity: 0.6; } #maze div.hero::after { From 62c97ed54c40abefda1b71557a5411e01d468320 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jun 2020 15:07:58 -0700 Subject: [PATCH 2/3] send/recv works --- src/maze_assets/index.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/maze_assets/index.js b/src/maze_assets/index.js index 8d1f0af..1bbcb8c 100644 --- a/src/maze_assets/index.js +++ b/src/maze_assets/index.js @@ -1,4 +1,5 @@ import canister from 'ic:canisters/maze'; +//import asset from 'ic:canisters/maze_assets'; import './maze.css'; // util for creating maze @@ -64,22 +65,15 @@ async function mazeKeyPressHandler(e) { // Remove processed moves pendingMoves = pendingMoves.filter(m => m.seq >= processedSeq); // send p2p msgs - const others = state.getOtherPlayers(); + const others = tmpState.getOtherPlayers(); others.forEach(id => { const conn = peer.connect(id, { debug: 2 }); - conn.send(pendingMoves); - conn.on('data', data => { - console.log(data); - }); - //console.log(conn); - /*conn.on('open', () => { - console.log(id, pendingMoves); + conn.on('open', () => { + console.log("send", pendingMoves); conn.send(pendingMoves); - });*/ - //conn.close(); + }); }); - await render(); e.preventDefault(); } @@ -92,6 +86,12 @@ async function render() { score.innerText = processedSeq.toString(); if (pending > 0) score.innerText += " pending: " + pending.toString(); + // receive p2p msgs + peer.on('connection', conn => { + conn.on('data', data => { + console.log("recv", data); + }); + }); } class Pos { From 7e491fec2a59c3f38b2f3edc3ac1942716b2e89b Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jun 2020 19:37:51 -0700 Subject: [PATCH 3/3] why cpu increase? --- README.md | 5 ++++ src/main.mo | 13 +++++---- src/maze_assets/index.js | 57 ++++++++++++++++++++++++++++------------ 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c06de8a..06088bd 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,8 @@ Click the above icon to play online! - `dfx build` - `dfx canister install --all` - visit `127.0.0.1:8000/?canisterId={maze_assets_canister_id}` + +# Start peerjs server locally + +- install: `npm install peer -g` +- `peerjs --port 9000 --key peerjs --path /myapp` diff --git a/src/main.mo b/src/main.mo index 68529d3..b3d3502 100644 --- a/src/main.mo +++ b/src/main.mo @@ -173,20 +173,23 @@ actor { let id = msg.caller; maze.move(id, dir); }; + // Not needed. For debugging only public query func getState() : async [OutputState] { maze.outputState() }; // Output: // - Array of non-empty cells - // - Processed sequence number + // - Processed sequence number public query(msg) func getMap() : async ([OutputGrid], Nat) { (maze.outputMap(), maze.getSeq(msg.caller)) }; - public query(msg) func fakeMove(dirs : [Msg]) : async ([OutputGrid], Nat) { - let id = msg.caller; + // query move takes pending moves from all players + public query(msg) func fakeMove(dirs : [(Principal, [Msg])]) : async ([OutputGrid], Nat) { let processedSeq = maze.getSeq(msg.caller); - for (dir in dirs.vals()) { - maze.move(id, dir); + for ((id, msgs) in dirs.vals()) { + for (m in msgs.vals()) { + maze.move(id, m); + }; }; (maze.outputMap(), processedSeq) }; diff --git a/src/maze_assets/index.js b/src/maze_assets/index.js index 1bbcb8c..1df0e72 100644 --- a/src/maze_assets/index.js +++ b/src/maze_assets/index.js @@ -1,6 +1,6 @@ import canister from 'ic:canisters/maze'; -//import asset from 'ic:canisters/maze_assets'; import './maze.css'; +import { CanisterId } from '@dfinity/agent'; // util for creating maze @@ -56,23 +56,36 @@ async function mazeKeyPressHandler(e) { const msg = {}; msg.seq = myseq++; msg.dir = dir; + pendingMoves.push(msg); // Call move without waiting for reply canister.move(msg); - // Query move with pendingMoves - pendingMoves.push(msg); - const tmp = await canister.fakeMove(pendingMoves); - tmpState.update(tmp); - // Remove processed moves - pendingMoves = pendingMoves.filter(m => m.seq >= processedSeq); - // send p2p msgs - const others = tmpState.getOtherPlayers(); + // Update playMessages for myself + playerMessages[myid] = pendingMoves; + // Send p2p msgs + const others = state.getOtherPlayers(); others.forEach(id => { - const conn = peer.connect(id, { debug: 2 }); + const conn = peer.connect(id); conn.on('open', () => { console.log("send", pendingMoves); - conn.send(pendingMoves); + conn.send([myid, pendingMoves]); + //conn.send("hi"); }); }); + + // Query move with playerMessages + // construct candid format + const messages = []; + for (const id in playerMessages) { + const m = { + _0_: CanisterId.fromHex(id), + _1_: playerMessages[id] + }; + messages.push(m); + } + const tmp = await canister.fakeMove(messages); + tmpState.update(tmp); + // Remove processed moves + pendingMoves = pendingMoves.filter(m => m.seq >= processedSeq); await render(); e.preventDefault(); @@ -80,8 +93,10 @@ async function mazeKeyPressHandler(e) { async function render() { + // Draw confirmed state const res = await canister.getMap(); state.update(res); + const pending = myseq - processedSeq; score.innerText = processedSeq.toString(); if (pending > 0) @@ -90,6 +105,8 @@ async function render() { peer.on('connection', conn => { conn.on('data', data => { console.log("recv", data); + const [id, pending] = data; + playerMessages[id] = pending; }); }); } @@ -125,8 +142,8 @@ class Map { for (const pos in this._grids) { const person = this._grids[pos].person; if (typeof person !== 'undefined') { - const id = person.toText().slice(3); - if (id != myid) { + const id = idToPeerId(person); + if (id !== myid) { list.push(id); } } @@ -173,10 +190,15 @@ let myid; let myseq; let processedSeq; let peer; +let playerMessages = []; const score = document.createElement('div'); score.id = "maze_score"; +function idToPeerId(principal) { + return principal.toText().slice(3, -2); +} + function init() { const link = document.createElement('script'); link.setAttribute('src', 'https://cdn.jsdelivr.net/npm/peerjs@1.2.0/dist/peerjs.min.js'); @@ -206,17 +228,18 @@ function init() { join.addEventListener('click', () => { (async () => { const res = await canister.join(); - myid = res[0].toText().slice(3); + myid = idToPeerId(res[0]); myseq = res[1].toNumber(); // create p2p object - peer = new Peer(myid, { + peer = new Peer(myid, { debug: 2 }); + /*peer = new Peer(peerid, { host: 'localhost', port: 9000, path: '/myapp', debug: 2 - }); + });*/ // set timer - setInterval(render, 200); + //setInterval(render, 200); })(); }); }