Skip to content

Commit 5f2702e

Browse files
authored
add the same block events as mineflayer (#56)
* add the same block events as mineflayer see https://github.com/PrismarineJS/mineflayer/blob/master/docs/api.md#blockupdate-oldblock-newblock working towards PrismarineJS/mineflayer#334 (comment) this will do a get at each set, making the set methods a bit slower it is needed to keep compatibility with mineflayer I think it is ok as initialize can be used to do a faster set for many blocks * fix posInChunk thing
1 parent bc94235 commit 5f2702e

File tree

4 files changed

+139
-100
lines changed

4 files changed

+139
-100
lines changed

docs/API.md

Lines changed: 21 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ Create a world instance, takes an optional `generateChunk(chunkX, chunkZ)` funct
2626
If provided, prismarine-world will first try to load the map from these regions, and then try to generate the world if
2727
the chunk isn't saved. `savingInterval` default to 50ms.
2828

29+
#### "blockUpdate" (oldBlock, newBlock)
30+
31+
Fires when a block updates. Both `oldBlock` and `newBlock` provided for
32+
comparison.
33+
34+
Note that `oldBlock` may be `null`.
35+
36+
#### "blockUpdate:(x, y, z)" (oldBlock, newBlock)
37+
38+
Fires for a specific point. Both `oldBlock` and `newBlock` provided for
39+
comparison.
40+
41+
Note that `oldBlock` may be `null`.
42+
43+
#### "chunkColumnLoad" (point)
44+
#### "chunkColumnUnload" (point)
45+
46+
Fires when a chunk has updated. `point` is the coordinates to the corner
47+
of the chunk with the smallest x, y, and z values.
48+
2949
### World.initialize(iniFunc,length,width,height=256,iniPos=new Vec3(0,0,0))
3050

3151
Initialize the world with a given blocks cube. Useful to load quickly a schematic.
@@ -127,91 +147,7 @@ Returns a promise that is resolved when all saving is done.
127147

128148
Build a sync world, will delegate all the saving work to the async one
129149

130-
### World.initialize(iniFunc,length,width,height=256,iniPos=new Vec3(0,0,0))
131-
132-
Initialize the world with a given blocks cube. Useful to load quickly a schematic.
133-
134-
* `iniFunc` is a function(x,y,z) that returns a prismarine-block
135-
* `length`, `width` and `height` are the size to iterate on
136-
* `iniPos` is the position where to start the iteration
137-
138-
Returns an array of `{chunkX,chunkZ}`
139-
140-
This works only on loaded columns.
141-
142-
### World.sync.getColumns()
143-
144-
Return all loaded columns
145-
146-
All the following methods are sync.
147-
148-
### World.sync.unloadColumn(chunkX,chunkZ)
149-
150-
Unload column from memory
151-
152-
### World.sync.setColumn(chunkX,chunkZ,chunk)
153-
154-
Set `chunk` at `chunkX` and `chunkZ`
155-
156-
### World.sync.getColumn(chunkX,chunkZ)
157-
158-
Return the column at `chunkX` and `chunkZ`
159-
160-
### World.sync.getBlock(pos)
161-
162-
Get the [Block](https://github.com/PrismarineJS/prismarine-block) at [pos](https://github.com/andrewrk/node-vec3)
163-
164-
### World.sync.setBlock(pos,block)
165-
166-
Set the [Block](https://github.com/PrismarineJS/prismarine-block) at [pos](https://github.com/andrewrk/node-vec3)
167-
168-
### World.sync.getBlockStateId(pos)
169-
170-
Get the block state at `pos`
171-
172-
### World.sync.getBlockType(pos)
173-
174-
Get the block type at `pos`
175-
176-
### World.sync.getBlockData(pos)
177-
178-
Get the block data (metadata) at `pos`
179-
180-
### World.sync.getBlockLight(pos)
181-
182-
Get the block light at `pos`
183-
184-
### World.sync.getSkyLight(pos)
185-
186-
Get the block sky light at `pos`
187-
188-
### World.sync.getBiome(pos)
189-
190-
Get the block biome id at `pos`
191-
192-
### World.sync.setBlockStateId(pos, stateId)
193-
194-
Set the block state `stateId` at `pos`
195-
196-
### World.sync.setBlockType(pos, id)
197-
198-
Set the block type `id` at `pos`
199-
200-
### World.sync.setBlockData(pos, data)
201-
202-
Set the block `data` (metadata) at `pos`
203-
204-
### World.sync.setBlockLight(pos, light)
205-
206-
Set the block `light` at `pos`
207-
208-
### World.sync.setSkyLight(pos, light)
209-
210-
Set the block sky `light` at `pos`
211-
212-
### World.sync.setBiome(pos, biome)
213-
214-
Set the block `biome` id at `pos`
150+
It exposes the same methods as World but all methods are sync.
215151

216152
## Iterators
217153

examples/simple.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const World = require('../index')('1.16')
2+
const Chunk = require('prismarine-chunk')('1.16')
3+
const Vec3 = require('vec3')
4+
5+
function generateSimpleChunk (chunkX, chunkZ) {
6+
const chunk = new Chunk()
7+
8+
for (let x = 0; x < 16; x++) {
9+
for (let z = 0; z < 16; z++) {
10+
chunk.setBlockType(new Vec3(x, 50, z), 2)
11+
for (let y = 0; y < 256; y++) {
12+
chunk.setSkyLight(new Vec3(x, y, z), 15)
13+
}
14+
}
15+
}
16+
17+
return chunk
18+
}
19+
20+
const world = new World(generateSimpleChunk)
21+
22+
async function main () {
23+
world.on('blockUpdate', (oldBlock, newBlock) => {
24+
console.log('blockUpdate', oldBlock.stateId, newBlock.stateId)
25+
})
26+
world.on('blockUpdate:(3, 50, 3)', (oldBlock, newBlock) => {
27+
console.log('blockUpdate:(3, 50, 3)', oldBlock.stateId, newBlock.stateId)
28+
})
29+
const pos = new Vec3(3, 50, 3)
30+
console.log('initial', await world.getBlockStateId(pos))
31+
await world.setBlockStateId(pos, 47)
32+
console.log('last', await world.getBlockStateId(pos))
33+
}
34+
35+
main()

src/world.js

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,18 @@ class World extends EventEmitter {
100100
return this.columns[key]
101101
}
102102

103+
_emitBlockUpdate (oldBlock, newBlock, position) {
104+
this.emit('blockUpdate', oldBlock, newBlock)
105+
this.emit(`blockUpdate:${position}`, oldBlock, newBlock)
106+
}
107+
103108
setLoadedColumn (chunkX, chunkZ, chunk, save = true) {
104109
const key = columnKeyXZ(chunkX, chunkZ)
105110
this.columns[key] = chunk
106111

112+
const columnCorner = new Vec3(chunkX * 16, 0, chunkZ * 16)
113+
this.emit('chunkColumnLoad', columnCorner)
114+
107115
if (this.storageProvider && save) { this.queueSaving(chunkX, chunkZ) }
108116
}
109117

@@ -115,6 +123,8 @@ class World extends EventEmitter {
115123
unloadColumn (chunkX, chunkZ) {
116124
const key = columnKeyXZ(chunkX, chunkZ)
117125
delete this.columns[key]
126+
const columnCorner = new Vec3(chunkX * 16, 0, chunkZ * 16)
127+
this.emit('chunkColumnUnload', columnCorner)
118128
}
119129

120130
async saveNow () {
@@ -183,8 +193,12 @@ class World extends EventEmitter {
183193
}
184194

185195
async setBlock (pos, block) {
186-
(await this.getColumnAt(pos)).setBlock(posInChunk(pos), block)
196+
const chunk = (await this.getColumnAt(pos))
197+
const pInChunk = posInChunk(pos)
198+
const oldBlock = chunk.getBlock(pInChunk)
199+
chunk.setBlock(pInChunk, block)
187200
this.saveAt(pos)
201+
this._emitBlockUpdate(oldBlock, block, pos)
188202
}
189203

190204
async getBlock (pos) {
@@ -216,33 +230,57 @@ class World extends EventEmitter {
216230
}
217231

218232
async setBlockStateId (pos, stateId) {
219-
(await this.getColumnAt(pos)).setBlockStateId(posInChunk(pos), stateId)
233+
const chunk = (await this.getColumnAt(pos))
234+
const pInChunk = posInChunk(pos)
235+
const oldBlock = chunk.getBlock(pInChunk)
236+
chunk.setBlockStateId(pInChunk, stateId)
220237
this.saveAt(pos)
238+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
221239
}
222240

223241
async setBlockType (pos, blockType) {
224-
(await this.getColumnAt(pos)).setBlockType(posInChunk(pos), blockType)
242+
const chunk = (await this.getColumnAt(pos))
243+
const pInChunk = posInChunk(pos)
244+
const oldBlock = chunk.getBlock(pInChunk)
245+
chunk.setBlockType(pInChunk, blockType)
225246
this.saveAt(pos)
247+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
226248
}
227249

228250
async setBlockData (pos, data) {
229-
(await this.getColumnAt(pos)).setBlockData(posInChunk(pos), data)
251+
const chunk = (await this.getColumnAt(pos))
252+
const pInChunk = posInChunk(pos)
253+
const oldBlock = chunk.getBlock(pInChunk)
254+
chunk.setBlockData(pInChunk, data)
230255
this.saveAt(pos)
256+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
231257
}
232258

233259
async setBlockLight (pos, light) {
234-
(await this.getColumnAt(pos)).setBlockLight(posInChunk(pos), light)
260+
const chunk = (await this.getColumnAt(pos))
261+
const pInChunk = posInChunk(pos)
262+
const oldBlock = chunk.getBlock(pInChunk)
263+
chunk.setBlockLight(pInChunk, light)
235264
this.saveAt(pos)
265+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
236266
}
237267

238268
async setSkyLight (pos, light) {
239-
(await this.getColumnAt(pos)).setSkyLight(posInChunk(pos), light)
269+
const chunk = (await this.getColumnAt(pos))
270+
const pInChunk = posInChunk(pos)
271+
const oldBlock = chunk.getBlock(pInChunk)
272+
chunk.setSkyLight(pInChunk, light)
240273
this.saveAt(pos)
274+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
241275
}
242276

243277
async setBiome (pos, biome) {
244-
(await this.getColumnAt(pos)).setBiome(posInChunk(pos), biome)
278+
const chunk = (await this.getColumnAt(pos))
279+
const pInChunk = posInChunk(pos)
280+
const oldBlock = chunk.getBlock(pInChunk)
281+
chunk.setBiome(pInChunk, biome)
245282
this.saveAt(pos)
283+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
246284
}
247285
}
248286

src/worldsync.js

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,15 @@ class WorldSync extends EventEmitter {
5757
return null
5858
}
5959

60+
_emitBlockUpdate (oldBlock, newBlock, position) {
61+
this.emit('blockUpdate', oldBlock, newBlock)
62+
if (position) this.emit(`blockUpdate:${position}`, oldBlock, newBlock)
63+
}
64+
6065
unloadColumn (chunkX, chunkZ) {
6166
this.async.unloadColumn(chunkX, chunkZ)
67+
const columnCorner = new Vec3(chunkX * 16, 0, chunkZ * 16)
68+
this.emit('chunkColumnUnload', columnCorner)
6269
}
6370

6471
getColumns () {
@@ -74,7 +81,9 @@ class WorldSync extends EventEmitter {
7481
}
7582

7683
setColumn (chunkX, chunkZ, chunk, save = true) {
77-
return this.async.setLoadedColumn(chunkX, chunkZ, chunk, save)
84+
this.async.setLoadedColumn(chunkX, chunkZ, chunk, save)
85+
const columnCorner = new Vec3(chunkX * 16, 0, chunkZ * 16)
86+
this.emit('chunkColumnLoad', columnCorner)
7887
}
7988

8089
// Block accessors:
@@ -124,50 +133,71 @@ class WorldSync extends EventEmitter {
124133
setBlock (pos, block) {
125134
const chunk = this.getColumnAt(pos)
126135
if (!chunk) return
127-
chunk.setBlock(posInChunk(pos), block)
136+
const pInChunk = posInChunk(pos)
137+
const oldBlock = chunk.getBlock(pInChunk)
138+
chunk.setBlock(pInChunk, block)
128139
this.async.saveAt(pos)
140+
this._emitBlockUpdate(oldBlock, block)
129141
}
130142

131143
setBlockStateId (pos, stateId) {
132144
const chunk = this.getColumnAt(pos)
133145
if (!chunk) return
134-
chunk.setBlockStateId(posInChunk(pos), stateId)
146+
const pInChunk = posInChunk(pos)
147+
const oldBlock = chunk.getBlock(pInChunk)
148+
chunk.setBlockStateId(pInChunk, stateId)
135149
this.async.saveAt(pos)
150+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
136151
}
137152

138153
setBlockType (pos, blockType) {
139154
const chunk = this.getColumnAt(pos)
140155
if (!chunk) return
141-
chunk.setBlockType(posInChunk(pos), blockType)
156+
const pInChunk = posInChunk(pos)
157+
const oldBlock = chunk.getBlock(pInChunk)
158+
chunk.setBlockType(pInChunk, blockType)
142159
this.async.saveAt(pos)
160+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
143161
}
144162

145163
setBlockData (pos, data) {
146164
const chunk = this.getColumnAt(pos)
147165
if (!chunk) return
148-
chunk.setBlockData(posInChunk(pos), data)
166+
const pInChunk = posInChunk(pos)
167+
const oldBlock = chunk.getBlock(pInChunk)
168+
chunk.setBlockData(pInChunk, data)
149169
this.async.saveAt(pos)
170+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
150171
}
151172

152173
setBlockLight (pos, light) {
153174
const chunk = this.getColumnAt(pos)
154175
if (!chunk) return
155-
chunk.setBlockLight(posInChunk(pos), light)
176+
const pInChunk = posInChunk(pos)
177+
const oldBlock = chunk.getBlock(pInChunk)
178+
chunk.setBlockLight(pInChunk, light)
156179
this.async.saveAt(pos)
180+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
157181
}
158182

159183
setSkyLight (pos, light) {
160184
const chunk = this.getColumnAt(pos)
161185
if (!chunk) return
162-
chunk.setSkyLight(posInChunk(pos), light)
186+
const pInChunk = posInChunk(pos)
187+
const oldBlock = chunk.getBlock(pInChunk)
188+
chunk.setSkyLight(pInChunk, light)
163189
this.async.saveAt(pos)
190+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
164191
}
165192

166193
setBiome (pos, biome) {
167194
const chunk = this.getColumnAt(pos)
168195
if (!chunk) return
169-
chunk.setBiome(posInChunk(pos), biome)
196+
const pInChunk = posInChunk(pos)
197+
const oldBlock = chunk.getBlock(pInChunk)
198+
chunk.setBiome(pInChunk, biome)
170199
this.async.saveAt(pos)
200+
this._emitBlockUpdate(oldBlock, chunk.getBlock(pInChunk), pos)
171201
}
172202
}
173203

0 commit comments

Comments
 (0)