Added new kick/ban screen.

This commit is contained in:
Pachira 2024-02-24 20:26:40 +00:00
parent dd2fd189dc
commit 123b21f8cb
7 changed files with 181 additions and 74 deletions

67
src/mami.css/baka.css Normal file
View file

@ -0,0 +1,67 @@
@keyframes baka-marquee-anim {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
.baka {
color: #000;
background: repeating-linear-gradient(-45deg, #ff3d3d, #ff3d3d 20px, #f00 20px, #f00 40px);
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size: 16px;
line-height: 25px;
color: #fff;
display: flex;
flex-direction: column;
}
.baka-container {
flex-shrink: 1;
flex-grow: 1;
background: #0008;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.baka-bottom {
flex-grow: 0;
flex-shrink: 0;
height: 6em;
}
.baka-spacing {
flex-grow: 1;
flex-shrink: 1;
}
.baka-marquee {
flex-grow: 0;
flex-shrink: 0;
display: flex;
width: 100%;
height: 6em;
overflow: hidden;
white-space: nowrap;
background: #0005;
backdrop-filter: blur(4px);
}
.baka-marquee-text {
font-size: 5rem;
line-height: 1.2em;
font-weight: 700;
padding: 0 .25em;
text-transform: uppercase;
animation: baka-marquee-anim 2.33s infinite linear;
}
.baka-duration {
flex-grow: 0;
flex-shrink: 0;
margin: 5px;
}
.baka-duration-inner {
padding: 5px 10px;
background: #0002;
display: inline-block;
backdrop-filter: blur(4px);
}

View file

@ -3,6 +3,7 @@
@include views.css;
@include baka.css;
@include chat.css;
@include eeprom.css;
@include emote.css;

View file

@ -25,6 +25,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
#include sound/context.js
#include sound/osukeys.js
#include sound/umisound.js
#include ui/baka.jsx
#include ui/chat-layout.js
#include ui/hooks.js
#include ui/emotes.js
@ -564,6 +565,12 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
'_1013': 'You cannot connect to the server right now, try again later.',
'_1015': 'Your client and the server could not establish a secure connection.',
};
const sessFailReasons = {
'authfail': 'Authentication failed.',
'sockfail': 'Too many active connections.',
'userfail': 'Name in use.',
'joinfail': 'You are banned.',
};
let dumpEvents = false;
settings.watch('dumpEvents', value => dumpEvents = value);
@ -606,64 +613,6 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
});
const playBannedSfx = async () => {
await soundCtx.library.play('touhou:pichuun');
};
const playBannedBgm = async preload => {
const name = 'touhou:th10score';
if(preload) {
await soundCtx.library.loadBuffer(name);
return;
}
const source = await soundCtx.library.loadSource(name);
source.setLoop(true, 10.512, 38.074);
await source.play();
};
const displayBanMessage = baka => {
let message;
if(baka.perma)
message = 'You have been banned till the end of time, please try again in a different dimension.';
else if(baka.until)
message = `You were banned until ${baka.until.toLocaleString()}!`;
else
message = 'You were kicked, refresh to log back in!';
const icon = baka.type === 'kick' ? 'bomb' : 'hammer';
const header = baka.type === 'kick' ? 'Kicked!' : 'Banned!';
const currentView = views.current();
if(currentView === undefined || 'setIcon' in currentView) {
playBannedBgm();
getLoadingOverlay(icon, header, message);
} else {
const currentViewElem = views.currentElement();
MamiAnimate({
duration: 550,
easing: 'outExpo',
start: () => {
playBannedBgm(true);
playBannedSfx();
},
update: t => {
currentViewElem.style.transform = `scale(${(1 - .5 * t)}, ${(1 - 1 * t)})`;
},
end: () => {
getLoadingOverlay(icon, header, message).then(() => {
playBannedBgm();
// there's currently no way to reconnect after a kick/ban so just dispose of the ui entirely
if(views.count() > 1)
views.shift();
});
},
});
}
};
Umi.Server.watch('session:start', start => {
if(dumpEvents) console.log('session:start', start);
@ -697,23 +646,14 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
if(dumpEvents) console.log('session:fail', fail);
if(fail.baka !== undefined) {
displayBanMessage(fail.baka);
new MamiForceDisconnectNotice(fail.baka).pushOn(views);
return;
}
const message = (reason => {
if(reason === 'authfail')
return 'Authentication failed.';
if(reason === 'sockfail')
return 'Too many active connections.';
if(reason === 'userfail')
return 'Name in use.';
if(reason === 'joinfail')
return 'You are banned.';
return `Unknown reason: ${reason}`;
})(fail.session.reason);
getLoadingOverlay('cross', 'Failed!', message);
getLoadingOverlay(
'cross', 'Failed!',
sessFailReasons[fail.session.reason] ?? `Unknown reason: ${fail.session.reason}`
);
if(fail.session.needsAuth)
setTimeout(() => location.assign(futami.get('login')), 1000);
@ -721,7 +661,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
Umi.Server.watch('session:term', term => {
if(dumpEvents) console.log('session:term', term);
displayBanMessage(term.baka);
new MamiForceDisconnectNotice(term.baka).pushOn(views);
});
Umi.Server.watch('user:add', add => {

1
src/mami.js/sleep.js Normal file
View file

@ -0,0 +1 @@
const MamiSleep = durationMs => new Promise(resolve => { setTimeout(resolve, durationMs); });

82
src/mami.js/ui/baka.jsx Normal file
View file

@ -0,0 +1,82 @@
#include animate.js
#include easings.js
#include rng.js
const MamiForceDisconnectNotice = function(banInfo) {
const message = (() => {
if(banInfo.perma)
return 'You have been banned till the end of time, please try again in a different dimension';
if(banInfo.until)
return `You were banned until ${banInfo.until.toLocaleString()}`;
return 'You were kicked, refresh to log back in';
})();
let marqueeElem;
const html = <div class="baka">
<div class="baka-container">
<div class="baka-duration">
<div class="baka-duration-inner">{message}</div>
</div>
{marqueeElem = <div class="baka-marquee"></div>}
</div>
<div class="baka-bottom"/>
</div>;
const marqueeString = banInfo.type === 'kick' ? 'Kicked' : 'Banned';
for(let i = 0; i < 10; ++i)
marqueeElem.append(<div class="baka-marquee-text">{marqueeString}</div>);
const rng = new MamiRNG;
let sfxBuf, sfxSrc, bgmSrc;
const pub = {
getElement: () => html,
onViewPush: async () => {
try {
sfxBuf = await mami.sound.library.loadBuffer('touhou:pichuun');
sfxSrc = mami.sound.audio.createSource(sfxBuf);
} catch(ex) {
sfxBuf = sfxSrc = undefined;
}
try {
bgmSrc = await mami.sound.library.loadSource('touhou:th10score');
bgmSrc.setLoop(true, 10.512, 38.074);
} catch(ex) {
bgmSrc = undefined;
}
},
onViewPop: async () => {
bgmSrc?.stop();
bgmSrc = sfxBuf = sfxSrc = undefined;
},
pushOn: async views => {
const rotate = rng.next(-20, 20);
await views.push(pub, ctx => MamiAnimate({
async: true,
duration: (sfxBuf?.duration ?? 1.4) * 1000,
start: () => {
sfxSrc?.play();
ctx.toElem.style.top = '-100%';
},
update: t => {
const tOutBounce = MamiEasings.outBounce(t);
ctx.toElem.style.top = `${-100 + (tOutBounce * 100)}%`;
const tOutExpo = MamiEasings.outExpo(t);
ctx.fromElem.style.transform = `scale(${1 - (1 * tOutExpo)}) rotate(${rotate * tOutExpo}deg)`;
ctx.fromElem.style.filter = `grayscale(${tOutExpo * 100}%)`;
},
end: () => {
bgmSrc?.play();
ctx.toElem.style.top = null;
ctx.fromElem.style.transform = null;
ctx.fromElem.style.filter = null;
},
}));
},
};
return pub;
};

View file

@ -1,12 +1,14 @@
#include animate.js
#include common.js
#include emotes.js
#include sleep.js
#include utility.js
#include youare.jsx
#include settings/backup.js
#include ui/baka.jsx
#include ui/emotes.js
#include ui/menus.js
#include ui/view.js
#include ui/youare.jsx
Umi.UI.Settings = (function() {
const items = [
@ -384,6 +386,20 @@ Umi.UI.Settings = (function() {
title: 'Disable Old Theme System',
type: 'checkbox',
},
{
title: 'Test kick/ban notice',
type: 'button',
invoke: async button => {
button.disabled = true;
await (new MamiForceDisconnectNotice({
perma: true,
type: 'ban',
})).pushOn(mami.views);
await MamiSleep(5000);
await mami.views.pop();
button.disabled = false;
},
},
{
title: 'You are an idiot!',
type: 'button',