refactor: rm loadedGameState, add a way to copy server resource pack to local

This commit is contained in:
Vitaly Turovsky 2025-01-31 05:52:55 +03:00
commit f755385981
9 changed files with 66 additions and 36 deletions

View file

@ -7,7 +7,7 @@ import { ControMax } from 'contro-max/build/controMax'
import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types'
import { stringStartsWith } from 'contro-max/build/stringUtils'
import { UserOverrideCommand, UserOverridesConfig } from 'contro-max/build/types/store'
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState, hideModal, hideAllModals } from './globalState'
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, hideModal, hideAllModals } from './globalState'
import { goFullscreen, pointerLock, reloadChunks } from './utils'
import { options } from './optionsStorage'
import { openPlayerInventory } from './inventoryWindows'
@ -19,7 +19,7 @@ import { showOptionsModal } from './react/SelectOption'
import widgets from './react/widgets'
import { getItemFromBlock } from './chatUtils'
import { gamepadUiCursorState, moveGamepadCursorByPx } from './react/GamepadUiCursor'
import { completeTexturePackInstall, resourcePackState } from './resourcePack'
import { completeTexturePackInstall, copyServerResourcePackToRegular, resourcePackState } from './resourcePack'
import { showNotification } from './react/NotificationProvider'
import { lastConnectOptions } from './react/AppStatusProvider'
@ -450,7 +450,12 @@ contro.on('release', ({ command }) => {
// hard-coded keybindings
export const f3Keybinds = [
export const f3Keybinds: Array<{
key?: string,
action: () => void,
mobileTitle: string
enabled?: () => boolean
}> = [
{
key: 'KeyA',
action () {
@ -496,9 +501,9 @@ export const f3Keybinds = [
key: 'KeyT',
async action () {
// TODO!
if (resourcePackState.resourcePackInstalled || loadedGameState.usingServerResourcePack) {
if (resourcePackState.resourcePackInstalled || gameAdditionalState.usingServerResourcePack) {
showNotification('Reloading textures...')
await completeTexturePackInstall('default', 'default', loadedGameState.usingServerResourcePack)
await completeTexturePackInstall('default', 'default', gameAdditionalState.usingServerResourcePack)
}
},
mobileTitle: 'Reload Textures'
@ -539,7 +544,15 @@ export const f3Keybinds = [
const proxyPing = await bot['pingProxy']()
void showOptionsModal(`${username}: last known total latency (ping): ${playerPing}. Connected to ${lastConnectOptions.value?.proxy} with current ping ${proxyPing}. Player UUID: ${uuid}`, [])
},
mobileTitle: 'Show Proxy & Ping Details'
mobileTitle: 'Show Proxy & Ping Details',
enabled: () => !!lastConnectOptions.value?.proxy
},
{
action () {
void copyServerResourcePackToRegular()
},
mobileTitle: 'Copy Server Resource Pack',
enabled: () => !!gameAdditionalState.usingServerResourcePack
}
]
@ -548,7 +561,7 @@ document.addEventListener('keydown', (e) => {
if (!isGameActive(false)) return
if (hardcodedPressedKeys.has('F3')) {
const keybind = f3Keybinds.find((v) => v.key === e.code)
if (keybind) {
if (keybind && (keybind.enabled?.() ?? true)) {
keybind.action()
e.stopPropagation()
}

View file

@ -146,12 +146,6 @@ export const miscUiState = proxy({
displaySearchInput: false,
})
export const loadedGameState = proxy({
username: '',
serverIp: '' as string | null,
usingServerResourcePack: false,
})
export const isGameActive = (foregroundCheck: boolean) => {
if (foregroundCheck && activeModalStack.length) return false
return miscUiState.gameLoaded
@ -165,7 +159,9 @@ export const gameAdditionalState = proxy({
isSprinting: false,
isSneaking: false,
isZooming: false,
warps: [] as WorldWarp[]
warps: [] as WorldWarp[],
usingServerResourcePack: false,
})
window.gameAdditionalState = gameAdditionalState

View file

@ -53,7 +53,6 @@ import {
hideModal,
insertActiveModalStack,
isGameActive,
loadedGameState,
miscUiState,
showModal
} from './globalState'
@ -884,12 +883,6 @@ async function connect (connectOptions: ConnectOptions) {
console.log('Done!')
// todo
onGameLoad(async () => {
loadedGameState.serverIp = server.host ?? null
loadedGameState.username = username
})
if (appStatusState.isError) return
setTimeout(() => {
// todo

View file

@ -2,7 +2,7 @@ import { useRef, useState } from 'react'
import { useSnapshot } from 'valtio'
import { openURL } from 'prismarine-viewer/viewer/lib/simpleUtils'
import { noCase } from 'change-case'
import { loadedGameState, miscUiState, openOptionsMenu, showModal } from './globalState'
import { gameAdditionalState, miscUiState, openOptionsMenu, showModal } from './globalState'
import { AppOptions, options } from './optionsStorage'
import Button from './react/Button'
import { OptionMeta, OptionSlider } from './react/OptionsItems'
@ -157,7 +157,7 @@ export const guiOptionsScheme: {
{
custom () {
const { resourcePackInstalled } = useSnapshot(resourcePackState)
const { usingServerResourcePack } = useSnapshot(loadedGameState)
const { usingServerResourcePack } = useSnapshot(gameAdditionalState)
const { enabledResourcepack } = useSnapshot(options)
return <Button
label={`Resource Pack: ${usingServerResourcePack ? 'SERVER ON' : resourcePackInstalled ? enabledResourcepack ? 'ON' : 'OFF' : 'NO'}`} inScreen onClick={async () => {

View file

@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { useSnapshot } from 'valtio'
import { formatMessage } from '../chatUtils'
import { getBuiltinCommandsList, tryHandleBuiltinCommand } from '../builtinCommands'
import { hideCurrentModal, loadedGameState, miscUiState } from '../globalState'
import { hideCurrentModal, miscUiState } from '../globalState'
import { options } from '../optionsStorage'
import Chat, { Message, fadeMessage } from './Chat'
import { useIsModalActive } from './utilsApp'
@ -54,7 +54,7 @@ export default () => {
updateLoadedServerData((server) => {
server.autoLogin ??= {}
const password = message.split(' ')[1]
server.autoLogin[loadedGameState.username] = password
server.autoLogin[bot.player.username] = password
return server
})
hideNotification()

View file

@ -15,11 +15,12 @@ import { useSnapshot } from 'valtio'
import BlockData from '../../prismarine-viewer/viewer/lib/moreBlockDataGenerated.json'
import preflatMap from '../preflatMap.json'
import { contro } from '../controls'
import { gameAdditionalState, showModal, hideModal, miscUiState, loadedGameState, activeModalStack } from '../globalState'
import { gameAdditionalState, showModal, hideModal, miscUiState, activeModalStack } from '../globalState'
import { options } from '../optionsStorage'
import Minimap, { DisplayMode } from './Minimap'
import { ChunkInfo, DrawerAdapter, MapUpdates, MinimapDrawer } from './MinimapDrawer'
import { useIsModalActive } from './utilsApp'
import { lastConnectOptions } from './AppStatusProvider'
const getBlockKey = (x: number, z: number) => {
return `${x},${z}`
@ -167,9 +168,9 @@ export class DrawerAdapterImpl extends TypedEventEmitter<MapUpdates> implements
// type suppressed until server is updated. It works fine
void (localServer as any).setWarp(warp, remove)
} else if (remove) {
localStorage.removeItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`)
localStorage.removeItem(`warps: ${bot.player.username} ${lastConnectOptions.value!.server}`)
} else {
localStorage.setItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`, JSON.stringify(this.warps))
localStorage.setItem(`warps: ${bot.player.username} ${lastConnectOptions.value!.server}`, JSON.stringify(this.warps))
}
this.emit('updateWarps')
}

View file

@ -21,7 +21,7 @@ export default () => {
}, [])
const onLongPress = async () => {
const select = await showOptionsModal('', f3Keybinds.filter(f3Keybind => f3Keybind.mobileTitle).map(f3Keybind => f3Keybind.mobileTitle))
const select = await showOptionsModal('', f3Keybinds.filter(f3Keybind => f3Keybind.mobileTitle && (f3Keybind.enabled?.() ?? true)).map(f3Keybind => f3Keybind.mobileTitle))
if (!select) return
const f3Keybind = f3Keybinds.find(f3Keybind => f3Keybind.mobileTitle === select)
if (f3Keybind) f3Keybind.action()

View file

@ -1,15 +1,16 @@
import { useSnapshot } from 'valtio'
import { useState, useEffect, useMemo } from 'react'
import { isGameActive, loadedGameState } from '../globalState'
import { isGameActive } from '../globalState'
import PlayerListOverlay from './PlayerListOverlay'
import './PlayerListOverlay.css'
import { lastConnectOptions } from './AppStatusProvider'
const MAX_ROWS_PER_COL = 10
type Players = typeof bot.players
export default () => {
const { serverIp } = useSnapshot(loadedGameState)
const serverIp = lastConnectOptions.value?.server
const [clientId, setClientId] = useState('')
const [players, setPlayers] = useState<Players>({})
const [isOpen, setIsOpen] = useState(false)

View file

@ -4,14 +4,14 @@ import fs from 'fs'
import JSZip from 'jszip'
import { proxy, subscribe } from 'valtio'
import { WorldRendererThree } from 'prismarine-viewer/viewer/lib/worldrendererThree'
import { mkdirRecursive, removeFileRecursiveAsync } from './browserfs'
import { collectFilesToCopy, copyFilesAsyncWithProgress, mkdirRecursive, removeFileRecursiveAsync } from './browserfs'
import { setLoadingScreenStatus } from './utils'
import { showNotification } from './react/NotificationProvider'
import { options } from './optionsStorage'
import { showOptionsModal } from './react/SelectOption'
import { appStatusState } from './react/AppStatusProvider'
import { appReplacableResources, resourcesContentOriginal } from './generated/resources'
import { loadedGameState, miscUiState } from './globalState'
import { gameAdditionalState, miscUiState } from './globalState'
import { watchUnloadForCleanup } from './gameUnload'
export const resourcePackState = proxy({
@ -32,7 +32,7 @@ const texturePackBasePath = '/data/resourcePacks/'
export const uninstallTexturePack = async (name = 'default') => {
if (await existsAsync('/resourcepack/pack.mcmeta')) {
await removeFileRecursiveAsync('/resourcepack')
loadedGameState.usingServerResourcePack = false
gameAdditionalState.usingServerResourcePack = false
}
const basePath = texturePackBasePath + name
if (!(await existsAsync(basePath))) return
@ -113,7 +113,7 @@ export const installTexturePack = async (file: File | ArrayBuffer, displayName =
done++
upStatus()
}))
console.log('done')
console.log('resource pack install done')
await completeTexturePackInstall(displayName, name, isServer)
}
@ -129,7 +129,7 @@ export const completeTexturePackInstall = async (displayName: string | undefined
showNotification('Texturepack installed & enabled')
await updateTexturePackInstalledState()
if (isServer) {
loadedGameState.usingServerResourcePack = true
gameAdditionalState.usingServerResourcePack = true
} else {
options.enabledResourcepack = name
}
@ -463,3 +463,29 @@ const updateTextures = async () => {
export const resourcepackReload = async (version) => {
await updateTextures()
}
export const copyServerResourcePackToRegular = async (name = 'default') => {
// Check if server resource pack exists
if (!(await existsAsync('/resourcepack/pack.mcmeta'))) {
throw new Error('No server resource pack is currently installed')
}
// Get display name from server resource pack if available
let displayName
try {
displayName = await fs.promises.readFile('/resourcepack/name.txt', 'utf8')
} catch {
displayName = 'Server Resource Pack'
}
// Copy all files from server resource pack to regular location
const destPath = texturePackBasePath + name
await mkdirRecursive(destPath)
setLoadingScreenStatus('Copying server resource pack to regular location')
await copyFilesAsyncWithProgress('/resourcepack', destPath, true, ' (server -> regular)')
// Complete the installation
await completeTexturePackInstall(displayName, name, false)
showNotification('Server resource pack copied to regular location')
}