Merge pull request #294 from bui/bug-fixes

Bug fixes
This commit is contained in:
Bui 2020-12-05 03:14:12 +00:00 committed by GitHub
commit 665fc57929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 211 additions and 73 deletions

10
app.py
View File

@ -191,10 +191,10 @@ def route_admin():
@app.route('/admin/songs')
@admin_required(level=50)
def route_admin_songs():
songs = db.songs.find({})
songs = sorted(list(db.songs.find({})), key=lambda x: x['id'])
categories = db.categories.find({})
user = db.users.find_one({'username': session['username']})
return render_template('admin_songs.html', songs=list(songs), admin=user, categories=list(categories))
return render_template('admin_songs.html', songs=songs, admin=user, categories=list(categories), config=get_config())
@app.route('/admin/songs/<int:id>')
@ -210,7 +210,7 @@ def route_admin_songs_id(id):
user = db.users.find_one({'username': session['username']})
return render_template('admin_song_detail.html',
song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user)
song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user, config=get_config())
@app.route('/admin/songs/new')
@ -219,8 +219,10 @@ def route_admin_songs_new():
categories = list(db.categories.find({}))
song_skins = list(db.song_skins.find({}))
makers = list(db.makers.find({}))
seq = db.seq.find_one({'name': 'songs'})
seq_new = seq['value'] + 1 if seq else 1
return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers)
return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers, config=get_config(), id=seq_new)
@app.route('/admin/songs/new', methods=['POST'])

View File

@ -15,6 +15,7 @@
z-index: 1;
width: 100%;
height: 100%;
touch-action: none;
}
#touch-drum{
display: none;

View File

@ -55,6 +55,9 @@
white-space: nowrap;
transition: background-image 0.5s;
}
#song-select.unfocused{
animation-play-state: paused;
}
#song-sel-canvas{
position: absolute;
right: 0;

View File

@ -59,6 +59,9 @@ kbd{
line-height: 1.4;
white-space: nowrap;
}
.key-join{
font-size: 0.6em;
}
.taibtn{
display: inline-block;
background: #f6ead4;

View File

@ -53,6 +53,9 @@ function browserSupport(){
},
"OGG or WebAssembly": function(){
return new Audio().canPlayType("audio/ogg;codecs=vorbis") || "WebAssembly" in window
},
"KeyboardEvent.key": function(){
return "key" in KeyboardEvent.prototype
}
}
failedTests = []

View File

@ -25,7 +25,7 @@ class Controller{
this.videoLatency = 0
if(!this.calibrationMode){
var latency = settings.getItem("latency")
if(!autoPlayEnabled){
if(!autoPlayEnabled || this.multiplayer){
this.audioLatency = Math.round(latency.audio) || 0
}
this.videoLatency = Math.round(latency.video) || 0 + this.audioLatency
@ -218,6 +218,9 @@ class Controller{
}
displayResults(){
if(this.multiplayer !== 2){
if(this.view.cursorHidden){
this.view.canvas.style.cursor = ""
}
this.scoresheet = new Scoresheet(this, this.getGlobalScore(), this.multiplayer, this.touchEnabled)
}
}
@ -251,15 +254,15 @@ class Controller{
var chartDiff = this.selectedSong.difficulty
chart = chart[chartDiff]
}
promises.push(chart.read(this.selectedSong.type === "tja" ? "sjis" : undefined).then(data => {
this.addPromise(promises, chart.read(this.selectedSong.type === "tja" ? "sjis" : undefined).then(data => {
this.songData = data.replace(/\0/g, "").split("\n")
return Promise.resolve()
}))
}), chart.url)
}
if(songObj.lyricsFile){
promises.push(songObj.lyricsFile.read().then(result => {
this.addPromise(promises, songObj.lyricsFile.read().then(result => {
songObj.lyricsData = result
}, () => Promise.resolve()), songObj.lyricsFile.path)
}, () => Promise.resolve()), songObj.lyricsFile.url)
}
Promise.all(promises).then(resolve)
}
@ -269,6 +272,32 @@ class Controller{
})
}
}
addPromise(promises, promise, url){
promises.push(promise.catch(error => {
if(this.restartSongError){
return
}
this.restartSongError = true
if(url){
error = (Array.isArray(error) ? error[0] + ": " : (error ? error + ": " : "")) + url
}
pageEvents.send("load-song-error", error)
errorMessage(new Error(error).stack)
var title = this.selectedSong.title
if(title !== this.selectedSong.originalTitle){
title += " (" + this.selectedSong.originalTitle + ")"
}
setTimeout(() => {
new SongSelect(false, false, this.touchEnabled, null, {
name: "loadSongError",
title: title,
id: this.selectedSong.folder,
error: error
})
}, 500)
return Promise.reject(error)
}))
}
playSound(id, time, noSnd){
if(!this.drumSounds && (id === "neiro_1_don" || id === "neiro_1_ka" || id === "se_don" || id === "se_ka")){
return

View File

@ -20,12 +20,18 @@ class CustomSongs{
this.items = []
this.linkLocalFolder = document.getElementById("link-localfolder")
this.hasLocal = "webkitdirectory" in HTMLInputElement.prototype && !(/Android|iPhone|iPad/.test(navigator.userAgent))
this.selected = -1
if(this.hasLocal){
this.browse = document.getElementById("browse")
pageEvents.add(this.browse, "change", this.browseChange.bind(this))
this.setAltText(this.linkLocalFolder, strings.customSongs.localFolder)
pageEvents.add(this.linkLocalFolder, ["mousedown", "touchstart"], this.localFolder.bind(this))
this.items.push(this.linkLocalFolder)
if(this.selected === -1){
this.linkLocalFolder.classList.add("selected")
this.selected = this.items.length - 1
}
}else{
this.linkLocalFolder.parentNode.removeChild(this.linkLocalFolder)
}
@ -35,6 +41,10 @@ class CustomSongs{
this.setAltText(this.linkGdriveFolder, strings.customSongs.gdriveFolder)
pageEvents.add(this.linkGdriveFolder, ["mousedown", "touchstart"], this.gdriveFolder.bind(this))
this.items.push(this.linkGdriveFolder)
if(this.selected === -1){
this.linkGdriveFolder.classList.add("selected")
this.selected = this.items.length - 1
}
}else{
this.linkGdriveFolder.parentNode.removeChild(this.linkGdriveFolder)
}
@ -43,7 +53,10 @@ class CustomSongs{
this.setAltText(this.endButton, strings.session.cancel)
pageEvents.add(this.endButton, ["mousedown", "touchstart"], event => this.onEnd(event, true))
this.items.push(this.endButton)
if(this.selected === -1){
this.endButton.classList.add("selected")
this.selected = this.items.length - 1
}
this.loaderDiv = document.createElement("div")
this.loaderDiv.innerHTML = assets.pages["loadsong"]

View File

@ -212,11 +212,6 @@ class GameInput{
}
this.keyboardEvents++
}
}else{
this.keys[name] = false
this.waitKeyupScore[name] = false
this.waitKeyupSound[name] = false
this.waitKeyupMenu[name] = false
}
}
isWaiting(name, type){

View File

@ -110,7 +110,7 @@ class LoadSong{
if(songObj.custom){
this.addPromise(song.songSkin[filename + ".png"].blob().then(blob => {
img.src = URL.createObjectURL(blob)
}))
}), song.songSkin[filename + ".png"].url)
}else{
img.src = skinBase + filename + ".png"
}
@ -118,7 +118,7 @@ class LoadSong{
}
this.loadSongBg(id)
if(songObj.sound){
if(songObj.sound && songObj.sound.buffer){
songObj.sound.gain = snd.musicGain
}else if(songObj.music !== "muted"){
this.addPromise(snd.musicGain.load(songObj.music).then(sound => {

View File

@ -4,6 +4,7 @@ class Mekadon{
this.game = game
this.lr = false
this.lastHit = -Infinity
this.delay = controller.audioLatency
}
play(circle){
var type = circle.type
@ -24,7 +25,7 @@ class Mekadon{
}
}
playAt(circle, ms, score, dai, reverse){
var currentMs = circle.ms - this.getMS()
var currentMs = circle.ms - this.getMS() + this.delay
if(ms > currentMs - 10){
return this.playNow(circle, score, dai, reverse)
}

View File

@ -218,7 +218,7 @@ class P2Connection{
var type = circle.type
var drumrollNotes = type === "balloon" || type === "drumroll" || type === "daiDrumroll"
if(drumrollNotes && mekadon.getMS() > circle.endTime){
if(drumrollNotes && mekadon.getMS() > circle.endTime + mekadon.delay){
circle.played(-1, false)
mekadon.game.updateCurrentCircle()
}

View File

@ -226,7 +226,6 @@
for (var i = 0; i < currentMeasure.length; i++){
//console.log(note_chain.length);
var note = currentMeasure[i]
if (note.type) {
circleID++
var circleObj = new Circle({
id: circleID,
@ -241,6 +240,7 @@
branch: currentBranch,
section: note.section
})
if (note.type) {
if (note.type === "don" || note.type === "ka" || note.type === "daiDon" || note.type === "daiKa") {
note_chain.push(circleObj);
} else {
@ -253,9 +253,6 @@
lastDrumroll = circleObj
}
if(note.event){
this.events.push(circleObj)
}
if(note.type !== "event"){
circles.push(circleObj)
}
@ -266,6 +263,9 @@
}
note_chain = [];
}
if(note.event){
this.events.push(circleObj)
}
if("lyricsLine" in note){
if(!this.lyrics){
this.lyrics = []
@ -488,8 +488,9 @@
sectionBegin = false
if(lastDrumroll){
if(symbol === "9"){
insertBlankNote({
insertNote({
endDrumroll: lastDrumroll,
gogo: gogo,
bpm: bpm,
scroll: scroll,
section: sectionBegin
@ -514,8 +515,9 @@
break
case "8":
if(lastDrumroll){
insertBlankNote({
insertNote({
endDrumroll: lastDrumroll,
gogo: gogo,
bpm: bpm,
scroll: scroll,
section: sectionBegin
@ -523,10 +525,7 @@
sectionBegin = false
lastDrumroll = false
}else{
insertBlankNote({
bpm: bpm,
scroll: scroll
})
insertBlankNote()
}
break
case ",":

View File

@ -236,6 +236,12 @@ class Scoresheet{
}
}
}else if(!document.hasFocus() && this.state.screen === "scoresShown"){
if(this.state["countup0"]){
this.stopSound("se_results_countup", 0)
}
if(this.state["countup1"]){
this.stopSound("se_results_countup", 1)
}
return
}else{
ctx.clearRect(0, 0, winW / ratio, winH / ratio)

View File

@ -258,13 +258,15 @@ class SongSelect{
screenMS: this.getMS(),
move: 0,
moveMS: 0,
mouseMoveMS: 0,
ura: 0,
moveHover: null,
locked: true,
hasPointer: false,
options: 0,
selLock: false,
catJump: false
catJump: false,
focused: true
}
this.songSelecting = {
speed: 800,
@ -284,7 +286,8 @@ class SongSelect{
down: ["down"],
session: ["backspace"],
ctrl: ["ctrl"],
shift: ["shift"]
shift: ["shift"],
mute: ["q"]
}, this.keyPress.bind(this))
this.gamepad = new Gamepad({
confirm: ["b", "start", "ls", "rs"],
@ -294,7 +297,7 @@ class SongSelect{
up: ["u", "lsu"],
down: ["d", "lsd"],
session: ["back"],
ctrl: ["y"],
ctrlGamepad: ["y"],
shift: ["x"],
jump_left: ["lb"],
jump_right: ["rb"]
@ -341,6 +344,7 @@ class SongSelect{
if(name === "ctrl" || name === "shift" || !this.redrawRunning){
return
}
var ctrl = this.pressedKeys["ctrl"] || this.pressedKeys["ctrlGamepad"]
var shift = event ? event.shiftKey : this.pressedKeys["shift"]
if(this.state.showWarning){
if(name === "confirm"){
@ -375,6 +379,9 @@ class SongSelect{
this.categoryJump(-1)
}else if(name === "jump_right" && !repeat){
this.categoryJump(1)
}else if(name === "mute" || name === "ctrlGamepad"){
this.endPreview(true)
this.playBgm(false)
}
}else if(this.state.screen === "difficulty"){
if(name === "confirm"){
@ -383,7 +390,7 @@ class SongSelect{
}else if(this.selectedDiff === 1){
this.toOptions(1)
}else{
this.toLoadSong(this.selectedDiff - this.diffOptions.length, shift, this.pressedKeys["ctrl"])
this.toLoadSong(this.selectedDiff - this.diffOptions.length, shift, ctrl)
}
}else if(name === "back" || name === "session"){
this.toSongSelect()
@ -393,6 +400,9 @@ class SongSelect{
this.moveToDiff(1)
}else if(this.selectedDiff === 1 && (name === "up" || name === "down")){
this.toOptions(name === "up" ? -1 : 1)
}else if(name === "mute" || name === "ctrlGamepad"){
this.endPreview(true)
this.playBgm(false)
}
}
}
@ -417,7 +427,9 @@ class SongSelect{
var touch = false
}else{
event.preventDefault()
var mouse = this.mouseOffset(event.touches[0].pageX, event.touches[0].pageY)
var x = event.touches[0].pageX - this.canvas.offsetLeft
var y = event.touches[0].pageY - this.canvas.offsetTop
var mouse = this.mouseOffset(x, y)
var shift = false
var ctrl = false
var touch = true
@ -472,7 +484,9 @@ class SongSelect{
if(this.state.screen === "song" && this.redrawRunning){
var currentSong = this.songs[this.selectedSong]
if(currentSong.action === "customSongs"){
var mouse = this.mouseOffset(event.changedTouches[0].pageX, event.changedTouches[0].pageY)
var x = event.changedTouches[0].pageX - this.canvas.offsetLeft
var y = event.changedTouches[0].pageY - this.canvas.offsetTop
var mouse = this.mouseOffset(x, y)
var moveBy = this.songSelMouse(mouse.x, mouse.y)
if(moveBy === 0){
this.toCustomSongs()
@ -499,14 +513,14 @@ class SongSelect{
}else{
var moveTo = this.songSelMouse(mouse.x, mouse.y)
if(moveTo === null && this.state.moveHover === 0 && !this.songs[this.selectedSong].courses){
this.state.moveMS = this.getMS() - this.songSelecting.speed
this.state.mouseMoveMS = this.getMS() - this.songSelecting.speed
}
}
this.state.moveHover = moveTo
}else if(this.state.screen === "difficulty"){
var moveTo = this.diffSelMouse(mouse.x, mouse.y)
if(moveTo === null && this.state.moveHover === this.selectedDiff){
this.state.moveMS = this.getMS() - 1000
this.state.mouseMoveMS = this.getMS() - 1000
}
this.state.moveHover = moveTo
}
@ -953,11 +967,18 @@ class SongSelect{
this.selectableText = ""
}else if(!document.hasFocus() && !p2.session){
this.pointer(false)
if(this.state.focused){
this.state.focused = false
this.songSelect.classList.add("unfocused")
}
return
}else{
ctx.clearRect(0, 0, winW / ratio, winH / ratio)
}
if(!this.state.focused){
this.state.focused = true
this.songSelect.classList.remove("unfocused")
}
this.winW = winW
this.winH = winH
this.ratio = ratio
@ -1178,7 +1199,9 @@ class SongSelect{
selectedWidth = this.songAsset.width
}
}else{
if(this.previewing !== "muted"){
this.playBgm(!this.songs[this.selectedSong].courses)
}
this.state.locked = 0
}
}else if(screen === "difficulty"){
@ -1220,7 +1243,7 @@ class SongSelect{
this.endPreview()
}
}else if(screen !== "title" && screen !== "titleFadeIn" && ms > this.state.moveMS + 100){
if(this.previewing !== this.selectedSong && "id" in this.songs[this.selectedSong]){
if(this.previewing !== "muted" && this.previewing !== this.selectedSong && "id" in this.songs[this.selectedSong]){
this.startPreview()
}
}
@ -1328,7 +1351,7 @@ class SongSelect{
borderStyle: selectedSkin.border,
highlight: highlight,
noCrop: screen === "difficulty",
animateMS: this.state.moveMS,
animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS),
cached: selectedWidth === this.songAsset.fullWidth ? 3 : (selectedWidth === this.songAsset.selectedWidth ? 2 : (selectedWidth === this.songAsset.width ? 1 : 0)),
frameCache: this.songFrameCache,
disabled: p2.session && currentSong.action && currentSong.action !== "random",
@ -1430,7 +1453,7 @@ class SongSelect{
w: 64,
h: 304,
animate: highlight === 1,
animateMS: this.state.moveMS,
animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS),
opacity: highlight === 2 ? 0.8 : 1,
radius: 24
})
@ -1547,7 +1570,8 @@ class SongSelect{
var songStarsObj = (currentUra ? currentSong.courses.ura : currentSong.courses[this.difficultyId[i]])
var songStars = songStarsObj.stars
var songBranch = songStarsObj.branch
var elapsedMS = this.state.screenMS > this.state.moveMS || !songSel ? this.state.screenMS : this.state.moveMS
var moveMS = Math.max(this.state.moveMS, this.state.mouseMoveMS)
var elapsedMS = this.state.screenMS > moveMS || !songSel ? this.state.screenMS : moveMS
var fade = ((ms - elapsedMS) % 2000) / 2000
if(songBranch && fade > 0.25 && fade < 0.75){
this.draw.verticalText({
@ -1616,7 +1640,7 @@ class SongSelect{
w: 64,
h: 362,
animate: highlight === 1,
animateMS: this.state.moveMS,
animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS),
opacity: highlight === 2 ? 0.8 : 1
})
}
@ -1627,7 +1651,7 @@ class SongSelect{
var currentUra = i === 3 && (this.state.ura && !songSel || currentSong.courses.ura && songSel)
if(songSel && currentUra){
drawDifficulty(ctx, i, false)
var elapsedMS = this.state.screenMS > this.state.moveMS ? this.state.screenMS : this.state.moveMS
var elapsedMS = Math.max(this.state.screenMS, this.state.moveMS, this.state.mouseMoveMS)
var fade = ((ms - elapsedMS) % 4000) / 4000
var alphaFade = 0
if(fade > 0.95){
@ -1651,6 +1675,9 @@ class SongSelect{
var _x = x + 402 + i * 100
var _y = y + 87
var currentDiff = this.selectedDiff - this.diffOptions.length
if(this.selectedDiff === 4 + this.diffOptions.length){
currentDiff = 3
}
this.draw.diffCursor({
ctx: ctx,
font: this.font,
@ -2241,7 +2268,7 @@ class SongSelect{
w: _w + 7,
h: _h + 7,
animate: highlight === 1,
animateMS: this.state.moveMS,
animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS),
opacity: highlight === 2 ? 0.8 : 1,
radius: 30
})
@ -2288,7 +2315,7 @@ class SongSelect{
config.borderStyle = config.song.skin.border
config.outline = config.song.skin.outline
config.text = config.song.title
config.animateMS = this.state.moveMS
config.animateMS = Math.max(this.state.moveMS, this.state.mouseMoveMS)
config.cached = 1
config.frameCache = this.songFrameCache
config.innerContent = (x, y, w, h) => {
@ -2376,7 +2403,7 @@ class SongSelect{
var currentSong = this.songs[this.selectedSong]
var id = currentSong.id
var prvTime = currentSong.preview
this.endPreview(true)
this.endPreview()
if("id" in currentSong){
var startLoad = this.getMS()
@ -2445,9 +2472,9 @@ class SongSelect{
snd.previewGain.setVolumeMul(volume || 1)
this.preview.playLoop(delay / 1000, false, prvTime)
}
endPreview(){
endPreview(force){
this.previewId++
this.previewing = null
this.previewing = force ? "muted" : null
if(this.preview){
this.preview.stop()
}

View File

@ -506,6 +506,33 @@ var translations = {
cn: "确定",
tw: "確定",
ko: "확인"
},
key: {
ctrl: {
en: "CTRL"
},
shift: {
en: "⇧ SHIFT"
},
leftArrow: {
en: "\u2190"
},
rightArrow: {
en: "\u2192"
},
esc: {
en: "ESC"
},
join: {
en: "+"
},
or: {
ja: "または",
en: " or ",
cn: "或",
tw: "或",
ko: " 또는 "
}
}
},
about: {

View File

@ -36,10 +36,30 @@ class Tutorial{
parent.appendChild(document.createTextNode(text))
}
insertKey(key, parent){
if(!Array.isArray(key)){
key = [key]
}
var join = true
for(var i = 0; i < key.length; i++){
if(key[i] === false){
join = false
continue
}
if(i !== 0){
if(join){
var span = document.createElement("span")
span.classList.add("key-join")
span.innerText = strings.tutorial.key.join
parent.appendChild(span)
}else{
parent.appendChild(document.createTextNode(strings.tutorial.key.or))
}
}
var kbd = document.createElement("kbd")
kbd.innerText = key
kbd.innerText = key[i]
parent.appendChild(kbd)
}
}
onEnd(pressed, name){
if(pressed){
this.clean()
@ -59,13 +79,21 @@ class Tutorial{
this.endButton.setAttribute("alt", strings.tutorial.ok)
this.tutorialDiv.innerHTML = ""
var kbdSettings = settings.getItem("keyboardSettings")
var pauseKey = "ESC"
var pauseKey = [strings.tutorial.key.esc]
if(pageEvents.kbd.indexOf("q") === -1){
pauseKey.push(false)
pauseKey.push("Q")
}
var keys = [
kbdSettings.don_l[0].toUpperCase(),
kbdSettings.don_r[0].toUpperCase(),
kbdSettings.ka_l[0].toUpperCase(),
kbdSettings.ka_r[0].toUpperCase(),
pauseKey, "SHIFT+LEFT", "SHIFT+RIGHT", "SHIFT", "CTRL"
pauseKey,
[strings.tutorial.key.shift, strings.tutorial.key.leftArrow],
[strings.tutorial.key.shift, strings.tutorial.key.rightArrow],
strings.tutorial.key.shift,
strings.tutorial.key.ctrl
]
var keyIndex = 0
strings.tutorial.basics.forEach(string => {

View File

@ -6,7 +6,7 @@
<div id="link-localfolder" class="taibtn stroke-sub link-btn"></div>
<div id="link-gdrivefolder" class="taibtn stroke-sub link-btn"></div>
</div>
<div class="view-end-button taibtn stroke-sub selected"></div>
<div class="view-end-button taibtn stroke-sub"></div>
<div class="view-outer shadow-outer" id="dropzone">
<div class="view">
<div class="view-content"></div>

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<title>Taiko Web Admin</title>
<link rel="icon" href="{{config.assets_baseurl}}img/favicon.png" type="image/png">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">

View File

@ -1,6 +1,6 @@
{% extends 'admin.html' %}
{% block content %}
{% if song.title_lang.en %}
{% if song.title_lang.en and song.title_lang.en != song.title %}
<h1>{{ song.title_lang.en }} <small>({{ song.title }})</small> <small class="song-id">(ID: {{ song.id }})</small></h1>
{% else %}
<h1>{{ song.title }} <small class="song-id">(ID: {{ song.id }})</small></h1>

View File

@ -1,6 +1,6 @@
{% extends 'admin.html' %}
{% block content %}
<h1>New song</h1>
<h1>New song <small class="song-id">(ID: {{ id }})</small></h1>
{% for message in get_flashed_messages() %}
<div class="message">{{ message }}</div>
{% endfor %}
@ -9,7 +9,7 @@
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="form-field">
<span class="checkbox"><input type="checkbox" name="enabled" id="enabled"><label for="enabled"> Enabled</label></span>
<span class="checkbox"><input type="checkbox" name="enabled" id="enabled" checked><label for="enabled"> Enabled</label></span>
</div>
<div class="form-field">