]> git.cworth.org Git - lmno.games/blobdiff - tictactoe/tictactoe.jsx
Be more selective about when to display buttons for joining a team
[lmno.games] / tictactoe / tictactoe.jsx
index 579526b7dcb401e0310027da092f47c8fead5691..ca0bce3fd4985bf8636893cbfeae92ea4235508b 100644 (file)
@@ -44,11 +44,19 @@ events.addEventListener("player-info", event => {
   window.game.set_player_info(info);
 });
 
+events.addEventListener("player-enter", event => {
+  const info = JSON.parse(event.data);
+
+  window.game.set_opponent_info(info);
+});
+
 events.addEventListener("player-update", event => {
   const info = JSON.parse(event.data);
 
   if (info.id === window.game.state.player_info.id)
     window.game.set_player_info(info);
+  else
+    window.game.set_opponent_info(info);
 });
 
 events.addEventListener("move", event => {
@@ -83,15 +91,59 @@ function GameInfo(props) {
   );
 }
 
+function TeamButton(props) {
+  return <button className="inline"
+                 onClick={() => props.game.join_team(props.team)}>
+           {props.label}
+         </button>;
+}
+
+function TeamChoices(props) {
+  let other_team;
+  if (props.player.team === "X")
+    other_team = "O";
+  else
+    other_team = "X";
+
+  if (props.player.team === "") {
+    if (props.first_move) {
+      return null;
+    } else {
+      return [
+        <TeamButton key="X" game={props.game} team="X" label="Join X" />,
+        " ",
+        <TeamButton key="O" game={props.game} team="O" label="Join O" />
+      ];
+    }
+  } else {
+    return <TeamButton game={props.game} team={other_team} label="Switch" />;
+  }
+}
+
 function PlayerInfo(props) {
   if (! props.player.id)
     return null;
 
+  const choices = <TeamChoices
+                    game={props.game}
+                    first_move={props.first_move}
+                    player={props.player}
+                  />;
+
   return (
     <div className="player-info">
-      <h2>Player</h2>
+      <h2>Players</h2>
       {props.player.name}
       {props.player.team ? ` (${props.player.team})` : ""}
+      {props.first_move ? "" : " "}
+      {choices}
+      {props.opponents.map(opponent => (
+        <span key={opponent.id}>
+          {", "}
+          {opponent.name}
+          {opponent.team ? ` (${opponent.team})` : ""}
+        </span>
+      ))}
     </div>
   );
 }
@@ -175,6 +227,7 @@ class Game extends React.Component {
     this.state = {
       game_info: {},
       player_info: {},
+      opponent_info: [],
       history: [
         {
           squares: Array(9).fill(null)
@@ -197,6 +250,19 @@ class Game extends React.Component {
     });
   }
 
+  set_opponent_info(info) {
+    const new_opponents = [...this.state.opponent_info];
+    const idx = new_opponents.findIndex(o => o.id === info.id);
+    if (idx >= 0) {
+      new_opponents[idx] = info;
+    } else {
+      new_opponents.push(info);
+    }
+    this.setState({
+      opponent_info: new_opponents
+    });
+  }
+
   reset_board() {
     this.setState({
       history: [
@@ -303,14 +369,12 @@ class Game extends React.Component {
       />,
       <PlayerInfo
         key="player-info"
+        game={this}
+        first_move={first_move}
         player={state.player_info}
+        opponents={state.opponent_info}
       />,
       <div key="game" className="game">
-        <button className="inline"
-                onClick={() => this.join_team('X')}>Join Team X</button>
-        {" "}
-        <button className="inline"
-                onClick={() => this.join_team('O')}>Join Team O</button>
         <div>{status}</div>
         <div className="game-board">
           <Board