Skip to content

Commit

Permalink
feat: minimap and full screen map (disabled by default) (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
gguio authored Nov 27, 2024
1 parent b89cf52 commit af088d9
Show file tree
Hide file tree
Showing 21 changed files with 1,799 additions and 39 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"react-dom": "^18.2.0",
"react-select": "^5.8.0",
"react-transition-group": "^4.4.5",
"react-zoom-pan-pinch": "3.4.4",
"remark": "^15.0.1",
"sanitize-filename": "^1.6.3",
"skinview3d": "^3.0.1",
Expand Down
35 changes: 25 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 9 additions & 12 deletions prismarine-viewer/viewer/lib/mesher/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import legacyJson from '../../../../src/preflatMap.json'
import { BlockType } from '../../../examples/shared'
import { World, BlockModelPartsResolved, WorldBlock as Block } from './world'
import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon'
import { MesherGeometryOutput } from './shared'
import { INVISIBLE_BLOCKS } from './worldConstants'
import { MesherGeometryOutput, HighestBlockInfo } from './shared'


let blockProvider: WorldBlockProvider

Expand Down Expand Up @@ -439,8 +441,6 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO:
}
}

const invisibleBlocks = new Set(['air', 'cave_air', 'void_air', 'barrier'])

const isBlockWaterlogged = (block: Block) => block.getProperties().waterlogged === true || block.getProperties().waterlogged === 'true'

let unknownBlockModel: BlockModelPartsResolved
Expand All @@ -464,7 +464,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
// todo this can be removed here
signs: {},
// isFull: true,
highestBlocks: {}, // todo migrate to map for 2% boost perf
highestBlocks: new Map<string, HighestBlockInfo>([]),
hadErrors: false,
blocksCount: 0
}
Expand All @@ -474,16 +474,13 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
for (cursor.z = sz; cursor.z < sz + 16; cursor.z++) {
for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) {
let block = world.getBlock(cursor, blockProvider, attr)!
if (!invisibleBlocks.has(block.name)) {
const highest = attr.highestBlocks[`${cursor.x},${cursor.z}`]
if (!INVISIBLE_BLOCKS.has(block.name)) {
const highest = attr.highestBlocks.get(`${cursor.x},${cursor.z}`)
if (!highest || highest.y < cursor.y) {
attr.highestBlocks[`${cursor.x},${cursor.z}`] = {
y: cursor.y,
name: block.name
}
attr.highestBlocks.set(`${cursor.x},${cursor.z}`, { y: cursor.y, stateId: block.stateId, biomeId: block.biome.id })
}
}
if (invisibleBlocks.has(block.name)) continue
if (INVISIBLE_BLOCKS.has(block.name)) continue
if ((block.name.includes('_sign') || block.name === 'sign') && !world.config.disableSignsMapsSupport) {
const key = `${cursor.x},${cursor.y},${cursor.z}`
const props: any = block.getProperties()
Expand Down Expand Up @@ -531,7 +528,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr)
attr.blocksCount++
}
if (block.name !== 'water' && block.name !== 'lava' && !invisibleBlocks.has(block.name)) {
if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) {
// cache
let { models } = block

Expand Down
4 changes: 3 additions & 1 deletion prismarine-viewer/viewer/lib/mesher/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export type MesherGeometryOutput = {
tiles: Record<string, BlockType>,
signs: Record<string, any>,
// isFull: boolean
highestBlocks: Record<string, { y: number, name: string }>
highestBlocks: Map<string, HighestBlockInfo>
hadErrors: boolean
blocksCount: number
}

export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined }
3 changes: 2 additions & 1 deletion prismarine-viewer/viewer/lib/mesher/test/tests.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test, expect } from 'vitest'
import supportedVersions from '../../../../../src/supportedVersions.mjs'
import { INVISIBLE_BLOCKS } from '../worldConstants'
import { setup } from './mesherTester'

const lastVersion = supportedVersions.at(-1)
Expand All @@ -16,7 +17,7 @@ const addPositions = [

test('Known blocks are not rendered', () => {
const { mesherWorld, getGeometry, pos, mcData } = setup(lastVersion, addPositions as any)
const ignoreAsExpected = new Set(['air', 'cave_air', 'void_air', 'barrier', 'water', 'lava', 'moving_piston', 'light'])
const ignoreAsExpected = new Set([...INVISIBLE_BLOCKS, 'water', 'lava', 'moving_piston', 'light'])

let time = 0
let times = 0
Expand Down
1 change: 1 addition & 0 deletions prismarine-viewer/viewer/lib/mesher/worldConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const INVISIBLE_BLOCKS = new Set(['air', 'void_air', 'cave_air', 'barrier'])
16 changes: 9 additions & 7 deletions prismarine-viewer/viewer/lib/worldrendererCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import TypedEmitter from 'typed-emitter'
import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs'
import { toMajorVersion } from '../../../src/utils'
import { buildCleanupDecorator } from './cleanupDecorator'
import { MesherGeometryOutput, defaultMesherConfig } from './mesher/shared'
import { defaultMesherConfig, HighestBlockInfo, MesherGeometryOutput } from './mesher/shared'
import { chunkPos } from './simpleUtils'
import { HandItemBlock } from './holdingBlock'
import { updateStatText } from './ui/newStats'
Expand Down Expand Up @@ -62,6 +62,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
dirty (pos: Vec3, value: boolean): void
update (/* pos: Vec3, value: boolean */): void
textureDownloaded (): void
chunkFinished (key: string): void
}>
customTexturesDataUrl = undefined as string | undefined
@worldCleanup()
Expand All @@ -81,7 +82,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
handleResize = () => { }
mesherConfig = defaultMesherConfig
camera: THREE.PerspectiveCamera
highestBlocks: Record<string, { y: number, name: string }> = {}
highestBlocks = new Map<string, HighestBlockInfo>()
blockstatesModels: any
customBlockStates: Record<string, any> | undefined
customModels: Record<string, any> | undefined
Expand Down Expand Up @@ -134,10 +135,10 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
this.handleWorkerMessage(data)
if (data.type === 'geometry') {
const geometry = data.geometry as MesherGeometryOutput
for (const key in geometry.highestBlocks) {
const highest = geometry.highestBlocks[key]
if (!this.highestBlocks[key] || this.highestBlocks[key].y < highest.y) {
this.highestBlocks[key] = highest
for (const [key, highest] of geometry.highestBlocks.entries()) {
const currHighest = this.highestBlocks.get(key)
if (!currHighest || currHighest.y < highest.y) {
this.highestBlocks.set(key, highest)
}
}
const chunkCoords = data.key.split(',').map(Number)
Expand All @@ -156,6 +157,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
return x === chunkCoords[0] && z === chunkCoords[2]
})) {
this.finishedChunks[`${chunkCoords[0]},${chunkCoords[2]}`] = true
this.renderUpdateEmitter.emit(`chunkFinished`, `${chunkCoords[0] / 16},${chunkCoords[2] / 16}`)
}
}
if (this.sectionsOutstanding.size === 0) {
Expand Down Expand Up @@ -363,7 +365,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
const endZ = Math.ceil((z + 1) / 16) * 16
for (let x = startX; x < endX; x += 16) {
for (let z = startZ; z < endZ; z += 16) {
delete this.highestBlocks[`${x},${z}`]
this.highestBlocks.delete(`${x},${z}`)
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 } from './globalState'
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState, hideModal } from './globalState'
import { goFullscreen, pointerLock, reloadChunks } from './utils'
import { options } from './optionsStorage'
import { openPlayerInventory } from './inventoryWindows'
Expand Down Expand Up @@ -54,6 +54,7 @@ export const contro = new ControMax({
ui: {
toggleFullscreen: ['F11'],
back: [null/* 'Escape' */, 'B'],
toggleMap: ['KeyM'],
leftClick: [null, 'A'],
rightClick: [null, 'Y'],
speedupCursor: [null, 'Left Stick'],
Expand Down Expand Up @@ -424,6 +425,14 @@ contro.on('trigger', ({ command }) => {
if (command === 'ui.toggleFullscreen') {
void goFullscreen(true)
}

if (command === 'ui.toggleMap') {
if (activeModalStack.at(-1)?.reactType === 'full-map') {
hideModal({ reactType: 'full-map' })
} else {
showModal({ reactType: 'full-map' })
}
}
})

contro.on('release', ({ command }) => {
Expand Down
2 changes: 2 additions & 0 deletions src/globalState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ts-check

import { proxy, ref, subscribe } from 'valtio'
import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
import { pointerLock } from './utils'
import type { OptionsGroupType } from './optionsGuiScheme'

Expand Down Expand Up @@ -153,6 +154,7 @@ export const gameAdditionalState = proxy({
isFlying: false,
isSprinting: false,
isSneaking: false,
warps: [] as WorldWarp[]
})

window.gameAdditionalState = gameAdditionalState
Expand Down
13 changes: 13 additions & 0 deletions src/optionsGuiScheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,19 @@ export const guiOptionsScheme: {
],
},
},
{
custom () {
return <Category>Map</Category>
},
showMinimap: {
text: 'Enable Minimap',
values: [
'always',
'singleplayer',
'never'
],
},
},
{
custom () {
return <Category>Experimental</Category>
Expand Down
2 changes: 2 additions & 0 deletions src/optionsStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ const defaultOptions = {
/** Wether to popup sign editor on server action */
autoSignEditor: true,
wysiwygSignEditor: 'auto' as 'auto' | 'always' | 'never',
showMinimap: 'never' as 'always' | 'singleplayer' | 'never',
minimapOptimizations: true,
displayBossBars: false, // boss bar overlay was removed for some reason, enable safely
disabledUiParts: [] as string[],
neighborChunkUpdates: true
Expand Down
13 changes: 13 additions & 0 deletions src/react/Fullmap.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

.map {
width: 70% !important;
height: 80% !important;
border: 1px solid black;
}

@media (max-width: 500px) {
.map {
width: 100% !important;
height: 100% !important;
}
}
Loading

0 comments on commit af088d9

Please sign in to comment.