refactor options

This commit is contained in:
Vitaly 2023-10-16 20:20:52 +03:00
commit 819a436fa0
8 changed files with 151 additions and 111 deletions

12
pnpm-lock.yaml generated
View file

@ -63,7 +63,7 @@ importers:
version: 4.18.2
flying-squid:
specifier: github:zardoy/space-squid#everything
version: github.com/zardoy/space-squid/acf7b6f8cbcc204007eed767eb52a527a85b3ab0
version: github.com/zardoy/space-squid/bdf1e0859ad435bf722e5b7794b84a50b84c5c7f
fs-extra:
specifier: ^11.1.1
version: 11.1.1
@ -211,7 +211,7 @@ importers:
version: github.com/zardoy/minecraft-inventory-gui/c1331c91fb39bd562dc48eeb33321240d4870edd(@types/react@18.2.20)(react@18.2.0)
mineflayer:
specifier: github:zardoy/mineflayer#custom
version: github.com/zardoy/mineflayer/66e34da4a02381a6a45582afe0d3bfab6dba60c6
version: github.com/zardoy/mineflayer/e828c161aab120f2d926fba48de3b4d57c361710
mineflayer-pathfinder:
specifier: ^2.4.4
version: 2.4.4
@ -14391,8 +14391,8 @@ packages:
- encoding
- supports-color
github.com/zardoy/mineflayer/66e34da4a02381a6a45582afe0d3bfab6dba60c6:
resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/66e34da4a02381a6a45582afe0d3bfab6dba60c6}
github.com/zardoy/mineflayer/e828c161aab120f2d926fba48de3b4d57c361710:
resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/e828c161aab120f2d926fba48de3b4d57c361710}
name: mineflayer
version: 4.14.0
engines: {node: '>=14'}
@ -14467,8 +14467,8 @@ packages:
- utf-8-validate
dev: false
github.com/zardoy/space-squid/acf7b6f8cbcc204007eed767eb52a527a85b3ab0:
resolution: {tarball: https://codeload.github.com/zardoy/space-squid/tar.gz/acf7b6f8cbcc204007eed767eb52a527a85b3ab0}
github.com/zardoy/space-squid/bdf1e0859ad435bf722e5b7794b84a50b84c5c7f:
resolution: {tarball: https://codeload.github.com/zardoy/space-squid/tar.gz/bdf1e0859ad435bf722e5b7794b84a50b84c5c7f}
name: flying-squid
version: 1.5.0
engines: {node: '>=8'}

View file

@ -232,11 +232,12 @@ document.addEventListener('keydown', (e) => {
if (localServer) {
localServer.players[0].world.columns = {}
}
reloadChunks()
void reloadChunks()
}
if (e.code === 'KeyG') {
// todo make it work without reload
options.showChunkBorders = !options.showChunkBorders
void reloadChunks()
}
return
}

View file

@ -2,7 +2,8 @@
import { proxy, ref, subscribe } from 'valtio'
import { pointerLock } from './utils'
import { OptionsGroupType, options } from './optionsStorage'
import { options } from './optionsStorage'
import type { OptionsGroupType } from './optionsGuiScheme'
// todo: refactor structure with support of hideNext=false

3
src/globals.d.ts vendored
View file

@ -7,6 +7,9 @@ declare const __type_bot: typeof bot
declare const viewer: import('prismarine-viewer/viewer/lib/viewer').Viewer | undefined
declare const worldView: import('prismarine-viewer/viewer/lib/worldDataEmitter').WorldDataEmitter | undefined
declare const localServer: any
/** all currently loaded mc data */
declare const mcData: Record<string, any>
declare const loadedData: import('minecraft-data').IndexedData
declare interface Document {
getElementById (id): any

View file

@ -1,73 +1,19 @@
// todo implement async options storage
import { proxy, subscribe } from 'valtio/vanilla'
// weird webpack configuration bug: it cant import valtio/utils in this file
import { subscribeKey } from 'valtio/utils'
import { useState } from 'react'
import { useSnapshot } from 'valtio'
import { OptionMeta, OptionSlider } from './react/OptionsItems'
import Button from './react/Button'
import { openOptionsMenu } from './globalState'
import { isGameActive, openOptionsMenu } from './globalState'
import { openURL } from './menus/components/common'
import { AppOptions, options } from './optionsStorage'
import Button from './react/Button'
import { OptionMeta } from './react/OptionsItems'
import Slider from './react/Slider'
import { getScreenRefreshRate } from './utils'
import { getScreenRefreshRate, openFilePicker, setLoadingScreenStatus } from './utils'
import { getResourcePackName, resourcePackState, uninstallTexturePack } from './texturePack'
import { fsState } from './loadSave'
const mergeAny: <T>(arg1: T, arg2: any) => T = Object.assign
const defaultOptions = {
renderDistance: 4,
closeConfirmation: true,
autoFullScreen: false,
mouseRawInput: false,
autoExitFullscreen: false,
localUsername: 'wanderer',
mouseSensX: 50,
mouseSensY: 50 as number | true,
// mouseInvertX: false,
chatWidth: 320,
chatHeight: 180,
chatScale: 100,
volume: 50,
// fov: 70,
fov: 75,
guiScale: 3,
autoRequestCompletions: true,
touchButtonsSize: 40,
highPerformanceGpu: false,
showChunkBorders: false,
frameLimit: false as number | false,
alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null,
alwaysShowMobileControls: false,
maxMultiplayerRenderDistance: null as number | null,
excludeCommunicationDebugEvents: [],
preventDevReloadWhilePlaying: false,
numWorkers: 4,
localServerOptions: {} as any,
preferLoadReadonly: false,
disableLoadPrompts: false,
guestUsername: 'guest',
askGuestName: true,
// advanced bot options
autoRespawn: false
}
export type AppOptions = typeof defaultOptions
export type OptionsGroupType = 'main' | 'render' | 'interface' | 'controls' | 'sound' | 'advanced'
// todo refactor to separate file like optionsGUI.tsx
export const guiOptionsScheme: {
[t in OptionsGroupType]: Array<{ [k in keyof AppOptions]?: Partial<OptionMeta> } & { custom?}>
} = {
render: [
{
renderDistance: {
unit: '',
min: 2,
max: 16
},
},
{
custom () {
const frameLimitValue = useSnapshot(options).frameLimit
@ -106,8 +52,10 @@ export const guiOptionsScheme: {
}
},
{
custom () {
return <Button label='Interface...' onClick={() => openOptionsMenu('interface')} inScreen />
renderDistance: {
unit: '',
min: 2,
max: 16
},
},
{
@ -115,6 +63,11 @@ export const guiOptionsScheme: {
return <Button label='Render...' onClick={() => openOptionsMenu('render')} inScreen />
},
},
{
custom () {
return <Button label='Interface...' onClick={() => openOptionsMenu('interface')} inScreen />
},
},
{
custom () {
return <Button label='Sound...' onClick={() => openOptionsMenu('sound')} inScreen />
@ -124,6 +77,33 @@ export const guiOptionsScheme: {
custom () {
return <Button label='Controls...' onClick={() => openOptionsMenu('controls')} inScreen />
},
},
// {
// custom () {
// return <Button label='Advanced...' onClick={() => openOptionsMenu('advanced')} inScreen />
// },
// },
{
custom () {
const { resourcePackInstalled } = useSnapshot(resourcePackState)
return <Button label={`Resource Pack... ${resourcePackInstalled ? 'ON' : 'OFF'}`} inScreen onClick={async () => {
if (resourcePackState.resourcePackInstalled) {
const resourcePackName = await getResourcePackName()
if (confirm(`Uninstall ${resourcePackName} resource pack?`)) {
// todo make hidable
setLoadingScreenStatus('Uninstalling texturepack...')
await uninstallTexturePack()
setLoadingScreenStatus(undefined)
}
} else {
if (!fsState.inMemorySave && isGameActive(false)) {
alert('Unable to install resource pack in loaded save for now')
return
}
openFilePicker('resourcepack')
}
}} />
},
}
],
interface: [
@ -148,12 +128,16 @@ export const guiOptionsScheme: {
// keybindings
mouseSensX: {},
mouseSensY: {},
mouseRawInput: {},
mouseRawInput: {
tooltip: 'Wether to disable any mouse acceleration (MC does it by default). Most probably it is still supported only by Chrome.',
disabledReason: document.documentElement.requestPointerLock ? undefined : 'Your browser does not support pointer lock.',
},
alwaysShowMobileControls: {
text: 'Always Mobile Controls',
},
autoFullScreen: {
tooltip: 'Auto Fullscreen allows you to use Ctrl+W and Escape having to wait/click on screen again.',
disabledReason: navigator['keyboard'] ? undefined : 'Your browser doesn\'t support keyboard lock API'
},
autoExitFullscreen: {
tooltip: 'Exit fullscreen on escape (pause menu open). But note you can always do it with F11.',
@ -164,45 +148,11 @@ export const guiOptionsScheme: {
}
],
sound: [
{ volume: {} }
{ volume: {} },
// { ignoreSilentSwitch: {} },
],
advanced: [
],
}
export const options = proxy(
mergeAny(defaultOptions, JSON.parse(localStorage.options || '{}'))
)
window.options = window.settings = options
subscribe(options, () => {
localStorage.options = JSON.stringify(options)
})
type WatchValue = <T extends Record<string, any>>(proxy: T, callback: (p: T) => void) => void
export const watchValue: WatchValue = (proxy, callback) => {
const watchedProps = new Set<string>()
callback(new Proxy(proxy, {
get (target, p, receiver) {
watchedProps.add(p.toString())
return Reflect.get(target, p, receiver)
},
}))
for (const prop of watchedProps) {
subscribeKey(proxy, prop, () => {
callback(proxy)
})
}
}
watchValue(options, o => {
globalThis.excludeCommunicationDebugEvents = o.excludeCommunicationDebugEvents
})
export const useOptionValue = (setting, valueCallback) => {
valueCallback(setting)
subscribe(setting, valueCallback)
}
export type OptionsGroupType = 'main' | 'render' | 'interface' | 'controls' | 'sound' | 'advanced'

84
src/optionsStorage.ts Normal file
View file

@ -0,0 +1,84 @@
// todo implement async options storage
import { proxy, subscribe } from 'valtio/vanilla'
// weird webpack configuration bug: it cant import valtio/utils in this file
import { subscribeKey } from 'valtio/utils'
const mergeAny: <T>(arg1: T, arg2: any) => T = Object.assign
const defaultOptions = {
renderDistance: 4,
closeConfirmation: true,
autoFullScreen: false,
mouseRawInput: false,
autoExitFullscreen: false,
localUsername: 'wanderer',
mouseSensX: 50,
mouseSensY: 50 as number | true,
// mouseInvertX: false,
chatWidth: 320,
chatHeight: 180,
chatScale: 100,
volume: 50,
// fov: 70,
fov: 75,
guiScale: 3,
autoRequestCompletions: true,
touchButtonsSize: 40,
highPerformanceGpu: false,
showChunkBorders: false,
frameLimit: false as number | false,
alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null,
alwaysShowMobileControls: false,
maxMultiplayerRenderDistance: null as number | null,
excludeCommunicationDebugEvents: [],
preventDevReloadWhilePlaying: false,
numWorkers: 4,
localServerOptions: {} as any,
preferLoadReadonly: false,
disableLoadPrompts: false,
guestUsername: 'guest',
askGuestName: true,
// advanced bot options
autoRespawn: false
}
export type AppOptions = typeof defaultOptions
export const options = proxy(
mergeAny(defaultOptions, JSON.parse(localStorage.options || '{}'))
)
window.options = window.settings = options
subscribe(options, () => {
localStorage.options = JSON.stringify(options)
})
type WatchValue = <T extends Record<string, any>>(proxy: T, callback: (p: T) => void) => void
export const watchValue: WatchValue = (proxy, callback) => {
const watchedProps = new Set<string>()
callback(new Proxy(proxy, {
get (target, p, receiver) {
watchedProps.add(p.toString())
return Reflect.get(target, p, receiver)
},
}))
for (const prop of watchedProps) {
subscribeKey(proxy, prop, () => {
callback(proxy)
})
}
}
watchValue(options, o => {
globalThis.excludeCommunicationDebugEvents = o.excludeCommunicationDebugEvents
})
export const useOptionValue = (setting, valueCallback) => {
valueCallback(setting)
subscribe(setting, valueCallback)
}

View file

@ -1,5 +1,6 @@
import { titleCase } from 'title-case'
import { OptionsGroupType, guiOptionsScheme, options } from '../optionsStorage'
import { options } from '../optionsStorage'
import { OptionsGroupType, guiOptionsScheme } from '../optionsGuiScheme'
import OptionsItems, { OptionMeta } from './OptionsItems'
const optionValueToType = (optionValue: any) => {

View file

@ -1,6 +1,6 @@
import { useSnapshot } from 'valtio'
import { activeModalStack, hideCurrentModal } from '../globalState'
import { OptionsGroupType } from '../optionsStorage'
import { OptionsGroupType } from '../optionsGuiScheme'
import OptionsGroup from './OptionsGroup'
export default () => {