aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstonedDiscord <stoned@derpymail.org>2019-12-19 16:21:26 +0100
committerGitHub <noreply@github.com>2019-12-19 16:21:26 +0100
commit2b5a66ded5bbb868b1e78c7295ef0a869a5af53d (patch)
tree87a06fd501cf73ddfb7b1e098c1d8ea0c030af4f
parentbf15ff1b5df6877c14011ebe7f5ca8b7d4b8f060 (diff)
parentba34f06c77aa93a862d9047be393696c0ececee7 (diff)
Merge branch 'master' into delete-bb
-rw-r--r--webAO/client.css7
-rw-r--r--webAO/client.js214
-rw-r--r--webAO/index.html7
-rw-r--r--webAO/master.js19
4 files changed, 141 insertions, 106 deletions
diff --git a/webAO/client.css b/webAO/client.css
index 4ce37f0..b32a7cf 100644
--- a/webAO/client.css
+++ b/webAO/client.css
@@ -105,8 +105,11 @@ img {
}
.demothing {
+ display: block;
height: 60px;
width: 60px;
+ max-width: 60px;
+ max-height: 60px;
margin: 3px;
border: 1px solid #000;
}
@@ -421,6 +424,10 @@ img {
filter: brightness(50%);
}
+.noini {
+ transform: rotate(180deg);
+}
+
.hrtext {
overflow: hidden;
text-align: center;
diff --git a/webAO/client.js b/webAO/client.js
index 567eb02..d0f0086 100644
--- a/webAO/client.js
+++ b/webAO/client.js
@@ -74,6 +74,9 @@ class Client extends EventEmitter {
this.playerID = 1;
this.charID = -1;
+ this.char_list_length = 0;
+ this.evidence_list_length = 0;
+ this.music_list_length = 0;
this.testimonyID = 0;
this.chars = [];
@@ -309,25 +312,6 @@ class Client extends EventEmitter {
background_arr.forEach(background => {
background_select.add(new Option(background));
});
-
- this.resources.map(async (resource) => {
- // Check if image exists and replace `src` with an absolute URL
- const spriteSrc = `${AO_HOST}themes/default/${resource.src}.gif`;
- if (await fileExists(spriteSrc)) {
- Object.assign(resource, {
- src: spriteSrc,
- duration: await viewport.getAnimLength(spriteSrc)
- });
- }
-
- // Check if sfx exists and replace `sfx` with an absolute URL
- if (resource.sfx) {
- const sfxSrc = AO_HOST + resource.sfx.toLowerCase();
- if (await fileExists(sfxSrc)) {
- resource.sfx = sfxSrc;
- }
- }
- });
}
/**
@@ -357,13 +341,9 @@ class Client extends EventEmitter {
* Triggered when a connection is established to the server.
*/
onOpen(_e) {
- // XXX: Why does watching mean just SITTING there and doing nothing?
- if (mode === "watch") {
- document.getElementById("client_loading").style.display = "none";
- document.getElementById("client_charselect").style.display = "none";
- } else {
- client.joinServer();
- }
+ client.initialObservBBCode();
+ client.loadResources();
+ client.joinServer();
}
/**
@@ -430,14 +410,15 @@ class Client extends EventEmitter {
if (args[4] !== viewport.chatmsg.content) {
document.getElementById("client_inner_chat").innerHTML = "";
const chatmsg = {
- preanim: escape(args[2]), // get preanim
- nameplate: args[3], // TODO: parse INI to get this info
- name: args[3],
- speaking: "(b)" + escape(args[4]),
- silent: "(a)" + escape(args[4]),
+ preanim: escape(args[2]).toLowerCase(), // get preanim
+ nameplate: this.chars[args[9]].showname,
+ name: args[3].toLowerCase(),
+ speaking: "(b)" + escape(args[4]).toLowerCase(),
+ silent: "(a)" + escape(args[4]).toLowerCase(),
content: this.prepChat(args[5]), // Escape HTML tag
- side: args[6],
- sound: escape(args[7]),
+ side: args[6].toLowerCase(),
+ sound: escape(args[7]).toLowerCase(),
+ blips: this.chars[args[9]].gender,
type: args[8],
charid: args[9],
snddelay: args[10],
@@ -505,41 +486,74 @@ class Client extends EventEmitter {
}
/**
+ * Handles the incoming character information, and downloads the sprite + ini for it
+ * @param {Array} args packet arguments
+ */
+ async handleCharacterInfo(chargs, charid) {
+ let cini = {};
+ let icon = AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char_icon.png";
+ let img = document.getElementById(`demo_${charid}`);
+ img.alt = chargs[0];
+ img.src = icon; // seems like a good time to load the icon
+
+ try {
+ const cinidata = await request(AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char.ini");
+ cini = INI.parse(cinidata);
+ } catch(err) {
+ cini = {};
+ img.classList.add("noini");
+ }
+
+ // fix all the funny ini business
+ const default_options = {
+ name: chargs[0].toLowerCase(),
+ showname: chargs[0],
+ side: "def",
+ gender: "male"
+ };
+ cini.options = Object.assign(default_options, cini.options);
+
+ this.chars[charid] = {
+ name: chargs[0].toLowerCase(),
+ showname: cini.options.showname,
+ desc: chargs[1],
+ gender: cini.options.gender.toLowerCase(),
+ evidence: chargs[3],
+ icon: icon,
+ inifile: cini
+ };
+
+
+ }
+
+ /**
* Handles incoming character information, bundling multiple characters
* per packet.
* @param {Array} args packet arguments
*/
handleCI(args) {
document.getElementById("client_loadingtext").innerHTML = "Loading Character " + args[1];
- this.serv.send("AN#" + ((args[1] / 10) + 1) + "#%");
for (let i = 2; i < args.length - 1; i++) {
if (i % 2 === 0) {
+ document.getElementById("client_loadingtext").innerHTML = `Loading Character ${i}/${this.char_list_length}`;
const chargs = args[i].split("&");
- this.chars[args[i - 1]] = {
- name: chargs[0],
- desc: chargs[1],
- evidence: chargs[3],
- icon: AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char_icon.png"
- };
+ this.handleCharacterInfo(chargs, i-1);
}
}
+ this.serv.send("AN#" + ((args[1] / 10) + 1) + "#%");
}
/**
- * Handles incoming character information, containing only one character
- * per packet.
+ * Handles incoming character information, containing all characters
+ * in one packet.
* @param {Array} args packet arguments
*/
handleSC(args) {
document.getElementById("client_loadingtext").innerHTML = "Loading Characters";
for (let i = 1; i < args.length - 1; i++) {
+ document.getElementById("client_loadingtext").innerHTML = `Loading Character ${i}/${this.char_list_length}`;
const chargs = args[i].split("&");
- this.chars[i - 1] = {
- name: chargs[0],
- desc: chargs[1],
- evidence: chargs[3],
- icon: AO_HOST + "characters/" + escape(chargs[0].toLowerCase()) + "/char_icon.png"
- };
+ this.handleCharacterInfo(chargs, i-1);
}
this.serv.send("RM#%");
}
@@ -552,7 +566,7 @@ class Client extends EventEmitter {
* @param {Array} args packet arguments
*/
handleEI(args) {
- document.getElementById("client_loadingtext").innerHTML = "Loading Evidence " + args[1];
+ document.getElementById("client_loadingtext").innerHTML = `Loading Evidence ${args[1]}/${this.evidence_list_length}`;
//serv.send("AE#" + (args[1] + 1) + "#%");
this.serv.send("RM#%");
}
@@ -597,6 +611,7 @@ class Client extends EventEmitter {
const hmusiclist = document.getElementById("client_musiclist");
for (let i = 2; i < args.length - 1; i++) {
if (i % 2 === 0) {
+ document.getElementById("client_loadingtext").innerHTML = `Loading Music ${i}/${this.music_list_length}`;
const newentry = document.createElement("OPTION");
newentry.text = args[i];
hmusiclist.options.add(newentry);
@@ -616,6 +631,7 @@ class Client extends EventEmitter {
for (let i = 1; i < args.length - 1; i++) {
// Check when found the song for the first time
+ document.getElementById("client_loadingtext").innerHTML = `Loading Music ${i}/${this.music_list_length}`;
if (/\.(?:wav|mp3|mp4|ogg|opus)$/i.test(args[i]) && !flagAudio) {
flagAudio = true;
}
@@ -698,7 +714,11 @@ class Client extends EventEmitter {
*/
handleDONE(_args) {
document.getElementById("client_loading").style.display = "none";
- document.getElementById("client_charselect").style.display = "block";
+ if (mode === "watch") { // Spectators don't need to pick a character
+ document.getElementById("client_charselect").style.display = "none";
+ } else {
+ document.getElementById("client_charselect").style.display = "block";
+ }
}
/**
@@ -800,7 +820,28 @@ class Client extends EventEmitter {
* but we use it as a cue to begin retrieving characters.
* @param {Array} args packet arguments
*/
- handleSI(_args) {
+ handleSI(args) {
+ this.char_list_length = args[1];
+ this.evidence_list_length = args[2];
+ this.music_list_length = args[3];
+
+ // create the charselect grid, to be filled by the character loader
+ document.getElementById("client_chartable").innerHTML = "";
+ let tr;
+ for (let i = 0; i < this.char_list_length; i++) {
+ if (i % CHAR_SELECT_WIDTH === 0) {
+ tr = document.createElement("TR");
+ }
+ const td = document.createElement("TD");
+
+ td.innerHTML = `<img class='demothing' id='demo_${i}' onclick='pickChar(${i})' >`;
+
+ tr.appendChild(td);
+ if (i % CHAR_SELECT_WIDTH === 0) {
+ document.getElementById("client_chartable").appendChild(tr);
+ }
+ }
+
if (oldLoading) {
this.serv.send("askchar2#%");
} else {
@@ -813,26 +854,19 @@ class Client extends EventEmitter {
* @param {Array} args packet arguments
*/
handleCharsCheck(args) {
- document.getElementById("client_chartable").innerHTML = "";
- let tr;
- for (let i = 0; i < this.chars.length; i++) {
- if (i % CHAR_SELECT_WIDTH === 0) {
- tr = document.createElement("TR");
- }
- const td = document.createElement("TD");
- let icon_chosen = "";
- const thispick = this.chars[i].icon;
- if (args[i + 1] === "-1") {
- icon_chosen = " dark";
- }
- td.innerHTML = `<img class='demothing${icon_chosen}' id='demo_${i}' ` +
- `src='${thispick}' alt='${this.chars[i].name}' onclick='pickChar(${i})' ` +
- `onerror='demoError(this);'>`;
- tr.appendChild(td);
- if (i % CHAR_SELECT_WIDTH === 0) {
- document.getElementById("client_chartable").appendChild(tr);
- }
+ for (let i = 0; i < this.char_list_length; i++) {
+ let img = document.getElementById(`demo_${i}`);
+ let icon_chosen = "demothing";
+
+ if (img.classList.contains("noini"))
+ icon_chosen += " noini";
+
+ if (args[i + 1] === "-1")
+ icon_chosen += " dark";
+
+ img.classList = icon_chosen;
}
+
//changeBackground("def");
}
@@ -852,9 +886,7 @@ class Client extends EventEmitter {
const emotesList = document.getElementById("client_emo");
emotesList.innerHTML = ""; // Clear emote box
emotesList.style.display = "";
-
- const data = await request(AO_HOST + "characters/" + escape(this.character.name.toLowerCase()) + "/char.ini");
- const ini = INI.parse(data.toLowerCase());
+ const ini = me.inifile;
me.side = ini.options.side;
updateActionCommands(me.side);
for (let i = 1; i <= ini.emotions.number; i++) {
@@ -903,7 +935,6 @@ class Viewport {
// Allocate multiple blip audio channels to make blips less jittery
- // TODO: read blip type ("gender") from ini
this.blipChannels = new Array(6);
this.blipChannels.fill(new Audio(AO_HOST + "sounds/general/sfx-blipmale.wav"))
.forEach(channel => channel.volume = 0.5);
@@ -960,6 +991,7 @@ class Viewport {
this.chatmsg = chatmsg;
appendICLog(chatmsg.content, chatmsg.nameplate);
changeBackground(chatmsg.side);
+ this.blipChannels.forEach(channel => channel.src = AO_HOST + `sounds/general/sfx-blip${chatmsg.blips}.wav`);
this.textnow = "";
this.sfxplayed = 0;
this.textTimer = 0;
@@ -967,7 +999,7 @@ class Viewport {
clearTimeout(this.updater);
// If preanim existed then determine the length
if (chatmsg.preanim !== "-") {
- const delay = await this.getAnimLength(`${AO_HOST}characters/${escape(chatmsg.name.toLowerCase())}/${chatmsg.preanim.toLowerCase()}.gif`);
+ const delay = await this.getAnimLength(`${AO_HOST}characters/${escape(chatmsg.name)}/${chatmsg.preanim}.gif`);
chatmsg.preanimdelay = delay;
this.initUpdater(delay);
} else {
@@ -1017,7 +1049,6 @@ class Viewport {
async getAnimLength(filename) {
try {
const file = await requestBuffer(filename);
- console.log(filename);
return this.calculateGifLength(file);
} catch (err) {
return 0;
@@ -1284,14 +1315,18 @@ class INI {
} else if (regex.param.test(line)) {
const match = line.match(regex.param);
if (section) {
- value[section][match[1]] = match[2];
- } else {
- value[match[1]] = match[2];
+ if(match[1].toLowerCase() === "showname"){ //don't lowercase the showname
+ value[section][match[1].toLowerCase()] = match[2];
+ } else {
+ value[section][match[1].toLowerCase()] = match[2].toLowerCase();
+ }
+ //} else { // we don't care about attributes without a section
+ // value[match[1]] = match[2];
}
} else if (regex.section.test(line)) {
const match = line.match(regex.section);
- value[match[1]] = {};
- section = match[1];
+ value[match[1].toLowerCase()] = {}; //lowercase everything else
+ section = match[1].toLowerCase();
}
});
return value;
@@ -1479,17 +1514,6 @@ export function imgError(image) {
window.imgError = imgError;
/**
- * Triggered when there was an error loading a character icon.
- * @param {HTMLImageElement} image the element containing the missing image
- */
-export function demoError(image) {
- image.onerror = "";
- image.src = "misc/placeholder.png";
- return true;
-}
-window.demoError = demoError;
-
-/**
* Make a GET request for a specific URI.
* @param {string} url the URI to be requested
* @returns response data
@@ -1636,7 +1660,6 @@ async function changeBackground(position) {
export function ReconnectButton() {
client.cleanup();
client = new Client(serverIP);
- console.log(client);
if (client) {
mode = "join"; // HACK: see client.onOpen
document.getElementById("client_error").style.display = "none";
@@ -2163,11 +2186,6 @@ function decodeChat(estring) {
let client = new Client(serverIP);
let viewport = new Viewport();
-export function onLoad(){
- client.loadResources();
-}
-window.onLoad = onLoad;
-
// Create dialog and link to button
$(function () {
$("#callmod_dialog").dialog({
diff --git a/webAO/index.html b/webAO/index.html
index 05afdf6..28fe555 100644
--- a/webAO/index.html
+++ b/webAO/index.html
@@ -68,9 +68,10 @@
</p>
</div>
<ul class="serverlist" id="masterlist">
- <li onmouseover="setServ(99)">
- <p>Localhost</p> <a class="button" href="client.html?ip=127.0.0.1:27016">Watch</a><a class="button" href="client.html?ip=127.0.0.1:27016">Join</a></li>
-
+ <li id="server-1" class="unavailable" onmouseover="setServ(-1)"><p>Localhost</p>
+ <a class="button" href="client.html?mode=watch&ip=127.0.0.1:50001">Watch</a>
+ <a class="button" href="client.html?mode=join&ip=127.0.0.1:50001">Join</a>
+ </li>
</ul>
</div>
</body>
diff --git a/webAO/master.js b/webAO/master.js
index 3c2c01b..608cc29 100644
--- a/webAO/master.js
+++ b/webAO/master.js
@@ -25,7 +25,7 @@ masterserver.onopen = (evt) => onOpen(evt);
masterserver.onmessage = (evt) => onMessage(evt);
const server_description = [];
-server_description[99] = "This is your computer on port 27016";
+server_description[-1] = "This is your computer on port 50001";
const online_counter = [];
export function setServ(ID) {
@@ -50,7 +50,7 @@ function onOpen(_e) {
masterserver.send("VC#%");
}
-function checkOnline(serverID, coIP) {
+async function checkOnline(serverID, coIP) {
function onCOOpen(_e) {
document.getElementById(`server${serverID}`).className = "available";
oserv.send(`HI#${hdid}#%`);
@@ -72,6 +72,10 @@ function checkOnline(serverID, coIP) {
}
}
+ function onCOError(_e) {
+ console.warn(serverID + " threw an error.");
+ }
+
var oserv = new WebSocket("ws://" + coIP);
oserv.onopen = function (evt) {
@@ -82,6 +86,10 @@ function checkOnline(serverID, coIP) {
onCOMessage(evt);
};
+ oserv.onerror = function(evt) {
+ onCOError(evt)
+ };
+
}
function onMessage(e) {
@@ -91,7 +99,7 @@ function onMessage(e) {
if (header === "ALL") {
const servers = msg.split("#").slice(1);
- for (let i = 0; i < servers.length; i++) {
+ for (let i = 0; i < servers.length-1; i++) {
const serverEntry = servers[i];
const args = serverEntry.split("&");
const asset = args[4] ? `&asset=${args[4]}` : "";
@@ -101,8 +109,9 @@ function onMessage(e) {
+ `<a class="button" href="client.html?mode=watch&ip=${args[2]}:${args[3]}${asset}">Watch</a>`
+ `<a class="button" href="client.html?mode=join&ip=${args[2]}:${args[3]}${asset}">Join</a></li>`;
server_description[i] = args[1];
- setTimeout(checkOnline(i, args[2] + ":" + args[3]), 100);
+ checkOnline(i, `${args[2]}:${args[3]}`);
}
+ checkOnline(-1, "127.0.0.1:50001");
}
else if (header === "SN") {
const args = msg.split("#");
@@ -113,7 +122,7 @@ function onMessage(e) {
+ `<a class="button" href="client.html?mode=join&ip=${args[2]}:${args[4]}">Join</a></li>`;
server_description[i] = args[6];
masterserver.send("SR#" + i + "#%");
- setTimeout(checkOnline(i, args[2] + ":" + args[4]), i*1000);
+ checkOnline(i, `${args[2]}:${args[3]}`);
}
else if (header === "servercheok") {
const args = msg.split("#").slice(1);