Move some comments, and remove some of them
[vchess.git] / client / src / views / Game.vue
... / ...
CommitLineData
1<!-- TODO: component Game, + handle players + observers connect/disconnect
2 event = "gameconnect" ...etc
3 connect/disconnect with sid+name (ID not required); name slightly redundant but easier
4quand on arrive dans la partie, on poll les sids pour savoir qui est en ligne (ping)
5(éventuel échange lastate avec les connectés, pong ...etc)
6ensuite quand qqun se deco il suffit d'écouter "disconnect"
7pareil quand quelqu'un reco.
8(c'est assez rudimentaire et écoute trop de messages, mais dans un premier temps...)
9 // TODO: [in game] send move + elapsed time (in milliseconds); in case of "lastate" message too
10// TODO: if I'm an observer and player(s) disconnect/reconnect, how to find me ?
11// onClick :: ask full game to remote player, and register as an observer in game
12// (use gameId to communicate)
13// on landing on game :: if gameId not found locally, check remotely
14// ==> il manque un param dans game : "remoteId"
15-->
16<template lang="pug">
17.row
18 .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
19 BaseGame(:vname="variant.name" :analyze="analyze"
20 :vr="vr" :fen-start="fenStart" :players="players" :mycolor="mycolor"
21 ref="basegame" @newmove="processMove")
22 .button-group(v-if="mode!='analyze'")
23 button(@click="offerDraw") Draw
24 button(@click="abortGame") Abort
25 button(@click="resign") Resign
26 div(v-if="mode=='corr'")
27 textarea(v-show="score=='*' && vr.turn==mycolor" v-model="corrMsg")
28 div(v-show="cursor>=0") {{ moves[cursor].message }}
29</template>
30
31<script>
32import Board from "@/components/Board.vue";
33//import Chat from "@/components/Chat.vue";
34//import MoveList from "@/components/MoveList.vue";
35import { store } from "@/store";
36
37export default {
38 name: 'my-game',
39 components: {
40 BaseGame,
41 },
42 // gameRef: to find the game in (potentially remote) storage
43 // mode: "live" or "corr" (correspondance game), or "analyze"
44 data: function() {
45 return {
46 st: store.state,
47 // variables passed to BaseGame:
48 fenStart: "",
49 vr: null,
50 players: ["Myself","Computer"], //always playing white for now
51 mycolor: "w",
52 ////////////
53 gameRef: {id: "", rid: ""}, //given in URL (rid = remote ID, if applicable)
54 mode: "live", //or "corr"
55 variant: {}, //filled when game is retrieved
56 drawOfferSent: false, //did I just ask for draw?
57 players: [], //filled later (2 to 4 players)
58 people: [], //potential observers
59 };
60 },
61 computed: {
62 analyze: function() {
63 return this.mode == "analyze";
64 },
65 },
66 watch: {
67 '$route' (to, from) {
68 this.gameRef.id = to.params["id"];
69 this.gameRef.rid = to.query["rid"];
70 this.launchGame();
71 },
72 },
73 created: function() {
74 if (!!this.$route.params["id"])
75 {
76 this.gameRef.id = this.$route.params["id"];
77 this.gameRef.rid = this.$route.query["rid"];
78 this.launchGame();
79 }
80 // Poll all players except me (if I'm playing) to know online status.
81 // --> Send ping to server (answer pong if players[s] are connected)
82 if (!!this.gameRef.id)
83 {
84 this.players.forEach(p => {
85 if (p.sid != this.st.user.sid)
86 this.st.conn.send(JSON.stringify({code:"ping", oppid:p.sid}));
87 });
88 }
89 // TODO: how to know who is observing ? Send message to everyone with game ID ?
90 // and then just listen to (dis)connect events
91
92 // TODO: also handle "draw accepted" (use opponents array?)
93 // --> must give this info also when sending lastState...
94 // and, if all players agree then OK draw (end game ...etc)
95 const socketMessageListener = msg => {
96 const data = JSON.parse(msg.data);
97 let L = undefined;
98 switch (data.code)
99 {
100 case "newmove":
101 // TODO: observer on dark games must see all board ? Or alternate ? (seems better)
102 // ...or just see nothing as on buho21
103 this.$refs["baseGame"].play(
104 data.move, this.variant.name!="Dark" ? "animate" : null);
105 break;
106 case "pong": //received if we sent a ping (game still alive on our side)
107 if (this.gameRef.id != data.gameId)
108 break; //games IDs don't match: the game is definitely over...
109 this.oppConnected = true;
110 // Send our "last state" informations to opponent(s)
111 L = this.vr.moves.length;
112 Object.keys(this.opponents).forEach(oid => {
113 this.conn.send(JSON.stringify({
114 code: "lastate",
115 oppid: oid,
116 gameId: this.gameRef.id,
117 lastMove: (L>0?this.vr.moves[L-1]:undefined),
118 movesCount: L,
119 }));
120 });
121 break;
122 // TODO: refactor this, because at 3 or 4 players we may have missed 2 or 3 moves
123 case "lastate": //got opponent infos about last move
124 L = this.vr.moves.length;
125 if (this.gameRef.id != data.gameId)
126 break; //games IDs don't match: nothing we can do...
127 // OK, opponent still in game (which might be over)
128 if (this.score != "*")
129 {
130 // We finished the game (any result possible)
131 this.conn.send(JSON.stringify({
132 code: "lastate",
133 oppid: data.oppid,
134 gameId: this.gameRef.id,
135 score: this.score,
136 }));
137 }
138 else if (!!data.score) //opponent finished the game
139 this.endGame(data.score);
140 else if (data.movesCount < L)
141 {
142 // We must tell last move to opponent
143 this.conn.send(JSON.stringify({
144 code: "lastate",
145 oppid: this.opponent.id,
146 gameId: this.gameRef.id,
147 lastMove: this.vr.moves[L-1],
148 movesCount: L,
149 }));
150 }
151 else if (data.movesCount > L) //just got last move from him
152 this.play(data.lastMove, "animate");
153 break;
154 case "resign": //..you won!
155 this.endGame(this.mycolor=="w"?"1-0":"0-1");
156 break;
157 // TODO: also use (dis)connect info to count online players?
158 case "gameconnect":
159 case "gamedisconnect":
160 if (this.mode=="human")
161 {
162 const online = (data.code == "connect");
163 // If this is an opponent ?
164 if (!!this.opponents[data.id])
165 this.opponents[data.id].online = online;
166 else
167 {
168 // Or an observer ?
169 if (!online)
170 delete this.people[data.id];
171 else
172 this.people[data.id] = data.name;
173 }
174 }
175 break;
176 }
177 };
178 const socketCloseListener = () => {
179 this.conn.addEventListener('message', socketMessageListener);
180 this.conn.addEventListener('close', socketCloseListener);
181 };
182 if (!!this.conn)
183 {
184 this.conn.onmessage = socketMessageListener;
185 this.conn.onclose = socketCloseListener;
186 }
187 },
188 // dans variant.js (plutôt room.js) conn gère aussi les challenges
189 // et les chats dans chat.js. Puis en webRTC, repenser tout ça.
190 methods: {
191 offerDraw: function() {
192 if (!confirm("Offer draw?"))
193 return;
194 // Stay in "draw offer sent" state until next move is played
195 this.drawOfferSent = true;
196 if (this.subMode == "corr")
197 {
198 // TODO: set drawOffer on in game (how ?)
199 }
200 else //live game
201 {
202 this.opponents.forEach(o => {
203 if (!!o.online)
204 {
205 try {
206 this.conn.send(JSON.stringify({code: "draw", oppid: o.id}));
207 } catch (INVALID_STATE_ERR) {
208 return;
209 }
210 }
211 });
212 }
213 },
214 // + conn handling: "draw" message ==> agree for draw (if we have "drawOffered" at true)
215 receiveDrawOffer: function() {
216 //if (...)
217 // TODO: ignore if preventDrawOffer is set; otherwise show modal box with option "prevent future offers"
218 // if accept: send message "draw"
219 },
220 abortGame: function() {
221 if (!confirm("Abort the game?"))
222 return;
223 //+ bouton "abort" avec score == "?" + demander confirmation pour toutes ces actions,
224 //send message: "gameOver" avec score "?"
225 },
226 resign: function(e) {
227 if (!confirm("Resign the game?"))
228 return;
229 if (this.mode == "human" && this.oppConnected(this.oppid))
230 {
231 try {
232 this.conn.send(JSON.stringify({code: "resign", oppid: this.oppid}));
233 } catch (INVALID_STATE_ERR) {
234 return;
235 }
236 }
237 this.endGame(this.mycolor=="w"?"0-1":"1-0");
238 },
239 launchGame: async function() {
240 const vModule = await import("@/variants/" + this.variant.name + ".js");
241 window.V = vModule.VariantRules;
242 this.loadGame(this.gid);
243 },
244 loadGame: function(gid) {
245 // TODO: ask game to remote peer if this.remoteId is set
246 // (or just if game not found locally)
247 // NOTE: if it's a corr game, ask it from server
248 const game = getGameFromStorage(gid); //, this.gameRef.uid); //uid may be blank
249 this.opponent.id = game.oppid; //opponent ID in case of running HH game
250 this.opponent.name = game.oppname; //maye be blank (if anonymous)
251 this.score = game.score;
252 this.mycolor = game.mycolor;
253 this.fenStart = game.fenStart;
254 this.moves = game.moves;
255 this.cursor = game.moves.length-1;
256 this.lastMove = (game.moves.length > 0 ? game.moves[this.cursor] : null);
257 // TODO: fill players array
258 },
259 oppConnected: function(uid) {
260 return this.opponents.any(o => o.id == uidi && o.online);
261 },
262 },
263};
264</script>