merged feature/user_management into master
This commit is contained in:
		| @ -1,199 +0,0 @@ | ||||
| class GameServerConnection | ||||
| { | ||||
|     constructor(ip, port) | ||||
|     { | ||||
|         this.ip = ip; | ||||
|         this.port = port; | ||||
|         this.player = null; | ||||
|         this.socket = null; | ||||
|         this.registered = false; | ||||
|  | ||||
|         this.game_manager = null; | ||||
|         this.connected = false; | ||||
|     } | ||||
|  | ||||
|     set_player(p) | ||||
|     { | ||||
|         this.player = p; | ||||
|     } | ||||
|  | ||||
|     set_game_manager(gm) | ||||
|     { | ||||
|         this.game_manager = gm; | ||||
|     } | ||||
|  | ||||
|     is_registered() | ||||
|     { | ||||
|         return this.registered; | ||||
|     } | ||||
|  | ||||
|     is_connected() | ||||
|     { | ||||
|         return this.connected; | ||||
|     } | ||||
|  | ||||
|     on_open(callback_func) | ||||
|     { | ||||
|         // TODO | ||||
|         console.log("connected to " + this.ip + ":" + this.port); | ||||
|         this.connected = true; | ||||
|         callback_func(); | ||||
|     } | ||||
|  | ||||
|     on_close() | ||||
|     { | ||||
|         this.game_manager.end_game_listener() | ||||
|     } | ||||
|  | ||||
|     on_error() | ||||
|     { | ||||
|         console.log("error in websocket connection"); | ||||
|         this.game_manager.connection_error_listener(); | ||||
|     } | ||||
|  | ||||
|     on_message(event) | ||||
|     { | ||||
|         var json_msg = event.data; | ||||
|         var msg = JSON.parse(json_msg); | ||||
|  | ||||
|         if (!msg.hasOwnProperty("type") || !msg.hasOwnProperty("data")) | ||||
|         { | ||||
|             console.log("received wrong formatted message"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         switch(msg.type) | ||||
|         { | ||||
|             case "register_response": | ||||
|                 this.on_register_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "game_starts": | ||||
|                 this.on_game_starts(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "move": | ||||
|                 this.on_move(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "move_response": | ||||
|                 this.on_move_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "end_game": | ||||
|                 this.on_end_game(msg.data); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     on_register_response(data) | ||||
|     { | ||||
|         var success = data.success; | ||||
|         this.game_manager.register_response_listener(success); | ||||
|  | ||||
|         if (!success) | ||||
|         { | ||||
|             this.socket.close(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     on_game_starts(data) | ||||
|     { | ||||
|         var op_name = data.opponent_name; | ||||
|         var is_first_move = data.is_first_move; | ||||
|  | ||||
|         this.game_manager.start_game_listener(op_name, is_first_move); | ||||
|     } | ||||
|  | ||||
|     on_move(data) | ||||
|     { | ||||
|         var sub_x = data.sub_x; | ||||
|         var sub_y = data.sub_y; | ||||
|         var x = data.x; | ||||
|         var y = data.y; | ||||
|  | ||||
|         this.game_manager.move_listener(sub_x, sub_y, x, y); | ||||
|     } | ||||
|  | ||||
|     on_move_response(data) | ||||
|     { | ||||
|         if (data.success) | ||||
|         { | ||||
|             console.log("move accepted"); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             console.error("move not accepted"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     on_end_game(data) | ||||
|     { | ||||
|         this.game_manager.end_game_listener(); | ||||
|         this.close(); | ||||
|     } | ||||
|  | ||||
|     connect(callback_func) | ||||
|     { | ||||
|         this.socket = new WebSocket("wss://" + this.ip + ":" + this.port); | ||||
|         this.socket.onmessage = (e => this.on_message(e)); | ||||
|         this.socket.onopen = (() => this.on_open(callback_func)); | ||||
|         this.socket.onerror = (() => this.on_error()); | ||||
|         this.socket.onclose = (() => this.on_close()); | ||||
|     } | ||||
|  | ||||
|     send_move(sub_x, sub_y, x, y) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "move", | ||||
|             data: { | ||||
|                 sub_x: "" + sub_x, | ||||
|                 sub_y: "" + sub_y, | ||||
|                 x: "" + x, | ||||
|                 y: "" + y | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     register() | ||||
|     { | ||||
|         // register for game queue | ||||
|         var msg_object = { | ||||
|             type: "register", | ||||
|             data: { | ||||
|                 id: this.player.get_id(), | ||||
|                 name: this.player.get_name() | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     send_disconnect() | ||||
|     { | ||||
|         if (!this.is_connected) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         var msg_object = { | ||||
|             type: "end_game", | ||||
|             data: { | ||||
|                 msg: "" | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     close() | ||||
|     { | ||||
|         if (this.is_connected) | ||||
|         { | ||||
|             this.is_connected = false; | ||||
|             this.socket.close(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								grid.js
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								grid.js
									
									
									
									
									
								
							| @ -1,9 +1,9 @@ | ||||
| class Grid | ||||
| { | ||||
|     constructor(n, grid_container_div, tile_width, tile_height, ground_color) | ||||
|     constructor(n, parent, tile_width, tile_height, ground_color) | ||||
|     { | ||||
|         this.n = n; | ||||
|         this.grid_container_div = grid_container_div; | ||||
|         this.grid_container_div = null; | ||||
|         this.tile_width = tile_width; | ||||
|         this.tile_height = tile_height; | ||||
|         this.ground_color = ground_color; | ||||
| @ -11,6 +11,8 @@ class Grid | ||||
|         this.won_player = null; | ||||
|         this.n_complete_subgrids = 0; | ||||
|  | ||||
|         this.parent = parent; | ||||
|  | ||||
|         this.subgrids = [] | ||||
|  | ||||
|         console.log("create grid of size " + this.n); | ||||
| @ -20,6 +22,10 @@ class Grid | ||||
|  | ||||
|     create() | ||||
|     { | ||||
|         this.grid_container_div = document.createElement("div"); | ||||
|         this.grid_container_div.className = "grid-container"; | ||||
|         this.parent.appendChild(this.grid_container_div); | ||||
|  | ||||
|         var x,y; | ||||
|         for (y = 0; y < this.n; y++) | ||||
|         { | ||||
| @ -49,8 +55,11 @@ class Grid | ||||
|     { | ||||
|         this.check_win(sub_x, sub_y, x, y); | ||||
|         this.check_complete(sub_x, sub_y, x, y); | ||||
|         if (this.click_callback != null) | ||||
|         { | ||||
|             this.click_callback(sub_x, sub_y, x, y); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     player_change_listener(player) | ||||
|     { | ||||
| @ -81,7 +90,7 @@ class Grid | ||||
|  | ||||
|     check_complete(sub_x, sub_y, x, y) | ||||
|     { | ||||
|         if (this.subgrids[sub_x][sub_y].is_won() || this.subgrids[sub_x][sub_y].is_draw()) | ||||
|         if (this.subgrids[sub_y][sub_x].is_won() || this.subgrids[sub_y][sub_x].is_draw()) | ||||
|         { | ||||
|             this.n_complete_subgrids++; | ||||
|         } | ||||
| @ -211,6 +220,22 @@ class Grid | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     unblock_all_non_completed() | ||||
|     { | ||||
|         var x,y; | ||||
|         for (y = 0; y < this.n; y++) | ||||
|         { | ||||
|             for (x = 0; x < this.n; x++) | ||||
|             { | ||||
|                 if (this.subgrids[y][x].is_won() || this.subgrids[y][x].is_draw()) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|                 this.subgrids[y][x].unblock(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     block(x,y) | ||||
|     { | ||||
|         this.subgrids[y][x].block(); | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								icon.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icon.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 19 KiB | 
							
								
								
									
										20
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								index.html
									
									
									
									
									
								
							| @ -2,29 +2,25 @@ | ||||
|     <link rel="stylesheet" type="text/css" href="style.css"> | ||||
| 	<head> | ||||
|         <meta name="viewport" content="width=device-width, user-scalable=no" /> | ||||
|         <meta name="theme-color" content="#7e57c2" /> | ||||
|         <link rel="manifest" href="./manifest.json" /> | ||||
|         <link rel="icon" href="icon.png" type="image/png"/> | ||||
|         <script defer src="site.js"></script> | ||||
| 		<title>ultimate tictactoe</title> | ||||
| 	</head> | ||||
| 	<body> | ||||
|         <div id="main-container" class="main-container"> | ||||
|             <div id="grid-container" class="grid-container"></div> | ||||
|             <div id="sidebar-container" class="sidebar-container"> | ||||
|                 <div id="create-game-container" class="create-game-container"></div> | ||||
|                 <div id="setting-container" class="setting-container"></div> | ||||
|                 <div id="control-container" class="control-container"></div> | ||||
|                 <div id="info-container" class="info-container"></div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div id="main-container" class="main-container"></div> | ||||
|         <script src="tools.js"></script> | ||||
|         <script src="settings.js"></script> | ||||
|         <script src="player.js"></script> | ||||
|         <script src="tile.js"></script> | ||||
|         <script src="grid.js"></script> | ||||
|         <script src="subgrid.js"></script> | ||||
|         <script src="game_manager.js"></script> | ||||
|         <script src="game_server_connection.js"></script> | ||||
|         <script src="sidebar.js"></script> | ||||
|         <script src="local_match_manager.js"></script> | ||||
|         <script src="online_match_manager.js"></script> | ||||
|         <script src="websocket_connection.js"></script> | ||||
|         <script src="infobar.js"></script> | ||||
|         <script src="infocontainer.js"></script> | ||||
|         <script src="main.js"></script> | ||||
|          | ||||
| 	</body> | ||||
|  | ||||
							
								
								
									
										15
									
								
								infobar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								infobar.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| class Infobar | ||||
| { | ||||
|     constructor(parent) | ||||
|     { | ||||
|         this.parent = parent; | ||||
|         this.container = document.createElement("div"); | ||||
|         this.container.className = "infobar-container"; | ||||
|         this.parent.appendChild(this.container); | ||||
|     } | ||||
|  | ||||
|     create_infocontainer() | ||||
|     { | ||||
|         return new Infocontainer(this.container); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										76
									
								
								infocontainer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								infocontainer.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| class Infocontainer | ||||
| { | ||||
|     constructor(parent) | ||||
|     { | ||||
|         this.parent = parent; | ||||
|         this.container = document.createElement("div"); | ||||
|         this.container.className = "info-container"; | ||||
|         this.parent.appendChild(this.container); | ||||
|     } | ||||
|  | ||||
|     create_button(text) | ||||
|     { | ||||
|         var b = document.createElement("button"); | ||||
|         b.className = "infobar-button"; | ||||
|         b.appendChild(document.createTextNode(text)); | ||||
|         this.container.appendChild(b) | ||||
|         return b; | ||||
|     } | ||||
|  | ||||
|     create_input(placeholder, pw=false) | ||||
|     { | ||||
|         var i = document.createElement("input"); | ||||
|         i.className = "infobar-input"; | ||||
|         i.placeholder = placeholder; | ||||
|         i.type = pw ? "password" : "text";  | ||||
|  | ||||
|         this.container.appendChild(i); | ||||
|         return i; | ||||
|     } | ||||
|  | ||||
|     create_label(text) | ||||
|     { | ||||
|         var l = document.createElement("label"); | ||||
|         l.className = "infobar-label"; | ||||
|         l.innerHTML = text; | ||||
|         this.container.appendChild(l); | ||||
|         return l; | ||||
|     } | ||||
|  | ||||
|     create_double_button(text, option) | ||||
|     { | ||||
|         var div = document.createElement("div"); | ||||
|         div.className = "option-button-container"; | ||||
|         var b1 = document.createElement("button"); | ||||
|         var b2 = document.createElement("button"); | ||||
|  | ||||
|         b1.style.width = "10%"; | ||||
|  | ||||
|         b1.className = "infobar-button"; | ||||
|         b2.className = "infobar-button"; | ||||
|  | ||||
|         b1.style.width = "80%"; | ||||
|         b2.style.width = "20%"; | ||||
|          | ||||
|  | ||||
|         b1.appendChild(document.createTextNode(text)); | ||||
|         b2.appendChild(document.createTextNode(option)); | ||||
|  | ||||
|         div.appendChild(b1); | ||||
|         div.appendChild(b2); | ||||
|  | ||||
|         this.container.appendChild(div); | ||||
|  | ||||
|         return [div, b1,b2]; | ||||
|     } | ||||
|  | ||||
|     hide() | ||||
|     { | ||||
|         this.container.style.display = "none"; | ||||
|     } | ||||
|  | ||||
|     show() | ||||
|     { | ||||
|         this.container.style.display = "inline-block"; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										72
									
								
								local_match_manager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								local_match_manager.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| class LocalMatchManager | ||||
| { | ||||
|     constructor(grid, status_label, control_container) | ||||
|     { | ||||
|         this.grid = grid; | ||||
|         this.status_label = status_label; | ||||
|  | ||||
|         this.control_container = control_container; | ||||
|  | ||||
|         this.control_container.show(); | ||||
|  | ||||
|         this.local_player_a = new Player("red player", 255,0,0); | ||||
|         this.local_player_b = new Player("green player", 0,255,0); | ||||
|         this.is_local_player_a = false; | ||||
|  | ||||
|         this.grid.register_click_callback((i,j,k,l) => this.click_listener(i,j,k,l)); | ||||
|  | ||||
|         this.grid.deactivate_all(); | ||||
|         this.grid.unblock_all(); | ||||
|  | ||||
|  | ||||
|         this.toggle_local_player(); | ||||
|     } | ||||
|  | ||||
|     click_listener(sub_x, sub_y, x,y) | ||||
|     { | ||||
|         // check whether the game is over: | ||||
|         if (grid.is_won()) | ||||
|         { | ||||
|             this.status_label.innerHTML = "" + grid.get_won_player().get_name() + " has won."; | ||||
|             this.end_game(); | ||||
|         } | ||||
|         else if (grid.is_complete()) | ||||
|         { | ||||
|             this.status_label.innerHTML = "Draw. Everybody looses!"; | ||||
|             this.end_game(false); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.toggle_local_player(); | ||||
|             this.grid.block_all() | ||||
|             if (this.grid.subgrids[y][x].is_draw() || this.grid.subgrids[y][x].is_won()) | ||||
|             { | ||||
|                 this.grid.unblock_all_non_completed(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 this.grid.subgrids[y][x].unblock(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     toggle_local_player() | ||||
|     { | ||||
|         this.is_local_player_a = !this.is_local_player_a; | ||||
|         var next_player = this.is_local_player_a ? this.local_player_a : this.local_player_b; | ||||
|          | ||||
|         this.status_label.innerHTML = "" + "it's " + next_player.get_name() + "'s turn..."; | ||||
|         this.grid.player_change_listener(next_player); | ||||
|     } | ||||
|  | ||||
|     end_game(closed_by_player = true) | ||||
|     { | ||||
|         if (closed_by_player) | ||||
|         { | ||||
|             this.status_label.innerHTML = "Game Over. Game Closed"; | ||||
|         } | ||||
|         this.grid.block_all(); | ||||
|     } | ||||
|  | ||||
|      | ||||
| } | ||||
							
								
								
									
										304
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										304
									
								
								main.js
									
									
									
									
									
								
							| @ -3,18 +3,304 @@ var n = style.getPropertyValue("--tictactoe_n"); | ||||
| var tilesize = style.getPropertyValue("--tile-size"); | ||||
| var default_opacity = style.getPropertyValue("--opacity"); | ||||
| var ground_color = style.getPropertyValue("--ground-color"); | ||||
| var main_container = document.getElementById("main-container"); | ||||
|  | ||||
| var create_game_container = document.getElementById("create-game-container"); | ||||
| var setting_container = document.getElementById("setting-container"); | ||||
| var control_container = document.getElementById("control-container"); | ||||
| var info_container = document.getElementById("info-container"); | ||||
|  | ||||
| var grid = new Grid(n, document.getElementById("grid-container"), tilesize, tilesize, ground_color); | ||||
| var server_connection = new GameServerConnection(server_url, server_port); | ||||
| var game_manager = new GameManager(grid, server_connection); | ||||
| var sidebar = new Sidebar(create_game_container, setting_container, control_container, info_container, game_manager); | ||||
| var main_menu = new Infobar(main_container); | ||||
| var grid = new Grid(n, main_container, tilesize, tilesize, ground_color); | ||||
| var sub_menu = new Infobar(main_container); | ||||
|  | ||||
|  | ||||
| // fill containers with buttons and containers: | ||||
|  | ||||
| // empty dummy container on top (to force other containers to be at the bottom) | ||||
| dummy_main = main_menu.create_infocontainer(); | ||||
| dummy_sub = sub_menu.create_infocontainer(); | ||||
|  | ||||
| // start container: | ||||
| create_game_container = main_menu.create_infocontainer(); | ||||
| create_game_container.create_label("Start Local Game"); | ||||
| b_local_game = create_game_container.create_button("Local Game"); | ||||
|  | ||||
|  | ||||
|  | ||||
| // register container: | ||||
| register_container = main_menu.create_infocontainer(); | ||||
| register_container.create_label("Login to play online"); | ||||
| i_register_username = register_container.create_input("username"); | ||||
| i_register_pw = register_container.create_input("password", true); | ||||
| b_register = register_container.create_button("register/login"); | ||||
| //register_container.create_label("(creates new account for a new username)"); | ||||
|  | ||||
| // logout: | ||||
| logout_container = main_menu.create_infocontainer(); | ||||
| l_username = logout_container.create_label("logged in as: "); | ||||
| b_logout = logout_container.create_button("logout"); | ||||
|  | ||||
|  | ||||
| // fill subcontainer: | ||||
| match_slot_container = sub_menu.create_infocontainer(); | ||||
| match_slot_container.create_label("Running Matches<br>(click to open)"); | ||||
|  | ||||
|  | ||||
| // local match control: | ||||
| match_control = sub_menu.create_infocontainer(); | ||||
| b_end_game = match_control.create_button("Close Match"); | ||||
|  | ||||
|  | ||||
| // search match: | ||||
| search_match_container = sub_menu.create_infocontainer(); | ||||
| search_match_container.create_label("Create Online Match"); | ||||
| b_match_search = search_match_container.create_button("random match"); | ||||
|  | ||||
| l_match_op = search_match_container.create_input("player name"); | ||||
| b_match_invite = search_match_container.create_button("invite player"); | ||||
|  | ||||
| search_match_container.create_label("Invite friends:") | ||||
|  | ||||
|  | ||||
|  | ||||
| //status: | ||||
| status_container = main_menu.create_infocontainer(); | ||||
| l_status_head = status_container.create_label("Status:"); | ||||
| l_status = status_container.create_label("select gamemode. click <br> <a href=https://en.wikipedia.org/wiki/Ultimate_tic-tac-toe#Rules>[here]</a> for the rules!"); | ||||
|  | ||||
|  | ||||
| // global vars: | ||||
|  | ||||
| game_manager = null; | ||||
|  | ||||
| logged_in = false; | ||||
|  | ||||
| // connection stuff: | ||||
|  | ||||
| var connection = null; | ||||
| var session_id = null; | ||||
|  | ||||
|  | ||||
| // cookies: | ||||
| function get_cookie(cname) { | ||||
|     var name = cname + "="; | ||||
|     var ca = document.cookie.split(';'); | ||||
|     for(var i = 0; i < ca.length; i++) { | ||||
|         var c = ca[i]; | ||||
|         while (c.charAt(0) == ' ') { | ||||
|             c = c.substring(1); | ||||
|         } | ||||
|         if (c.indexOf(name) == 0) { | ||||
|             return c.substring(name.length, c.length); | ||||
|         } | ||||
|     } | ||||
|     return ""; | ||||
| } | ||||
|  | ||||
| function set_cookie(cname, cvalue, exdays) { | ||||
|     var d = new Date(); | ||||
|     d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); | ||||
|     var expires = "expires="+d.toUTCString(); | ||||
|     document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; | ||||
| } | ||||
|  | ||||
| function check_cookie(cname) { | ||||
|     var tmp = get_cookie(cname); | ||||
|     if (tmp != "") { | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| // global funcs: | ||||
|  | ||||
| disable_all_containers = function() | ||||
| { | ||||
|     create_game_container.hide(); | ||||
|     register_container.hide(); | ||||
|     logout_container.hide(); | ||||
|     match_slot_container.hide(); | ||||
|     search_match_container.hide(); | ||||
|     match_control.hide(); | ||||
|     status_container.hide(); | ||||
|  | ||||
|     dummy_main.hide(); | ||||
|     dummy_sub.hide(); | ||||
| } | ||||
|  | ||||
|  | ||||
| end_local_game = function() | ||||
| { | ||||
|     disable_all_containers(); | ||||
|     create_game_container.show(); | ||||
|     status_container.show(); | ||||
|     if (logged_in) | ||||
|     { | ||||
|         logout_container.show(); | ||||
|         search_match_container.show(); | ||||
|         match_slot_container.show(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         register_container.show(); | ||||
|     } | ||||
|      | ||||
|     game_manager = null; | ||||
| } | ||||
|  | ||||
| on_close_click = function() { | ||||
|     if (game_manager != null) | ||||
|     { | ||||
|         game_manager.end_game(); | ||||
|         end_local_game(); | ||||
|     } | ||||
|     else if (connection != null) | ||||
|     { | ||||
|         connection.on_close_click(); | ||||
|         match_control.hide(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| start_local_game = function() | ||||
| { | ||||
|     console.log("clicked"); | ||||
|     disable_all_containers(); | ||||
|     match_control.show(); | ||||
|     dummy_main.show(); | ||||
|     dummy_sub.show(); | ||||
|  | ||||
|     status_container.show(); | ||||
|  | ||||
|     game_manager = new LocalMatchManager(grid, l_status, match_control, end_local_game); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| // connection stuff: | ||||
|  | ||||
| login_callback = function() | ||||
| { | ||||
|     logged_in = true; | ||||
|     if (game_manager != null) | ||||
|     { | ||||
|         game_manager.end_game(); | ||||
|          | ||||
|     } | ||||
|     end_local_game(); | ||||
|     l_username.innerHTML = "logged in as: " + connection.player.get_name(); | ||||
|  | ||||
|     set_cookie("sessionid", connection.session_id, 30); | ||||
|  | ||||
| } | ||||
|  | ||||
| logout = function() | ||||
| { | ||||
|     logged_in = false; | ||||
|     if (connection != null) | ||||
|     { | ||||
|  | ||||
|         connection.close(); | ||||
|         if (check_cookie("sessionid")) | ||||
|         { | ||||
|             // delete session: | ||||
|             session_id = get_cookie("sessionid"); | ||||
|             set_cookie("sessionid", session_id, -100); | ||||
|             session_id = null; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     connection = null; | ||||
|     grid.unblock_all(); | ||||
|     grid.deactivate_all(); | ||||
|     grid.block_all(); | ||||
|     end_local_game(); | ||||
| } | ||||
|  | ||||
| reconnect = function() | ||||
| { | ||||
|     if (check_cookie("sessionid")) | ||||
|     { | ||||
|         session_id = get_cookie("sessionid"); | ||||
|         if (connection != null) | ||||
|         { | ||||
|             connection.close(); | ||||
|         } | ||||
|         connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, search_match_container, login_callback, on_connection_error); | ||||
|         connection.reconnect(session_id); | ||||
|     } | ||||
| } | ||||
|  | ||||
| on_connection_error = function() | ||||
| { | ||||
|     connection = null; | ||||
|     logout(); | ||||
| } | ||||
|  | ||||
| login = function(){ | ||||
|  | ||||
|     if (connection != null) | ||||
|     { | ||||
|         connection.close(); | ||||
|     } | ||||
|     connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, search_match_container, login_callback, on_connection_error); | ||||
|     connection.connect(i_register_username.value.toLowerCase(), i_register_pw.value); | ||||
| } | ||||
|  | ||||
| search_match = function() | ||||
| { | ||||
|     if (connection != null) | ||||
|     { | ||||
|         connection.send_match_request(null); | ||||
|     } | ||||
| } | ||||
|  | ||||
| invite_player = function() | ||||
| { | ||||
|     if (connection != null) | ||||
|     { | ||||
|         if (l_match_op.value == "") | ||||
|         { | ||||
|             l_status.innerHTML = "choose your opponent first!"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             connection.send_match_request(l_match_op.value); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // initiate stuff and connect events: | ||||
|  | ||||
| end_local_game(); | ||||
|  | ||||
|  | ||||
| b_local_game.addEventListener("click", start_local_game); | ||||
| b_end_game.addEventListener("click", on_close_click); | ||||
| b_register.addEventListener("click", login); | ||||
| b_logout.addEventListener("click", logout); | ||||
|  | ||||
| b_match_search.addEventListener("click", search_match); | ||||
| b_match_invite.addEventListener("click", invite_player); | ||||
|  | ||||
| reconnect(); | ||||
|  | ||||
| // register resize event: | ||||
|  | ||||
| window.addEventListener("resize", function() { | ||||
|     var tilesize = getComputedStyle(document.body).getPropertyValue("--tile-size"); | ||||
|     grid.on_screen_orientation_change(tilesize, tilesize); | ||||
| }) | ||||
| }); | ||||
|  | ||||
| window.onload = function() {  | ||||
|     window.onfocus = function() { | ||||
|         if (session_id != null && connection == null) | ||||
|         { | ||||
|             reconnect(); | ||||
|         } | ||||
|     }; | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -4,8 +4,8 @@ | ||||
|     "display": "standalone", | ||||
|     "start_url": "/website/ultimate_tictactoe/", | ||||
|     "scope": "/website/ultimate_tictactoe/", | ||||
|     "theme_color": "#4650e2", | ||||
|     "background_color": "#1e2477", | ||||
|     "theme_color": "#7e57c2", | ||||
|     "background_color": "#31364A", | ||||
|     "icons": [ | ||||
|       { | ||||
|         "src": "icon.png", | ||||
|  | ||||
							
								
								
									
										257
									
								
								online_match_manager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								online_match_manager.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,257 @@ | ||||
| class OnlineMatchManager | ||||
| { | ||||
|     constructor(grid, status_label, matches_container, control_container, game_server_connection, match_id, match_state, player_name) | ||||
|     { | ||||
|         this.grid = grid; | ||||
|         this.status_label = status_label; | ||||
|  | ||||
|         this.match_id = match_id; | ||||
|  | ||||
|         this.game_server_connection = game_server_connection; | ||||
|  | ||||
|  | ||||
|         this.match_state = match_state; | ||||
|         this.player_name = player_name | ||||
|  | ||||
|         var player_a = this.match_state.player_a; | ||||
|         var player_b = this.match_state.player_b; | ||||
|  | ||||
|         this.online_opponent = new Player(player_a == this.player_name ? player_b : player_a, 255,0,0); | ||||
|         this.local_player = new Player(this.player_name, 0,255,0); | ||||
|  | ||||
|         // create match button in match list: | ||||
|         this.control_container = control_container; | ||||
|         this.matches_container = matches_container; | ||||
|  | ||||
|         var tmp = matches_container.create_double_button("" + this.online_opponent.get_name(), "+") | ||||
|  | ||||
|         this.match_button = tmp[1]; | ||||
|         this.match_button_div = tmp[0]; | ||||
|         this.match_button_option = tmp[2]; | ||||
|  | ||||
|         if (this.game_server_connection.is_friend(this.online_opponent.get_name())) | ||||
|         { | ||||
|             this.match_button_option.disabled = true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.match_button_option.addEventListener("click", () => { | ||||
|                 this.game_server_connection.send_friend_request(this.online_opponent.get_name()); | ||||
|                 this.match_button_option.disabled = true; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         this.match_button.addEventListener("click", () => this.open_match()); | ||||
|  | ||||
|         if (this.online_opponent.get_name() == this.match_state.active_player) | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-red"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-green" | ||||
|         } | ||||
|  | ||||
|         this.is_closed = false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     click_listener(sub_x, sub_y, x,y) | ||||
|     { | ||||
|         this.grid.block_all(); | ||||
|  | ||||
|         this.game_server_connection.send_move(sub_x, sub_y, x, y, this.match_id); | ||||
|  | ||||
|         this.status_label.innerHTML = "waiting for " + this.online_opponent.get_name() + "'s move"; | ||||
|     } | ||||
|  | ||||
|     on_user_close() | ||||
|     { | ||||
|  | ||||
|         // send end match message: | ||||
|         if (!this.match_state.game_over) | ||||
|         { | ||||
|             this.game_server_connection.send_end_match(this.match_id); | ||||
|         } | ||||
|  | ||||
|         if (this.match_button_div != null) | ||||
|         { | ||||
|             clearInner(this.match_button_div) | ||||
|             this.matches_container.container.removeChild(this.match_button_div); | ||||
|             this.match_button_div = null; | ||||
|         } | ||||
|         this.status_label.innerHTML = "match is closed"; | ||||
|         this.control_container.hide(); | ||||
|         this.is_closed = true; | ||||
|          | ||||
|     } | ||||
|  | ||||
|     remove_match() | ||||
|     { | ||||
|         if (this.match_button_div != null) | ||||
|         { | ||||
|             clearInner(this.match_button_div); | ||||
|             this.matches_container.container.removeChild(this.match_button_div); | ||||
|             this.match_button_div = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     update_match_state(match_state) | ||||
|     { | ||||
|         this.match_state = match_state; | ||||
|          | ||||
|         if (this.online_opponent.get_name() == this.match_state.active_player) | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-red"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-green" | ||||
|         } | ||||
|  | ||||
|         if (this.match_state.active_player == this.local_player.get_name()) | ||||
|         { | ||||
|             this.game_server_connection.notify("your turn against " + this.online_opponent.get_name()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     on_focus_loose() | ||||
|     { | ||||
|         if (this.online_opponent.get_name() == this.match_state.active_player) | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-red"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.match_button.className = "infobar-button-green" | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     open_match() | ||||
|     { | ||||
|         this.grid.register_click_callback(null); | ||||
|  | ||||
|         this.grid.deactivate_all(); | ||||
|         this.grid.unblock_all(); | ||||
|  | ||||
|         this.match_button.className = "infobar-button-active"; | ||||
|  | ||||
|         this.game_server_connection.set_active_match(this.match_id); | ||||
|  | ||||
|         this.control_container.show(); | ||||
|  | ||||
|         var complete_field = this.match_state.complete_field; | ||||
|         var global_field = this.match_state.global_field; | ||||
|  | ||||
|         var sub_x = null; | ||||
|         var sub_y = null; | ||||
|         var x = null; | ||||
|         var y = null;         | ||||
|  | ||||
|         if (this.match_state.last_move != null) | ||||
|         { | ||||
|             sub_x = this.match_state.last_move.sub_x; | ||||
|             sub_y = this.match_state.last_move.sub_y; | ||||
|             x = this.match_state.last_move.x; | ||||
|             y = this.match_state.last_move.y; | ||||
|         } | ||||
|  | ||||
|         var game_over = this.match_state.game_over; | ||||
|         var player_won = this.match_state.player_won; | ||||
|         var current_player_name = this.match_state.active_player; | ||||
|  | ||||
|         var player_a = this.match_state.player_a; | ||||
|         var player_b = this.match_state.player_b; | ||||
|  | ||||
|         console.log(game_over); | ||||
|         console.log(current_player); | ||||
|  | ||||
|         var FIELD_EMPTY = 0 | ||||
|         var FIELD_USER = player_a == this.player_name ? 1 : 2; | ||||
|         var FIELD_OPPONENT = player_a == this.player_name ? 2 : 1; | ||||
|         var FIELD_DRAW = 3 | ||||
|  | ||||
|         this.online_opponent = new Player(player_a == this.player_name ? player_b : player_a, 255,0,0); | ||||
|         this.local_player = new Player(this.player_name, 0,255,0); | ||||
|  | ||||
|         var i,j; | ||||
|         for(j = 0; j < 9; j++) | ||||
|         { | ||||
|             for(i = 0; i < 9; i++) | ||||
|             { | ||||
|                 var si = Math.floor(i / 3); | ||||
|                 var sj = Math.floor(j / 3); | ||||
|                 if (complete_field[j][i] == FIELD_USER) | ||||
|                 { | ||||
|                     this.grid.subgrids[sj][si].player_change_listener(this.local_player); | ||||
|                     this.grid.subgrids[sj][si].cells[j % 3][i % 3].on_click(); | ||||
|                 } | ||||
|                 if (complete_field[j][i] == FIELD_OPPONENT) | ||||
|                 { | ||||
|                     this.grid.subgrids[sj][si].player_change_listener(this.online_opponent); | ||||
|                     this.grid.subgrids[sj][si].cells[j % 3][i % 3].on_click(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this.grid.block_all(); | ||||
|         this.grid.register_click_callback((i,j,k,l) => this.click_listener(i,j,k,l)); | ||||
|  | ||||
|         if (game_over && player_won != null) | ||||
|         { | ||||
|             if (player_won == this.player_name) | ||||
|             { | ||||
|                 this.status_label.innerHTML = "Congratulation, you won!"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 this.status_label.innerHTML = "Game over, you lost!"; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         else if(game_over) | ||||
|         { | ||||
|             if (this.grid.is_complete()) | ||||
|             { | ||||
|                 this.status_label.innerHTML = "Draw. Everyone looses!"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 this.status_label.innerHTML = "Game was closed by server or opponent"; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var current_player = this.player_name == current_player_name ? this.local_player : this.online_opponent; | ||||
|         this.grid.player_change_listener(current_player); | ||||
|  | ||||
|          | ||||
|         if (this.player_name == current_player_name) | ||||
|         { | ||||
|              | ||||
|             if (this.match_state.last_move != null) | ||||
|             { | ||||
|                 if (this.grid.subgrids[y][x].is_won() || this.grid.subgrids[y][x].is_draw()) | ||||
|                 { | ||||
|                     this.grid.unblock_all_non_completed(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     this.grid.unblock(x,y); | ||||
|                 } | ||||
|                 this.status_label.innerHTML = "It's your turn!"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 this.grid.unblock_all(); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.status_label.innerHTML = "waiting for " + this.online_opponent.get_name() + "'s move"; | ||||
|         } | ||||
|  | ||||
|          | ||||
|  | ||||
|     } | ||||
| } | ||||
| @ -1,4 +1,6 @@ | ||||
| var server_protocol = "ws://" | ||||
| var server_url = "127.0.0.1"; | ||||
| var server_port = "5556"; | ||||
|  | ||||
| var home = "https://the-cake-is-a-lie.net/website/ultimate_tictactoe/"; | ||||
| var rel_home = "/website/ultimate_tictactoe"; | ||||
| var server_url = "the-cake-is-a-lie.net"; | ||||
| var server_port = "5555"; | ||||
							
								
								
									
										184
									
								
								sidebar.js
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								sidebar.js
									
									
									
									
									
								
							| @ -1,184 +0,0 @@ | ||||
| class Sidebar | ||||
| { | ||||
|     constructor(create_game_container, setting_container, control_container, info_container, game_manager) | ||||
|     { | ||||
|         this.create_game_container = create_game_container; | ||||
|         this.setting_container = setting_container; | ||||
|         this.control_container = control_container; | ||||
|         this.info_container = info_container; | ||||
|  | ||||
|         this.game_manager = game_manager; | ||||
|  | ||||
|         this.fill_containers(); | ||||
|         this.bind_events(); | ||||
|  | ||||
|         this.activate_create_game(); | ||||
|         this.activate_setting(); | ||||
|         this.activate_info(); | ||||
|     } | ||||
|  | ||||
|     create_button(text) | ||||
|     { | ||||
|         var b = document.createElement("button"); | ||||
|         b.className = "sidebar-button"; | ||||
|         b.appendChild(document.createTextNode(text)); | ||||
|         return b; | ||||
|     } | ||||
|  | ||||
|     create_input(text) | ||||
|     { | ||||
|         var i = document.createElement("input"); | ||||
|         i.className = "sidebar-input"; | ||||
|         i.type = "text"; | ||||
|         i.value = text; | ||||
|         return i; | ||||
|     } | ||||
|  | ||||
|     create_label(text) | ||||
|     { | ||||
|         var l = document.createElement("label"); | ||||
|         l.className = "sidebar-label"; | ||||
|         l.innerHTML = text; | ||||
|         return l; | ||||
|     } | ||||
|  | ||||
|     fill_containers() | ||||
|     { | ||||
|  | ||||
|         // create new game area: | ||||
|         this.create_game_container.appendChild(this.create_label("Choose game type")); | ||||
|         this.b_local = this.create_button("local game") | ||||
|         this.create_game_container.appendChild(this.b_local); | ||||
|  | ||||
|         this.b_remote = this.create_button("remote game"); | ||||
|         this.create_game_container.appendChild(this.b_remote); | ||||
|  | ||||
|         this.create_game_container.style.display = "none"; | ||||
|  | ||||
|  | ||||
|         // settings area | ||||
|         this.setting_container.appendChild(this.create_label("select online name:")); | ||||
|  | ||||
|         this.i_player_name = this.create_input(""); | ||||
|         this.setting_container.appendChild(this.i_player_name); | ||||
|  | ||||
|         this.setting_container.style.display = "none"; | ||||
|  | ||||
|         // control area: | ||||
|  | ||||
|         this.b_end_game = this.create_button("end game"); | ||||
|         this.control_container.appendChild(this.b_end_game); | ||||
|  | ||||
|         this.control_container.style.display = "none"; | ||||
|  | ||||
|  | ||||
|         // status area: | ||||
|         this.status_title = this.create_label(""); | ||||
|         this.info_container.appendChild(this.status_title); | ||||
|  | ||||
|         this.status_text = this.create_label("select gamemode. <br> <a href=https://en.wikipedia.org/wiki/Ultimate_tic-tac-toe#Rules>here are the rules </a>"); | ||||
|         this.info_container.appendChild(this.status_text); | ||||
|  | ||||
|         this.info_container.style.display = "none"; | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bind_events() | ||||
|     { | ||||
|         // TODO | ||||
|         this.game_manager.register_game_mode_change_listener((c) => this.game_mode_change_listener(c)); | ||||
|         this.game_manager.register_status_change_listener((c,t=null) => this.status_change_listener(c, t)); | ||||
|  | ||||
|         this.b_local.addEventListener("click", () => this.game_manager.start_local_game()); | ||||
|         this.b_end_game.addEventListener("click", () => this.game_manager.end_game(true)); | ||||
|         this.b_remote.addEventListener("click", () => this.game_manager.register_remote_game(this.get_player_name())); | ||||
|     } | ||||
|  | ||||
|     set_status(text) | ||||
|     { | ||||
|         this.status_text.innerHTML = text; | ||||
|     } | ||||
|  | ||||
|     get_player_name() | ||||
|     { | ||||
|         return this.i_player_name.value; | ||||
|     } | ||||
|  | ||||
|     activate_create_game() | ||||
|     { | ||||
|         this.create_game_container.style.display = "inline-block"; | ||||
|     } | ||||
|  | ||||
|     activate_setting() | ||||
|     { | ||||
|         this.setting_container.style.display = "inline-block"; | ||||
|     } | ||||
|  | ||||
|     activate_control() | ||||
|     { | ||||
|         this.control_container.style.display = "inline-block"; | ||||
|     } | ||||
|  | ||||
|     activate_info() | ||||
|     { | ||||
|         this.info_container.style.display = "inline-block"; | ||||
|     } | ||||
|  | ||||
|     deactivate_create_game() | ||||
|     { | ||||
|         this.create_game_container.style.display = "none"; | ||||
|     } | ||||
|  | ||||
|     deactivate_setting() | ||||
|     { | ||||
|         this.setting_container.style.display = "none"; | ||||
|     } | ||||
|  | ||||
|     deactivate_control() | ||||
|     { | ||||
|         this.control_container.style.display = "none"; | ||||
|     } | ||||
|  | ||||
|     deactivate_info() | ||||
|     { | ||||
|         this.info_container.style.display = "none"; | ||||
|     } | ||||
|  | ||||
|     game_mode_change_listener(gamemode) | ||||
|     { | ||||
|         if (gamemode == "none") | ||||
|         { | ||||
|             this.activate_create_game(); | ||||
|             this.activate_setting(); | ||||
|             this.deactivate_control(); | ||||
|             this.activate_info(); | ||||
|             return | ||||
|         } | ||||
|         if (gamemode == "local") | ||||
|         { | ||||
|             this.deactivate_create_game(); | ||||
|             this.deactivate_setting(); | ||||
|             this.activate_control(); | ||||
|             this.activate_info(); | ||||
|         } | ||||
|         if (gamemode == "remote") | ||||
|         { | ||||
|             this.deactivate_create_game(); | ||||
|             this.deactivate_setting(); | ||||
|             this.activate_control(); | ||||
|             this.activate_info(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     status_change_listener(statustext, title=null) | ||||
|     { | ||||
|         this.status_text.innerHTML = statustext; | ||||
|         if (title != null) | ||||
|         { | ||||
|             this.status_title.innerHTML = "<p>" + title + "</p>"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										271
									
								
								style.css
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								style.css
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ html, body { | ||||
|  | ||||
| body {  | ||||
|     margin: 0; | ||||
|     background: rgb(30, 36, 119) ; | ||||
|     background: rgb(49, 54, 74) ; | ||||
|     outline: 0; | ||||
|     position: relative; | ||||
| } | ||||
| @ -15,21 +15,36 @@ body { | ||||
|     --tile-size: calc((100vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin)); | ||||
|     --opacity: 1; | ||||
|     --border-radius: 1vh; | ||||
|     --sidebar-width: 25vh; | ||||
|     --ground-color: rgb(30, 36, 119) ; | ||||
|     --sidebar-width: 26vh; | ||||
|     --ground-color: rgb(41, 45, 62) ; | ||||
|     --board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin) ); | ||||
|     --sidebar-height: calc(var(--board-size) - 2 * var(--border-radius)); | ||||
| } | ||||
|  | ||||
| /* override settings on portrait mode: */ | ||||
| @media (orientation: portrait) { | ||||
| @media (max-aspect-ratio: 16/10) { | ||||
|  | ||||
|     :root{ | ||||
|         --button-margin: 0.35vh; | ||||
|         --tile-size: calc(((70vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin))); | ||||
|         --border-radius: 0.7vh; | ||||
|         --sidebar-width: 18.2vh; | ||||
|         --board-size: calc((var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin))); | ||||
|         --sidebar-height: calc(var(--board-size) - 2 * var(--border-radius)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /* override settings on portrait mode: */ | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     :root{ | ||||
|         --button-margin: 0.5vw; | ||||
|         --tile-size: calc((100vw / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin)); | ||||
|         --tile-size: calc(((100vw / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin))); | ||||
|         --border-radius: 1vw; | ||||
|         --board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin) ); | ||||
|         --sidebar-width: calc(var(--board-size) - 2 * var(--border-radius)); | ||||
|         --sidebar-height: 15vw; | ||||
|         --sidebar-height: 25vw; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -51,11 +66,11 @@ a:visited { | ||||
| } | ||||
|  | ||||
| /* override settings on portrait mode: */ | ||||
| @media (orientation: portrait) { | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .main-container { | ||||
|         white-space: normal; | ||||
|         padding-top: calc(50vh - 0.5 * var(--board-size)); | ||||
|         padding-top: 0; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -114,11 +129,11 @@ a:visited { | ||||
|     transition-duration: 0.5s; | ||||
| } | ||||
|  | ||||
| .sidebar-container { | ||||
| .infobar-container { | ||||
|     border-radius: var(--border-radius); | ||||
|     padding: var(--border-radius); | ||||
|     vertical-align: top; | ||||
|     background: rgba(255, 255, 255, 0.05); | ||||
|     background: none; | ||||
|     display: inline-flex; | ||||
|     justify-content: space-between; | ||||
|     flex-direction:column; | ||||
| @ -129,44 +144,17 @@ a:visited { | ||||
| } | ||||
|  | ||||
| /* override settings on portrait mode: */ | ||||
| @media (orientation: portrait) { | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .sidebar-container { | ||||
|     .infobar-container { | ||||
|         flex-direction:row; | ||||
|         padding: none; | ||||
|         min-height: var(--sidebar-height); | ||||
|         height: calc((100vh - var(--board-size)) * 0.5 - 2* var(--border-radius)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| .create-game-container { | ||||
|     border-radius: var(--border-radius); | ||||
|     padding: var(--border-radius); | ||||
|     top: 0; | ||||
|     background: none; | ||||
|     display: inline-block; | ||||
|     vertical-align: middle; | ||||
| } | ||||
|  | ||||
|  | ||||
| .control-container { | ||||
|     border-radius: var(--border-radius); | ||||
|     padding: var(--border-radius); | ||||
|     top: 0; | ||||
|     background: none; | ||||
|     display: inline-block; | ||||
|     vertical-align: middle; | ||||
| } | ||||
|  | ||||
|  | ||||
| .setting-container { | ||||
|     border-radius: var(--border-radius); | ||||
|     padding: var(--border-radius); | ||||
|     top: 0; | ||||
|     background: none; | ||||
|     display: inline-block; | ||||
|     vertical-align: middle; | ||||
| } | ||||
|  | ||||
| .info-container { | ||||
|     border-radius: var(--border-radius); | ||||
|     padding: var(--border-radius); | ||||
| @ -176,78 +164,183 @@ a:visited { | ||||
|     text-align: center; | ||||
|     background: none; | ||||
|     white-space: normal; | ||||
|     overflow-y: scroll; | ||||
| } | ||||
|  | ||||
| .sidebar-label { | ||||
|     color: white; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .info-container{ | ||||
|         width: calc(0.3 * var(--sidebar-width)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .infobar-label { | ||||
|     color: rgba(224, 217, 235, 0.8); | ||||
|     font-size: calc(2 * var(--border-radius)); | ||||
|     width: calc(var(--sidebar-width) - 4 * var(--border-radius)); | ||||
|     text-align: left; | ||||
| } | ||||
|  | ||||
| @media (orientation: portrait) { | ||||
|     .sidebar-label | ||||
|     { | ||||
|         width: calc(var(--sidebar-width) * 0.3); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .sidebar-button { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(0, 0, 0, 0.5); | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(3 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     width: calc(var(--sidebar-width) - 4 * var(--border-radius)); | ||||
|     vertical-align: middle; | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     text-align: center; | ||||
|  | ||||
| } | ||||
|  | ||||
| @media (orientation: portrait) { | ||||
|  | ||||
|     .sidebar-button{ | ||||
|         width: calc(0.25 * var(--sidebar-width)); | ||||
|         height: calc(0.3 * var(--sidebar-height)); | ||||
|     } | ||||
| .option-button-container | ||||
| { | ||||
|     border-radius: 0%; | ||||
|     margin: 0%; | ||||
|     top: 0%; | ||||
|     display: flex; | ||||
|     flex-direction:row; | ||||
|     padding: none; | ||||
| } | ||||
|  | ||||
|  | ||||
| .sidebar-button:hover { | ||||
|     background: rgba(255, 255, 255, 0.2); | ||||
| } | ||||
|  | ||||
| .sidebar-button:active { | ||||
|     background: rgba(255, 255, 255, 0.4); | ||||
| } | ||||
|  | ||||
| .sidebar-input { | ||||
| .infobar-button { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(0, 0, 0, 0.5); | ||||
|     background: rgba(126,87,194, 0.2) ; | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(3 * var(--border-radius)); | ||||
|     font-size: calc(2.8 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     width: calc(var(--sidebar-width) - 4 * var(--border-radius)); | ||||
|     vertical-align: middle; | ||||
|     /* width: calc(var(--sidebar-width) - 4 * var(--border-radius)); */ | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     vertical-align: middle; | ||||
|     flex-direction: column; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| @media (orientation: portrait) { | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .sidebar-input{ | ||||
|         height: calc(0.3 * var(--sidebar-height)); | ||||
|         width: calc(0.25 * var(--sidebar-width)); | ||||
|     .infobar-button{ | ||||
|         height: calc(0.18 * var(--sidebar-height)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .infobar-button-green { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(0, 255, 0, 0.2); | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(2.8 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     vertical-align: middle; | ||||
|     flex-direction: column; | ||||
| } | ||||
|  | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .infobar-button-green{ | ||||
|         height: calc(0.18 * var(--sidebar-height)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .infobar-button-red { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(255, 0, 0, 0.2); | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(2.8 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     vertical-align: middle; | ||||
|     flex-direction: column; | ||||
| } | ||||
|  | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .infobar-button-red{ | ||||
|         height: calc(0.18 * var(--sidebar-height)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| .infobar-button-active { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(126,87,194, 0.8) ; | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(2.8 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     vertical-align: middle; | ||||
|     flex-direction: column; | ||||
| } | ||||
|  | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .infobar-button-active{ | ||||
|         height: calc(0.18 * var(--sidebar-height)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| .infobar-button:hover { | ||||
|     background: rgba(126,87,194, 0.5); | ||||
| } | ||||
|  | ||||
| .infobar-button:active { | ||||
|     background: rgba(126,87,194, 0.8); | ||||
| } | ||||
|  | ||||
| .infobar-button:disabled { | ||||
|     background: rgba(0, 0, 0, 0.1); | ||||
|     color: rgb(64,64,64); | ||||
| } | ||||
|  | ||||
| .infobar-input { | ||||
|     border-radius: var(--border-radius); | ||||
|     margin: var(--border-radius); | ||||
|     border: none; | ||||
|     outline: 0; | ||||
|     transition-duration: 0.3s; | ||||
|     background: rgba(126,87,194, 0.2); | ||||
|     color: rgb(255, 255, 255); | ||||
|     font-size: calc(3 * var(--border-radius)); | ||||
|     height: calc(4 * var(--border-radius)); | ||||
|     margin-left: 0; | ||||
|     margin-right: 0; | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     vertical-align: middle; | ||||
|     flex-direction: column; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| .infobar-input::placeholder { | ||||
|     color: rgba(255,255,255,0.3); | ||||
| } | ||||
|  | ||||
| @media (max-aspect-ratio: 1/1) { | ||||
|  | ||||
|     .infobar-input{ | ||||
|         height: calc(0.18 * var(--sidebar-height)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								sw.js
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								sw.js
									
									
									
									
									
								
							| @ -1,18 +1,24 @@ | ||||
|  | ||||
| self.addEventListener('install', function(e) { | ||||
| var home = "https://the-cake-is-a-lie.net/website/ultimate_tictactoe/"; | ||||
| var rel_home = "/website/ultimate_tictactoe"; | ||||
|  | ||||
| self.addEventListener('install', function (e) { | ||||
|   e.waitUntil( | ||||
|       caches.open('your-magic-cache').then(function(cache) { | ||||
|     caches.open('your-magic-cache').then(function (cache) { | ||||
|       return cache.addAll([ | ||||
|         '/website/ultimate_tictactoe/', | ||||
|         '/website/ultimate_tictactoe/tools.js', | ||||
|         '/website/ultimate_tictactoe/index.html', | ||||
|         '/website/ultimate_tictactoe/manifest.json', | ||||
|         '/website/ultimate_tictactoe/icon.png', | ||||
|         '/website/ultimate_tictactoe/LICENSE', | ||||
|         '/website/ultimate_tictactoe/main.js', | ||||
|         '/website/ultimate_tictactoe/grid.js', | ||||
|           '/website/ultimate_tictactoe/game_manager.js', | ||||
|           '/website/ultimate_tictactoe/game_server_connection.js', | ||||
|           '/website/ultimate_tictactoe/sidebar.js', | ||||
|         '/website/ultimate_tictactoe/local_match_manager.js', | ||||
|         '/website/ultimate_tictactoe/online_match_manager.js', | ||||
|         '/website/ultimate_tictactoe/websocket_connection.js', | ||||
|         '/website/ultimate_tictactoe/infobar.js', | ||||
|         '/website/ultimate_tictactoe/infocontainer.js', | ||||
|         '/website/ultimate_tictactoe/settings.js', | ||||
|         '/website/ultimate_tictactoe/subgrid.js', | ||||
|         '/website/ultimate_tictactoe/tile.js', | ||||
| @ -22,16 +28,17 @@ self.addEventListener('install', function(e) { | ||||
|       ]); | ||||
|     }) | ||||
|   ); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
|   self.addEventListener('fetch', function(event) { | ||||
| self.addEventListener('fetch', function (event) { | ||||
|   event.respondWith( | ||||
|       caches.match(event.request).then(function(response) { | ||||
|     caches.match(event.request).then(function (response) { | ||||
|       return response || fetch(event.request); | ||||
|     }) | ||||
|   ); | ||||
| }); | ||||
|  | ||||
| self.addEventListener('notificationclick', function (event) { | ||||
|     console.log ("push message clicked"); | ||||
|   event.notification.close(); | ||||
|   clients.openWindow(home); | ||||
| }); | ||||
							
								
								
									
										13
									
								
								tools.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tools.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
|    | ||||
| function clear(node) { | ||||
|     while (node.hasChildNodes()) { | ||||
|         clear(node.firstChild); | ||||
|     } | ||||
|     node.parentNode.removeChild(node); | ||||
| } | ||||
|  | ||||
| function clearInner(node) { | ||||
|     while (node.hasChildNodes()) { | ||||
|         clear(node.firstChild); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										519
									
								
								websocket_connection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										519
									
								
								websocket_connection.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,519 @@ | ||||
| class WebsocketConnection | ||||
| { | ||||
|     constructor(ip, port, grid, status_label, matches_container, control_container, search_container, login_callback_func, error_callback_func) | ||||
|     { | ||||
|         this.ip = ip; | ||||
|         this.port = port; | ||||
|         this.session_id = null; | ||||
|         this.player = new Player("player", 128, 0,0); | ||||
|         this.socket = null; | ||||
|         this.registered = false; | ||||
|  | ||||
|         this.grid = grid; | ||||
|         this.status_label = status_label; | ||||
|         this.matches_container = matches_container; | ||||
|         this.control_container = control_container; | ||||
|         this.search_container  = search_container; | ||||
|  | ||||
|         this.active_match = null; | ||||
|  | ||||
|         this.connected = false; | ||||
|  | ||||
|         this.current_end_button = null; | ||||
|  | ||||
|         this.login_callback_func = login_callback_func; | ||||
|  | ||||
|         this.openmatches = {}; | ||||
|         this.error_callback_func = error_callback_func; | ||||
|  | ||||
|         this.closed_by_user = false; | ||||
|  | ||||
|  | ||||
|         this.friends = []; | ||||
|  | ||||
|         this.friend_name_divs = []; | ||||
|  | ||||
|         matches_container.hide(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     set_player(p) | ||||
|     { | ||||
|         this.player = p; | ||||
|     } | ||||
|  | ||||
|     set_game_manager(gm) | ||||
|     { | ||||
|         this.game_manager = gm; | ||||
|     } | ||||
|  | ||||
|     is_registered() | ||||
|     { | ||||
|         return this.registered; | ||||
|     } | ||||
|  | ||||
|     is_connected() | ||||
|     { | ||||
|         return this.connected; | ||||
|     } | ||||
|  | ||||
|     is_friend(friend) | ||||
|     { | ||||
|         return this.friends.includes(friend); | ||||
|     } | ||||
|  | ||||
|     on_open(username, pw) | ||||
|     { | ||||
|  | ||||
|         this.connected = true; | ||||
|         this.login(username, pw) | ||||
|     } | ||||
|  | ||||
|     on_reopen(session_id) | ||||
|     { | ||||
|  | ||||
|         this.connected = true; | ||||
|         this.relogin(session_id); | ||||
|     } | ||||
|  | ||||
|     on_close(login_failed=false) | ||||
|     { | ||||
|         for (var key in this.openmatches) | ||||
|         { | ||||
|             this.openmatches[key].remove_match(); | ||||
|         } | ||||
|         this.openmatches = {}; | ||||
|          | ||||
|         // remove complete friend list: | ||||
|         var n = this.friend_name_divs.length; | ||||
|  | ||||
|         var i; | ||||
|  | ||||
|         for (i = 0; i < n; i++) | ||||
|         { | ||||
|             clearInner(this.friend_name_divs[i]); | ||||
|             this.search_container.container.removeChild(this.friend_name_divs[i]); | ||||
|             this.friend_name_divs[i] = null; | ||||
|         } | ||||
|         this.friend_name_divs = []; | ||||
|         this.friends = []; | ||||
|  | ||||
|         var login_failed = !this.registered; | ||||
|         this.registered = false; | ||||
|         this.connected = false; | ||||
|         if (!this.closed_by_user && !login_failed) | ||||
|         { | ||||
|             this.status_label.innerHTML = "connection to server closed"; | ||||
|             this.error_callback_func(); | ||||
|         } | ||||
|          | ||||
|     } | ||||
|  | ||||
|     on_error() | ||||
|     { | ||||
|         for (var key in this.openmatches) | ||||
|         { | ||||
|             this.openmatches[key].remove_match(); | ||||
|         } | ||||
|         this.openmatches = {}; | ||||
|  | ||||
|         // remove complete friend list: | ||||
|         var n = this.friend_name_divs.length; | ||||
|  | ||||
|         var i; | ||||
|  | ||||
|         for (i = 0; i < n; i++) | ||||
|         { | ||||
|             clearInner(this.friend_name_divs[i]); | ||||
|             this.search_container.container.removeChild(this.friend_name_divs[i]); | ||||
|             this.friend_name_divs[i] = null; | ||||
|         } | ||||
|         this.friend_name_divs = []; | ||||
|         this.friends = []; | ||||
|  | ||||
|         console.log("error in websocket connection"); | ||||
|         this.registered = false; | ||||
|         this.connected = false; | ||||
|         if (!this.closed_by_user) | ||||
|         { | ||||
|             this.status_label.innerHTML = "connection to server lost"; | ||||
|             this.error_callback_func(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|      | ||||
|     on_message(event) | ||||
|     { | ||||
|         var json_msg = event.data; | ||||
|         var msg = JSON.parse(json_msg); | ||||
|  | ||||
|         if (!msg.hasOwnProperty("type") || !msg.hasOwnProperty("data")) | ||||
|         { | ||||
|             console.log("received wrong formatted message"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         console.log("raw_msg: " + json_msg); | ||||
|  | ||||
|         switch(msg.type) | ||||
|         { | ||||
|             case "login_response": | ||||
|                 this.on_register_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "reconnect_response": | ||||
|                 this.on_reconnect_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "match_update": | ||||
|                 this.on_match_update(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "match_request_response": | ||||
|                 this.on_match_request_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "friend_request_response": | ||||
|                 this.on_friend_request_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "unfriend_request_response": | ||||
|                 this.on_unfriend_request_response(msg.data); | ||||
|                 break; | ||||
|              | ||||
|             case "friends_update": | ||||
|                 this.on_friends_update(msg.data); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     set_active_match(id) | ||||
|     { | ||||
|         for (var key in this.openmatches) | ||||
|         { | ||||
|             if (key == id) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             this.openmatches[key].on_focus_loose(); | ||||
|         } | ||||
|         this.active_match = id; | ||||
|     } | ||||
|  | ||||
|     on_close_click() | ||||
|     { | ||||
|         if (this.active_match != null && (this.active_match in this.openmatches)) | ||||
|         { | ||||
|             this.openmatches[this.active_match].on_user_close(); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (this.current_end_button != null) | ||||
|         { | ||||
|             this.control_container.container.deleteChild(this.current_end_button); | ||||
|             this.current_end_button = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     on_match_update(data) | ||||
|     { | ||||
|         var id = data.id | ||||
|         var match_state = data.match_state; | ||||
|  | ||||
|         if (match_state == null) | ||||
|         { | ||||
|             // checking whether we can delete our dict object | ||||
|             if (id in this.openmatches) | ||||
|             { | ||||
|                 delete this.openmatches[id]; | ||||
|                 if (this.active_match == id) | ||||
|                 { | ||||
|                     if (this.current_end_button != null) | ||||
|                     { | ||||
|                         this.control_container.container.deleteChild(this.current_end_button); | ||||
|                         this.current_end_button = null; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (id in this.openmatches) | ||||
|             { | ||||
|                 this.openmatches[id].update_match_state(match_state) | ||||
|                 if (this.active_match == id) | ||||
|                 { | ||||
|                     this.openmatches[id].open_match(); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (!match_state.game_over) | ||||
|                 { | ||||
|                     this.openmatches[id] = new OnlineMatchManager(this.grid, this.status_label, this.matches_container, this.control_container, this, id, match_state, this.player.get_name()); | ||||
|                     if (match_state.last_move == null) | ||||
|                     { | ||||
|                         this.notify("new Game against " + this.openmatches[id].online_opponent.get_name()); | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     on_register_response(data) | ||||
|     { | ||||
|         if (data.success) | ||||
|         { | ||||
|             this.registered = true; | ||||
|             this.session_id = data.id; | ||||
|             this.login_callback_func(); | ||||
|         } | ||||
|         this.status_label.innerHTML = data.msg; | ||||
|          | ||||
|     } | ||||
|  | ||||
|     on_reconnect_response(data) | ||||
|     { | ||||
|         if (data.success) | ||||
|         { | ||||
|             this.registered = true; | ||||
|             this.session_id = data.id; | ||||
|             this.player.set_name(data.user); | ||||
|             this.login_callback_func(); | ||||
|         } | ||||
|  | ||||
|         this.status_label.innerHTML = data.msg; | ||||
|     } | ||||
|  | ||||
|     on_match_request_response(data) | ||||
|     { | ||||
|         if (data.success) | ||||
|         { | ||||
|             this.status_label.innerHTML = "match request sent"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             this.status_label.innerHTML = "could not send request: " + data.msg; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     on_friend_request_response(data) | ||||
|     { | ||||
|         this.status_label.innerHTML = data.msg; | ||||
|     } | ||||
|  | ||||
|     on_unfriend_request_response(data) | ||||
|     { | ||||
|         this.status_label.innerHTML = data.msg; | ||||
|     } | ||||
|  | ||||
|     on_friends_update(data) | ||||
|     { | ||||
|         this.friends = data.friends; | ||||
|  | ||||
|         // remove complete friend list: | ||||
|         var n = this.friend_name_divs.length; | ||||
|  | ||||
|         var i; | ||||
|  | ||||
|         for (i = 0; i < n; i++) | ||||
|         { | ||||
|             clearInner(this.friend_name_divs[i]); | ||||
|             this.search_container.container.removeChild(this.friend_name_divs[i]); | ||||
|             this.friend_name_divs[i] = null; | ||||
|         } | ||||
|         this.friend_name_divs = []; | ||||
|         // rebuild friend list: | ||||
|         n = this.friends.length; | ||||
|          | ||||
|         for (i = 0; i < n; i++) | ||||
|         { | ||||
|             var tmp = this.search_container.create_double_button("" + this.friends[i], "-"); | ||||
|  | ||||
|             tmp[1].name = this.friends[i]; | ||||
|             tmp[2].name = this.friends[i]; | ||||
|             tmp[1].connection = this; | ||||
|             tmp[2].connection = this; | ||||
|              | ||||
|              | ||||
|             tmp[1].addEventListener("click", function() { | ||||
|                 this.connection.send_match_request(this.name); | ||||
|             }); | ||||
|  | ||||
|             tmp[2].addEventListener("click", function (){ | ||||
|                 this.connection.send_unfriend_request(this.name); | ||||
|             }); | ||||
|  | ||||
|             this.friend_name_divs.push(tmp[0]) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     connect(username, pw) | ||||
|     { | ||||
|         this.socket = new WebSocket(server_protocol + this.ip + ":" + this.port); | ||||
|         this.socket.onmessage = (e => this.on_message(e)); | ||||
|         this.socket.onopen = (() => this.on_open(username, pw)); | ||||
|         this.socket.onerror = (() => this.on_error()); | ||||
|         this.socket.onclose = (() => this.on_close()); | ||||
|     } | ||||
|  | ||||
|     reconnect(session_id) | ||||
|     { | ||||
|         for (var key in this.openmatches) | ||||
|         { | ||||
|             this.openmatches[key].remove_match(); | ||||
|         } | ||||
|         this.openmatches = {}; | ||||
|         this.socket = new WebSocket(server_protocol + this.ip + ":" + this.port); | ||||
|         this.socket.onmessage = (e => this.on_message(e)); | ||||
|         this.socket.onopen = (() => this.on_reopen(session_id)); | ||||
|         this.socket.onerror = (() => this.on_error()); | ||||
|         this.socket.onclose = (() => this.on_close()); | ||||
|     } | ||||
|  | ||||
|     send_move(sub_x, sub_y, x, y, match_id) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "move", | ||||
|             data: { | ||||
|                 id: match_id, | ||||
|                 sub_x: "" + sub_x, | ||||
|                 sub_y: "" + sub_y, | ||||
|                 x: "" + x, | ||||
|                 y: "" + y | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     send_end_match(match_id) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "end_match", | ||||
|             data: { | ||||
|                 id: match_id, | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     send_match_request(player_name) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "match_request", | ||||
|             data: { | ||||
|                 player: player_name | ||||
|             } | ||||
|         }; | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     send_friend_request(friend_name) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "friend_request", | ||||
|             data: { | ||||
|                 user: friend_name | ||||
|             } | ||||
|         }; | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     send_unfriend_request(friend_name) | ||||
|     { | ||||
|         var msg_object = { | ||||
|             type: "unfriend_request", | ||||
|             data: { | ||||
|                 user: friend_name | ||||
|             } | ||||
|         }; | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     login(username, pw) | ||||
|     { | ||||
|         this.player.set_name(username); | ||||
|         // register for game queue | ||||
|         var msg_object = { | ||||
|             type: "login", | ||||
|             data: { | ||||
|                 name: this.player.get_name(), | ||||
|                 pw: pw | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     relogin(session_id) | ||||
|     { | ||||
|         for (var key in this.openmatches) | ||||
|         { | ||||
|             this.openmatches[key].remove_match(); | ||||
|         } | ||||
|         // register for game queue | ||||
|         var msg_object = { | ||||
|             type: "reconnect", | ||||
|             data: { | ||||
|                 id: session_id | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     send_disconnect() | ||||
|     { | ||||
|         if (!this.is_connected) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         var msg_object = { | ||||
|             type: "end_game", | ||||
|             data: { | ||||
|                 msg: "" | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         this.socket.send(JSON.stringify(msg_object)); | ||||
|     } | ||||
|  | ||||
|     close() | ||||
|     { | ||||
|         this.status_label.innerHTML = "logged out"; | ||||
|         this.closed_by_user = true; | ||||
|         this.socket.close(); | ||||
|     } | ||||
|  | ||||
|     notify(text) { | ||||
|  | ||||
|         if (document.hasFocus()) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|          | ||||
|         Notification.requestPermission(function(result) { | ||||
|             if (result === 'granted') { | ||||
|                 navigator.serviceWorker.ready.then(function(registration) { | ||||
|                 registration.showNotification(text, { | ||||
|                         icon: './icon.png', | ||||
|                         vibrate: [200, 200], | ||||
|                         tag: "tictactoe-notification" | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|        | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user