WIP: New Overworld Generator
Some checks failed
Node.js Build / build (18.x) (push) Has been cancelled

This commit is contained in:
Holly Stubbs 2024-07-09 21:52:13 +01:00
parent f606d1547b
commit 5c60d1d758
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
5 changed files with 173 additions and 12 deletions

View file

@ -11,6 +11,8 @@ export default class AABB {
public initMin:Vec3;
public initMax:Vec3;
public prevMin:Vec3;
public prevMax:Vec3;
public min:Vec3;
public max:Vec3;
@ -28,6 +30,8 @@ export default class AABB {
this.initMin = new Vec3(this.min);
this.initMax = new Vec3(this.max);
this.prevMin = new Vec3(this.min);
this.prevMax = new Vec3(this.min);
this.pooled = pooled;
@ -105,13 +109,63 @@ export default class AABB {
return minZ <= maxZ ? maxZ - minZ : 0;
}
public static copy(aabb:AABB) {
const newAABB = new AABB(new Vec3(aabb.min), new Vec3(aabb.max));
newAABB.min.set(aabb.min);
newAABB.max.set(aabb.max);
return newAABB;
}
public copy() {
const newAABB = new AABB(new Vec3(this.min), new Vec3(this.max));
newAABB.min.set(this.min);
newAABB.max.set(this.max);
return newAABB;
}
// Can only revert one step
public revert() {
this.min.set(this.prevMin);
this.max.set(this.prevMax);
}
public set(aabb:AABB) {
this.prevMin.set(this.min);
this.prevMax.set(this.max);
this.min.set(aabb.min);
this.max.set(aabb.min);
}
public move(xOrVec3:Vec3 | number, y?:number, z?:number) {
if (this.pooled) {
throw new Error(`Attempted to move a pooled AABB. This is not allowed!`);
}
this.prevMin.set(this.min);
this.prevMax.set(this.max);
this.min.set(this.initMin);
this.max.set(this.initMax);
if (xOrVec3 instanceof Vec3) {
//this.pos.set(xOrVec3);
this.min.add(xOrVec3);
this.max.add(xOrVec3);
} else if (typeof(xOrVec3) === "number" && typeof(y) === "number" && typeof(z) === "number") {
//this.pos.set(xOrVec3, y, z);
this.min.add(xOrVec3, y, z);
this.max.add(xOrVec3, y, z);
}
}
public offset(xOrVec3:Vec3 | number, y?:number, z?:number) {
if (this.pooled) {
throw new Error(`Attempted to offset a pooled AABB. This is not allowed!`);
}
this.prevMin.set(this.min);
this.prevMax.set(this.max);
if (xOrVec3 instanceof Vec3) {
this.min.add(xOrVec3);
this.max.add(xOrVec3);

View file

@ -7,6 +7,7 @@ import { World } from "./World";
export class Chunk {
private readonly MAX_HEIGHT:number = 128;
private readonly FULLBRIGHT = false;
public readonly world:World;
public readonly x:number;
public readonly z:number;
@ -65,6 +66,18 @@ export class Chunk {
}
public calculateLighting() {
if (this.FULLBRIGHT) {
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
for (let y = this.MAX_HEIGHT - 1; y > 0; y--) {
this.setBlockLight(15, x, y, z);
this.setSkyLight(15, x, y, z);
}
}
}
return;
}
let blockId = 0;
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {

View file

@ -23,6 +23,7 @@ import { HillyGenerator } from "./generators/Hilly";
import { NetherGenerator } from "./generators/Nether";
import { PacketWindowItems } from "./packets/WindowItems";
import { getRandomValues } from "crypto";
import { NewOverworld } from "./generators/NewOverworld";
const chunkFrom = -15;
const chunkTo = 15;
@ -121,6 +122,7 @@ export class MinecraftServer {
}
this.worlds = new FunkyArray<number, World>();
//this.worlds.set(0, new World(this.saveManager, 0, worldSeed, new NewOverworld(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)));

View file

@ -249,31 +249,40 @@ export class Entity implements IEntity {
}
}
private getBlockAABBFor(x:number, y:number, z:number) {
const blockId = this.chunk.getBlockId(x, y, z);
const blockEntityIsTouching = blockId > 0 ? Block.blocks[blockId] : null;
if (blockEntityIsTouching != null) {
return blockEntityIsTouching.getBoundingBox(Math.floor(this.position.x), Math.floor(this.position.y), Math.floor(this.position.z));
}
return null;
}
moveEntity(motionX:number, motionY:number, motionZ:number) {
this.position.add(motionX, motionY, motionZ);
this.entityAABB.move(this.position);
const blockId = this.chunk.getBlockId(Math.floor(this.position.x) & 0xf, Math.floor(this.position.y), Math.floor(this.position.z) & 0xf);
const blockUnderEntity = blockId > 0 ? Block.blocks[blockId] : null;
let blockAABB = this.getBlockAABBFor(Math.floor(this.position.x) & 0xf, Math.floor(this.position.y), Math.floor(this.position.z) & 0xf);
if (blockUnderEntity !== null) {
if (blockAABB !== null) {
this.moveEntityBlockPosRel.set(this.position);
this.moveEntityBlockPosRel.sub(Math.floor(this.position.x), Math.floor(this.position.y), Math.floor(this.position.z));
console.log(this.moveEntityBlockPosRel);
const blockBoundingBox = blockUnderEntity.getBoundingBox(Math.floor(this.position.x), Math.floor(this.position.y), Math.floor(this.position.z));
// TODO: Handle X and Z collisions.
if (this.entityAABB.intersects(blockBoundingBox)) {
const intersectionY = this.entityAABB.intersectionY(blockBoundingBox);
if (this.entityAABB.intersects(blockAABB)) {
const intersectionY = this.entityAABB.intersectionY(blockAABB);
if (this.moveEntityBlockPosRel.y > 0.5) {
this.position.add(0, intersectionY, 0);
motionY = intersectionY;
} else {
this.position.sub(0, intersectionY, 0);
motionY = -intersectionY;
}
this.motion.y = 0;
this.onGround = true;
}
this.position.add(0, motionY, 0);
this.motion.y = 0;
this.onGround = true;
}
}

View file

@ -0,0 +1,83 @@
import { makeNoise2D, Noise2D } from "../../external/OpenSimplex2D";
import { makeNoise3D, Noise3D } from "../../external/OpenSimplex3D";
import { Block } from "../blocks/Block";
import { Chunk } from "../Chunk";
import mulberry32 from "../mulberry32";
import { IGenerator } from "./IGenerator";
export class NewOverworld implements IGenerator {
private seed:number;
seedGenerator:() => number;
public layer1:Noise3D;
public layer2:Noise3D;
public mix:Noise3D;
public maxHeight:Noise2D;
private createGenerator2D() {
return makeNoise2D(this.seedGenerator() * Number.MAX_SAFE_INTEGER);
}
private createGenerator3D() {
return makeNoise3D(this.seedGenerator() * Number.MAX_SAFE_INTEGER);
}
public constructor(seed:number) {
this.seed = seed;
this.seedGenerator = mulberry32(this.seed);
this.layer1 = this.createGenerator3D();
this.layer2 = this.createGenerator3D();
this.mix = this.createGenerator3D();
this.maxHeight = this.createGenerator2D();
}
private noiseForCoord(chunk:Chunk, x:number, y:number, z:number) {
const mixValue = this.mix((chunk.x * 16 + x) / 16, y / 16, (chunk.z * 16 + z) / 16);
const layer1 = this.layer1((chunk.x * 16 + x) / 64, y / 64, (chunk.z * 16 + z) / 64) / 2048;
const layer2 = this.layer2((chunk.x * 16 + x) / 64, y / 64, (chunk.z * 16 + z) / 64) / 2048;
const maxHeightLayer = 80 + this.maxHeight((chunk.x * 16 + x) / 64, (chunk.z * 16 + z) / 64) * 32;
if (y > maxHeightLayer) {
return 0;
}
if (mixValue < 0) {
return layer1;
} else if (mixValue > 1) {
return layer2;
} else {
return layer1 + (layer2 - layer1) * mixValue;
}
}
public generate(chunk:Chunk) {
for (let y = 0; y < 128; y++) {
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
if (y === 0 || (y < 3 && this.layer1(x, y, z) > 0.1)) {
chunk.setBlock(Block.bedrock.blockId, x, y, z);
} else {
if (this.noiseForCoord(chunk, x, y, z) > 0) {
chunk.setBlock(Block.stone.blockId, x, y, z);
} else if (y < 64) {
chunk.setBlock(Block.waterStill.blockId, x, y, z);
}
}
}
}
}
for (let y = 0; y < 128; y++) {
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
if (y === 0 || (y < 3 && this.layer1(x, y, z) > 0.1)) {
chunk.setBlock(Block.bedrock.blockId, x, y, z);
} else {
}
}
}
}
}
}