Set up basic WebSocket frontend
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,3 @@ | |||||||
|  | assets/main.js | ||||||
|  | dist | ||||||
|  | node_modules | ||||||
							
								
								
									
										39
									
								
								assets/game.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,39 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html style="height:100%"> | ||||||
|  |   <head> | ||||||
|  |     <link rel="manifest" href="manifest.json" /> | ||||||
|  |     <link rel="icon" href="images/logo96.png" type="image/png" /> | ||||||
|  |     <title>Blastmud</title> | ||||||
|  |     <style> | ||||||
|  |       .button { | ||||||
|  |           border: solid black 1px; | ||||||
|  |           padding: 5px; | ||||||
|  |           cursor: pointer; | ||||||
|  |           text-decoration: none; | ||||||
|  |           border-radius: 10px; | ||||||
|  |           color: white; | ||||||
|  |           background: grey; | ||||||
|  |       } | ||||||
|  |     </style> | ||||||
|  |     <link rel="stylesheet" href="xterm.css" /> | ||||||
|  |     <script src="xterm.js"></script> | ||||||
|  |   </head> | ||||||
|  |   <body style="background: black; height: 100%"> | ||||||
|  |     <div style="background: black; color: white; display: flex; flex-direction: column; margin: 0px; height: 100%; width: 100%"> | ||||||
|  |       <h1 style="text-align: center">Play Blastmud</h1> | ||||||
|  |       <div id="console" style="flex: 1"> </div> | ||||||
|  |     </div> | ||||||
|  |     <div id="over18" style="position: absolute; top: 0; left: 0; background: rgba(80,80,80,0.8); width: 100%; height: 100%"> | ||||||
|  |       <div style="display: block; padding: 10px; background: white; width: 80%; margin-left: auto; margin-right: auto; margin-top: 10%; border-radius: 10px;"> | ||||||
|  |         <h1>You must be 18+ to play Blastmud</h1> | ||||||
|  |         <p>This game is restricted to adults (18 years or above). It contains violence, | ||||||
|  |           sex scenes, and online interactions with other adults.</p> | ||||||
|  |         <div style="text-align: right"> | ||||||
|  |           <a class="button" href="https://google.com/">I'm under 18</a> | ||||||
|  |           <a class="button" href="#" onclick="over18();">I'm 18 or over</a> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </body> | ||||||
|  |   <script src="main.js"></script> | ||||||
|  | </html> | ||||||
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo144.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo168.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo48.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo72.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/images/logo96.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										38
									
								
								assets/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,38 @@ | |||||||
|  | { | ||||||
|  |   "$schema": "https://json.schemastore.org/web-manifest-combined.json", | ||||||
|  |   "name": "BlastMud", | ||||||
|  |   "short_name": "BlastMud", | ||||||
|  |   "start_url": ".", | ||||||
|  |   "display": "standalone", | ||||||
|  |   "background_color": "#000", | ||||||
|  |   "description": "A post-apocalyptic multi user dungeon game", | ||||||
|  |   "icons": [{ | ||||||
|  |     "src": "images/logo48.png", | ||||||
|  |     "sizes": "48x48", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }, { | ||||||
|  |     "src": "images/logo72.png", | ||||||
|  |     "sizes": "72x72", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }, { | ||||||
|  |     "src": "images/logo96.png", | ||||||
|  |     "sizes": "96x96", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }, { | ||||||
|  |     "src": "images/logo144.png", | ||||||
|  |     "sizes": "144x144", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }, { | ||||||
|  |     "src": "images/logo168.png", | ||||||
|  |     "sizes": "168x168", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }, { | ||||||
|  |     "src": "images/logo192.png", | ||||||
|  |     "sizes": "192x192", | ||||||
|  |     "type": "image/png" | ||||||
|  |   }], | ||||||
|  |   "related_applications": [{ | ||||||
|  |     "platform": "play", | ||||||
|  |     "url": "https://play.google.com/store/apps/details?id=org.blastmud.game" | ||||||
|  |   }] | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								assets/offline.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,9 @@ | |||||||
|  | <html> | ||||||
|  |   <body> | ||||||
|  |     <h1>You're offline</h1> | ||||||
|  |     <p>This app only works when you are online. | ||||||
|  |       Check your network connection and try again. | ||||||
|  |       If your network connection is okay, our servers might be | ||||||
|  |       under maintenance - try again later.</p> | ||||||
|  |   </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										60
									
								
								assets/service-worker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,60 @@ | |||||||
|  | /* | ||||||
|  | Copyright 2015, 2019 Google Inc. All Rights Reserved. | ||||||
|  |  Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |  you may not use this file except in compliance with the License. | ||||||
|  |  You may obtain a copy of the License at | ||||||
|  |  http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  |  Unless required by applicable law or agreed to in writing, software | ||||||
|  |  distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  See the License for the specific language governing permissions and | ||||||
|  |  limitations under the License. | ||||||
|  | */ | ||||||
|  | const OFFLINE_VERSION = 1; | ||||||
|  | const CACHE_NAME = 'offline'; | ||||||
|  | const OFFLINE_URL = 'offline.html'; | ||||||
|  | self.addEventListener('install', (event) => { | ||||||
|  |   event.waitUntil((async () => { | ||||||
|  |     const cache = await caches.open(CACHE_NAME); | ||||||
|  |     await cache.add(new Request(OFFLINE_URL, {cache: 'reload'})); | ||||||
|  |   })()); | ||||||
|  | }); | ||||||
|  | self.addEventListener('activate', (event) => { | ||||||
|  |   event.waitUntil((async () => { | ||||||
|  |     // Enable navigation preload if it's supported.
 | ||||||
|  |     // See https://developers.google.com/web/updates/2017/02/navigation-preload
 | ||||||
|  |     if ('navigationPreload' in self.registration) { | ||||||
|  |       await self.registration.navigationPreload.enable(); | ||||||
|  |     } | ||||||
|  |   })()); | ||||||
|  |   // Tell the active service worker to take control of the page immediately.
 | ||||||
|  |   self.clients.claim(); | ||||||
|  | }); | ||||||
|  | self.addEventListener('fetch', (event) => { | ||||||
|  |   // We only want to call event.respondWith() if this is a navigation request
 | ||||||
|  |   // for an HTML page.
 | ||||||
|  |   if (event.request.mode === 'navigate') { | ||||||
|  |     event.respondWith((async () => { | ||||||
|  |       try { | ||||||
|  |         // First, try to use the navigation preload response if it's supported.
 | ||||||
|  |         const preloadResponse = await event.preloadResponse; | ||||||
|  |         if (preloadResponse && preloadResponse.type !== 'error') { | ||||||
|  |           return preloadResponse; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const networkResponse = await fetch(event.request); | ||||||
|  |         return networkResponse; | ||||||
|  |       } catch (error) { | ||||||
|  |         // catch is only triggered if an exception is thrown, which is likely
 | ||||||
|  |         // due to a network error.
 | ||||||
|  |         // If fetch() returns a valid HTTP response with a response code in
 | ||||||
|  |         // the 4xx or 5xx range, the catch() will NOT be called.
 | ||||||
|  |         console.log('Fetch failed; returning offline page instead.', error); | ||||||
|  | 
 | ||||||
|  |         const cache = await caches.open(CACHE_NAME); | ||||||
|  |         const cachedResponse = await cache.match(OFFLINE_URL); | ||||||
|  |         return cachedResponse; | ||||||
|  |       } | ||||||
|  |     })()); | ||||||
|  |   } | ||||||
|  | }); | ||||||
							
								
								
									
										191
									
								
								assets/xterm.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,191 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright (c) 2014 The xterm.js authors. All rights reserved. | ||||||
|  |  * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) | ||||||
|  |  * https://github.com/chjj/term.js | ||||||
|  |  * @license MIT | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * Originally forked from (with the author's permission): | ||||||
|  |  *   Fabrice Bellard's javascript vt100 for jslinux: | ||||||
|  |  *   http://bellard.org/jslinux/ | ||||||
|  |  *   Copyright (c) 2011 Fabrice Bellard | ||||||
|  |  *   The original design remains. The terminal itself | ||||||
|  |  *   has been extended to include xterm CSI codes, among | ||||||
|  |  *   other features. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  *  Default styles for xterm.js | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | .xterm { | ||||||
|  |     cursor: text; | ||||||
|  |     position: relative; | ||||||
|  |     user-select: none; | ||||||
|  |     -ms-user-select: none; | ||||||
|  |     -webkit-user-select: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm.focus, | ||||||
|  | .xterm:focus { | ||||||
|  |     outline: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-helpers { | ||||||
|  |     position: absolute; | ||||||
|  |     top: 0; | ||||||
|  |     /** | ||||||
|  |      * The z-index of the helpers must be higher than the canvases in order for | ||||||
|  |      * IMEs to appear on top. | ||||||
|  |      */ | ||||||
|  |     z-index: 5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-helper-textarea { | ||||||
|  |     padding: 0; | ||||||
|  |     border: 0; | ||||||
|  |     margin: 0; | ||||||
|  |     /* Move textarea out of the screen to the far left, so that the cursor is not visible */ | ||||||
|  |     position: absolute; | ||||||
|  |     opacity: 0; | ||||||
|  |     left: -9999em; | ||||||
|  |     top: 0; | ||||||
|  |     width: 0; | ||||||
|  |     height: 0; | ||||||
|  |     z-index: -5; | ||||||
|  |     /** Prevent wrapping so the IME appears against the textarea at the correct position */ | ||||||
|  |     white-space: nowrap; | ||||||
|  |     overflow: hidden; | ||||||
|  |     resize: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .composition-view { | ||||||
|  |     /* TODO: Composition position got messed up somewhere */ | ||||||
|  |     background: #000; | ||||||
|  |     color: #FFF; | ||||||
|  |     display: none; | ||||||
|  |     position: absolute; | ||||||
|  |     white-space: nowrap; | ||||||
|  |     z-index: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .composition-view.active { | ||||||
|  |     display: block; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-viewport { | ||||||
|  |     /* On OS X this is required in order for the scroll bar to appear fully opaque */ | ||||||
|  |     background-color: #000; | ||||||
|  |     overflow-y: scroll; | ||||||
|  |     cursor: default; | ||||||
|  |     position: absolute; | ||||||
|  |     right: 0; | ||||||
|  |     left: 0; | ||||||
|  |     top: 0; | ||||||
|  |     bottom: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-screen { | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-screen canvas { | ||||||
|  |     position: absolute; | ||||||
|  |     left: 0; | ||||||
|  |     top: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-scroll-area { | ||||||
|  |     visibility: hidden; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-char-measure-element { | ||||||
|  |     display: inline-block; | ||||||
|  |     visibility: hidden; | ||||||
|  |     position: absolute; | ||||||
|  |     top: 0; | ||||||
|  |     left: -9999em; | ||||||
|  |     line-height: normal; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm.enable-mouse-events { | ||||||
|  |     /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ | ||||||
|  |     cursor: default; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm.xterm-cursor-pointer, | ||||||
|  | .xterm .xterm-cursor-pointer { | ||||||
|  |     cursor: pointer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm.column-select.focus { | ||||||
|  |     /* Column selection mode */ | ||||||
|  |     cursor: crosshair; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .xterm-accessibility, | ||||||
|  | .xterm .xterm-message { | ||||||
|  |     position: absolute; | ||||||
|  |     left: 0; | ||||||
|  |     top: 0; | ||||||
|  |     bottom: 0; | ||||||
|  |     z-index: 10; | ||||||
|  |     color: transparent; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm .live-region { | ||||||
|  |     position: absolute; | ||||||
|  |     left: -9999px; | ||||||
|  |     width: 1px; | ||||||
|  |     height: 1px; | ||||||
|  |     overflow: hidden; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-dim { | ||||||
|  |     opacity: 0.5; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-underline-1 { text-decoration: underline; } | ||||||
|  | .xterm-underline-2 { text-decoration: double underline; } | ||||||
|  | .xterm-underline-3 { text-decoration: wavy underline; } | ||||||
|  | .xterm-underline-4 { text-decoration: dotted underline; } | ||||||
|  | .xterm-underline-5 { text-decoration: dashed underline; } | ||||||
|  | 
 | ||||||
|  | .xterm-strikethrough { | ||||||
|  |     text-decoration: line-through; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-screen .xterm-decoration-container .xterm-decoration { | ||||||
|  | 	z-index: 6; | ||||||
|  | 	position: absolute; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-decoration-overview-ruler { | ||||||
|  |     z-index: 7; | ||||||
|  |     position: absolute; | ||||||
|  |     top: 0; | ||||||
|  |     right: 0; | ||||||
|  |     pointer-events: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .xterm-decoration-top { | ||||||
|  |     z-index: 2; | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								assets/xterm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,26 @@ | |||||||
|  | /* | ||||||
|  | Copyright 2021 Erik Bremen | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any | ||||||
|  | person obtaining a copy of this software and associated | ||||||
|  | documentation files (the "Software"), to deal in the | ||||||
|  | Software without restriction, including without | ||||||
|  | limitation the rights to use, copy, modify, merge, | ||||||
|  | publish, distribute, sublicense, and/or sell copies of | ||||||
|  | the Software, and to permit persons to whom the Software | ||||||
|  | is furnished to do so, subject to the following | ||||||
|  | conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice | ||||||
|  | shall be included in all copies or substantial portions | ||||||
|  | of the Software. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||||||
|  | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||||||
|  | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||||||
|  | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | ||||||
|  | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||||
|  | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||||
|  | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR | ||||||
|  | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||||
|  | DEALINGS IN THE SOFTWARE.*/ | ||||||
							
								
								
									
										15572
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |   "dependencies": { | ||||||
|  |     "xterm": "^5.1.0", | ||||||
|  |     "xterm-readline": "^1.1.0" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@webpack-cli/generators": "^3.0.1", | ||||||
|  |     "ts-loader": "^9.4.2", | ||||||
|  |     "workbox-webpack-plugin": "^6.5.4" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										158
									
								
								src/Logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,158 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <svg | ||||||
|  |    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||||
|  |    xmlns:cc="http://creativecommons.org/ns#" | ||||||
|  |    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:xlink="http://www.w3.org/1999/xlink" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    width="40mm" | ||||||
|  |    height="40mm" | ||||||
|  |    viewBox="0 0 40 40" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg8" | ||||||
|  |    inkscape:version="1.0.2 (e86c870879, 2021-01-15)" | ||||||
|  |    sodipodi:docname="Logo.svg"> | ||||||
|  |   <defs | ||||||
|  |      id="defs2"> | ||||||
|  |     <linearGradient | ||||||
|  |        inkscape:collect="always" | ||||||
|  |        id="linearGradient841"> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#ff2f1b;stop-opacity:0.94338685" | ||||||
|  |          offset="0" | ||||||
|  |          id="stop837" /> | ||||||
|  |       <stop | ||||||
|  |          style="stop-color:#ff981b;stop-opacity:1" | ||||||
|  |          offset="1" | ||||||
|  |          id="stop839" /> | ||||||
|  |     </linearGradient> | ||||||
|  |     <linearGradient | ||||||
|  |        inkscape:collect="always" | ||||||
|  |        xlink:href="#linearGradient841" | ||||||
|  |        id="linearGradient843" | ||||||
|  |        x1="0.09372035" | ||||||
|  |        y1="32.445991" | ||||||
|  |        x2="40.099368" | ||||||
|  |        y2="32.445991" | ||||||
|  |        gradientUnits="userSpaceOnUse" /> | ||||||
|  |   </defs> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="base" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#666666" | ||||||
|  |      borderopacity="1.0" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pageshadow="2" | ||||||
|  |      inkscape:zoom="3.959798" | ||||||
|  |      inkscape:cx="33.612988" | ||||||
|  |      inkscape:cy="79.88823" | ||||||
|  |      inkscape:document-units="mm" | ||||||
|  |      inkscape:current-layer="layer1" | ||||||
|  |      inkscape:document-rotation="0" | ||||||
|  |      showgrid="false" | ||||||
|  |      units="mm" | ||||||
|  |      width="10in" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1080" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="0" | ||||||
|  |      inkscape:window-maximized="1" /> | ||||||
|  |   <metadata | ||||||
|  |      id="metadata5"> | ||||||
|  |     <rdf:RDF> | ||||||
|  |       <cc:Work | ||||||
|  |          rdf:about=""> | ||||||
|  |         <dc:format>image/svg+xml</dc:format> | ||||||
|  |         <dc:type | ||||||
|  |            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||||
|  |         <dc:title></dc:title> | ||||||
|  |       </cc:Work> | ||||||
|  |     </rdf:RDF> | ||||||
|  |   </metadata> | ||||||
|  |   <g | ||||||
|  |      inkscape:label="Layer 1" | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      id="layer1"> | ||||||
|  |     <rect | ||||||
|  |        style="opacity:0.996;fill:#bdbdbf;fill-opacity:1;stroke:none;stroke-width:3.26501" | ||||||
|  |        id="rect845" | ||||||
|  |        width="40.060905" | ||||||
|  |        height="39.918461" | ||||||
|  |        x="0.038461588" | ||||||
|  |        y="0.040780049" /> | ||||||
|  |     <path | ||||||
|  |        style="fill:#000096;fill-rule:evenodd;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" | ||||||
|  |        d="m 0.01924099,11.770051 c 0,0 4.23471871,-9.0904555 7.97328241,0.07001 3.7385636,9.160462 10.9886006,0.01079 10.9886006,0.01079 0,0 5.966783,-14.2485618 11.666,0.158241 5.699215,14.406802 9.288732,-1.270883 9.288732,-1.270883 L 40.044468,-0.00924326 0.03846159,0.04078005 Z" | ||||||
|  |        id="path833" /> | ||||||
|  |     <path | ||||||
|  |        style="fill:url(#linearGradient843);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||||
|  |        d="m 40.086823,30.112199 c 0,0 -4.210076,7.636771 -7.973427,-0.04911 -3.763352,-7.685876 -10.98857,0.0043 -10.98857,0.0043 0,0 -5.92816,11.969217 -11.6663624,-0.118701 -5.738201,-12.087915 -9.28523872,1.078198 -9.28523872,1.078198 l -0.07950453,9.022855 40.00564765,-0.0905 z" | ||||||
|  |        id="path835" /> | ||||||
|  |     <g | ||||||
|  |        id="g893"> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 2.4325,0 V 40.079086" | ||||||
|  |          id="path847" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 8.1530386,0 V 40.079086" | ||||||
|  |          id="path849" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 13.873575,0 V 40.079086" | ||||||
|  |          id="path851" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 19.594114,0 V 40.079086" | ||||||
|  |          id="path853" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 25.314652,0 V 40.079086" | ||||||
|  |          id="path855" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 31.035191,0 V 40.079086" | ||||||
|  |          id="path857" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 36.755726,0 V 40.079086" | ||||||
|  |          id="path859" /> | ||||||
|  |     </g> | ||||||
|  |     <g | ||||||
|  |        id="g909" | ||||||
|  |        transform="rotate(89.785681,20.14727,20.064174)"> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 2.4325,0 V 40.079086" | ||||||
|  |          id="path895" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 8.1530386,0 V 40.079086" | ||||||
|  |          id="path897" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 13.873575,0 V 40.079086" | ||||||
|  |          id="path899" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 19.594114,0 V 40.079086" | ||||||
|  |          id="path901" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 25.314652,0 V 40.079086" | ||||||
|  |          id="path903" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 31.035191,0 V 40.079086" | ||||||
|  |          id="path905" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.865;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||||
|  |          d="M 36.755726,0 V 40.079086" | ||||||
|  |          id="path907" /> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 7.0 KiB | 
							
								
								
									
										63
									
								
								src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,63 @@ | |||||||
|  | import {Terminal} from 'xterm'; | ||||||
|  | import { Readline } from "xterm-readline"; | ||||||
|  | 
 | ||||||
|  | let isScreened = false, sendLessExplicit = false; | ||||||
|  |      | ||||||
|  | const term = new Terminal(); | ||||||
|  | const rl = new Readline(); | ||||||
|  | term.options.scrollback = 1000; | ||||||
|  | term.loadAddon(rl); | ||||||
|  | term.open(document.getElementById('console')); | ||||||
|  | 
 | ||||||
|  | let lineHandler = (l: string) => { console.log("Default handler", l); }; | ||||||
|  | 
 | ||||||
|  | async function readForever() { | ||||||
|  |   while (true) { | ||||||
|  |     const l = await rl.read(""); | ||||||
|  |     lineHandler(l); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | readForever(); | ||||||
|  | 
 | ||||||
|  | function connectTerm() { | ||||||
|  |   lineHandler = () => {}; | ||||||
|  |   term.writeln("\x1b[0mConnecting to server..."); | ||||||
|  |   const wsurl = document.location.href.replace(/^https:\/\/(.*)\/game(.html)?(\?.*)?(\#.*)?/, 'wss:\/\/$1/wsgame'); | ||||||
|  |   let webSocket = new WebSocket(wsurl); | ||||||
|  |   webSocket.addEventListener('open', (event) => { | ||||||
|  |     lineHandler = (l: string) => { console.log("Send handler", l); webSocket.send(l); } | ||||||
|  |     term.writeln("\x1b[0mConnected"); | ||||||
|  |   }); | ||||||
|  |   webSocket.addEventListener('close', (event) => { | ||||||
|  |     lineHandler = connectTerm; | ||||||
|  |     term.writeln("\x1b[0mDisconnected; use r (followed by enter) to reconnect."); | ||||||
|  |   }); | ||||||
|  |   webSocket.addEventListener('error', (event) => { | ||||||
|  |     term.writeln("\x1b[0mNetwork error with connection."); | ||||||
|  |   }); | ||||||
|  |   webSocket.addEventListener('message', (msg) => { | ||||||
|  |     term.write(msg.data); | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function over18() { | ||||||
|  |   document.getElementById("over18").style.display = 'none'; | ||||||
|  |   isScreened = true; | ||||||
|  |   window.localStorage['over18'] = true; | ||||||
|  |   term.focus(); | ||||||
|  |   connectTerm(); | ||||||
|  | } | ||||||
|  |      | ||||||
|  | if ('serviceWorker' in navigator) navigator.serviceWorker.register('service-worker.js'); | ||||||
|  | const params: {[key:string]: string} = | ||||||
|  |   location.search.substr(1).split('&') | ||||||
|  |     .reduce((o, s) => { const [k, v] = s.split('='); o[k] = v; return o;}, | ||||||
|  |             {} as {[key:string]: string}); | ||||||
|  | if (params["source"] && params["source"] === "android") { | ||||||
|  |   isScreened = true; | ||||||
|  |   sendLessExplicit = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | if (isScreened || window.localStorage['over18']) { | ||||||
|  |   over18(); | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "allowSyntheticDefaultImports": true, | ||||||
|  |     "noImplicitAny": true, | ||||||
|  |     "module": "es6", | ||||||
|  |     "target": "es5", | ||||||
|  |     "allowJs": true, | ||||||
|  |     "moduleResolution": "node" | ||||||
|  |   }, | ||||||
|  |   "files": ["src/index.ts"] | ||||||
|  | } | ||||||
							
								
								
									
										4
									
								
								update-deps.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @ -0,0 +1,4 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | npx webpack | ||||||
|  | cp dist/main.js ./assets/main.js | ||||||
							
								
								
									
										50
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,50 @@ | |||||||
|  | // Generated using webpack-cli https://github.com/webpack/webpack-cli
 | ||||||
|  | 
 | ||||||
|  | const path = require('path'); | ||||||
|  | const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); | ||||||
|  | 
 | ||||||
|  | const isProduction = process.env.NODE_ENV !== 'test'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const config = { | ||||||
|  |     entry: './src/index.ts', | ||||||
|  |     output: { | ||||||
|  |         path: path.resolve(__dirname, 'dist'), | ||||||
|  |     }, | ||||||
|  |     plugins: [ | ||||||
|  |         // Add your plugins here
 | ||||||
|  |         // Learn more about plugins from https://webpack.js.org/configuration/plugins/
 | ||||||
|  |     ], | ||||||
|  |     module: { | ||||||
|  |         rules: [ | ||||||
|  |             { | ||||||
|  |                 test: /\.(ts|tsx)$/i, | ||||||
|  |                 loader: 'ts-loader', | ||||||
|  |                 exclude: ['/node_modules/'], | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, | ||||||
|  |                 type: 'asset', | ||||||
|  |             }, | ||||||
|  | 
 | ||||||
|  |             // Add your rules for custom modules here
 | ||||||
|  |             // Learn more about loaders from https://webpack.js.org/loaders/
 | ||||||
|  |         ], | ||||||
|  |     }, | ||||||
|  |     resolve: { | ||||||
|  |         extensions: ['.tsx', '.ts', '.jsx', '.js', '...'], | ||||||
|  |     }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module.exports = () => { | ||||||
|  |     if (isProduction) { | ||||||
|  |         config.mode = 'production'; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); | ||||||
|  |          | ||||||
|  |     } else { | ||||||
|  |         config.mode = 'development'; | ||||||
|  |     } | ||||||
|  |     return config; | ||||||
|  | }; | ||||||