205 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| {% extends 'pageWrapper.html' %}
 | |
| {% import "macros.html" as macros %}
 | |
| {% block head %}
 | |
|     <title>Multiworld {{ room.id|suuid }}</title>
 | |
|     {% if should_refresh %}<meta http-equiv="refresh" content="2">{% endif %}
 | |
|     <meta name="og:site_name" content="Archipelago">
 | |
|     <meta property="og:title" content="Multiworld {{ room.id|suuid }}">
 | |
|     <meta property="og:type" content="website" />
 | |
|     {% if room.seed.slots|length < 2 %}
 | |
|     <meta property="og:description" content="{{ room.seed.slots|length }} Player World
 | |
|     {% if room.last_port != -1 %}running on {{ config['HOST_ADDRESS'] }} with port {{ room.last_port }}{% endif %}">
 | |
|     {% else %}
 | |
|     <meta property="og:description" content="{{ room.seed.slots|length }} Players Multiworld
 | |
|     {% if room.last_port != -1 %}running on {{ config['HOST_ADDRESS'] }} with port {{ room.last_port }}{% endif %}">
 | |
|     {% endif %}
 | |
|     <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/hostRoom.css") }}"/>
 | |
| {% endblock %}
 | |
| 
 | |
| {% block body %}
 | |
|     {% include 'header/grassHeader.html' %}
 | |
|     <div id="host-room">
 | |
|         <span id="host-room-info">
 | |
|             {% if room.owner == session["_id"] %}
 | |
|                 Room created from <a href="{{ url_for("view_seed", seed=room.seed.id) }}">Seed #{{ room.seed.id|suuid }}</a>
 | |
|                 <br />
 | |
|             {% endif %}
 | |
|             {% if room.tracker %}
 | |
|                 This room has a <a href="{{ url_for("get_multiworld_tracker", tracker=room.tracker) }}">Multiworld Tracker</a>
 | |
|                 and a <a href="{{ url_for("get_multiworld_sphere_tracker", tracker=room.tracker) }}">Sphere Tracker</a> enabled.
 | |
|                 <br />
 | |
|             {% endif %}
 | |
|             The server for this room will be paused after {{ room.timeout//60//60 }} hours of inactivity.
 | |
|             Should you wish to continue later,
 | |
|             anyone can simply refresh this page and the server will resume.<br>
 | |
|             {% if room.last_port == -1 %}
 | |
|                 There was an error hosting this Room. Another attempt will be made on refreshing this page.
 | |
|                 The most likely failure reason is that the multiworld is too old to be loaded now.
 | |
|             {% elif room.last_port %}
 | |
|                 You can connect to this room by using <span class="interactive"
 | |
|                 data-tooltip="This means address/ip is {{ config['HOST_ADDRESS'] }} and port is {{ room.last_port }}.">
 | |
|                 '/connect {{ config['HOST_ADDRESS'] }}:{{ room.last_port }}'
 | |
|                 </span>
 | |
|                 in the <a href="{{ url_for("tutorial_landing")}}">client</a>.<br>
 | |
|             {% endif %}
 | |
|         </span>
 | |
|         {{ macros.list_patches_room(room) }}
 | |
|         {% if room.owner == session["_id"] %}
 | |
|             <div style="display: flex; align-items: center;">
 | |
|                 <form method="post" id="command-form" style="flex-grow: 1; margin-right: 1em;">
 | |
|                     <div class="form-group">
 | |
|                         <label for="cmd"></label>
 | |
|                         <input class="form-control" type="text" id="cmd" name="cmd"
 | |
|                                placeholder="Server Command. /help to list them, list gets appended to log.">
 | |
|                         <span class="loader"></span>
 | |
|                     </div>
 | |
|                 </form>
 | |
|                 <a href="{{ url_for("display_log", room=room.id) }}">
 | |
|                     Open Log File...
 | |
|                 </a>
 | |
|             </div>
 | |
|         {%  set log = get_log() -%}
 | |
|         {%- set log_len = log | length - 1 if log.endswith("…") else log | length -%}
 | |
|         <div id="logger" style="white-space: pre">{{ log }}</div>
 | |
|         <script>
 | |
|           let url = '{{ url_for('display_log', room = room.id) }}';
 | |
|           let bytesReceived = {{ log_len }};
 | |
|           let updateLogTimeout;
 | |
|           let updateLogImmediately = false;
 | |
|           let awaitingCommandResponse = false;
 | |
|           let logger = document.getElementById("logger");
 | |
| 
 | |
|           function scrollToBottom(el) {
 | |
|             let bot = el.scrollHeight - el.clientHeight;
 | |
|             el.scrollTop += Math.ceil((bot - el.scrollTop)/10);
 | |
|             if (bot - el.scrollTop >= 1) {
 | |
|               window.clearTimeout(el.scrollTimer);
 | |
|               el.scrollTimer = window.setTimeout(() => {
 | |
|                 scrollToBottom(el)
 | |
|               }, 16);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           async function updateLog() {
 | |
|             try {
 | |
|               if (!document.hidden) {
 | |
|                 updateLogImmediately = false;
 | |
|                 let res = await fetch(url, {
 | |
|                   headers: {
 | |
|                     'Range': `bytes=${bytesReceived}-`,
 | |
|                   }
 | |
|                 });
 | |
|                 if (res.ok) {
 | |
|                   let text = await res.text();
 | |
|                   if (text.length > 0) {
 | |
|                     awaitingCommandResponse = false;
 | |
|                     if (bytesReceived === 0 || res.status !== 206) {
 | |
|                       logger.innerHTML = '';
 | |
|                     }
 | |
|                     if (res.status !== 206) {
 | |
|                       bytesReceived = 0;
 | |
|                     } else {
 | |
|                       bytesReceived += new Blob([text]).size;
 | |
|                     }
 | |
|                     if (logger.innerHTML.endsWith('…')) {
 | |
|                       logger.innerHTML = logger.innerHTML.substring(0, logger.innerHTML.length - 1);
 | |
|                     }
 | |
|                     logger.appendChild(document.createTextNode(text));
 | |
|                     scrollToBottom(logger);
 | |
|                     let loader = document.getElementById("command-form").getElementsByClassName("loader")[0];
 | |
|                     loader.classList.remove("loading");
 | |
|                   }
 | |
|                 }
 | |
|               } else {
 | |
|                 updateLogImmediately = true;
 | |
|               }
 | |
|             }
 | |
|             finally {
 | |
|               window.clearTimeout(updateLogTimeout);
 | |
|               updateLogTimeout = window.setTimeout(updateLog, awaitingCommandResponse ? 500 : 10000);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           async function postForm(ev) {
 | |
|             /** @type {HTMLInputElement} */
 | |
|             let cmd = document.getElementById("cmd");
 | |
|             if (cmd.value === "") {
 | |
|               ev.preventDefault();
 | |
|               return;
 | |
|             }
 | |
|             /** @type {HTMLFormElement} */
 | |
|             let form = document.getElementById("command-form");
 | |
|             let req = fetch(form.action || window.location.href, {
 | |
|               method: form.method,
 | |
|               body: new FormData(form),
 | |
|               redirect: "manual",
 | |
|             });
 | |
|             ev.preventDefault(); // has to happen before first await
 | |
|             form.reset();
 | |
|             let loader = form.getElementsByClassName("loader")[0];
 | |
|             loader.classList.add("loading");
 | |
|             try {
 | |
|               let res = await req;
 | |
|               if (res.ok || res.type === 'opaqueredirect') {
 | |
|                 awaitingCommandResponse = true;
 | |
|                 window.clearTimeout(updateLogTimeout);
 | |
|                 updateLogTimeout = window.setTimeout(updateLog, 100);
 | |
|               } else {
 | |
|                 loader.classList.remove("loading");
 | |
|                 window.alert(res.statusText);
 | |
|               }
 | |
|             } catch (e) {
 | |
|                 console.error(e);
 | |
|                 loader.classList.remove("loading");
 | |
|                 window.alert(e.message);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           document.getElementById("command-form").addEventListener("submit", postForm);
 | |
|           updateLogTimeout = window.setTimeout(updateLog, 1000);
 | |
|           logger.scrollTop = logger.scrollHeight;
 | |
|           document.addEventListener("visibilitychange", () => {
 | |
|             if (!document.hidden && updateLogImmediately) {
 | |
|               updateLog();
 | |
|             }
 | |
|           })
 | |
|         </script>
 | |
|         {% endif %}
 | |
|         <script>
 | |
|           function updateInfo() {
 | |
|             let url = new URL(window.location.href);
 | |
|             url.search = "?update";
 | |
|             fetch(url)
 | |
|               .then(res => {
 | |
|                 if (!res.ok) {
 | |
|                   throw new Error(`HTTP error ${res.status}`);
 | |
|                 }
 | |
|                 return res.text()
 | |
|               })
 | |
|               .then(text => new DOMParser().parseFromString(text, 'text/html'))
 | |
|               .then(newDocument => {
 | |
|                 ["host-room-info", "slots-table"].forEach(function(id) {
 | |
|                   const newEl = newDocument.getElementById(id);
 | |
|                   const oldEl = document.getElementById(id);
 | |
|                   if (oldEl && newEl) {
 | |
|                     oldEl.innerHTML = newEl.innerHTML;
 | |
|                   } else if (newEl) {
 | |
|                     console.warn(`Did not find element to replace for ${id}`)
 | |
|                   }
 | |
|                 });
 | |
|             });
 | |
|           }
 | |
| 
 | |
|           if (document.querySelector("meta[http-equiv='refresh']")) {
 | |
|             console.log("Refresh!");
 | |
|             window.addEventListener('load', function () {
 | |
|               for (let i=0; i<3; i++) {
 | |
|                 window.setTimeout(updateInfo, Math.pow(2, i) * 2000); // 2, 4, 8s
 | |
|               }
 | |
|               window.stop(); // cancel meta refresh
 | |
|             })
 | |
|           }
 | |
|         </script>
 | |
|     </div>
 | |
| {% endblock %}
 | 
