Skip to content

Commit cdc6ea3

Browse files
authored
Release (#312)
2 parents 225f957 + 4a4823f commit cdc6ea3

32 files changed

+780
-406
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"mojangson": "^2.0.4",
8787
"net-browserify": "github:zardoy/prismarinejs-net-browserify",
8888
"node-gzip": "^1.1.2",
89-
"mcraft-fun-mineflayer": "^0.1.12",
89+
"mcraft-fun-mineflayer": "^0.1.14",
9090
"peerjs": "^1.5.0",
9191
"pixelarticons": "^1.8.1",
9292
"pretty-bytes": "^6.1.1",
@@ -151,7 +151,7 @@
151151
"http-server": "^14.1.1",
152152
"https-browserify": "^1.0.0",
153153
"mc-assets": "^0.2.42",
154-
"mineflayer-mouse": "^0.1.1",
154+
"mineflayer-mouse": "^0.1.2",
155155
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
156156
"mineflayer": "github:zardoy/mineflayer",
157157
"mineflayer-pathfinder": "^2.4.4",

pnpm-lock.yaml

+44-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/mcStatusApi.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const isServerValid = (ip: string) => {
1515
return !isInLocalNetwork && VALID_IP_OR_DOMAIN
1616
}
1717

18-
export async function fetchServerStatus (ip: string, signal?: AbortSignal) {
18+
export async function fetchServerStatus (ip: string, signal?: AbortSignal, versionOverride?: string) {
1919
if (!isServerValid(ip)) return
2020

2121
const response = await fetch(`https://api.mcstatus.io/v2/status/java/${ip}`, { signal })
@@ -25,7 +25,7 @@ export async function fetchServerStatus (ip: string, signal?: AbortSignal) {
2525
return {
2626
formattedText: data.motd?.raw ?? '',
2727
textNameRight: data.online ?
28-
`${versionClean} ${data.players?.online ?? '??'}/${data.players?.max ?? '??'}` :
28+
`${versionOverride ?? versionClean} ${data.players?.online ?? '??'}/${data.players?.max ?? '??'}` :
2929
'',
3030
icon: data.icon,
3131
offline: !data.online,

src/appConfig.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { disabledSettings, options, qsOptions } from './optionsStorage'
22
import { miscUiState } from './globalState'
33
import { setLoadingScreenStatus } from './appStatus'
4+
import { setStorageDataOnAppConfigLoad } from './react/appStorageProvider'
45

56
export type AppConfig = {
67
// defaultHost?: string
@@ -42,6 +43,8 @@ export const loadAppConfig = (appConfig: AppConfig) => {
4243
}
4344
}
4445
}
46+
47+
setStorageDataOnAppConfigLoad()
4548
}
4649

4750
export const isBundledConfigUsed = !!process.env.INLINED_APP_CONFIG

src/appParams.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AppConfig } from './appConfig'
2+
import { miscUiState } from './globalState'
23

34
const qsParams = new URLSearchParams(window.location?.search ?? '')
45

@@ -73,7 +74,7 @@ export const appQueryParams = new Proxy<AppQsParams>({} as AppQsParams, {
7374
}
7475
const qsParam = qsParams.get(property)
7576
if (qsParam) return qsParam
76-
return initialAppConfig.appParams?.[property]
77+
return miscUiState.appConfig?.appParams?.[property]
7778
},
7879
})
7980

@@ -84,7 +85,7 @@ export const appQueryParamsArray = new Proxy({} as AppQsParamsArrayTransformed,
8485
}
8586
const qsParam = qsParams.getAll(property)
8687
if (qsParam.length) return qsParam
87-
return initialAppConfig.appParams?.[property] ?? []
88+
return miscUiState.appConfig?.appParams?.[property] ?? []
8889
},
8990
})
9091

src/browserfs.ts

+5-15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { getFixedFilesize } from './downloadAndOpenFile'
1515
import { packetsReplayState } from './react/state/packetsReplayState'
1616
import { createFullScreenProgressReporter } from './core/progressReporter'
1717
import { showNotification } from './react/NotificationProvider'
18+
import { resetAppStorage } from './react/appStorageProvider'
1819
const { GoogleDriveFileSystem } = require('google-drive-browserfs/src/backends/GoogleDrive')
1920

2021
browserfs.install(window)
@@ -620,24 +621,13 @@ export const openWorldZip = async (...args: Parameters<typeof openWorldZipInner>
620621
}
621622
}
622623

623-
export const resetLocalStorageWorld = () => {
624-
for (const key of Object.keys(localStorage)) {
625-
if (/^[\da-fA-F]{8}(?:\b-[\da-fA-F]{4}){3}\b-[\da-fA-F]{12}$/g.test(key) || key === '/') {
626-
localStorage.removeItem(key)
627-
}
628-
}
629-
}
630-
631-
export const resetLocalStorageWithoutWorld = () => {
632-
for (const key of Object.keys(localStorage)) {
633-
if (!/^[\da-fA-F]{8}(?:\b-[\da-fA-F]{4}){3}\b-[\da-fA-F]{12}$/g.test(key) && key !== '/') {
634-
localStorage.removeItem(key)
635-
}
636-
}
624+
export const resetLocalStorage = () => {
637625
resetOptions()
626+
resetAppStorage()
638627
}
639628

640-
window.resetLocalStorageWorld = resetLocalStorageWorld
629+
window.resetLocalStorage = resetLocalStorage
630+
641631
export const openFilePicker = (specificCase?: 'resourcepack') => {
642632
// create and show input picker
643633
let picker: HTMLInputElement = document.body.querySelector('input#file-zip-picker')!

src/controls.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ControMax } from 'contro-max/build/controMax'
88
import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types'
99
import { stringStartsWith } from 'contro-max/build/stringUtils'
1010
import { UserOverrideCommand, UserOverridesConfig } from 'contro-max/build/types/store'
11+
import { GameMode } from 'mineflayer'
1112
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, hideModal, hideAllModals } from './globalState'
1213
import { goFullscreen, isInRealGameSession, pointerLock, reloadChunks } from './utils'
1314
import { options } from './optionsStorage'
@@ -25,11 +26,13 @@ import { showNotification } from './react/NotificationProvider'
2526
import { lastConnectOptions } from './react/AppStatusProvider'
2627
import { onCameraMove, onControInit } from './cameraRotationControls'
2728
import { createNotificationProgressReporter } from './core/progressReporter'
29+
import { appStorage } from './react/appStorageProvider'
30+
import { switchGameMode } from './packetsReplay/replayPackets'
2831

2932

30-
export const customKeymaps = proxy(JSON.parse(localStorage.keymap || '{}')) as UserOverridesConfig
33+
export const customKeymaps = proxy(appStorage.keybindings)
3134
subscribe(customKeymaps, () => {
32-
localStorage.keymap = JSON.stringify(customKeymaps)
35+
appStorage.keybindings = customKeymaps
3336
})
3437

3538
const controlOptions = {
@@ -636,29 +639,35 @@ export const f3Keybinds: Array<{
636639
{
637640
key: 'F4',
638641
async action () {
642+
let nextGameMode: GameMode
639643
switch (bot.game.gameMode) {
640644
case 'creative': {
641-
bot.chat('/gamemode survival')
645+
nextGameMode = 'survival'
642646

643647
break
644648
}
645649
case 'survival': {
646-
bot.chat('/gamemode adventure')
650+
nextGameMode = 'adventure'
647651

648652
break
649653
}
650654
case 'adventure': {
651-
bot.chat('/gamemode spectator')
655+
nextGameMode = 'spectator'
652656

653657
break
654658
}
655659
case 'spectator': {
656-
bot.chat('/gamemode creative')
660+
nextGameMode = 'creative'
657661

658662
break
659663
}
660664
// No default
661665
}
666+
if (lastConnectOptions.value?.worldStateFileContents) {
667+
switchGameMode(nextGameMode)
668+
} else {
669+
bot.chat(`/gamemode ${nextGameMode}`)
670+
}
662671
},
663672
mobileTitle: 'Cycle Game Mode'
664673
},
@@ -809,15 +818,16 @@ let allowFlying = false
809818
export const onBotCreate = () => {
810819
let wasSpectatorFlying = false
811820
bot._client.on('abilities', ({ flags }) => {
821+
allowFlying = !!(flags & 4)
812822
if (flags & 2) { // flying
813823
toggleFly(true, false)
814824
} else {
815825
toggleFly(false, false)
816826
}
817-
allowFlying = !!(flags & 4)
818827
})
819828
const gamemodeCheck = () => {
820829
if (bot.game.gameMode === 'spectator') {
830+
allowFlying = true
821831
toggleFly(true, false)
822832
wasSpectatorFlying = true
823833
} else if (wasSpectatorFlying) {

src/downloadAndOpenFile.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,43 @@ export const getFixedFilesize = (bytes: number) => {
1313
const inner = async () => {
1414
const { replayFileUrl } = appQueryParams
1515
if (replayFileUrl) {
16-
setLoadingScreenStatus('Downloading replay file...')
16+
setLoadingScreenStatus('Downloading replay file')
1717
const response = await fetch(replayFileUrl)
1818
const contentLength = response.headers?.get('Content-Length')
1919
const size = contentLength ? +contentLength : undefined
2020
const filename = replayFileUrl.split('/').pop()
2121

22-
const contents = await response.text()
22+
let downloadedBytes = 0
23+
const buffer = await new Response(new ReadableStream({
24+
async start (controller) {
25+
if (!response.body) throw new Error('Server returned no response!')
26+
const reader = response.body.getReader()
27+
28+
// eslint-disable-next-line no-constant-condition
29+
while (true) {
30+
const { done, value } = await reader.read()
31+
32+
if (done) {
33+
controller.close()
34+
break
35+
}
36+
37+
downloadedBytes += value.byteLength
38+
39+
// Calculate download progress as a percentage
40+
const progress = size ? (downloadedBytes / size) * 100 : undefined
41+
setLoadingScreenStatus(`Download replay file progress: ${progress === undefined ? '?' : Math.floor(progress)}% (${getFixedFilesize(downloadedBytes)} / ${size && getFixedFilesize(size)})`, false, true)
42+
43+
// Pass the received data to the controller
44+
controller.enqueue(value)
45+
}
46+
},
47+
})).arrayBuffer()
48+
49+
// Convert buffer to text, handling any compression automatically
50+
const decoder = new TextDecoder()
51+
const contents = decoder.decode(buffer)
52+
2353
openFile({
2454
contents,
2555
filename,

src/globalState.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,12 @@
33
import { proxy, ref, subscribe } from 'valtio'
44
import type { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
55
import type { OptionsGroupType } from './optionsGuiScheme'
6-
import { appQueryParams } from './appParams'
76
import { options, disabledSettings } from './optionsStorage'
87
import { AppConfig } from './appConfig'
98

109
// todo: refactor structure with support of hideNext=false
1110

12-
const notHideableModalsWithoutForce = new Set(['app-status'])
13-
14-
if (appQueryParams.lockConnect) {
15-
notHideableModalsWithoutForce.add('editServer')
16-
}
11+
export const notHideableModalsWithoutForce = new Set(['app-status'])
1712

1813
type Modal = ({ elem?: HTMLElement & Record<string, any> } & { reactType: string })
1914

src/globals.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ declare const customEvents: import('typed-emitter').default<{
2626
mineflayerBotCreated (): void
2727
search (q: string): void
2828
activateItem (item: Item, slot: number, offhand: boolean): void
29-
hurtAnimation (): void
29+
hurtAnimation (yaw?: number): void
3030
}>
3131
declare const beforeRenderFrame: Array<() => void>
3232

0 commit comments

Comments
 (0)