11
app.py
11
app.py
@@ -371,12 +371,15 @@ def route_admin_users_post():
|
|||||||
max_level = admin['user_level'] - 1
|
max_level = admin['user_level'] - 1
|
||||||
|
|
||||||
username = request.form.get('username')
|
username = request.form.get('username')
|
||||||
level = int(request.form.get('level')) or 0
|
try:
|
||||||
|
level = int(request.form.get('level')) or 0
|
||||||
|
except ValueError:
|
||||||
|
level = 0
|
||||||
|
|
||||||
user = db.users.find_one({'username': username})
|
user = db.users.find_one({'username_lower': username.lower()})
|
||||||
if not user:
|
if not user:
|
||||||
flash('Error: User was not found.')
|
flash('Error: User was not found.')
|
||||||
elif admin_name == username:
|
elif admin['username'] == user['username']:
|
||||||
flash('Error: You cannot modify your own level.')
|
flash('Error: You cannot modify your own level.')
|
||||||
else:
|
else:
|
||||||
user_level = user['user_level']
|
user_level = user['user_level']
|
||||||
@@ -386,7 +389,7 @@ def route_admin_users_post():
|
|||||||
flash('Error: This user has higher level than you.')
|
flash('Error: This user has higher level than you.')
|
||||||
else:
|
else:
|
||||||
output = {'user_level': level}
|
output = {'user_level': level}
|
||||||
db.users.update_one({'username': username}, {'$set': output})
|
db.users.update_one({'username': user['username']}, {'$set': output})
|
||||||
flash('User updated.')
|
flash('User updated.')
|
||||||
|
|
||||||
return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)
|
return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)
|
||||||
|
|||||||
@@ -201,6 +201,20 @@ kbd{
|
|||||||
.setting-name::before{
|
.setting-name::before{
|
||||||
padding-left: 0.3em;
|
padding-left: 0.3em;
|
||||||
}
|
}
|
||||||
|
.setting-name::after{
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 100%;
|
||||||
|
background-image: linear-gradient(90deg, transparent, #f6ead4 90%);
|
||||||
|
}
|
||||||
|
.view-content:not(:hover) .setting-box.selected .setting-name::after,
|
||||||
|
.setting-box:hover .setting-name::after{
|
||||||
|
background-image: linear-gradient(90deg, transparent, #ffb547 90%);
|
||||||
|
}
|
||||||
.setting-value{
|
.setting-value{
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@@ -403,6 +417,7 @@ kbd{
|
|||||||
}
|
}
|
||||||
.customdon-canvas{
|
.customdon-canvas{
|
||||||
width: 13em;
|
width: 13em;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.customdon-div label{
|
.customdon-div label{
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function filePermission(file){
|
|||||||
if(response === "granted"){
|
if(response === "granted"){
|
||||||
return file
|
return file
|
||||||
}else{
|
}else{
|
||||||
return Promise.reject(file)
|
return Promise.reject(strings.accessNotGrantedError)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ class Account{
|
|||||||
this.inputForms.push(this.displayname)
|
this.inputForms.push(this.displayname)
|
||||||
|
|
||||||
this.redrawRunning = true
|
this.redrawRunning = true
|
||||||
|
this.redrawPaused = matchMedia("(prefers-reduced-motion: reduce)").matches
|
||||||
|
this.redrawForce = true
|
||||||
this.customdonRedrawBind = this.customdonRedraw.bind(this)
|
this.customdonRedrawBind = this.customdonRedraw.bind(this)
|
||||||
this.start = new Date().getTime()
|
this.start = new Date().getTime()
|
||||||
this.frames = [
|
this.frames = [
|
||||||
@@ -57,6 +59,7 @@ class Account{
|
|||||||
this.customdonCache = new CanvasCache()
|
this.customdonCache = new CanvasCache()
|
||||||
this.customdonCache.resize(723 * 2, 1858, 1)
|
this.customdonCache.resize(723 * 2, 1858, 1)
|
||||||
this.customdonCanvas = this.getElement("customdon-canvas")
|
this.customdonCanvas = this.getElement("customdon-canvas")
|
||||||
|
pageEvents.add(this.customdonCanvas, "click", this.customdonPause.bind(this))
|
||||||
this.customdonCtx = this.customdonCanvas.getContext("2d")
|
this.customdonCtx = this.customdonCanvas.getContext("2d")
|
||||||
this.customdonBodyFill = this.getElement("customdon-bodyfill")
|
this.customdonBodyFill = this.getElement("customdon-bodyfill")
|
||||||
this.customdonBodyFill.value = account.don.body_fill
|
this.customdonBodyFill.value = account.don.body_fill
|
||||||
@@ -120,6 +123,11 @@ class Account{
|
|||||||
pageEvents.add(this.inputForms[i], ["keydown", "keyup", "keypress"], this.onFormPress.bind(this))
|
pageEvents.add(this.inputForms[i], ["keydown", "keyup", "keypress"], this.onFormPress.bind(this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
customdonPause(){
|
||||||
|
this.redrawPaused = !this.redrawPaused
|
||||||
|
this.redrawForce = true
|
||||||
|
this.start = new Date().getTime()
|
||||||
|
}
|
||||||
customdonChange(){
|
customdonChange(){
|
||||||
var ctx = this.customdonCtx
|
var ctx = this.customdonCtx
|
||||||
this.customdonCache.clear()
|
this.customdonCache.clear()
|
||||||
@@ -148,6 +156,7 @@ class Account{
|
|||||||
id: "bodyFill"
|
id: "bodyFill"
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
this.redrawForce = true
|
||||||
}
|
}
|
||||||
customdonReset(event){
|
customdonReset(event){
|
||||||
if(event.type === "touchstart"){
|
if(event.type === "touchstart"){
|
||||||
@@ -162,12 +171,16 @@ class Account{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
requestAnimationFrame(this.customdonRedrawBind)
|
requestAnimationFrame(this.customdonRedrawBind)
|
||||||
if(!document.hasFocus()){
|
if(!document.hasFocus() || this.redrawPaused && !this.redrawForce){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var ms = new Date().getTime()
|
var ms = new Date().getTime()
|
||||||
var ctx = this.customdonCtx
|
var ctx = this.customdonCtx
|
||||||
var frame = this.frames[Math.floor((ms - this.start) / 30) % this.frames.length]
|
if(this.redrawPaused){
|
||||||
|
var frame = 0
|
||||||
|
}else{
|
||||||
|
var frame = this.frames[Math.floor((ms - this.start) / 30) % this.frames.length]
|
||||||
|
}
|
||||||
var w = 360
|
var w = 360
|
||||||
var h = 184
|
var h = 184
|
||||||
var sx = Math.floor(frame / 10) * (w + 2)
|
var sx = Math.floor(frame / 10) * (w + 2)
|
||||||
@@ -183,6 +196,7 @@ class Account{
|
|||||||
sx, sy, w, h,
|
sx, sy, w, h,
|
||||||
-26, 0, w, h
|
-26, 0, w, h
|
||||||
)
|
)
|
||||||
|
this.redrawForce = false
|
||||||
}
|
}
|
||||||
showDiv(event, div){
|
showDiv(event, div){
|
||||||
if(event){
|
if(event){
|
||||||
@@ -318,6 +332,7 @@ class Account{
|
|||||||
onFormPress(event){
|
onFormPress(event){
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
if(event.type === "keypress" && event.keyCode === 13){
|
if(event.type === "keypress" && event.keyCode === 13){
|
||||||
|
event.preventDefault()
|
||||||
if(this.mode === "account"){
|
if(this.mode === "account"){
|
||||||
this.onSave()
|
this.onSave()
|
||||||
}else{
|
}else{
|
||||||
@@ -611,6 +626,7 @@ class Account{
|
|||||||
}
|
}
|
||||||
this.redrawRunning = false
|
this.redrawRunning = false
|
||||||
this.customdonCache.clean()
|
this.customdonCache.clean()
|
||||||
|
pageEvents.remove(this.customdonCanvas, "click")
|
||||||
pageEvents.remove(this.customdonBodyFill, ["change", "input"])
|
pageEvents.remove(this.customdonBodyFill, ["change", "input"])
|
||||||
pageEvents.remove(this.customdonFaceFill, ["change", "input"])
|
pageEvents.remove(this.customdonFaceFill, ["change", "input"])
|
||||||
pageEvents.remove(this.customdonResetBtn, ["click", "touchstart"])
|
pageEvents.remove(this.customdonResetBtn, ["click", "touchstart"])
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ class CanvasCache{
|
|||||||
this.h = h
|
this.h = h
|
||||||
this.lastW = 0
|
this.lastW = 0
|
||||||
this.lastH = 0
|
this.lastH = 0
|
||||||
this.canvas.width = this.w * this.scale
|
this.canvas.width = Math.max(1, this.w * this.scale)
|
||||||
this.canvas.height = this.h * this.scale
|
this.canvas.height = Math.max(1, this.h * this.scale)
|
||||||
this.ctx.scale(this.scale, this.scale)
|
this.ctx.scale(this.scale, this.scale)
|
||||||
}
|
}
|
||||||
get(config, callback, setOnly){
|
get(config, callback, setOnly){
|
||||||
|
|||||||
@@ -157,7 +157,7 @@
|
|||||||
ctx.fillRect(0, 0, w, h)
|
ctx.fillRect(0, 0, w, h)
|
||||||
}
|
}
|
||||||
if(config.cached){
|
if(config.cached){
|
||||||
if(this.songFrameCache.w !== config.frameCache.w){
|
if(this.songFrameCache.w !== config.frameCache.w || this.songFrameCache.scale !== config.frameCache.ratio){
|
||||||
this.songFrameCache.resize(config.frameCache.w, config.frameCache.h, config.frameCache.ratio)
|
this.songFrameCache.resize(config.frameCache.w, config.frameCache.h, config.frameCache.ratio)
|
||||||
}
|
}
|
||||||
this.songFrameCache.get({
|
this.songFrameCache.get({
|
||||||
@@ -1680,8 +1680,8 @@
|
|||||||
if(amount >= 1){
|
if(amount >= 1){
|
||||||
return callback(ctx)
|
return callback(ctx)
|
||||||
}else if(amount >= 0){
|
}else if(amount >= 0){
|
||||||
this.tmpCanvas.width = winW || ctx.canvas.width
|
this.tmpCanvas.width = Math.max(1, winW || ctx.canvas.width)
|
||||||
this.tmpCanvas.height = winH || ctx.canvas.height
|
this.tmpCanvas.height = Math.max(1, winH || ctx.canvas.height)
|
||||||
callback(this.tmpCtx)
|
callback(this.tmpCtx)
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.globalAlpha = amount
|
ctx.globalAlpha = amount
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ class CanvasTest{
|
|||||||
var pixelRatio = window.devicePixelRatio || 1
|
var pixelRatio = window.devicePixelRatio || 1
|
||||||
var width = innerWidth * pixelRatio
|
var width = innerWidth * pixelRatio
|
||||||
var height = innerHeight * pixelRatio
|
var height = innerHeight * pixelRatio
|
||||||
this.canvas.width = width
|
this.canvas.width = Math.max(1, width)
|
||||||
this.canvas.height = height
|
this.canvas.height = Math.max(1, height)
|
||||||
this.ctx = this.canvas.getContext("2d")
|
this.ctx = this.canvas.getContext("2d")
|
||||||
this.ctx.scale(pixelRatio, pixelRatio)
|
this.ctx.scale(pixelRatio, pixelRatio)
|
||||||
this.ratio = pixelRatio
|
this.ratio = pixelRatio
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ class Controller{
|
|||||||
this.view.displayScore(score, notPlayed, bigNote)
|
this.view.displayScore(score, notPlayed, bigNote)
|
||||||
}
|
}
|
||||||
songSelection(fadeIn, showWarning){
|
songSelection(fadeIn, showWarning){
|
||||||
|
if(this.cleaned){
|
||||||
|
return
|
||||||
|
}
|
||||||
if(!fadeIn){
|
if(!fadeIn){
|
||||||
this.clean()
|
this.clean()
|
||||||
}
|
}
|
||||||
@@ -241,6 +244,9 @@ class Controller{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
restartSong(){
|
restartSong(){
|
||||||
|
if(this.cleaned){
|
||||||
|
return
|
||||||
|
}
|
||||||
this.clean()
|
this.clean()
|
||||||
if(this.multiplayer){
|
if(this.multiplayer){
|
||||||
new LoadSong(this.selectedSong, false, true, this.touchEnabled)
|
new LoadSong(this.selectedSong, false, true, this.touchEnabled)
|
||||||
@@ -363,6 +369,7 @@ class Controller{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
clean(){
|
clean(){
|
||||||
|
this.cleaned = true
|
||||||
if(this.multiplayer === 1){
|
if(this.multiplayer === 1){
|
||||||
this.syncWith.clean()
|
this.syncWith.clean()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -506,10 +506,10 @@ class Game{
|
|||||||
p2.send("gameend")
|
p2.send("gameend")
|
||||||
}
|
}
|
||||||
this.musicFadeOut++
|
this.musicFadeOut++
|
||||||
}else if(this.musicFadeOut === 2 && (ms >= started + 8600 && ms >= musicDuration + 250)){
|
}else if(this.musicFadeOut === 2 && (ms >= Math.max(started + 8600, Math.min(started + 8600 + 5000, musicDuration + 250)))){
|
||||||
this.controller.displayResults()
|
this.controller.displayResults()
|
||||||
this.musicFadeOut++
|
this.musicFadeOut++
|
||||||
}else if(this.musicFadeOut === 3 && (ms >= started + 9600 && ms >= musicDuration + 1250)){
|
}else if(this.musicFadeOut === 3 && (ms >= Math.max(started + 9600, Math.min(started + 9600 + 5000, musicDuration + 1250)))){
|
||||||
this.controller.clean()
|
this.controller.clean()
|
||||||
if(this.controller.scoresheet){
|
if(this.controller.scoresheet){
|
||||||
this.controller.scoresheet.startRedraw()
|
this.controller.scoresheet.startRedraw()
|
||||||
|
|||||||
@@ -111,10 +111,7 @@
|
|||||||
var plugin = plugins.add(obj.data, obj.name)
|
var plugin = plugins.add(obj.data, obj.name)
|
||||||
if(plugin){
|
if(plugin){
|
||||||
pluginAmount++
|
pluginAmount++
|
||||||
plugins.imported.push({
|
plugin.imported = true
|
||||||
name: plugin.name,
|
|
||||||
plugin: plugin
|
|
||||||
})
|
|
||||||
startPromises.push(plugin.start())
|
startPromises.push(plugin.start())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -239,8 +239,8 @@ class LoadSong{
|
|||||||
var canvas = document.createElement("canvas")
|
var canvas = document.createElement("canvas")
|
||||||
var w = Math.floor(img.width * scale)
|
var w = Math.floor(img.width * scale)
|
||||||
var h = Math.floor(img.height * scale)
|
var h = Math.floor(img.height * scale)
|
||||||
canvas.width = w
|
canvas.width = Math.max(1, w)
|
||||||
canvas.height = h
|
canvas.height = Math.max(1, h)
|
||||||
var ctx = canvas.getContext("2d")
|
var ctx = canvas.getContext("2d")
|
||||||
ctx.drawImage(img, 0, 0, w, h)
|
ctx.drawImage(img, 0, 0, w, h)
|
||||||
var saveScaled = url => {
|
var saveScaled = url => {
|
||||||
|
|||||||
@@ -64,8 +64,8 @@
|
|||||||
var pixelRatio = window.devicePixelRatio || 1
|
var pixelRatio = window.devicePixelRatio || 1
|
||||||
var winW = this.canvas.offsetWidth * pixelRatio
|
var winW = this.canvas.offsetWidth * pixelRatio
|
||||||
var winH = this.canvas.offsetHeight * pixelRatio
|
var winH = this.canvas.offsetHeight * pixelRatio
|
||||||
this.canvas.width = winW
|
this.canvas.width = Math.max(1, winW)
|
||||||
this.canvas.height = winH
|
this.canvas.height = Math.max(1, winH)
|
||||||
ctx.scale(winW / this.width, winH / this.height)
|
ctx.scale(winW / this.width, winH / this.height)
|
||||||
|
|
||||||
ctx.lineJoin = "round"
|
ctx.lineJoin = "round"
|
||||||
|
|||||||
@@ -28,16 +28,18 @@ class P2Connection{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
open(){
|
open(){
|
||||||
this.closed = false
|
if(this.closed && !this.disabled){
|
||||||
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
this.closed = false
|
||||||
this.socket = new WebSocket(wsProtocol + "//" + location.host + "/p2")
|
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
||||||
pageEvents.race(this.socket, "open", "close").then(response => {
|
this.socket = new WebSocket(wsProtocol + "//" + location.host + "/p2")
|
||||||
if(response.type === "open"){
|
pageEvents.race(this.socket, "open", "close").then(response => {
|
||||||
return this.openEvent()
|
if(response.type === "open"){
|
||||||
}
|
return this.openEvent()
|
||||||
return this.closeEvent()
|
}
|
||||||
})
|
return this.closeEvent()
|
||||||
pageEvents.add(this.socket, "message", this.messageEvent.bind(this))
|
})
|
||||||
|
pageEvents.add(this.socket, "message", this.messageEvent.bind(this))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
openEvent(){
|
openEvent(){
|
||||||
var addedType = this.allEvents.get("open")
|
var addedType = this.allEvents.get("open")
|
||||||
@@ -46,8 +48,12 @@ class P2Connection{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(){
|
close(){
|
||||||
this.closed = true
|
if(!this.closed){
|
||||||
this.socket.close()
|
this.closed = true
|
||||||
|
if(this.socket){
|
||||||
|
this.socket.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
closeEvent(){
|
closeEvent(){
|
||||||
this.removeEventListener(onmessage)
|
this.removeEventListener(onmessage)
|
||||||
@@ -250,4 +256,12 @@ class P2Connection{
|
|||||||
this.notes.shift()
|
this.notes.shift()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enable(){
|
||||||
|
this.disabled = false
|
||||||
|
this.open()
|
||||||
|
}
|
||||||
|
disable(){
|
||||||
|
this.disabled = true
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ class Plugins{
|
|||||||
this.init(...args)
|
this.init(...args)
|
||||||
}
|
}
|
||||||
init(){
|
init(){
|
||||||
this.imported = []
|
|
||||||
this.allPlugins = []
|
this.allPlugins = []
|
||||||
this.pluginMap = {}
|
this.pluginMap = {}
|
||||||
this.hashes = []
|
this.hashes = []
|
||||||
|
this.startOrder = []
|
||||||
}
|
}
|
||||||
add(script, name){
|
add(script, name){
|
||||||
var hash = md5.base64(script.toString())
|
var hash = md5.base64(script.toString())
|
||||||
@@ -16,7 +16,7 @@ class Plugins{
|
|||||||
}
|
}
|
||||||
name = name || "plugin"
|
name = name || "plugin"
|
||||||
var baseName = name
|
var baseName = name
|
||||||
for(var i = 2; name in this.allPlugins; i++){
|
for(var i = 2; name in this.pluginMap; i++){
|
||||||
name = baseName + i.toString()
|
name = baseName + i.toString()
|
||||||
}
|
}
|
||||||
var plugin = new PluginLoader(script, name, hash)
|
var plugin = new PluginLoader(script, name, hash)
|
||||||
@@ -37,10 +37,6 @@ class Plugins{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.unload(name)
|
this.unload(name)
|
||||||
var index = this.imported.findIndex(obj => obj.name === name)
|
|
||||||
if(index !== -1){
|
|
||||||
this.imported.splice(index, 1)
|
|
||||||
}
|
|
||||||
var index = this.allPlugins.findIndex(obj => obj.name === name)
|
var index = this.allPlugins.findIndex(obj => obj.name === name)
|
||||||
if(index !== -1){
|
if(index !== -1){
|
||||||
this.allPlugins.splice(index, 1)
|
this.allPlugins.splice(index, 1)
|
||||||
@@ -67,21 +63,33 @@ class Plugins{
|
|||||||
this.pluginMap[name].stop()
|
this.pluginMap[name].stop()
|
||||||
}
|
}
|
||||||
stopAll(){
|
stopAll(){
|
||||||
for(var i = this.allPlugins.length; i--;){
|
for(var i = this.startOrder.length; i--;){
|
||||||
this.allPlugins[i].plugin.stop()
|
this.pluginMap[this.startOrder[i]].stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unload(name){
|
unload(name){
|
||||||
this.pluginMap[name].unload()
|
this.pluginMap[name].unload()
|
||||||
}
|
}
|
||||||
unloadAll(){
|
unloadAll(){
|
||||||
|
for(var i = this.startOrder.length; i--;){
|
||||||
|
this.pluginMap[this.startOrder[i]].unload()
|
||||||
|
}
|
||||||
for(var i = this.allPlugins.length; i--;){
|
for(var i = this.allPlugins.length; i--;){
|
||||||
this.allPlugins[i].plugin.unload()
|
this.allPlugins[i].plugin.unload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unloadImported(){
|
unloadImported(){
|
||||||
for(var i = this.imported.length; i--;){
|
for(var i = this.startOrder.length; i--;){
|
||||||
this.imported[i].plugin.unload()
|
var plugin = this.pluginMap[this.startOrder[i]]
|
||||||
|
if(plugin.imported){
|
||||||
|
plugin.unload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(var i = this.allPlugins.length; i--;){
|
||||||
|
var obj = this.allPlugins[i]
|
||||||
|
if(obj.plugin.imported){
|
||||||
|
obj.plugin.unload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +138,9 @@ class Plugins{
|
|||||||
getItem: () => plugin.started,
|
getItem: () => plugin.started,
|
||||||
setItem: value => {
|
setItem: value => {
|
||||||
if(plugin.started && !value){
|
if(plugin.started && !value){
|
||||||
plugin.stop()
|
this.stop(plugin.name)
|
||||||
}else if(!plugin.started && value){
|
}else if(!plugin.started && value){
|
||||||
plugin.start()
|
this.start(plugin.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,10 +196,17 @@ class PluginLoader{
|
|||||||
console.error(e)
|
console.error(e)
|
||||||
this.error()
|
this.error()
|
||||||
}
|
}
|
||||||
|
}, e => {
|
||||||
|
console.error(e)
|
||||||
|
this.error()
|
||||||
|
return Promise.resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start(){
|
start(orderChange){
|
||||||
|
if(!orderChange){
|
||||||
|
plugins.startOrder.push(this.name)
|
||||||
|
}
|
||||||
return this.load().then(() => {
|
return this.load().then(() => {
|
||||||
if(!this.started && this.module){
|
if(!this.started && this.module){
|
||||||
this.started = true
|
this.started = true
|
||||||
@@ -209,8 +224,18 @@ class PluginLoader{
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
stop(error){
|
stop(orderChange, error){
|
||||||
if(this.loaded && this.started){
|
if(this.loaded && this.started){
|
||||||
|
if(!orderChange){
|
||||||
|
var stopIndex = plugins.startOrder.indexOf(this.name)
|
||||||
|
if(stopIndex !== -1){
|
||||||
|
plugins.startOrder.splice(stopIndex, 1)
|
||||||
|
for(var i = plugins.startOrder.length; i-- > stopIndex;){
|
||||||
|
plugins.pluginMap[plugins.startOrder[i]].stop(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.started = false
|
this.started = false
|
||||||
try{
|
try{
|
||||||
if(this.module.beforeStop){
|
if(this.module.beforeStop){
|
||||||
@@ -225,12 +250,18 @@ class PluginLoader{
|
|||||||
this.error()
|
this.error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!orderChange && stopIndex !== -1){
|
||||||
|
for(var i = stopIndex; i < plugins.startOrder.length; i++){
|
||||||
|
plugins.pluginMap[plugins.startOrder[i]].start(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unload(error){
|
unload(error){
|
||||||
if(this.loaded){
|
if(this.loaded){
|
||||||
if(this.started){
|
if(this.started){
|
||||||
this.stop(error)
|
this.stop(false, error)
|
||||||
}
|
}
|
||||||
this.loaded = false
|
this.loaded = false
|
||||||
plugins.remove(this.name)
|
plugins.remove(this.name)
|
||||||
@@ -267,7 +298,6 @@ class EditValue{
|
|||||||
}
|
}
|
||||||
init(parent, name){
|
init(parent, name){
|
||||||
if(name){
|
if(name){
|
||||||
this.original = parent[name]
|
|
||||||
this.name = [parent, name]
|
this.name = [parent, name]
|
||||||
this.delete = !(name in parent)
|
this.delete = !(name in parent)
|
||||||
}else{
|
}else{
|
||||||
@@ -275,18 +305,21 @@ class EditValue{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
load(callback){
|
load(callback){
|
||||||
var output = callback(this.original)
|
this.loadCallback = callback
|
||||||
if(typeof output === "undefined"){
|
|
||||||
throw new Error("A value is expected to be returned")
|
|
||||||
}
|
|
||||||
this.edited = output
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
start(){
|
start(){
|
||||||
if(this.name){
|
if(this.name){
|
||||||
this.name[0][this.name[1]] = this.edited
|
this.original = this.name[0][this.name[1]]
|
||||||
}
|
}
|
||||||
return this.edited
|
var output = this.loadCallback(this.original)
|
||||||
|
if(typeof output === "undefined"){
|
||||||
|
throw new Error("A value is expected to be returned")
|
||||||
|
}
|
||||||
|
if(this.name){
|
||||||
|
this.name[0][this.name[1]] = output
|
||||||
|
}
|
||||||
|
return output
|
||||||
}
|
}
|
||||||
stop(){
|
stop(){
|
||||||
if(this.name){
|
if(this.name){
|
||||||
@@ -300,20 +333,26 @@ class EditValue{
|
|||||||
}
|
}
|
||||||
unload(){
|
unload(){
|
||||||
delete this.name
|
delete this.name
|
||||||
delete this.edited
|
|
||||||
delete this.original
|
delete this.original
|
||||||
|
delete this.loadCallback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditFunction extends EditValue{
|
class EditFunction extends EditValue{
|
||||||
load(callback){
|
start(){
|
||||||
var output = callback(plugins.strFromFunc(this.original))
|
if(this.name){
|
||||||
|
this.original = this.name[0][this.name[1]]
|
||||||
|
}
|
||||||
|
var args = plugins.argsFromFunc(this.original)
|
||||||
|
var output = this.loadCallback(plugins.strFromFunc(this.original), args)
|
||||||
if(typeof output === "undefined"){
|
if(typeof output === "undefined"){
|
||||||
throw new Error("A value is expected to be returned")
|
throw new Error("A value is expected to be returned")
|
||||||
}
|
}
|
||||||
var args = plugins.argsFromFunc(this.original)
|
var output = Function(...args, output)
|
||||||
this.edited = Function(...args, output)
|
if(this.name){
|
||||||
return this
|
this.name[0][this.name[1]] = output
|
||||||
|
}
|
||||||
|
return output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,8 +215,8 @@ class Scoresheet{
|
|||||||
|
|
||||||
if(this.redrawing){
|
if(this.redrawing){
|
||||||
if(this.winW !== winW || this.winH !== winH){
|
if(this.winW !== winW || this.winH !== winH){
|
||||||
this.canvas.width = winW
|
this.canvas.width = Math.max(1, winW)
|
||||||
this.canvas.height = winH
|
this.canvas.height = Math.max(1, winH)
|
||||||
ctx.scale(ratio, ratio)
|
ctx.scale(ratio, ratio)
|
||||||
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
||||||
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
||||||
|
|||||||
@@ -104,18 +104,20 @@ class SongSelect{
|
|||||||
return a.id > b.id ? 1 : -1
|
return a.id > b.id ? 1 : -1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.songs.push({
|
if(assets.songs.length){
|
||||||
title: strings.back,
|
this.songs.push({
|
||||||
skin: this.songSkin.back,
|
title: strings.back,
|
||||||
action: "back"
|
skin: this.songSkin.back,
|
||||||
})
|
action: "back"
|
||||||
this.songs.push({
|
})
|
||||||
title: strings.randomSong,
|
this.songs.push({
|
||||||
skin: this.songSkin.random,
|
title: strings.randomSong,
|
||||||
action: "random",
|
skin: this.songSkin.random,
|
||||||
category: strings.random,
|
action: "random",
|
||||||
canJump: true
|
category: strings.random,
|
||||||
})
|
canJump: true
|
||||||
|
})
|
||||||
|
}
|
||||||
if(touchEnabled){
|
if(touchEnabled){
|
||||||
if(fromTutorial === "tutorial"){
|
if(fromTutorial === "tutorial"){
|
||||||
fromTutorial = false
|
fromTutorial = false
|
||||||
@@ -287,7 +289,8 @@ class SongSelect{
|
|||||||
options: 0,
|
options: 0,
|
||||||
selLock: false,
|
selLock: false,
|
||||||
catJump: false,
|
catJump: false,
|
||||||
focused: true
|
focused: true,
|
||||||
|
waitPreview: 0
|
||||||
}
|
}
|
||||||
this.songSelecting = {
|
this.songSelecting = {
|
||||||
speed: 400,
|
speed: 400,
|
||||||
@@ -472,7 +475,7 @@ class SongSelect{
|
|||||||
this.toAccount()
|
this.toAccount()
|
||||||
}else if(p2.session && 438 < mouse.x && mouse.x < 834 && mouse.y > 603){
|
}else if(p2.session && 438 < mouse.x && mouse.x < 834 && mouse.y > 603){
|
||||||
this.toSession()
|
this.toSession()
|
||||||
}else if(!p2.session && mouse.x > 641 && mouse.y > 603 && p2.socket.readyState === 1 && !assets.customSongs){
|
}else if(!p2.session && mouse.x > 641 && mouse.y > 603 && p2.socket && p2.socket.readyState === 1 && !assets.customSongs){
|
||||||
this.toSession()
|
this.toSession()
|
||||||
}else{
|
}else{
|
||||||
var moveBy = this.songSelMouse(mouse.x, mouse.y)
|
var moveBy = this.songSelMouse(mouse.x, mouse.y)
|
||||||
@@ -508,7 +511,7 @@ class SongSelect{
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
mouseWheel(event){
|
mouseWheel(event){
|
||||||
if(this.state.screen === "song"){
|
if(this.state.screen === "song" && this.state.focused){
|
||||||
this.wheelTimer = this.getMS()
|
this.wheelTimer = this.getMS()
|
||||||
|
|
||||||
if(event.deltaY < 0) {
|
if(event.deltaY < 0) {
|
||||||
@@ -809,7 +812,7 @@ class SongSelect{
|
|||||||
this.selectedDiff = 1
|
this.selectedDiff = 1
|
||||||
do{
|
do{
|
||||||
this.state.options = this.mod(this.optionsList.length, this.state.options + moveBy)
|
this.state.options = this.mod(this.optionsList.length, this.state.options + moveBy)
|
||||||
}while((p2.socket.readyState !== 1 || assets.customSongs) && this.state.options === 2)
|
}while((p2.socket && p2.socket.readyState !== 1 || assets.customSongs) && this.state.options === 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toTitleScreen(){
|
toTitleScreen(){
|
||||||
@@ -914,11 +917,6 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.wheelScrolls !== 0 && !this.state.locked && ms >= this.wheelTimer + 20) {
|
|
||||||
this.moveToSong(this.wheelScrolls)
|
|
||||||
this.wheelScrolls -= this.wheelScrolls
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!this.redrawRunning){
|
if(!this.redrawRunning){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -944,8 +942,8 @@ class SongSelect{
|
|||||||
var ratioY = winH / 720
|
var ratioY = winH / 720
|
||||||
var ratio = (ratioX < ratioY ? ratioX : ratioY)
|
var ratio = (ratioX < ratioY ? ratioX : ratioY)
|
||||||
if(this.winW !== winW || this.winH !== winH){
|
if(this.winW !== winW || this.winH !== winH){
|
||||||
this.canvas.width = winW
|
this.canvas.width = Math.max(1, winW)
|
||||||
this.canvas.height = winH
|
this.canvas.height = Math.max(1, winH)
|
||||||
ctx.scale(ratio, ratio)
|
ctx.scale(ratio, ratio)
|
||||||
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
||||||
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
||||||
@@ -1034,6 +1032,17 @@ class SongSelect{
|
|||||||
var screen = this.state.screen
|
var screen = this.state.screen
|
||||||
var selectedWidth = this.songAsset.width
|
var selectedWidth = this.songAsset.width
|
||||||
|
|
||||||
|
if(this.wheelScrolls !== 0 && !this.state.locked && ms >= this.wheelTimer + 20) {
|
||||||
|
if(p2.session){
|
||||||
|
this.moveToSong(this.wheelScrolls)
|
||||||
|
}else{
|
||||||
|
this.state.move = this.wheelScrolls
|
||||||
|
this.state.waitPreview = ms + 400
|
||||||
|
this.endPreview()
|
||||||
|
}
|
||||||
|
this.wheelScrolls = 0
|
||||||
|
}
|
||||||
|
|
||||||
if(screen === "title" || screen === "titleFadeIn"){
|
if(screen === "title" || screen === "titleFadeIn"){
|
||||||
if(ms > this.state.screenMS + 1000){
|
if(ms > this.state.screenMS + 1000){
|
||||||
this.state.screen = "song"
|
this.state.screen = "song"
|
||||||
@@ -2439,7 +2448,7 @@ class SongSelect{
|
|||||||
}
|
}
|
||||||
|
|
||||||
startPreview(loadOnly){
|
startPreview(loadOnly){
|
||||||
if(!loadOnly && this.state && this.state.showWarning){
|
if(!loadOnly && this.state && this.state.showWarning || this.state.waitPreview > this.getMS()){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var currentSong = this.songs[this.selectedSong]
|
var currentSong = this.songs[this.selectedSong]
|
||||||
|
|||||||
@@ -73,7 +73,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class SoundGain{
|
class SoundGain{
|
||||||
constructor(soundBuffer, channel){
|
constructor(...args){
|
||||||
|
this.init(...args)
|
||||||
|
}
|
||||||
|
init(soundBuffer, channel){
|
||||||
this.soundBuffer = soundBuffer
|
this.soundBuffer = soundBuffer
|
||||||
this.gainNode = soundBuffer.context.createGain()
|
this.gainNode = soundBuffer.context.createGain()
|
||||||
if(channel){
|
if(channel){
|
||||||
@@ -121,7 +124,10 @@ class SoundGain{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Sound{
|
class Sound{
|
||||||
constructor(gain, buffer){
|
constructor(...args){
|
||||||
|
this.init(...args)
|
||||||
|
}
|
||||||
|
init(gain, buffer){
|
||||||
this.gain = gain
|
this.gain = gain
|
||||||
this.buffer = buffer
|
this.buffer = buffer
|
||||||
this.soundBuffer = gain.soundBuffer
|
this.soundBuffer = gain.soundBuffer
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ var translations = {
|
|||||||
ja: "曲「%s」を読み込むことができませんでした。(ID:%s)\n\n%s",
|
ja: "曲「%s」を読み込むことができませんでした。(ID:%s)\n\n%s",
|
||||||
en: "Could not load song %s with ID %s.\n\n%s"
|
en: "Could not load song %s with ID %s.\n\n%s"
|
||||||
},
|
},
|
||||||
|
accessNotGrantedError: {
|
||||||
|
ja: null,
|
||||||
|
en: "Permission to access the file was not granted"
|
||||||
|
},
|
||||||
loading: {
|
loading: {
|
||||||
ja: "ロード中...",
|
ja: "ロード中...",
|
||||||
en: "Loading...",
|
en: "Loading...",
|
||||||
|
|||||||
@@ -12,29 +12,86 @@ class Tutorial{
|
|||||||
this.tutorialTitle = this.getElement("view-title")
|
this.tutorialTitle = this.getElement("view-title")
|
||||||
this.tutorialDiv = document.createElement("div")
|
this.tutorialDiv = document.createElement("div")
|
||||||
this.getElement("view-content").appendChild(this.tutorialDiv)
|
this.getElement("view-content").appendChild(this.tutorialDiv)
|
||||||
|
|
||||||
|
this.items = []
|
||||||
|
this.items.push(this.endButton)
|
||||||
|
this.selected = this.items.length - 1
|
||||||
|
|
||||||
this.setStrings()
|
this.setStrings()
|
||||||
|
|
||||||
pageEvents.add(this.endButton, ["mousedown", "touchstart"], event => {
|
pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this))
|
||||||
if(event.type === "touchstart"){
|
|
||||||
event.preventDefault()
|
|
||||||
this.touched = true
|
|
||||||
}else if(event.type === "mousedown" && event.which !== 1){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.onEnd(true)
|
|
||||||
})
|
|
||||||
this.keyboard = new Keyboard({
|
this.keyboard = new Keyboard({
|
||||||
confirm: ["enter", "space", "esc", "don_l", "don_r"]
|
confirm: ["enter", "space", "don_l", "don_r"],
|
||||||
}, this.onEnd.bind(this))
|
previous: ["left", "up", "ka_l"],
|
||||||
|
next: ["right", "down", "ka_r"],
|
||||||
|
back: ["escape"]
|
||||||
|
}, this.keyPressed.bind(this))
|
||||||
this.gamepad = new Gamepad({
|
this.gamepad = new Gamepad({
|
||||||
confirm: ["start", "b", "ls", "rs"]
|
"confirm": ["b", "ls", "rs"],
|
||||||
}, this.onEnd.bind(this))
|
"previous": ["u", "l", "lb", "lt", "lsu", "lsl"],
|
||||||
|
"next": ["d", "r", "rb", "rt", "lsd", "lsr"],
|
||||||
|
"back": ["start", "a"]
|
||||||
|
}, this.keyPressed.bind(this))
|
||||||
|
|
||||||
pageEvents.send("tutorial")
|
pageEvents.send("tutorial")
|
||||||
}
|
}
|
||||||
getElement(name){
|
getElement(name){
|
||||||
return loader.screen.getElementsByClassName(name)[0]
|
return loader.screen.getElementsByClassName(name)[0]
|
||||||
}
|
}
|
||||||
|
keyPressed(pressed, name){
|
||||||
|
if(!pressed){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var selected = this.items[this.selected]
|
||||||
|
if(name === "confirm"){
|
||||||
|
if(selected === this.endButton){
|
||||||
|
this.onEnd()
|
||||||
|
}else{
|
||||||
|
this.getLink(selected).click()
|
||||||
|
assets.sounds["se_don"].play()
|
||||||
|
}
|
||||||
|
}else if(name === "previous" || name === "next"){
|
||||||
|
if(this.items.length >= 2){
|
||||||
|
selected.classList.remove("selected")
|
||||||
|
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
|
||||||
|
this.items[this.selected].classList.add("selected")
|
||||||
|
assets.sounds["se_ka"].play()
|
||||||
|
}
|
||||||
|
}else if(name === "back"){
|
||||||
|
this.onEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod(length, index){
|
||||||
|
return ((index % length) + length) % length
|
||||||
|
}
|
||||||
|
onEnd(event){
|
||||||
|
var touched = false
|
||||||
|
if(event){
|
||||||
|
if(event.type === "touchstart"){
|
||||||
|
event.preventDefault()
|
||||||
|
touched = true
|
||||||
|
}else if(event.which !== 1){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.clean()
|
||||||
|
assets.sounds["se_don"].play()
|
||||||
|
try{
|
||||||
|
localStorage.setItem("tutorial", "true")
|
||||||
|
}catch(e){}
|
||||||
|
setTimeout(() => {
|
||||||
|
new SongSelect(this.fromSongSel ? "tutorial" : false, false, touched, this.songId)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
getLink(target){
|
||||||
|
return target.getElementsByTagName("a")[0]
|
||||||
|
}
|
||||||
|
linkButton(event){
|
||||||
|
if(event.target === event.currentTarget && (event.type === "touchstart" || event.which === 1)){
|
||||||
|
this.getLink(event.currentTarget).click()
|
||||||
|
assets.sounds["se_don"].play()
|
||||||
|
}
|
||||||
|
}
|
||||||
insertText(text, parent){
|
insertText(text, parent){
|
||||||
parent.appendChild(document.createTextNode(text))
|
parent.appendChild(document.createTextNode(text))
|
||||||
}
|
}
|
||||||
@@ -63,18 +120,6 @@ class Tutorial{
|
|||||||
parent.appendChild(kbd)
|
parent.appendChild(kbd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEnd(pressed, name){
|
|
||||||
if(pressed){
|
|
||||||
this.clean()
|
|
||||||
assets.sounds["se_don"].play()
|
|
||||||
try{
|
|
||||||
localStorage.setItem("tutorial", "true")
|
|
||||||
}catch(e){}
|
|
||||||
setTimeout(() => {
|
|
||||||
new SongSelect(this.fromSongSel ? "tutorial" : false, false, this.touched, this.songId)
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setStrings(){
|
setStrings(){
|
||||||
this.tutorialTitle.innerText = strings.howToPlay
|
this.tutorialTitle.innerText = strings.howToPlay
|
||||||
this.tutorialTitle.setAttribute("alt", strings.howToPlay)
|
this.tutorialTitle.setAttribute("alt", strings.howToPlay)
|
||||||
|
|||||||
@@ -199,8 +199,8 @@
|
|||||||
this.ratio = ratio
|
this.ratio = ratio
|
||||||
|
|
||||||
if(this.player !== 2){
|
if(this.player !== 2){
|
||||||
this.canvas.width = winW
|
this.canvas.width = Math.max(1, winW)
|
||||||
this.canvas.height = winH
|
this.canvas.height = Math.max(1, winH)
|
||||||
ctx.scale(ratio, ratio)
|
ctx.scale(ratio, ratio)
|
||||||
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
||||||
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
||||||
@@ -1515,6 +1515,7 @@
|
|||||||
}
|
}
|
||||||
updateNoteFaces(){
|
updateNoteFaces(){
|
||||||
var ms = this.getMS()
|
var ms = this.getMS()
|
||||||
|
var lastNextBeat = this.nextBeat
|
||||||
while(ms >= this.nextBeat){
|
while(ms >= this.nextBeat){
|
||||||
this.nextBeat += this.beatInterval
|
this.nextBeat += this.beatInterval
|
||||||
if(this.controller.getCombo() >= 50){
|
if(this.controller.getCombo() >= 50){
|
||||||
@@ -1529,6 +1530,9 @@
|
|||||||
big: 3
|
big: 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(this.nextBeat <= lastNextBeat){
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drawCircles(circles){
|
drawCircles(circles){
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<link rel="icon" href="{{config.assets_baseurl}}img/favicon.png" type="image/png">
|
<link rel="icon" href="{{config.assets_baseurl}}img/favicon.png" type="image/png">
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
<meta name="description" content="パソコンとスマホのブラウザ向けの太鼓の達人シミュレータ 🥁 Taiko no Tatsujin rhythm game simulator for desktop and mobile browsers">
|
<meta name="description" content="パソコンとスマホのブラウザ向けの太鼓の達人シミュレータ 🥁 Taiko no Tatsujin rhythm game simulator for desktop and mobile browsers">
|
||||||
|
<meta name="keywords" content="taiko no tatsujin, taiko, don chan, online, rhythm, browser, html5, game, for browsers, pc, arcade, emulator, free, download, website, 太鼓の達人, 太鼓ウェブ, 太鼓之達人, 太鼓達人, 太鼓网页, 网页版, 太鼓網頁, 網頁版, 태고의 달인, 태고 웹">
|
||||||
|
<meta name="color-scheme" content="only light">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
||||||
|
|
||||||
@@ -18,14 +20,20 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="assets"></div>
|
<div id="assets"></div>
|
||||||
<div id="screen" class="pattern-bg"></div>
|
<div id="screen" class="pattern-bg"></div>
|
||||||
<div id="version">
|
<div data-nosnippet id="version">
|
||||||
{% if version.version and version.commit_short and version.commit %}
|
{% if version.version and version.commit_short and version.commit %}
|
||||||
<a href="{{version.url}}commit/{{version.commit}}" target="_blank" id="version-link" class="stroke-sub" alt="taiko-web ver.{{version.version}} ({{version.commit_short}})">taiko-web ver.{{version.version}} ({{version.commit_short}})</a>
|
<a href="{{version.url}}commit/{{version.commit}}" target="_blank" id="version-link" class="stroke-sub" alt="taiko-web ver.{{version.version}} ({{version.commit_short}})">taiko-web ver.{{version.version}} ({{version.commit_short}})</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{version.url}}" target="_blank" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<script src="/src/js/browsersupport.js?{{version.commit_short}}"></script>
|
<script src="/src/js/browsersupport.js?{{version.commit_short}}"></script>
|
||||||
<script src="/src/js/main.js?{{version.commit_short}}"></script>
|
<script src="/src/js/main.js?{{version.commit_short}}"></script>
|
||||||
|
<noscript>
|
||||||
|
<div data-nosnippet id="unsupportedBrowser">
|
||||||
|
<div id="unsupportedWarn">!</div>
|
||||||
|
<span>Taiko Web requires JavaScript to be enabled in the browser</span>
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user