minecraft-renderer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +297 -0
- package/dist/index.html +83 -0
- package/dist/static/image/arrow.6f27b59f.png +0 -0
- package/dist/static/image/blocksAtlasLatest.7850afa3.png +0 -0
- package/dist/static/image/blocksAtlasLegacy.5c76823d.png +0 -0
- package/dist/static/image/itemsAtlasLatest.36036f95.png +0 -0
- package/dist/static/image/itemsAtlasLegacy.dcb1b58d.png +0 -0
- package/dist/static/image/tipped_arrow.6f27b59f.png +0 -0
- package/dist/static/js/365.f05233ab.js +8462 -0
- package/dist/static/js/365.f05233ab.js.LICENSE.txt +52 -0
- package/dist/static/js/async/738.efa27644.js +1 -0
- package/dist/static/js/index.092ec5be.js +56 -0
- package/dist/static/js/lib-polyfill.98986ac5.js +1 -0
- package/dist/static/js/lib-react.5c9129e0.js +2 -0
- package/dist/static/js/lib-react.5c9129e0.js.LICENSE.txt +39 -0
- package/package.json +104 -0
- package/src/assets/destroy_stage_0.png +0 -0
- package/src/assets/destroy_stage_1.png +0 -0
- package/src/assets/destroy_stage_2.png +0 -0
- package/src/assets/destroy_stage_3.png +0 -0
- package/src/assets/destroy_stage_4.png +0 -0
- package/src/assets/destroy_stage_5.png +0 -0
- package/src/assets/destroy_stage_6.png +0 -0
- package/src/assets/destroy_stage_7.png +0 -0
- package/src/assets/destroy_stage_8.png +0 -0
- package/src/assets/destroy_stage_9.png +0 -0
- package/src/examples/README.md +146 -0
- package/src/examples/appViewerExample.ts +205 -0
- package/src/examples/initialMenuStart.ts +161 -0
- package/src/graphicsBackend/appViewer.ts +297 -0
- package/src/graphicsBackend/config.ts +119 -0
- package/src/graphicsBackend/index.ts +10 -0
- package/src/graphicsBackend/playerState.ts +61 -0
- package/src/graphicsBackend/types.ts +143 -0
- package/src/index.ts +97 -0
- package/src/lib/DebugGui.ts +190 -0
- package/src/lib/animationController.ts +85 -0
- package/src/lib/buildSharedConfig.mjs +1 -0
- package/src/lib/cameraBobbing.ts +94 -0
- package/src/lib/canvas2DOverlay.example.ts +361 -0
- package/src/lib/canvas2DOverlay.quickstart.ts +242 -0
- package/src/lib/canvas2DOverlay.ts +381 -0
- package/src/lib/cleanupDecorator.ts +29 -0
- package/src/lib/createPlayerObject.ts +55 -0
- package/src/lib/frameTimingCollector.ts +164 -0
- package/src/lib/guiRenderer.ts +283 -0
- package/src/lib/items.ts +140 -0
- package/src/lib/mesherlogReader.ts +131 -0
- package/src/lib/moreBlockDataGenerated.json +714 -0
- package/src/lib/preflatMap.json +1741 -0
- package/src/lib/simpleUtils.ts +40 -0
- package/src/lib/smoothSwitcher.ts +168 -0
- package/src/lib/spiral.ts +29 -0
- package/src/lib/ui/newStats.ts +120 -0
- package/src/lib/utils/proxy.ts +23 -0
- package/src/lib/utils/skins.ts +63 -0
- package/src/lib/utils.ts +76 -0
- package/src/lib/workerProxy.ts +342 -0
- package/src/lib/worldrendererCommon.ts +1088 -0
- package/src/mesher/mesher.ts +253 -0
- package/src/mesher/models.ts +769 -0
- package/src/mesher/modelsGeometryCommon.ts +142 -0
- package/src/mesher/shared.ts +80 -0
- package/src/mesher/standaloneRenderer.ts +270 -0
- package/src/mesher/test/a.ts +3 -0
- package/src/mesher/test/mesherTester.ts +76 -0
- package/src/mesher/test/playground.ts +19 -0
- package/src/mesher/test/test-perf.ts +74 -0
- package/src/mesher/test/tests.test.ts +56 -0
- package/src/mesher/world.ts +294 -0
- package/src/mesher/worldConstants.ts +1 -0
- package/src/modules/index.ts +11 -0
- package/src/modules/starfield.ts +313 -0
- package/src/modules/types.ts +110 -0
- package/src/playerState/playerState.ts +78 -0
- package/src/playerState/types.ts +36 -0
- package/src/playground/allEntitiesDebug.ts +170 -0
- package/src/playground/baseScene.ts +587 -0
- package/src/playground/mobileControls.tsx +268 -0
- package/src/playground/playground.html +83 -0
- package/src/playground/playground.ts +11 -0
- package/src/playground/playgroundUi.tsx +140 -0
- package/src/playground/reactUtils.ts +71 -0
- package/src/playground/scenes/allEntities.ts +13 -0
- package/src/playground/scenes/entities.ts +37 -0
- package/src/playground/scenes/floorRandom.ts +33 -0
- package/src/playground/scenes/frequentUpdates.ts +148 -0
- package/src/playground/scenes/geometryExport.ts +142 -0
- package/src/playground/scenes/index.ts +12 -0
- package/src/playground/scenes/lightingStarfield.ts +40 -0
- package/src/playground/scenes/main.ts +313 -0
- package/src/playground/scenes/railsCobweb.ts +14 -0
- package/src/playground/scenes/rotationIssue.ts +7 -0
- package/src/playground/scenes/slabsOptimization.ts +16 -0
- package/src/playground/scenes/transparencyIssue.ts +11 -0
- package/src/playground/shared.ts +79 -0
- package/src/resourcesManager/index.ts +5 -0
- package/src/resourcesManager/resourcesManager.ts +314 -0
- package/src/shims/minecraftData.ts +41 -0
- package/src/sign-renderer/index.html +21 -0
- package/src/sign-renderer/index.ts +216 -0
- package/src/sign-renderer/noop.js +1 -0
- package/src/sign-renderer/playground.ts +38 -0
- package/src/sign-renderer/tests.test.ts +69 -0
- package/src/sign-renderer/vite.config.ts +10 -0
- package/src/three/appShared.ts +75 -0
- package/src/three/bannerRenderer.ts +275 -0
- package/src/three/cameraShake.ts +120 -0
- package/src/three/cinimaticScript.ts +350 -0
- package/src/three/documentRenderer.ts +491 -0
- package/src/three/entities.ts +1580 -0
- package/src/three/entity/EntityMesh.ts +707 -0
- package/src/three/entity/animations.js +171 -0
- package/src/three/entity/armorModels.json +204 -0
- package/src/three/entity/armorModels.ts +36 -0
- package/src/three/entity/entities.json +6230 -0
- package/src/three/entity/exportedModels.js +38 -0
- package/src/three/entity/externalTextures.json +1 -0
- package/src/three/entity/models/allay.obj +325 -0
- package/src/three/entity/models/arrow.obj +60 -0
- package/src/three/entity/models/axolotl.obj +509 -0
- package/src/three/entity/models/blaze.obj +601 -0
- package/src/three/entity/models/boat.obj +417 -0
- package/src/three/entity/models/camel.obj +1061 -0
- package/src/three/entity/models/cat.obj +509 -0
- package/src/three/entity/models/chicken.obj +371 -0
- package/src/three/entity/models/cod.obj +371 -0
- package/src/three/entity/models/creeper.obj +279 -0
- package/src/three/entity/models/dolphin.obj +371 -0
- package/src/three/entity/models/ender_dragon.obj +2993 -0
- package/src/three/entity/models/enderman.obj +325 -0
- package/src/three/entity/models/endermite.obj +187 -0
- package/src/three/entity/models/fox.obj +463 -0
- package/src/three/entity/models/frog.obj +739 -0
- package/src/three/entity/models/ghast.obj +463 -0
- package/src/three/entity/models/goat.obj +601 -0
- package/src/three/entity/models/guardian.obj +1015 -0
- package/src/three/entity/models/horse.obj +1061 -0
- package/src/three/entity/models/llama.obj +509 -0
- package/src/three/entity/models/minecart.obj +233 -0
- package/src/three/entity/models/parrot.obj +509 -0
- package/src/three/entity/models/piglin.obj +739 -0
- package/src/three/entity/models/pillager.obj +371 -0
- package/src/three/entity/models/rabbit.obj +555 -0
- package/src/three/entity/models/sheep.obj +555 -0
- package/src/three/entity/models/shulker.obj +141 -0
- package/src/three/entity/models/sniffer.obj +693 -0
- package/src/three/entity/models/spider.obj +509 -0
- package/src/three/entity/models/tadpole.obj +95 -0
- package/src/three/entity/models/turtle.obj +371 -0
- package/src/three/entity/models/vex.obj +325 -0
- package/src/three/entity/models/villager.obj +509 -0
- package/src/three/entity/models/warden.obj +463 -0
- package/src/three/entity/models/witch.obj +647 -0
- package/src/three/entity/models/wolf.obj +509 -0
- package/src/three/entity/models/zombie_villager.obj +463 -0
- package/src/three/entity/objModels.js +1 -0
- package/src/three/fireworks.ts +661 -0
- package/src/three/fireworksRenderer.ts +434 -0
- package/src/three/globals.d.ts +7 -0
- package/src/three/graphicsBackend.ts +274 -0
- package/src/three/graphicsBackendOffThread.ts +107 -0
- package/src/three/hand.ts +89 -0
- package/src/three/holdingBlock.ts +926 -0
- package/src/three/index.ts +20 -0
- package/src/three/itemMesh.ts +427 -0
- package/src/three/modules.d.ts +14 -0
- package/src/three/panorama.ts +308 -0
- package/src/three/panoramaShared.ts +1 -0
- package/src/three/renderSlot.ts +82 -0
- package/src/three/skyboxRenderer.ts +406 -0
- package/src/three/starField.ts +13 -0
- package/src/three/threeJsMedia.ts +731 -0
- package/src/three/threeJsMethods.ts +15 -0
- package/src/three/threeJsParticles.ts +160 -0
- package/src/three/threeJsSound.ts +95 -0
- package/src/three/threeJsUtils.ts +90 -0
- package/src/three/waypointSprite.ts +435 -0
- package/src/three/waypoints.ts +163 -0
- package/src/three/world/cursorBlock.ts +172 -0
- package/src/three/world/vr.ts +257 -0
- package/src/three/worldGeometryExport.ts +259 -0
- package/src/three/worldGeometryHandler.ts +279 -0
- package/src/three/worldRendererThree.ts +1381 -0
- package/src/worldView/index.ts +6 -0
- package/src/worldView/types.ts +66 -0
- package/src/worldView/worldView.ts +424 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { Vec3 } from 'vec3'
|
|
3
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
4
|
+
|
|
5
|
+
export default class extends BasePlaygroundScene {
|
|
6
|
+
viewDistance = 5
|
|
7
|
+
continuousRender = true
|
|
8
|
+
|
|
9
|
+
override initGui (): void {
|
|
10
|
+
this.params = {
|
|
11
|
+
testActive: false,
|
|
12
|
+
testUpdatesPerSecond: 10,
|
|
13
|
+
testInitialUpdate: false,
|
|
14
|
+
stopGeometryUpdate: false,
|
|
15
|
+
manualTest: () => {
|
|
16
|
+
this.updateBlock()
|
|
17
|
+
},
|
|
18
|
+
testNeighborUpdates: () => {
|
|
19
|
+
this.testNeighborUpdates()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
super.initGui()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
lastUpdatedOffset = 0
|
|
27
|
+
lastUpdatedId = 2
|
|
28
|
+
updateBlock () {
|
|
29
|
+
const x = this.lastUpdatedOffset % 16
|
|
30
|
+
const z = Math.floor(this.lastUpdatedOffset / 16)
|
|
31
|
+
const y = 90
|
|
32
|
+
worldView!.setBlockStateId(new Vec3(x, y, z), this.lastUpdatedId++)
|
|
33
|
+
this.lastUpdatedOffset++
|
|
34
|
+
if (this.lastUpdatedOffset > 16 * 16) this.lastUpdatedOffset = 0
|
|
35
|
+
if (this.lastUpdatedId > 500) this.lastUpdatedId = 1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
testNeighborUpdates () {
|
|
39
|
+
viewer.world.setBlockStateId(new Vec3(15, 95, 15), 1)
|
|
40
|
+
viewer.world.setBlockStateId(new Vec3(0, 95, 15), 1)
|
|
41
|
+
viewer.world.setBlockStateId(new Vec3(15, 95, 0), 1)
|
|
42
|
+
viewer.world.setBlockStateId(new Vec3(0, 95, 0), 1)
|
|
43
|
+
|
|
44
|
+
viewer.world.setBlockStateId(new Vec3(16, 95, 15), 1)
|
|
45
|
+
viewer.world.setBlockStateId(new Vec3(-1, 95, 15), 1)
|
|
46
|
+
viewer.world.setBlockStateId(new Vec3(15, 95, -1), 1)
|
|
47
|
+
viewer.world.setBlockStateId(new Vec3(-1, 95, 0), 1)
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
viewer.world.setBlockStateId(new Vec3(16, 96, 16), 1)
|
|
50
|
+
viewer.world.setBlockStateId(new Vec3(-1, 96, 16), 1)
|
|
51
|
+
viewer.world.setBlockStateId(new Vec3(16, 96, -1), 1)
|
|
52
|
+
viewer.world.setBlockStateId(new Vec3(-1, 96, -1), 1)
|
|
53
|
+
}, 3000)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setupTimer () {
|
|
57
|
+
// this.stopRender = true
|
|
58
|
+
|
|
59
|
+
let lastTime = 0
|
|
60
|
+
const tick = () => {
|
|
61
|
+
viewer.world.debugStopGeometryUpdate = this.params.stopGeometryUpdate
|
|
62
|
+
const updateEach = 1000 / this.params.testUpdatesPerSecond
|
|
63
|
+
requestAnimationFrame(tick)
|
|
64
|
+
if (!this.params.testActive) return
|
|
65
|
+
const updateCount = Math.floor(performance.now() - lastTime) / updateEach
|
|
66
|
+
for (let i = 0; i < updateCount; i++) {
|
|
67
|
+
this.updateBlock()
|
|
68
|
+
}
|
|
69
|
+
lastTime = performance.now()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
requestAnimationFrame(tick)
|
|
73
|
+
|
|
74
|
+
// const limit = 1000
|
|
75
|
+
// const limit = 100
|
|
76
|
+
// const limit = 1
|
|
77
|
+
// const updatedChunks = new Set<string>()
|
|
78
|
+
// const updatedBlocks = new Set<string>()
|
|
79
|
+
// let lastSecond = 0
|
|
80
|
+
// setInterval(() => {
|
|
81
|
+
// const second = Math.floor(performance.now() / 1000)
|
|
82
|
+
// if (lastSecond !== second) {
|
|
83
|
+
// lastSecond = second
|
|
84
|
+
// updatedChunks.clear()
|
|
85
|
+
// updatedBlocks.clear()
|
|
86
|
+
// }
|
|
87
|
+
// const isEven = second % 2 === 0
|
|
88
|
+
// if (updatedBlocks.size > limit) {
|
|
89
|
+
// return
|
|
90
|
+
// }
|
|
91
|
+
// const changeBlock = (x, z) => {
|
|
92
|
+
// const chunkKey = `${Math.floor(x / 16)},${Math.floor(z / 16)}`
|
|
93
|
+
// const key = `${x},${z}`
|
|
94
|
+
// if (updatedBlocks.has(chunkKey)) return
|
|
95
|
+
|
|
96
|
+
// updatedChunks.add(chunkKey)
|
|
97
|
+
// worldView!.world.setBlock(this.targetPos.offset(x, 0, z), this.Block.fromStateId(isEven ? 2 : 3, 0))
|
|
98
|
+
// updatedBlocks.add(key)
|
|
99
|
+
// }
|
|
100
|
+
// const { squareSize } = this.params
|
|
101
|
+
// const xStart = -squareSize
|
|
102
|
+
// const zStart = -squareSize
|
|
103
|
+
// const xEnd = squareSize
|
|
104
|
+
// const zEnd = squareSize
|
|
105
|
+
// for (let x = xStart; x <= xEnd; x += 16) {
|
|
106
|
+
// for (let z = zStart; z <= zEnd; z += 16) {
|
|
107
|
+
// const key = `${x},${z}`
|
|
108
|
+
// if (updatedChunks.has(key)) continue
|
|
109
|
+
// changeBlock(x, z)
|
|
110
|
+
// return
|
|
111
|
+
// }
|
|
112
|
+
// }
|
|
113
|
+
// for (let x = xStart; x <= xEnd; x += 16) {
|
|
114
|
+
// for (let z = zStart; z <= zEnd; z += 16) {
|
|
115
|
+
// const key = `${x},${z}`
|
|
116
|
+
// if (updatedChunks.has(key)) continue
|
|
117
|
+
// changeBlock(x, z)
|
|
118
|
+
// return
|
|
119
|
+
// }
|
|
120
|
+
// }
|
|
121
|
+
// }, 1)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
setupWorld () {
|
|
125
|
+
this.worldConfig.showChunkBorders = true
|
|
126
|
+
|
|
127
|
+
const maxSquareRadius = this.viewDistance * 16
|
|
128
|
+
// const fullBlocks = loadedData.blocksArray.map(x => x.name)
|
|
129
|
+
const squareSize = maxSquareRadius
|
|
130
|
+
for (let x = -squareSize; x <= squareSize; x++) {
|
|
131
|
+
for (let z = -squareSize; z <= squareSize; z++) {
|
|
132
|
+
const i = Math.abs(x + z) * squareSize
|
|
133
|
+
worldView!.world.setBlock(this.targetPos.offset(x, 0, z), this.Block.fromStateId(1, 0))
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
let done = false
|
|
137
|
+
viewer.world.renderUpdateEmitter.on('update', () => {
|
|
138
|
+
if (!viewer.world.allChunksFinished || done) return
|
|
139
|
+
done = true
|
|
140
|
+
this.setupTimer()
|
|
141
|
+
})
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
if (this.params.testInitialUpdate) {
|
|
144
|
+
this.updateBlock()
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import * as THREE from 'three'
|
|
2
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
3
|
+
import {
|
|
4
|
+
downloadWorldGeometry,
|
|
5
|
+
loadWorldGeometryFromUrl,
|
|
6
|
+
type ExportedWorldGeometry
|
|
7
|
+
} from '../../three/worldGeometryExport'
|
|
8
|
+
|
|
9
|
+
type GeometryExportBackendMethods = {
|
|
10
|
+
loadGeometryExport?: (exportData: ExportedWorldGeometry) => Promise<number>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Scene for exporting/importing world geometry
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* - Load normally: builds world from blocks, can export geometry
|
|
18
|
+
* - Load with ?geometryUrl=URL: loads pre-exported geometry from file (or default world-geometry.json)
|
|
19
|
+
*/
|
|
20
|
+
export default class extends BasePlaygroundScene {
|
|
21
|
+
params = {
|
|
22
|
+
exportGeometry: () => this.exportGeometry(),
|
|
23
|
+
exportWithTexture: () => this.exportGeometry(true),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Loaded geometry data (when loading from URL)
|
|
27
|
+
private loadedGeometry: ExportedWorldGeometry | null = null
|
|
28
|
+
private readonly geometryUrl: string | null
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
const qs = new URLSearchParams(window.location.search)
|
|
32
|
+
const geometryUrl = qs.get('geometryUrl') ?? 'world-geometry.json'
|
|
33
|
+
|
|
34
|
+
// If loading from URL, skip normal world setup (viewDistance 0 means no chunks loaded)
|
|
35
|
+
super({
|
|
36
|
+
viewDistance: geometryUrl ? 0 : 1,
|
|
37
|
+
continuousRender: false,
|
|
38
|
+
enableCameraOrbitControl: false,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
this.geometryUrl = geometryUrl
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Override initData to load geometry after base initialization completes
|
|
45
|
+
override async initData() {
|
|
46
|
+
await super.initData()
|
|
47
|
+
|
|
48
|
+
// Now camera and worldRenderer are ready - load geometry if URL provided
|
|
49
|
+
if (this.geometryUrl) {
|
|
50
|
+
await this.loadFromUrl(this.geometryUrl)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setupWorld() {
|
|
55
|
+
if (this.geometryUrl) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
// Default world setup - add some blocks for testing
|
|
59
|
+
this.addWorldBlock(0, 0, 0, 'stone')
|
|
60
|
+
this.addWorldBlock(1, 0, 0, 'grass_block')
|
|
61
|
+
this.addWorldBlock(0, 0, 1, 'dirt')
|
|
62
|
+
this.addWorldBlock(1, 0, 1, 'cobblestone')
|
|
63
|
+
this.addWorldBlock(0, 1, 0, 'oak_log')
|
|
64
|
+
this.addWorldBlock(1, 1, 0, 'oak_planks')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async loadFromUrl(url: string) {
|
|
68
|
+
try {
|
|
69
|
+
console.log('Loading geometry from:', url)
|
|
70
|
+
this.loadedGeometry = await loadWorldGeometryFromUrl(url)
|
|
71
|
+
|
|
72
|
+
// Restore camera position and rotation
|
|
73
|
+
const { camera: camData } = this.loadedGeometry
|
|
74
|
+
this.camera.position.set(camData.position.x, camData.position.y, camData.position.z)
|
|
75
|
+
|
|
76
|
+
// Apply rotation using lookAt direction
|
|
77
|
+
const { pitch, yaw } = camData.rotation
|
|
78
|
+
const forward = new THREE.Vector3(
|
|
79
|
+
-Math.sin(yaw) * Math.cos(pitch),
|
|
80
|
+
Math.sin(pitch),
|
|
81
|
+
-Math.cos(yaw) * Math.cos(pitch)
|
|
82
|
+
)
|
|
83
|
+
this.camera.lookAt(
|
|
84
|
+
camData.position.x + forward.x,
|
|
85
|
+
camData.position.y + forward.y,
|
|
86
|
+
camData.position.z + forward.z
|
|
87
|
+
)
|
|
88
|
+
this.controls?.update()
|
|
89
|
+
this.syncCameraToBackend()
|
|
90
|
+
|
|
91
|
+
const backendMethods = this.appViewer.backend?.backendMethods as GeometryExportBackendMethods | undefined
|
|
92
|
+
if (!backendMethods?.loadGeometryExport) {
|
|
93
|
+
console.warn('Three.js backend does not expose loadGeometryExport')
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const geometryData = this.loadedGeometry
|
|
98
|
+
if (!geometryData) {
|
|
99
|
+
console.warn('No geometry data available after load')
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const importedCount = await backendMethods.loadGeometryExport(geometryData)
|
|
104
|
+
console.log(`Loaded ${importedCount} sections from geometry file`)
|
|
105
|
+
this.requestRender()
|
|
106
|
+
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error('Failed to load geometry:', err)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private exportGeometry(includeTexture = false) {
|
|
113
|
+
const { worldRenderer } = this
|
|
114
|
+
if (!worldRenderer) {
|
|
115
|
+
console.error('WorldRenderer not available')
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Get camera position and rotation
|
|
120
|
+
const cameraPosition = {
|
|
121
|
+
x: this.camera.position.x,
|
|
122
|
+
y: this.camera.position.y,
|
|
123
|
+
z: this.camera.position.z
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Extract yaw/pitch from camera quaternion
|
|
127
|
+
const forward = new THREE.Vector3(0, 0, -1)
|
|
128
|
+
forward.applyQuaternion(this.camera.quaternion)
|
|
129
|
+
const cameraRotation = {
|
|
130
|
+
yaw: Math.atan2(-forward.x, -forward.z),
|
|
131
|
+
pitch: Math.asin(forward.y)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Generate filename with timestamp
|
|
135
|
+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-')
|
|
136
|
+
const filename = `world-geometry-${timestamp}.json`
|
|
137
|
+
|
|
138
|
+
downloadWorldGeometry(worldRenderer, cameraPosition, cameraRotation, filename, includeTexture)
|
|
139
|
+
console.log('Geometry exported to:', filename)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// export { default as rotation } from './rotation'
|
|
2
|
+
export { default as main } from './main'
|
|
3
|
+
export { default as railsCobweb } from './railsCobweb'
|
|
4
|
+
// export { default as floorRandom } from './floorRandom'
|
|
5
|
+
// export { default as lightingStarfield } from './lightingStarfield'
|
|
6
|
+
// export { default as transparencyIssue } from './transparencyIssue'
|
|
7
|
+
// export { default as rotationIssue } from './rotationIssue'
|
|
8
|
+
// export { default as entities } from './entities'
|
|
9
|
+
// export { default as frequentUpdates } from './frequentUpdates'
|
|
10
|
+
// export { default as slabsOptimization } from './slabsOptimization'
|
|
11
|
+
// export { default as allEntities } from './allEntities'
|
|
12
|
+
// export { default as geometryExport } from './geometryExport'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import * as THREE from 'three'
|
|
3
|
+
import { Vec3 } from 'vec3'
|
|
4
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
5
|
+
import { WorldRendererThree } from '../../viewer/three/worldrendererThree'
|
|
6
|
+
|
|
7
|
+
export default class extends BasePlaygroundScene {
|
|
8
|
+
continuousRender = true
|
|
9
|
+
|
|
10
|
+
override setupWorld (): void {
|
|
11
|
+
viewer.world.mesherConfig.enableLighting = true
|
|
12
|
+
viewer.world.mesherConfig.skyLight = 0
|
|
13
|
+
this.addWorldBlock(0, 0, 0, 'stone')
|
|
14
|
+
this.addWorldBlock(0, 0, 1, 'stone')
|
|
15
|
+
this.addWorldBlock(1, 0, 0, 'stone')
|
|
16
|
+
this.addWorldBlock(1, 0, 1, 'stone')
|
|
17
|
+
// chess like
|
|
18
|
+
worldView?.world.setBlockLight(this.targetPos.offset(0, 1, 0), 15)
|
|
19
|
+
worldView?.world.setBlockLight(this.targetPos.offset(0, 1, 1), 0)
|
|
20
|
+
worldView?.world.setBlockLight(this.targetPos.offset(1, 1, 0), 0)
|
|
21
|
+
worldView?.world.setBlockLight(this.targetPos.offset(1, 1, 1), 15)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
override renderFinish (): void {
|
|
25
|
+
viewer.scene.background = new THREE.Color(0x00_00_00)
|
|
26
|
+
// starfield and test entities
|
|
27
|
+
;(viewer.world as WorldRendererThree).starField.enabled = true
|
|
28
|
+
;(viewer.world as WorldRendererThree).starField.addToScene()
|
|
29
|
+
viewer.entities.update({
|
|
30
|
+
id: 0,
|
|
31
|
+
name: 'player',
|
|
32
|
+
pos: this.targetPos.clone()
|
|
33
|
+
} as any, {})
|
|
34
|
+
viewer.entities.update({
|
|
35
|
+
id: 1,
|
|
36
|
+
name: 'creeper',
|
|
37
|
+
pos: this.targetPos.offset(1, 0, 0)
|
|
38
|
+
} as any, {})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-named-as-default
|
|
2
|
+
import GUI, { Controller } from 'lil-gui'
|
|
3
|
+
import * as THREE from 'three'
|
|
4
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
5
|
+
import { TWEEN_DURATION } from '@/three/entities'
|
|
6
|
+
import { EntityMesh } from '@/three/entity/EntityMesh'
|
|
7
|
+
|
|
8
|
+
const includedVersions = globalThis.includedVersions
|
|
9
|
+
|
|
10
|
+
class MainScene extends BasePlaygroundScene {
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
12
|
+
constructor(...args) {
|
|
13
|
+
super(...args)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override initGui(): void {
|
|
17
|
+
// initial values
|
|
18
|
+
this.params = {
|
|
19
|
+
skipQs: '',
|
|
20
|
+
block: '',
|
|
21
|
+
metadata: 0,
|
|
22
|
+
supportBlock: false,
|
|
23
|
+
entity: '',
|
|
24
|
+
removeEntity() {
|
|
25
|
+
this.entity = ''
|
|
26
|
+
},
|
|
27
|
+
entityRotate: false,
|
|
28
|
+
camera: '',
|
|
29
|
+
playSound() { },
|
|
30
|
+
blockIsomorphicRenderBundle() { },
|
|
31
|
+
modelVariant: 0
|
|
32
|
+
}
|
|
33
|
+
this.metadataGui = this.gui.add(this.params, 'metadata')
|
|
34
|
+
this.paramOptions = {
|
|
35
|
+
version: {
|
|
36
|
+
options: includedVersions,
|
|
37
|
+
hide: false
|
|
38
|
+
},
|
|
39
|
+
block: {
|
|
40
|
+
options: this.mcData.blocksArray.map(b => b.name).sort((a, b) => a.localeCompare(b))
|
|
41
|
+
},
|
|
42
|
+
entity: {
|
|
43
|
+
options: this.mcData.entitiesArray.map(b => b.name).sort((a, b) => a.localeCompare(b))
|
|
44
|
+
},
|
|
45
|
+
camera: {
|
|
46
|
+
hide: true,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
super.initGui()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
blockProps = {}
|
|
53
|
+
metadataFolder: GUI | undefined
|
|
54
|
+
metadataGui: Controller | undefined
|
|
55
|
+
|
|
56
|
+
override onParamUpdate = {
|
|
57
|
+
version() {
|
|
58
|
+
// if (initialUpdate) return
|
|
59
|
+
// viewer.world.texturesVersion = params.version
|
|
60
|
+
// viewer.world.updateTexturesData()
|
|
61
|
+
// todo warning
|
|
62
|
+
},
|
|
63
|
+
block: () => {
|
|
64
|
+
this.blockProps = {}
|
|
65
|
+
this.metadataFolder?.destroy()
|
|
66
|
+
const block = this.mcData.blocksByName[this.params.block]
|
|
67
|
+
if (!block) return
|
|
68
|
+
console.log('block', block.name)
|
|
69
|
+
const props = new this.Block(block.id, 0, 0).getProperties()
|
|
70
|
+
const { states } = this.mcData.blocksByStateId[this.getBlock()?.minStateId] ?? {}
|
|
71
|
+
this.metadataFolder = this.gui.addFolder('metadata')
|
|
72
|
+
if (states) {
|
|
73
|
+
for (const state of states) {
|
|
74
|
+
let defaultValue: string | number | boolean
|
|
75
|
+
if (state.values) { // int, enum
|
|
76
|
+
defaultValue = state.values[0] as string | number | boolean
|
|
77
|
+
} else {
|
|
78
|
+
switch (state.type) {
|
|
79
|
+
case 'bool':
|
|
80
|
+
defaultValue = false
|
|
81
|
+
break
|
|
82
|
+
case 'int':
|
|
83
|
+
defaultValue = 0
|
|
84
|
+
break
|
|
85
|
+
case 'direction':
|
|
86
|
+
defaultValue = 'north'
|
|
87
|
+
break
|
|
88
|
+
|
|
89
|
+
default:
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
this.blockProps[state.name] = defaultValue
|
|
94
|
+
if (state.values) {
|
|
95
|
+
this.metadataFolder.add(this.blockProps, state.name, state.values)
|
|
96
|
+
} else {
|
|
97
|
+
this.metadataFolder.add(this.blockProps, state.name)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
for (const [name, value] of Object.entries(props)) {
|
|
102
|
+
this.blockProps[name] = value
|
|
103
|
+
this.metadataFolder.add(this.blockProps, name)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
console.log('props', this.blockProps)
|
|
107
|
+
this.metadataFolder.open()
|
|
108
|
+
},
|
|
109
|
+
entity: () => {
|
|
110
|
+
this.continuousRender = this.params.entity === 'player'
|
|
111
|
+
this.entityUpdateShared()
|
|
112
|
+
if (!this.params.entity) return
|
|
113
|
+
if (this.params.entity === 'player') {
|
|
114
|
+
this.worldRenderer.entities.updatePlayerSkin('id', this.worldRenderer.entities.entities.id.username, undefined, true, true)
|
|
115
|
+
this.worldRenderer.entities.playAnimation('id', 'running')
|
|
116
|
+
}
|
|
117
|
+
// let prev = false
|
|
118
|
+
// setInterval(() => {
|
|
119
|
+
// viewer.entities.playAnimation('id', prev ? 'running' : 'idle')
|
|
120
|
+
// prev = !prev
|
|
121
|
+
// }, 1000)
|
|
122
|
+
|
|
123
|
+
EntityMesh.getStaticData(this.params.entity)
|
|
124
|
+
// entityRotationFolder.destroy()
|
|
125
|
+
// entityRotationFolder = gui.addFolder('entity metadata')
|
|
126
|
+
// entityRotationFolder.add(params, 'entityRotate')
|
|
127
|
+
// entityRotationFolder.open()
|
|
128
|
+
},
|
|
129
|
+
supportBlock: () => {
|
|
130
|
+
this.worldView!.setBlockStateId(this.targetPos.offset(0, -1, 0), this.params.supportBlock ? 1 : 0)
|
|
131
|
+
},
|
|
132
|
+
modelVariant: () => {
|
|
133
|
+
this.worldRenderer.worldRendererConfig.debugModelVariant = this.params.modelVariant === 0 ? undefined : [this.params.modelVariant]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
entityUpdateShared() {
|
|
138
|
+
this.worldRenderer.entities.clear()
|
|
139
|
+
if (!this.params.entity) return
|
|
140
|
+
this.worldView!.emit('entity', {
|
|
141
|
+
id: 'id', name: this.params.entity, pos: this.targetPos.offset(0.5, 1, 0.5), width: 1, height: 1, username: localStorage.testUsername, yaw: Math.PI, pitch: 0
|
|
142
|
+
})
|
|
143
|
+
const enableSkeletonDebug = (obj) => {
|
|
144
|
+
const { children, isSkeletonHelper } = obj
|
|
145
|
+
if (!Array.isArray(children)) return
|
|
146
|
+
if (isSkeletonHelper) {
|
|
147
|
+
obj.visible = true
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
for (const child of children) {
|
|
151
|
+
if (typeof child === 'object') enableSkeletonDebug(child)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
enableSkeletonDebug(this.worldRenderer.entities.entities['id'])
|
|
155
|
+
setTimeout(() => {
|
|
156
|
+
this.render()
|
|
157
|
+
}, TWEEN_DURATION)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
getBlock() {
|
|
161
|
+
return this.mcData.blocksByName[this.params.block || 'air']
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// applyChanges (metadataUpdate = false, skipQs = false) {
|
|
165
|
+
override onParamsUpdate(paramName: string, object: any) {
|
|
166
|
+
const metadataUpdate = paramName === 'metadata'
|
|
167
|
+
|
|
168
|
+
const blockId = this.getBlock()?.id
|
|
169
|
+
let block: import('prismarine-block').Block
|
|
170
|
+
if (metadataUpdate) {
|
|
171
|
+
block = new this.Block(blockId, 0, this.params.metadata)
|
|
172
|
+
Object.assign(this.blockProps, block.getProperties())
|
|
173
|
+
for (const _child of this.metadataFolder!.children) {
|
|
174
|
+
const child = _child as import('lil-gui').Controller
|
|
175
|
+
child.updateDisplay()
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
try {
|
|
179
|
+
block = this.Block.fromProperties(blockId ?? -1, this.blockProps, 0)
|
|
180
|
+
} catch (err) {
|
|
181
|
+
console.error(err)
|
|
182
|
+
block = this.Block.fromStateId(0, 0)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
this.worldView!.setBlockStateId(this.targetPos, block.stateId ?? 0)
|
|
187
|
+
console.log('up stateId', block.stateId)
|
|
188
|
+
this.params.metadata = block.metadata
|
|
189
|
+
this.metadataGui?.updateDisplay()
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
override renderFinish() {
|
|
193
|
+
for (const update of Object.values(this.onParamUpdate)) {
|
|
194
|
+
// update(true)
|
|
195
|
+
update()
|
|
196
|
+
}
|
|
197
|
+
this.onParamsUpdate('', {})
|
|
198
|
+
this.gui.openAnimated()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
blockIsomorphicRenderBundle() {
|
|
202
|
+
const { renderer } = this.worldRenderer
|
|
203
|
+
|
|
204
|
+
const canvas = renderer.domElement
|
|
205
|
+
const onlyCurrent = !confirm('Ok - render all blocks, Cancel - render only current one')
|
|
206
|
+
const sizeRaw = prompt('Size', '512')
|
|
207
|
+
if (!sizeRaw) return
|
|
208
|
+
const size = parseInt(sizeRaw, 10)
|
|
209
|
+
// const size = 512
|
|
210
|
+
|
|
211
|
+
canvas.width = size
|
|
212
|
+
canvas.height = size
|
|
213
|
+
renderer.setSize(size, size)
|
|
214
|
+
|
|
215
|
+
// Temporarily replace PerspectiveCamera with OrthographicCamera for block rendering
|
|
216
|
+
this.worldRenderer.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 10) as any
|
|
217
|
+
this.worldRenderer.scene.background = null
|
|
218
|
+
|
|
219
|
+
const rad = THREE.MathUtils.degToRad(-120)
|
|
220
|
+
this.worldRenderer.directionalLight.position.set(
|
|
221
|
+
Math.cos(rad),
|
|
222
|
+
Math.sin(rad),
|
|
223
|
+
0.2
|
|
224
|
+
).normalize()
|
|
225
|
+
this.worldRenderer.directionalLight.intensity = 1
|
|
226
|
+
|
|
227
|
+
const cameraPos = this.targetPos.offset(2, 2, 2)
|
|
228
|
+
const pitch = THREE.MathUtils.degToRad(-30)
|
|
229
|
+
const yaw = THREE.MathUtils.degToRad(45)
|
|
230
|
+
this.worldRenderer.camera.rotation.set(pitch, yaw, 0, 'ZYX')
|
|
231
|
+
// this.worldRenderer!.camera.lookAt(center.x + 0.5, center.y + 0.5, center.z + 0.5)
|
|
232
|
+
this.worldRenderer.camera.position.set(cameraPos.x + 1, cameraPos.y + 0.5, cameraPos.z + 1)
|
|
233
|
+
|
|
234
|
+
const allBlocks = this.mcData.blocksArray.map(b => b.name)
|
|
235
|
+
// const allBlocks = ['stone', 'warped_slab']
|
|
236
|
+
|
|
237
|
+
let blockCount = 1
|
|
238
|
+
let blockName = allBlocks[0]
|
|
239
|
+
|
|
240
|
+
const updateBlock = () => {
|
|
241
|
+
// viewer.setBlockStateId(targetPos, mcData.blocksByName[blockName].minStateId)
|
|
242
|
+
this.params.block = blockName
|
|
243
|
+
// todo cleanup (introduce getDefaultState)
|
|
244
|
+
// TODO
|
|
245
|
+
// onUpdate.block()
|
|
246
|
+
// applyChanges(false, true)
|
|
247
|
+
}
|
|
248
|
+
void this.worldRenderer.waitForChunksToRender().then(async () => {
|
|
249
|
+
// wait for next macro task
|
|
250
|
+
await new Promise(resolve => {
|
|
251
|
+
setTimeout(resolve, 0)
|
|
252
|
+
})
|
|
253
|
+
if (onlyCurrent) {
|
|
254
|
+
this.render()
|
|
255
|
+
onWorldUpdate()
|
|
256
|
+
} else {
|
|
257
|
+
// will be called on every render update
|
|
258
|
+
this.worldRenderer.renderUpdateEmitter.addListener('update', onWorldUpdate)
|
|
259
|
+
updateBlock()
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
//@ts-ignore
|
|
264
|
+
const zip = new JSZip()
|
|
265
|
+
zip.file('description.txt', 'Generated with mcraft.fun/playground')
|
|
266
|
+
|
|
267
|
+
const end = async () => {
|
|
268
|
+
// download zip file
|
|
269
|
+
|
|
270
|
+
const a = document.createElement('a')
|
|
271
|
+
const blob = await zip.generateAsync({ type: 'blob' })
|
|
272
|
+
const dataUrlZip = URL.createObjectURL(blob)
|
|
273
|
+
a.href = dataUrlZip
|
|
274
|
+
a.download = 'blocks_render.zip'
|
|
275
|
+
a.click()
|
|
276
|
+
URL.revokeObjectURL(dataUrlZip)
|
|
277
|
+
console.log('end')
|
|
278
|
+
|
|
279
|
+
this.worldRenderer.renderUpdateEmitter.removeListener('update', onWorldUpdate)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function onWorldUpdate() {
|
|
283
|
+
// await new Promise(resolve => {
|
|
284
|
+
// setTimeout(resolve, 50)
|
|
285
|
+
// })
|
|
286
|
+
const dataUrl = canvas.toDataURL('image/png')
|
|
287
|
+
|
|
288
|
+
zip.file(`${blockName}.png`, dataUrl.split(',')[1], { base64: true })
|
|
289
|
+
|
|
290
|
+
if (onlyCurrent) {
|
|
291
|
+
end()
|
|
292
|
+
} else {
|
|
293
|
+
nextBlock()
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const nextBlock = async () => {
|
|
297
|
+
blockName = allBlocks[blockCount++]
|
|
298
|
+
console.log(allBlocks.length, '/', blockCount, blockName)
|
|
299
|
+
if (blockCount % 5 === 0) {
|
|
300
|
+
await new Promise(resolve => {
|
|
301
|
+
setTimeout(resolve, 100)
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
if (blockName) {
|
|
305
|
+
updateBlock()
|
|
306
|
+
} else {
|
|
307
|
+
end()
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export default MainScene
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
2
|
+
|
|
3
|
+
export default class RailsCobwebScene extends BasePlaygroundScene {
|
|
4
|
+
setupWorld () {
|
|
5
|
+
this.addWorldBlock(0, 0, 0, 'cobweb')
|
|
6
|
+
this.addWorldBlock(0, -1, 0, 'cobweb')
|
|
7
|
+
this.addWorldBlock(1, -1, 0, 'cobweb')
|
|
8
|
+
this.addWorldBlock(1, 0, 0, 'cobweb')
|
|
9
|
+
|
|
10
|
+
this.addWorldBlock(0, 0, 1, 'powered_rail', { shape: 'north_south', waterlogged: false })
|
|
11
|
+
this.addWorldBlock(0, 0, 2, 'powered_rail', { shape: 'ascending_south', waterlogged: false })
|
|
12
|
+
this.addWorldBlock(0, 1, 3, 'powered_rail', { shape: 'north_south', waterlogged: false })
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BasePlaygroundScene } from '../baseScene'
|
|
2
|
+
|
|
3
|
+
export default class extends BasePlaygroundScene {
|
|
4
|
+
expectedNumberOfFaces = 30
|
|
5
|
+
enableCameraOrbitControl = false
|
|
6
|
+
|
|
7
|
+
setupWorld () {
|
|
8
|
+
this.addWorldBlock(0, 1, 0, 'stone_slab')
|
|
9
|
+
this.addWorldBlock(0, 0, 0, 'stone')
|
|
10
|
+
this.addWorldBlock(0, -1, 0, 'stone_slab', { type: 'top', waterlogged: false })
|
|
11
|
+
this.addWorldBlock(0, -1, -1, 'stone_slab', { type: 'top', waterlogged: false })
|
|
12
|
+
this.addWorldBlock(0, -1, 1, 'stone_slab', { type: 'top', waterlogged: false })
|
|
13
|
+
this.addWorldBlock(-1, -1, 0, 'stone_slab', { type: 'top', waterlogged: false })
|
|
14
|
+
this.addWorldBlock(1, -1, 0, 'stone_slab', { type: 'top', waterlogged: false })
|
|
15
|
+
}
|
|
16
|
+
}
|