Merge pull request #422 from bui/misc-fixes

Misc fixes
This commit is contained in:
Bui 2022-03-03 23:39:56 +00:00 committed by GitHub
commit a92832d0ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 296 additions and 60 deletions

View File

@ -48,7 +48,7 @@
padding: 0.5em 0.7em;
border-radius: 0.2em;
border: 0.13em black solid;
font-family: TnT;
font-family: inherit;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;

View File

@ -160,6 +160,10 @@
diag.push("Language: " + strings.id + userLangStr)
var latency = settings.getItem("latency")
diag.push("Audio Latency: " + (latency.audio > 0 ? "+" : "") + latency.audio.toString() + "ms, Video Latency: " + (latency.video > 0 ? "+" : "") + latency.video.toString() + "ms")
var pluginList = plugins.allPlugins.map(pluginLoader => {
return (pluginLoader.plugin.module && pluginLoader.plugin.module.name || pluginLoader.name) + (pluginLoader.plugin.started ? " (started)" : "")
})
diag.push("Plugins: " + pluginList.join(", "))
var errorObj = {}
if(localStorage["lastError"]){
try{

View File

@ -299,7 +299,7 @@
verticalText(config){
var ctx = config.ctx
var inputText = config.text.toString()
var inputText = "" + config.text
var mul = config.fontSize / 40
var ura = false
var r = this.regex
@ -623,7 +623,7 @@
layeredText(config, layers){
var ctx = config.ctx
var inputText = config.text.toString()
var inputText = "" + config.text
var mul = config.fontSize / 40
var ura = false
var r = this.regex

View File

@ -327,7 +327,9 @@ class Loader{
p2.hash("")
}
promises.push(this.canvasTest.drawAllImages())
promises.push(this.canvasTest.drawAllImages().then(result => {
perf.allImg = result
}))
if(gameConfig.plugins){
gameConfig.plugins.forEach(obj => {
@ -349,8 +351,7 @@ class Loader{
})
}
Promise.all(promises).then(result => {
perf.allImg = result
Promise.all(promises).then(() => {
perf.load = Date.now() - this.startTime
this.canvasTest.clean()
this.clean()

View File

@ -77,7 +77,7 @@ class Lyrics{
break
}
var lang = text.slice(index1 + 6, index2).toLowerCase()
if(strings.id === lang){
if(strings.preferEn && lang === "en" || strings.id === lang){
var index3 = text.indexOf("<lang ", index2 + 1)
if(index3 !== -1){
textLang = text.slice(index2 + 1, index3)

View File

@ -20,6 +20,10 @@ class Plugins{
var name = options.name
if(!name && isUrl){
name = script
var index = name.lastIndexOf("?")
if(index !== -1){
name = name.slice(0, index)
}
var index = name.lastIndexOf("/")
if(index !== -1){
name = name.slice(index + 1)
@ -50,14 +54,16 @@ class Plugins{
return plugin
}
remove(name){
var hash = this.pluginMap[name].hash
if(hash){
var index = this.hashes.indexOf(hash)
if(index !== -1){
this.hashes.splice(index, 1)
if(name in this.pluginMap){
var hash = this.pluginMap[name].hash
if(hash){
var index = this.hashes.indexOf(hash)
if(index !== -1){
this.hashes.splice(index, 1)
}
}
this.unload(name)
}
this.unload(name)
var index = this.allPlugins.findIndex(obj => obj.name === name)
if(index !== -1){
this.allPlugins.splice(index, 1)
@ -159,6 +165,34 @@ class Plugins{
}
return input
}
isObject(input){
return input && typeof input === "object" && input.constructor === Object
}
deepMerge(target, ...sources){
sources.forEach(source => {
if(this.isObject(target) && this.isObject(source)){
for(var i in source){
if(this.isObject(source[i])){
if(!target[i]){
target[i] = {}
}
this.deepMerge(target[i], source[i])
}else if(source[i]){
target[i] = source[i]
}
}
}
})
return target
}
arrayDel(array, item){
var index = array.indexOf(item)
if(index !== -1){
array.splice(index, 1)
return true
}
return false
}
hasSettings(){
for(var i = 0; i < this.allPlugins.length; i++){
@ -207,10 +241,12 @@ class Plugins{
default: true,
getItem: () => plugin.started,
setItem: value => {
if(plugin.started && !value){
this.stop(plugin.name)
}else if(!plugin.started && value){
this.start(plugin.name)
if(plugin.name in this.pluginMap){
if(plugin.started && !value){
this.stop(plugin.name)
}else if(!plugin.started && value){
this.start(plugin.name)
}
}
}
})
@ -293,9 +329,15 @@ class PluginLoader{
try{
this.module = new module.default()
}catch(e){
console.error(e)
this.error()
return
var error = new Error()
error.stack = "Error initializing plugin: " + this.name + "\n" + e.stack
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
}
var output
try{
@ -306,22 +348,41 @@ class PluginLoader{
output = this.module.load(this)
}
}catch(e){
console.error(e)
this.error()
var error = new Error()
error.stack = "Error in plugin load: " + this.name + "\n" + e.stack
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
}
if(typeof output === "object" && output.constructor === Promise){
return output.catch(e => {
console.error(e)
this.error()
return Promise.resolve()
var error = new Error()
error.stack = "Error in plugin load promise: " + this.name + (e ? "\n" + e.stack : "")
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
})
}
}, e => {
console.error(e)
this.error()
if(loadErrors){
return Promise.reject(e)
if(e.name === "SyntaxError"){
var error = new SyntaxError()
error.stack = "Error in plugin syntax: " + this.name + "\n" + e.stack
}else{
var error = e
}
if(loadErrors){
return Promise.reject(error)
}else{
console.error(error)
return Promise.resolve()
}
})
@ -342,13 +403,15 @@ class PluginLoader{
this.module.start()
}
}catch(e){
console.error(e)
var error = new Error()
error.stack = "Error in plugin start: " + this.name + "\n" + e.stack
console.error(error)
this.error()
}
}
})
}
stop(orderChange, error){
stop(orderChange, noError){
if(this.loaded && this.started){
if(!orderChange){
var stopIndex = plugins.startOrder.indexOf(this.name)
@ -369,8 +432,10 @@ class PluginLoader{
this.module.stop()
}
}catch(e){
console.error(e)
if(!error){
var error = new Error()
error.stack = "Error in plugin stop: " + this.name + "\n" + e.stack
console.error(error)
if(!noError){
this.error()
}
}
@ -398,7 +463,9 @@ class PluginLoader{
this.module.unload()
}
}catch(e){
console.error(e)
var error = new Error()
error.stack = "Error in plugin unload: " + this.name + "\n" + e.stack
console.error(error)
}
delete this.module
}
@ -409,7 +476,9 @@ class PluginLoader{
try{
this.module.error()
}catch(e){
console.error(e)
var error = new Error()
error.stack = "Error in plugin error: " + this.name + "\n" + e.stack
console.error(error)
}
}
this.unload(true)
@ -453,9 +522,17 @@ class EditValue{
if(this.name){
this.original = this.name[0][this.name[1]]
}
var output = this.loadCallback(this.original)
try{
var output = this.loadCallback(this.original)
}catch(e){
console.error(this.loadCallback)
var error = new Error()
error.stack = "Error editing the value of " + this.getName() + "\n" + e.stack
throw error
}
if(typeof output === "undefined"){
throw new Error("A value is expected to be returned")
console.error(this.loadCallback)
throw new Error("Error editing the value of " + this.getName() + ": A value is expected to be returned")
}
if(this.name){
this.name[0][this.name[1]] = output
@ -472,6 +549,27 @@ class EditValue{
}
return this.original
}
getName(){
var name = "unknown"
try{
if(this.name){
var name = (
typeof this.name[0] === "function" && this.name[0].name
|| (
typeof this.name[0] === "object" && typeof this.name[0].constructor === "function" && (
this.name[0] instanceof this.name[0].constructor ? (() => {
var consName = this.name[0].constructor.name || ""
return consName.slice(0, 1).toLowerCase() + consName.slice(1)
})() : this.name[0].constructor.name + ".prototype"
)
) || name
) + (this.name[1] ? "." + this.name[1] : "")
}
}catch(e){
name = "error"
}
return name
}
unload(){
delete this.name
delete this.original
@ -485,11 +583,33 @@ class EditFunction extends EditValue{
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"){
throw new Error("A value is expected to be returned")
try{
var output = this.loadCallback(plugins.strFromFunc(this.original), args)
}catch(e){
console.error(this.loadCallback)
var error = new Error()
error.stack = "Error editing the function value of " + this.getName() + "\n" + e.stack
throw error
}
if(typeof output === "undefined"){
console.error(this.loadCallback)
throw new Error("Error editing the function value of " + this.getName() + ": A value is expected to be returned")
}
try{
var output = Function(...args, output)
}catch(e){
console.error(this.loadCallback)
var error = new SyntaxError()
var blob = new Blob([output], {
type: "application/javascript"
})
var url = URL.createObjectURL(blob)
error.stack = "Error editing the function value of " + this.getName() + ": Could not evaluate string, check the full string for errors: " + url + "\n" + e.stack
setTimeout(() => {
URL.revokeObjectURL(url)
}, 5 * 60 * 1000)
throw error
}
var output = Function(...args, output)
if(this.name){
this.name[0][this.name[1]] = output
}
@ -499,14 +619,32 @@ class EditFunction extends EditValue{
class Patch{
edits = []
addedLanguages = []
addEdits(...args){
args.forEach(arg => this.edits.push(arg))
}
addLanguage(lang, forceSet, fallback="en"){
if(fallback){
lang = plugins.deepMerge({}, allStrings[fallback], lang)
}
this.addedLanguages.push({
lang: lang,
forceSet: forceSet
})
}
beforeStart(){
this.edits.forEach(edit => edit.start())
this.addedLanguages.forEach(obj => {
settings.addLang(obj.lang, obj.forceSet)
})
}
beforeStop(){
this.edits.forEach(edit => edit.stop())
for(var i = this.edits.length; i--;){
this.edits[i].stop()
}
for(var i = this.addedLanguages.length; i--;){
settings.removeLang(this.addedLanguages[i].lang)
}
}
beforeUnload(){
this.edits.forEach(edit => edit.unload())

View File

@ -48,7 +48,7 @@ class ScoreStorage{
var scoreArray = diffArray[i].slice(1).split(",")
for(var j in this.scoreKeys){
var name = this.scoreKeys[j]
var value = parseInt(scoreArray[j], 36) || 0
var value = parseInt(scoreArray[j] || 0, 36) || 0
if(value < 0){
value = 0
}

View File

@ -159,6 +159,58 @@ class Settings{
pageEvents.send("language-change", lang.id)
}
}
addLang(lang, forceSet){
allStrings[lang.id] = lang
if(lang.categories){
assets.categories.forEach(category => {
if("title_lang" in category && lang.categories[category.title_lang.en]){
category.title_lang[lang.id] = lang.categories[category.title_lang.en]
}
})
}
languageList.push(lang.id)
this.allLanguages.push(lang.id)
this.items.language.default = this.getLang()
if(forceSet){
this.storage.language = lang.id
}else{
try{
this.storage.language = localStorage.getItem("lang")
}catch(e){}
if(this.items.language.options.indexOf(this.storage.language) === -1){
this.storage.language = null
}
}
if(settings.getItem("language") === lang.id){
settings.setLang(lang)
}
}
removeLang(lang){
delete allStrings[lang.id]
assets.categories.forEach(category => {
if("title_lang" in category){
delete category.title_lang[lang.id]
}
})
var index = languageList.indexOf(lang.id)
if(index !== -1){
languageList.splice(index, 1)
}
var index = this.allLanguages.indexOf(lang.id)
if(index !== -1){
this.allLanguages.splice(index, 1)
}
this.items.language.default = this.getLang()
try{
this.storage.language = localStorage.getItem("lang")
}catch(e){}
if(this.items.language.options.indexOf(this.storage.language) === -1){
this.storage.language = null
}
if(lang.id === strings.id){
settings.setLang(allStrings[this.getItem("language")])
}
}
}
class SettingsView{
@ -204,6 +256,10 @@ class SettingsView{
}
}, this.windowSymbol)
if(this.customSettings){
pageEvents.add(window, "language-change", event => this.setLang(), this.windowSymbol)
}
var gamepadEnabled = false
if("getGamepads" in navigator){
var gamepads = navigator.getGamepads()
@ -441,7 +497,11 @@ class SettingsView{
this.mode = "latency"
this.latencySet()
}
pageEvents.send("settings")
if(this.customSettings){
pageEvents.send("plugins")
}else{
pageEvents.send("settings")
}
}
getElement(name){
return loader.screen.getElementsByClassName(name)[0]
@ -1014,7 +1074,9 @@ class SettingsView{
return title
}
setLang(lang){
settings.setLang(lang)
if(lang){
settings.setLang(lang)
}
if(failedTests.length !== 0){
showUnsupported(strings)
}
@ -1098,6 +1160,9 @@ class SettingsView{
this.gamepad.clean()
assets.sounds["bgm_settings"].stop()
pageEvents.remove(window, ["mouseup", "touchstart", "touchmove", "touchend", "blur"], this.windowSymbol)
if(this.customSettings){
pageEvents.remove(window, "language-change", this.windowSymbol)
}
for(var i in this.items){
this.removeTouchEnd(this.items[i].settingBox)
}

View File

@ -86,6 +86,7 @@ class SongSelect{
if(category.songSkin.sort === null){
category.songSkin.sort = songSkinLength + 1
}
category.songSkin.id = category.id
this.songSkin[category.title] = category.songSkin
}
}
@ -95,12 +96,14 @@ class SongSelect{
var searchCss = []
Object.keys(this.songSkin).forEach(key => {
var skin = this.songSkin[key]
var stripped = key.replace(/\W/g, '')
searchCss.push('.song-search-' + stripped + ' { background-color: ' + skin.background + ' }')
searchCss.push('.song-search-' + stripped + '::before { border: 0.4em solid ' + skin.border[0] + ' ; border-bottom-color: ' + skin.border[1] + ' ; border-right-color: ' + skin.border[1] + ' }')
searchCss.push('.song-search-' + stripped + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }')
searchCss.push('.song-search-' + stripped + ' .song-search-result-subtitle::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }')
if("id" in skin || key === "default"){
var id = "id" in skin ? ("cat" + skin.id) : key
searchCss.push('.song-search-' + id + ' { background-color: ' + skin.background + ' }')
searchCss.push('.song-search-' + id + '::before { border: 0.4em solid ' + skin.border[0] + ' ; border-bottom-color: ' + skin.border[1] + ' ; border-right-color: ' + skin.border[1] + ' }')
searchCss.push('.song-search-' + id + ' .song-search-result-title::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }')
searchCss.push('.song-search-' + id + ' .song-search-result-subtitle::before { -webkit-text-stroke: 0.4em ' + skin.outline + ' }')
}
})
this.searchStyle.appendChild(document.createTextNode(searchCss.join("\n")))
loader.screen.appendChild(this.searchStyle)
@ -447,7 +450,7 @@ class SongSelect{
}
}else if(name === "confirm"){
if(Number.isInteger(this.search.active)){
this.searchProceed(parseInt(this.search.results[this.search.active].dataset.song_id))
this.searchProceed(parseInt(this.search.results[this.search.active].dataset.songId))
}
}
}else if(this.state.screen === "song"){
@ -487,7 +490,7 @@ class SongSelect{
}else if(this.state.screen === "difficulty"){
if(event && event.keyCode && event.keyCode === 70 && ctrl){
this.displaySearch()
event.preventDefault()
if(event){ event.preventDefault() }
}else if(name === "confirm"){
if(this.selectedDiff === 0){
this.toSongSelect()
@ -508,13 +511,18 @@ class SongSelect{
this.endPreview(true)
this.playBgm(false)
}
}else if(this.state.screen === "title" || this.state.screen === "titleFadeIn"){
if(event && event.keyCode && event.keyCode === 70 && ctrl){
this.displaySearch()
if(event){ event.preventDefault() }
}
}
}
mouseDown(event){
if(event.target === this.selectable || event.target.parentNode === this.selectable){
this.selectable.focus()
}else{
}else if(event.target.tagName !== "INPUT"){
getSelection().removeAllRanges()
this.selectable.blur()
}
@ -896,7 +904,7 @@ class SongSelect{
this.selectedDiff = 1
do{
this.state.options = this.mod(this.optionsList.length, this.state.options + moveBy)
}while((p2.socket && p2.socket.readyState !== 1 || assets.customSongs) && this.state.options === 2)
}while((!p2.socket || p2.socket.readyState !== 1 || assets.customSongs) && this.state.options === 2)
}
}
toTitleScreen(){
@ -2711,15 +2719,17 @@ class SongSelect{
var title = this.getLocalTitle(song.title, song.title_lang)
var subtitle = this.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
var strippedCat = "default"
var id = "default"
if(song.category_id){
var cat = assets.categories.find(cat => cat.id === song.category_id)
strippedCat = cat.title.replace(/\W/g, '')
if(cat && "id" in cat){
id = "cat" + cat.id
}
}
var resultDiv = document.createElement("div")
resultDiv.classList.add("song-search-result", "song-search-" + strippedCat)
resultDiv.dataset.song_id = song.id
resultDiv.classList.add("song-search-result", "song-search-" + id)
resultDiv.dataset.songId = song.id
var resultInfoDiv = document.createElement("div")
resultInfoDiv.classList.add("song-search-result-info")
@ -2868,9 +2878,15 @@ class SongSelect{
this.setSearchTip()
cancelTouch = false
noResizeRoot = true
if(this.songs[this.selectedSong].courses){
snd.previewGain.setVolumeMul(0.5)
}else if(this.bgmEnabled){
snd.musicGain.setVolumeMul(0.5)
}
setTimeout(() => {
this.search.input.focus()
this.search.input.setSelectionRange(0, this.search.input.value.length)
}, 10)
var lastQuery = localStorage.getItem("lastSearchQuery")
@ -2894,6 +2910,11 @@ class SongSelect{
delete this.search
cancelTouch = true
noResizeRoot = false
if(this.songs[this.selectedSong].courses){
snd.previewGain.setVolumeMul(1)
}else if(this.bgmEnabled){
snd.musicGain.setVolumeMul(1)
}
}
}
@ -2964,6 +2985,7 @@ class SongSelect{
case "creative":
case "played":
case "maker":
case "diverge":
filters[parts[0]] = parts[1]
break
}
@ -3037,7 +3059,12 @@ class SongSelect{
if(aliases.find(alias => alias.toLowerCase() === value.toLowerCase())){
passedFilters++
}
break
case "diverge":
var branch = Object.values(song.courses).find(course => course && course.branch)
if((value === "yes" && branch) || (value === "no" && !branch)){
passedFilters++
}
break
}
})
@ -3068,7 +3095,7 @@ class SongSelect{
}
lastIdx = range[1]
})
var index = a[0].target.indexOf(query)
var index = a[0].target.toLowerCase().indexOf(query)
if(index !== -1){
a[0].ranges = [[index, index + query.length - 1]]
}else if(rangeAmount > a[0].indexes.length / 2){
@ -3134,8 +3161,9 @@ class SongSelect{
}
searchInput(){
var text = this.search.input.value.toLowerCase()
var text = this.search.input.value
localStorage.setItem("lastSearchQuery", text)
text = text.toLowerCase()
if(text.length === 0){
this.setSearchTip()
@ -3181,7 +3209,7 @@ class SongSelect{
}else if(e.which === 1){
var songEl = e.target.closest(".song-search-result")
if(songEl){
var songId = parseInt(songEl.dataset.song_id)
var songId = parseInt(songEl.dataset.songId)
this.searchProceed(songId)
}
}
@ -3309,7 +3337,7 @@ class SongSelect{
getLocalTitle(title, titleLang){
if(titleLang){
for(var id in titleLang){
if(id === strings.id && titleLang[id]){
if(id === "en" && strings.preferEn && !(strings.id in titleLang) && titleLang.en || id === strings.id && titleLang[id]){
return titleLang[id]
}
}