allow changing metadata directly without updating block id
This commit is contained in:
parent
5c60d1d758
commit
45c08c0c5f
8 changed files with 107 additions and 14 deletions
|
@ -123,6 +123,16 @@ export class Chunk {
|
||||||
this.blocks[x << 11 | z << 7 | y] = blockId;
|
this.blocks[x << 11 | z << 7 | y] = blockId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setBlockMetadata(metadata:number, x:number, y:number, z:number) {
|
||||||
|
const index = x << 11 | z << 7 | y;
|
||||||
|
if (x < 0 || x > 15 || y < 0 || y > 127 || z < 0 || z > 15) {
|
||||||
|
this.queueBlockUpdateForOuterChunkBlock(this.blocks[index], metadata, x, y, z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.metadata.set(index, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
public setBlockWithMetadata(blockId:number, metadata:number, x:number, y:number, z:number) {
|
public setBlockWithMetadata(blockId:number, metadata:number, x:number, y:number, z:number) {
|
||||||
if (x < 0 || x > 15 || y < 0 || y > 127 || z < 0 || z > 15) {
|
if (x < 0 || x > 15 || y < 0 || y > 127 || z < 0 || z > 15) {
|
||||||
this.queueBlockUpdateForOuterChunkBlock(blockId, metadata, x, y, z);
|
this.queueBlockUpdateForOuterChunkBlock(blockId, metadata, x, y, z);
|
||||||
|
|
|
@ -126,17 +126,6 @@ export class MinecraftServer {
|
||||||
this.worlds.set(0, new World(this.saveManager, 0, worldSeed, new HillyGenerator(worldSeed)));
|
this.worlds.set(0, new World(this.saveManager, 0, worldSeed, new HillyGenerator(worldSeed)));
|
||||||
this.worlds.set(-1, new World(this.saveManager, -1, worldSeed, new NetherGenerator(worldSeed)));
|
this.worlds.set(-1, new World(this.saveManager, -1, worldSeed, new NetherGenerator(worldSeed)));
|
||||||
|
|
||||||
// Generate spawn area (overworld)
|
|
||||||
/*(async () => {
|
|
||||||
const generateStartTime = Date.now();
|
|
||||||
Console.printInfo("Generating spawn area...");
|
|
||||||
for (let x = -3; x < 3; x++) {
|
|
||||||
for (let z = -3; z < 3; z++) {
|
|
||||||
await this.overworld.getChunkSafe(x, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Console.printInfo(`Done! Took ${Date.now() - generateStartTime}ms`);
|
|
||||||
}).bind(this)();*/
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const generateStartTime = Date.now();
|
const generateStartTime = Date.now();
|
||||||
let timer = Date.now();
|
let timer = Date.now();
|
||||||
|
|
17
server/Random.ts
Normal file
17
server/Random.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import mulberry32 from "./mulberry32";
|
||||||
|
|
||||||
|
export default class Random {
|
||||||
|
private readonly mulberry32;
|
||||||
|
|
||||||
|
public constructor(seed:number = Date.now()) {
|
||||||
|
this.mulberry32 = mulberry32(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public nextInt(bound = Number.MAX_SAFE_INTEGER) {
|
||||||
|
return Math.floor(this.mulberry32() * bound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public nextFloat() {
|
||||||
|
return this.mulberry32();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import { PacketPickupSpawn } from "./packets/PickupSpawn";
|
||||||
import { QueuedBlockUpdate } from "./queuedUpdateTypes/BlockUpdate";
|
import { QueuedBlockUpdate } from "./queuedUpdateTypes/BlockUpdate";
|
||||||
import { IQueuedUpdate } from "./queuedUpdateTypes/IQueuedUpdate";
|
import { IQueuedUpdate } from "./queuedUpdateTypes/IQueuedUpdate";
|
||||||
import AABB from "./AABB";
|
import AABB from "./AABB";
|
||||||
|
import Random from "./Random";
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
public static ENTITY_MAX_SEND_DISTANCE = 50;
|
public static ENTITY_MAX_SEND_DISTANCE = 50;
|
||||||
|
@ -32,6 +33,8 @@ export class World {
|
||||||
public queuedUpdates:Array<IQueuedUpdate>;
|
public queuedUpdates:Array<IQueuedUpdate>;
|
||||||
public generator:IGenerator;
|
public generator:IGenerator;
|
||||||
|
|
||||||
|
public random:Random = new Random();
|
||||||
|
|
||||||
public readonly dimension:number;
|
public readonly dimension:number;
|
||||||
|
|
||||||
public constructor(saveManager:WorldSaveManager, dimension:number, seed:number, generator:IGenerator) {
|
public constructor(saveManager:WorldSaveManager, dimension:number, seed:number, generator:IGenerator) {
|
||||||
|
@ -157,8 +160,18 @@ export class World {
|
||||||
return this.getChunk(chunkX, chunkZ).getBlockMetadata(x & 0xf, y, z & 0xf);
|
return this.getChunk(chunkX, chunkZ).getBlockMetadata(x & 0xf, y, z & 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChunkBlockMetadata(chunk:Chunk, x:number, y:number, z:number) {
|
public getBlockLight(x:number, y:number, z:number) {
|
||||||
return chunk.getBlockMetadata(x & 0xf, y, z & 0xf);
|
const chunkX = x >> 4,
|
||||||
|
chunkZ = z >> 4;
|
||||||
|
|
||||||
|
return this.getChunk(chunkX, chunkZ).getBlockLight(x & 0xf, y, z & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSkyLight(x:number, y:number, z:number) {
|
||||||
|
const chunkX = x >> 4,
|
||||||
|
chunkZ = z >> 4;
|
||||||
|
|
||||||
|
return this.getChunk(chunkX, chunkZ).getSkyLight(x & 0xf, y, z & 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setBlock(blockId:number, x:number, y:number, z:number, doBlockUpdate?:boolean) {
|
public setBlock(blockId:number, x:number, y:number, z:number, doBlockUpdate?:boolean) {
|
||||||
|
@ -193,11 +206,33 @@ export class World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setBlockMetadata(x:number, y:number, z:number, metadata:number, doBlockUpdate?:boolean) {
|
||||||
|
const chunkX = x >> 4, chunkZ = z >> 4;
|
||||||
|
|
||||||
|
const chunk = this.getChunk(chunkX, chunkZ);
|
||||||
|
const xc = x & 0xf, zc = z & 0xf;
|
||||||
|
chunk.setBlockMetadata(metadata, xc, y, zc);
|
||||||
|
|
||||||
|
if (doBlockUpdate) {
|
||||||
|
const blockId = chunk.getBlockId(xc, y, zc);
|
||||||
|
const blockUpdatePacket = new PacketBlockChange(x, y, z, blockId, metadata).writeData();
|
||||||
|
// Send block update to all players that have this chunk loaded
|
||||||
|
chunk.playersInChunk.forEach(player => {
|
||||||
|
player.mpClient?.send(blockUpdatePacket);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public setBlockWithNotify(x:number, y:number, z:number, blockId:number) {
|
public setBlockWithNotify(x:number, y:number, z:number, blockId:number) {
|
||||||
this.setBlock(blockId, x, y, z, true);
|
this.setBlock(blockId, x, y, z, true);
|
||||||
this.notifyNeighborBlocksOfChange(x, y, z, blockId);
|
this.notifyNeighborBlocksOfChange(x, y, z, blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setBlockMetadataWithNotify(x:number, y:number, z:number, metadata:number) {
|
||||||
|
this.setBlockMetadata(x, y, z, metadata, true);
|
||||||
|
this.notifyNeighborBlocksOfChange(x, y, z, this.getBlockId(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
public setBlockAndMetadataWithNotify(x:number, y:number, z:number, blockId:number, metadata:number) {
|
public setBlockAndMetadataWithNotify(x:number, y:number, z:number, blockId:number, metadata:number) {
|
||||||
this.setBlockWithMetadata(blockId, metadata, x, y, z, true);
|
this.setBlockWithMetadata(blockId, metadata, x, y, z, true);
|
||||||
this.notifyNeighborBlocksOfChange(x, y, z, blockId);
|
this.notifyNeighborBlocksOfChange(x, y, z, blockId);
|
||||||
|
|
16
server/blocks/BlockBehaviorSapling.ts
Normal file
16
server/blocks/BlockBehaviorSapling.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import Random from "../Random";
|
||||||
|
import { World } from "../World";
|
||||||
|
import { BlockBehaviour } from "./BlockBehaviour";
|
||||||
|
|
||||||
|
export class BlockBehaviourSapling extends BlockBehaviour {
|
||||||
|
public randomTick(world:World, x:number, y:number, z:number, random:Random) {
|
||||||
|
if (world.getBlockLight(x, y + 1, z) >= 9 && random.nextInt(30) === 0) {
|
||||||
|
const blockMetadata = world.getBlockMetadata(x, y, z);
|
||||||
|
if ((blockMetadata & 8) === 0) {
|
||||||
|
world.setBlockMetadataWithNotify(x, y, z, blockMetadata | 8);
|
||||||
|
} else {
|
||||||
|
console.log("UNIMPLEMENTED TREE GROW!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import AABB from "../AABB";
|
import AABB from "../AABB";
|
||||||
|
import Random from "../Random";
|
||||||
import { World } from "../World";
|
import { World } from "../World";
|
||||||
import { IBlockBehaviour } from "./IBlockBehaviour";
|
import { IBlockBehaviour } from "./IBlockBehaviour";
|
||||||
|
|
||||||
|
@ -7,4 +8,5 @@ export class BlockBehaviour implements IBlockBehaviour {
|
||||||
public droppedItem(blockId:number) { return blockId; }
|
public droppedItem(blockId:number) { return blockId; }
|
||||||
public droppedCount(blockId:number) { return 1; }
|
public droppedCount(blockId:number) { return 1; }
|
||||||
public getBoundingBox(x:number, y:number, z:number) { return AABB.getAABB(0 + x, 0 + y, 0 + z, 1 + x, 1 + y, 1 + z); }
|
public getBoundingBox(x:number, y:number, z:number) { return AABB.getAABB(0 + x, 0 + y, 0 + z, 1 + x, 1 + y, 1 + z); }
|
||||||
|
public randomTick(world:World, x:number, y:number, z:number, random:Random) {}
|
||||||
}
|
}
|
12
server/blocks/BlockBehaviourOre.ts
Normal file
12
server/blocks/BlockBehaviourOre.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Item } from "../items/Item";
|
||||||
|
import { BlockBehaviour } from "./BlockBehaviour";
|
||||||
|
|
||||||
|
export default class BlockBehaviourOre extends BlockBehaviour {
|
||||||
|
public droppedItem(blockId:number) {
|
||||||
|
return Item.clay.shiftedItemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public droppedCount(blockId:number) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
12
server/blocks/BlockBehaviourRedstoneOre.ts
Normal file
12
server/blocks/BlockBehaviourRedstoneOre.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Item } from "../items/Item";
|
||||||
|
import { BlockBehaviour } from "./BlockBehaviour";
|
||||||
|
|
||||||
|
export default class BlockBehaviourRedstoneOre extends BlockBehaviour {
|
||||||
|
public droppedItem(blockId:number) {
|
||||||
|
return Item.clay.shiftedItemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public droppedCount(blockId:number) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue