use threejs module js, remove unused libraries, increase world generation seed to 64 bit, implement random world spawn, improve start script
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import Minecraft from './net/minecraft/client/Minecraft.js';
|
||||
|
||||
class Start {
|
||||
|
||||
constructor(preStatusElementId) {
|
||||
this.preStatusElement = document.getElementById(preStatusElementId);
|
||||
}
|
||||
|
||||
loadTextures(textures) {
|
||||
let resources = [];
|
||||
let index = 0;
|
||||
|
||||
return textures.reduce((currentPromise, texturePath) => {
|
||||
return currentPromise.then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Load texture
|
||||
let image = new Image();
|
||||
image.src = "src/resources/" + texturePath;
|
||||
image.onload = () => resolve();
|
||||
resources[texturePath] = image;
|
||||
|
||||
index++;
|
||||
});
|
||||
});
|
||||
}, Promise.resolve()).then(() => {
|
||||
return resources;
|
||||
});
|
||||
}
|
||||
|
||||
launch(canvasWrapperId) {
|
||||
this.loadTextures([
|
||||
"misc/grasscolor.png",
|
||||
"gui/font.png",
|
||||
"gui/gui.png",
|
||||
"gui/background.png",
|
||||
"gui/icons.png",
|
||||
"terrain/terrain.png",
|
||||
"terrain/sun.png",
|
||||
"terrain/moon.png",
|
||||
"char.png"
|
||||
]).then((resources) => {
|
||||
this.preStatusElement.remove();
|
||||
|
||||
// Launch actual game on canvas
|
||||
window.app = new Minecraft(canvasWrapperId, resources);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Launch game
|
||||
new Start("pre-status").launch("canvas-container");
|
||||
@@ -29,17 +29,6 @@ export default class GameWindow {
|
||||
this.canvasItems = document.createElement('canvas');
|
||||
this.wrapper.appendChild(this.canvasItems);
|
||||
|
||||
// Stats
|
||||
this.statsFps = new Stats()
|
||||
this.statsFps.showPanel(0);
|
||||
this.statsFps.domElement.style.cssText = 'position:absolute;top:0px;right:80px;float:right';
|
||||
//this.wrapper.appendChild(this.statsFps.dom);
|
||||
|
||||
this.statsMs = new Stats()
|
||||
this.statsMs.showPanel(1);
|
||||
this.statsMs.domElement.style.cssText = 'position:absolute;top:0px;right:160px;float:right';
|
||||
//this.wrapper.appendChild(this.statsMs.dom);
|
||||
|
||||
// On resize
|
||||
let scope = this;
|
||||
|
||||
|
||||
@@ -84,17 +84,14 @@ export default class Minecraft {
|
||||
}
|
||||
|
||||
init() {
|
||||
// Load spawn chunk
|
||||
for (let x = -WorldRenderer.RENDER_DISTANCE; x <= WorldRenderer.RENDER_DISTANCE; x++) {
|
||||
for (let z = -WorldRenderer.RENDER_DISTANCE; z <= WorldRenderer.RENDER_DISTANCE; z++) {
|
||||
this.world.getChunkAt(x, z);
|
||||
}
|
||||
}
|
||||
this.player.respawn();
|
||||
|
||||
// Start render loop
|
||||
this.running = true;
|
||||
this.requestNextFrame();
|
||||
|
||||
// Load spawn chunks and respawn player
|
||||
this.world.findSpawn();
|
||||
this.world.loadSpawnChunks();
|
||||
this.player.respawn();
|
||||
}
|
||||
|
||||
hasInGameFocus() {
|
||||
@@ -112,9 +109,6 @@ export default class Minecraft {
|
||||
}
|
||||
|
||||
onLoop() {
|
||||
this.window.statsFps.begin();
|
||||
this.window.statsMs.begin();
|
||||
|
||||
// Update the timer
|
||||
this.timer.advanceTime();
|
||||
|
||||
@@ -135,9 +129,6 @@ export default class Minecraft {
|
||||
this.lastTime += 1000;
|
||||
this.frames = 0;
|
||||
}
|
||||
|
||||
this.window.statsFps.end();
|
||||
this.window.statsMs.end();
|
||||
}
|
||||
|
||||
onRender(partialTicks) {
|
||||
|
||||
@@ -47,8 +47,8 @@ export default class PlayerEntity extends EntityLiving {
|
||||
}
|
||||
|
||||
respawn() {
|
||||
let spawnY = this.world.getHeightAt(0, 0);
|
||||
this.setPosition(0, spawnY + 8, 0);
|
||||
let spawn = this.world.getSpawn();
|
||||
this.setPosition(spawn.x, spawn.y, spawn.z);
|
||||
}
|
||||
|
||||
setPosition(x, y, z) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class Tessellator {
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import Tessellator from "./Tessellator.js";
|
||||
import ChunkSection from "../world/ChunkSection.js";
|
||||
import Random from "../../util/Random.js";
|
||||
import Vector3 from "../../util/Vector3.js";
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class WorldRenderer {
|
||||
|
||||
@@ -105,8 +106,8 @@ export default class WorldRenderer {
|
||||
|
||||
// Render chunks
|
||||
let player = this.minecraft.player;
|
||||
let cameraChunkX = Math.floor(player.x >> 4);
|
||||
let cameraChunkZ = Math.floor(player.z >> 4);
|
||||
let cameraChunkX = Math.floor(player.x) >> 4;
|
||||
let cameraChunkZ = Math.floor(player.z) >> 4;
|
||||
this.renderChunks(cameraChunkX, cameraChunkZ);
|
||||
|
||||
// Render sky
|
||||
@@ -611,6 +612,13 @@ export default class WorldRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update render order of chunks
|
||||
world.group.children.sort((a, b) => {
|
||||
let distance1 = Math.floor(Math.pow(a.chunkX - cameraChunkX, 2) + Math.pow(a.chunkZ - cameraChunkZ, 2));
|
||||
let distance2 = Math.floor(Math.pow(b.chunkX - cameraChunkX, 2) + Math.pow(b.chunkZ - cameraChunkZ, 2));
|
||||
return distance2 - distance1;
|
||||
});
|
||||
}
|
||||
|
||||
rebuildAll() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Tessellator from "../Tessellator.js";
|
||||
import MathHelper from "../../../util/MathHelper.js";
|
||||
import * as THREE from "../../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class EntityRenderer {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ModelPlayer from "../../model/model/ModelPlayer.js";
|
||||
import EntityRenderer from "../EntityRenderer.js";
|
||||
import Block from "../../../world/block/Block.js";
|
||||
import * as THREE from "../../../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class PlayerRenderer extends EntityRenderer {
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import * as THREE from "../../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class ItemRenderer {
|
||||
|
||||
constructor(minecraft, window) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Polygon from "./Polygon.js";
|
||||
import Vertex from "./Vertex.js";
|
||||
import * as THREE from "../../../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class ModelRenderer {
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Block from "../world/block/Block.js";
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class SoundManager {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import EnumSkyBlock from "../../util/EnumSkyBlock.js";
|
||||
import Block from "./block/Block.js";
|
||||
import World from "./World.js";
|
||||
import ChunkSection from "./ChunkSection.js";
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class Chunk {
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import EnumSkyBlock from "../../util/EnumSkyBlock.js";
|
||||
import Block from "./block/Block.js";
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
|
||||
export default class ChunkSection {
|
||||
|
||||
|
||||
@@ -8,12 +8,16 @@ import EnumBlockFace from "../../util/EnumBlockFace.js";
|
||||
import Vector3 from "../../util/Vector3.js";
|
||||
import Vector4 from "../../util/Vector4.js";
|
||||
import MetadataChunkBlock from "../../util/MetadataChunkBlock.js";
|
||||
import Long from "../../../../../../libraries/long.js";
|
||||
import * as THREE from "../../../../../../libraries/three.module.js";
|
||||
import WorldRenderer from "../render/WorldRenderer.js";
|
||||
import Random from "../../util/Random.js";
|
||||
|
||||
export default class World {
|
||||
|
||||
static TOTAL_HEIGHT = ChunkSection.SIZE * 8 - 1; // ChunkSection.SIZE * 16 - 1;
|
||||
|
||||
constructor(minecraft) {
|
||||
constructor(minecraft, seed = Long.fromInt(Date.now() % 100000)) {
|
||||
this.minecraft = minecraft;
|
||||
|
||||
this.entities = [];
|
||||
@@ -25,10 +29,9 @@ export default class World {
|
||||
this.lightUpdateQueue = [];
|
||||
|
||||
this.time = 0;
|
||||
this.spawn = new Vector3(0, 0, 0);
|
||||
|
||||
// Load world
|
||||
this.seed = Date.now() % 100000;
|
||||
this.generator = new WorldGenerator(this, this.seed);
|
||||
this.setSeed(seed);
|
||||
|
||||
// Update lights async
|
||||
let scope = this;
|
||||
@@ -41,18 +44,17 @@ export default class World {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
setSeed(seed) {
|
||||
this.seed = seed;
|
||||
this.generator = new WorldGenerator(this, seed);
|
||||
this.random = new Random(seed);
|
||||
}
|
||||
|
||||
getSeed() {
|
||||
return this.seed;
|
||||
}
|
||||
|
||||
onTick() {
|
||||
let player = this.minecraft.player;
|
||||
let cameraChunkX = Math.floor(player.x >> 4);
|
||||
let cameraChunkZ = Math.floor(player.z >> 4);
|
||||
|
||||
// Update render order of chunks
|
||||
this.group.children.sort((a, b) => {
|
||||
let distance1 = Math.floor(Math.pow(a.chunkX - cameraChunkX, 2) + Math.pow(a.chunkZ - cameraChunkZ, 2));
|
||||
let distance2 = Math.floor(Math.pow(b.chunkX - cameraChunkX, 2) + Math.pow(b.chunkZ - cameraChunkZ, 2));
|
||||
return distance2 - distance1;
|
||||
});
|
||||
|
||||
// Update skylight subtracted (To make the night dark)
|
||||
let lightLevel = this.calculateSkylightSubtracted(1.0);
|
||||
if (lightLevel !== this.skylightSubtracted) {
|
||||
@@ -108,9 +110,6 @@ export default class World {
|
||||
}
|
||||
|
||||
getChunkAtBlock(x, y, z) {
|
||||
if (!this.blockExists(x, y, z)) {
|
||||
return null;
|
||||
}
|
||||
return this.getChunkAt(x >> 4, z >> 4).getSection(y >> 4);
|
||||
}
|
||||
|
||||
@@ -617,4 +616,42 @@ export default class World {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getSpawn() {
|
||||
return this.spawn;
|
||||
}
|
||||
|
||||
setSpawn(x, z) {
|
||||
let y = this.getHeightAt(x, z);
|
||||
this.spawn = new Vector3(x, y + 8, z);
|
||||
}
|
||||
|
||||
findSpawn() {
|
||||
if (this.spawn.y <= 0) {
|
||||
this.spawn.y = 64;
|
||||
}
|
||||
|
||||
while (this.getBlockAboveSeaLevel(this.spawn.x, this.spawn.z) === 0) {
|
||||
this.spawn.x += this.random.nextInt(8) - this.random.nextInt(8);
|
||||
this.spawn.z += this.random.nextInt(8) - this.random.nextInt(8);
|
||||
}
|
||||
}
|
||||
|
||||
getBlockAboveSeaLevel(x, z) {
|
||||
let y = this.generator.seaLevel;
|
||||
while (this.getBlockAt(x, y + 1, z) !== 0) {
|
||||
y++;
|
||||
}
|
||||
return this.getBlockAt(x, y, z);
|
||||
}
|
||||
|
||||
loadSpawnChunks() {
|
||||
for (let x = -WorldRenderer.RENDER_DISTANCE; x <= WorldRenderer.RENDER_DISTANCE; x++) {
|
||||
for (let z = -WorldRenderer.RENDER_DISTANCE; z <= WorldRenderer.RENDER_DISTANCE; z++) {
|
||||
this.getChunkAt(x + this.spawn.x >> 4, z + this.spawn.z >> 4);
|
||||
}
|
||||
}
|
||||
this.spawn.y = this.getHeightAt(this.spawn.x, this.spawn.z) + 8;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import Random from "../../../util/Random.js";
|
||||
import Long from "../../../../../../../libraries/long.js";
|
||||
|
||||
export default class Generator {
|
||||
|
||||
@@ -15,4 +16,23 @@ export default class Generator {
|
||||
generateAtBlock(x, y, z, primer) {
|
||||
|
||||
}
|
||||
|
||||
generateSeedOffset() {
|
||||
this.random.setSeed(this.seed);
|
||||
|
||||
let seedX = this.random.nextLong().divide(2).multiply(2).add(1);
|
||||
let seedZ = this.random.nextLong().divide(2).multiply(2).add(1);
|
||||
|
||||
return {seedX, seedZ};
|
||||
}
|
||||
|
||||
setSeedOffset(chunkX, chunkZ, seedX, seedZ) {
|
||||
let seed = Long.fromInt(chunkX).multiply(seedX).add(Long.fromInt(chunkZ).multiply(seedZ)).xor(this.seed);
|
||||
this.random.setSeed(seed);
|
||||
}
|
||||
|
||||
setChunkSeed(chunkX, chunkZ) {
|
||||
let {seedX, seedZ} = this.generateSeedOffset();
|
||||
this.setSeedOffset(chunkX, chunkZ, seedX, seedZ);
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,13 @@ export default class WorldGenerator extends Generator {
|
||||
this.terrainGenerator4 = new NoiseGeneratorOctaves(this.random, 16);
|
||||
this.terrainGenerator5 = new NoiseGeneratorOctaves(this.random, 16);
|
||||
this.terrainGenerator3 = new NoiseGeneratorOctaves(this.random, 8);
|
||||
this.terrainGenerator1 = new NoiseGeneratorOctaves(this.random, 10);
|
||||
this.terrainGenerator2 = new NoiseGeneratorOctaves(this.random, 16);
|
||||
|
||||
this.natureGenerator1 = new NoiseGeneratorOctaves(this.random, 4);
|
||||
this.natureGenerator2 = new NoiseGeneratorOctaves(this.random, 4);
|
||||
|
||||
this.terrainGenerator1 = new NoiseGeneratorOctaves(this.random, 10);
|
||||
this.terrainGenerator2 = new NoiseGeneratorOctaves(this.random, 16);
|
||||
|
||||
this.populationNoiseGenerator = new NoiseGeneratorOctaves(this.random, 8);
|
||||
}
|
||||
|
||||
@@ -52,18 +53,13 @@ export default class WorldGenerator extends Generator {
|
||||
}
|
||||
|
||||
populateChunk(chunkX, chunkZ) {
|
||||
// Reset seed
|
||||
this.random.setSeed(this.seed);
|
||||
|
||||
// Set seed for chunk
|
||||
let seedX = (this.random.nextInt() / 2) * 2 + 1;
|
||||
let seedZ = (this.random.nextInt() / 2) * 2 + 1;
|
||||
this.random.setSeed(chunkX * seedX + chunkZ * seedZ ^ this.seed);
|
||||
this.setChunkSeed(chunkX, chunkZ);
|
||||
|
||||
// Access noise data for population
|
||||
let absoluteX = chunkX * 16;
|
||||
let absoluteY = chunkZ * 16;
|
||||
let amount = Math.floor((this.populationNoiseGenerator.perlin(absoluteX * 0.5, absoluteY * 0.5) / 8 + this.random.nextFloat() * 4 + 4) / 3);
|
||||
let amount = Math.floor((this.populationNoiseGenerator.perlin(absoluteX * 0.5, absoluteY * 0.5) / 8 + this.random.nextDouble() * 4 + 4) / 3);
|
||||
if (amount < 0) {
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ export default class NoiseGeneratorPerlin extends NoiseGenerator {
|
||||
constructor(random) {
|
||||
super();
|
||||
|
||||
this.offsetX = random.nextFloat() * 256;
|
||||
this.offsetY = random.nextFloat() * 256;
|
||||
this.offsetZ = random.nextFloat() * 256;
|
||||
this.offsetX = random.nextDouble() * 256;
|
||||
this.offsetY = random.nextDouble() * 256;
|
||||
this.offsetZ = random.nextDouble() * 256;
|
||||
|
||||
this.permutations = [];
|
||||
for (let i = 0; i < 256; i++) {
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class BigTreeGenerator extends Generator {
|
||||
}
|
||||
|
||||
generateAtBlock(x, y, z) {
|
||||
let seed = this.random.nextInt();
|
||||
let seed = this.random.nextLong();
|
||||
this.random.setSeed(seed);
|
||||
|
||||
this.coords[0] = x;
|
||||
|
||||
@@ -11,18 +11,14 @@ export default class CaveGenerator extends Generator {
|
||||
}
|
||||
|
||||
generateInChunk(originChunkX, originChunkZ, primer) {
|
||||
// Reset seed
|
||||
this.random.setSeed(this.seed);
|
||||
|
||||
let offset = this.chunkRange;
|
||||
let seedX = (this.random.nextInt() / 2) * 2 + 1;
|
||||
let seedZ = (this.random.nextInt() / 2) * 2 + 1;
|
||||
let {seedX, seedZ} = this.generateSeedOffset();
|
||||
|
||||
// Generate entire cave over 16x16 chunk area
|
||||
for (let chunkX = originChunkX - offset; chunkX <= originChunkX + offset; chunkX++) {
|
||||
for (let chunkZ = originChunkZ - offset; chunkZ <= originChunkZ + offset; chunkZ++) {
|
||||
// Set seed for position
|
||||
this.random.setSeed(chunkX * seedX + chunkZ * seedZ ^ this.seed);
|
||||
this.setSeedOffset(chunkX, chunkZ, seedX, seedZ);
|
||||
|
||||
// Generate entire cave
|
||||
this.generateCave(chunkX, chunkZ, originChunkX, originChunkZ, primer);
|
||||
@@ -50,10 +46,10 @@ export default class CaveGenerator extends Generator {
|
||||
}
|
||||
|
||||
for (let j = 0; j < amount; j++) {
|
||||
let num1 = this.random.nextFloat() * Math.PI * 2.0;
|
||||
let num2 = ((this.random.nextFloat() - 0.5) * 2.0) / 8;
|
||||
let num3 = this.random.nextFloat() * 2.0 + this.random.nextFloat();
|
||||
this.generateCaveAtBlock(originChunkX, originChunkZ, primer, x, y, z, num3, num1, num2, 0, 0, 1.0);
|
||||
let rotation1 = this.random.nextFloat() * Math.PI * 2.0;
|
||||
let rotation2 = ((this.random.nextFloat() - 0.5) * 2.0) / 8;
|
||||
let amplitude = this.random.nextFloat() * 2.0 + this.random.nextFloat();
|
||||
this.generateCaveAtBlock(originChunkX, originChunkZ, primer, x, y, z, amplitude, rotation1, rotation2, 0, 0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,47 +63,47 @@ export default class CaveGenerator extends Generator {
|
||||
);
|
||||
}
|
||||
|
||||
generateCaveAtBlock(originChunkX, originChunkZ, primer, absoluteX, absoluteY, absoluteZ, amplitude, rotation2, rotation1, progress, distance, strength) {
|
||||
generateCaveAtBlock(originChunkX, originChunkZ, primer, absoluteX, absoluteY, absoluteZ, amplitude, rotation1, rotation2, progress, distance, strength) {
|
||||
let centerX = originChunkX * 16 + 8;
|
||||
let centerZ = originChunkZ * 16 + 8;
|
||||
|
||||
let motion2 = 0;
|
||||
let motion1 = 0;
|
||||
|
||||
let random = new Random(this.random.nextInt());
|
||||
let random = new Random(this.random.nextLong());
|
||||
if (distance <= 0) {
|
||||
let i1 = this.chunkRange * 16 - 16;
|
||||
distance = i1 - random.nextInt(i1 / 4);
|
||||
let range = this.chunkRange * 16 - 16;
|
||||
distance = range - random.nextInt(Math.floor(range / 4));
|
||||
}
|
||||
|
||||
let isBeginning = false;
|
||||
if (progress === -1) {
|
||||
progress = distance / 2;
|
||||
progress = Math.floor(distance / 2);
|
||||
isBeginning = true;
|
||||
}
|
||||
|
||||
let maxProgress = random.nextInt(distance / 2) + distance / 4;
|
||||
let maxProgress = random.nextInt(Math.floor(distance / 2)) + Math.floor(distance / 4);
|
||||
let isStrong = random.nextInt(6) === 0;
|
||||
|
||||
for (; progress < distance; progress++) {
|
||||
let value = 1.5 + (Math.sin((progress * Math.PI) / distance) * amplitude);
|
||||
let valueWithStrength = value * strength;
|
||||
|
||||
let cos = Math.cos(rotation1);
|
||||
let sin = Math.sin(rotation1);
|
||||
let cos = Math.cos(rotation2);
|
||||
let sin = Math.sin(rotation2);
|
||||
|
||||
absoluteX += Math.cos(rotation2) * cos;
|
||||
absoluteX += Math.cos(rotation1) * cos;
|
||||
absoluteY += sin;
|
||||
absoluteZ += Math.sin(rotation2) * cos;
|
||||
absoluteZ += Math.sin(rotation1) * cos;
|
||||
|
||||
if (isStrong) {
|
||||
rotation1 *= 0.92;
|
||||
rotation2 *= 0.92;
|
||||
} else {
|
||||
rotation1 *= 0.7;
|
||||
rotation2 *= 0.7;
|
||||
}
|
||||
|
||||
rotation1 += motion1 * 0.1;
|
||||
rotation2 += motion2 * 0.1;
|
||||
rotation2 += motion1 * 0.1;
|
||||
rotation1 += motion2 * 0.1;
|
||||
|
||||
motion1 *= 0.9;
|
||||
motion2 *= 0.75;
|
||||
@@ -119,12 +115,12 @@ export default class CaveGenerator extends Generator {
|
||||
this.generateCaveAtBlock(
|
||||
originChunkX, originChunkZ, primer,
|
||||
absoluteX, absoluteY, absoluteZ,
|
||||
random.nextFloat() * 0.5 + 0.5, rotation2 - 1.570796, rotation1 / 3, progress, distance, 1.0
|
||||
random.nextFloat() * 0.5 + 0.5, rotation1 - 1.570796, rotation2 / 3, progress, distance, 1.0
|
||||
);
|
||||
this.generateCaveAtBlock(
|
||||
originChunkX, originChunkZ, primer,
|
||||
absoluteX, absoluteY, absoluteZ,
|
||||
random.nextFloat() * 0.5 + 0.5, rotation2 + 1.570796, rotation1 / 3, progress, distance, 1.0
|
||||
random.nextFloat() * 0.5 + 0.5, rotation1 + 1.570796, rotation2 / 3, progress, distance, 1.0
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,78 @@
|
||||
import Long from "../../../../../libraries/long.js";
|
||||
|
||||
export default class Random {
|
||||
|
||||
static instances = 0;
|
||||
|
||||
constructor(seed = Date.now() % 1000000000 ^ Random.instances++ * 1000) {
|
||||
this.mask = 0xffffffff;
|
||||
this.multiplier = Long.fromString("25214903917");
|
||||
this.mask = Long.fromInt(1).shiftLeft(48).subtract(1);
|
||||
this.addend = Long.fromInt(0xB);
|
||||
this.doubleUnit = 1.1102230246251565E-16;
|
||||
|
||||
this.setSeed(seed);
|
||||
}
|
||||
|
||||
nextBoolean() {
|
||||
return this.nextFloat() > 0.5;
|
||||
}
|
||||
|
||||
nextInt(max = 0x7fffffff) {
|
||||
return Math.floor(this.nextFloat() * (max + 1));
|
||||
}
|
||||
|
||||
nextFloat() {
|
||||
this.m_z = (36969 * (this.m_z & 65535) + (this.m_z >>> 16)) & this.mask;
|
||||
this.m_w = (18000 * (this.m_w & 65535) + (this.m_w >>> 16)) & this.mask;
|
||||
|
||||
let result = ((this.m_z << 16) + (this.m_w & 65535)) >>> 0;
|
||||
result /= 4294967296;
|
||||
return result;
|
||||
return this.next(24) / (1 << 24);
|
||||
}
|
||||
|
||||
setSeed(seed) {
|
||||
this.seed = seed;
|
||||
this.m_w = (123456789 + seed) & this.mask;
|
||||
this.m_z = (987654321 - seed) & this.mask;
|
||||
nextDouble() {
|
||||
return Long.fromInt(this.next(26)).shiftLeft(27).add(Long.fromInt(this.next(27))).toNumber() * this.doubleUnit;
|
||||
}
|
||||
|
||||
nextInt(max = -1) {
|
||||
if (max === -1) {
|
||||
return this.next(32);
|
||||
}
|
||||
|
||||
let r = this.next(31);
|
||||
let m = max - 1;
|
||||
if ((max & m) === 0) // i.e., bound is a power of 2
|
||||
r = Long.fromInt(max).multiply(Long.fromInt(r)).shiftRightUnsigned(31).toNumber();
|
||||
else {
|
||||
for (let u = r;
|
||||
u - (r = u % max) + m < 0;
|
||||
u = this.next(31))
|
||||
;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
nextLong() {
|
||||
return Long.fromInt(this.next(32)).shiftLeft(32).add(Long.fromInt(this.next(32)));
|
||||
}
|
||||
|
||||
next(bits) {
|
||||
let oldSeed;
|
||||
let nextSeed;
|
||||
do {
|
||||
oldSeed = this.seed;
|
||||
nextSeed = oldSeed.multiply(this.multiplier).add(this.addend).and(this.mask);
|
||||
} while (!this._compareAndSet(oldSeed, nextSeed));
|
||||
return nextSeed.shiftRight(48 - bits).toNumber();
|
||||
}
|
||||
|
||||
_compareAndSet(expect, update) {
|
||||
if (!this.seed.equals(expect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.seed = update;
|
||||
return true;
|
||||
}
|
||||
|
||||
setSeed(n) {
|
||||
let long;
|
||||
|
||||
if (typeof n === "number") {
|
||||
long = Long.fromInt(n);
|
||||
} else if (n instanceof Long) {
|
||||
long = n;
|
||||
} else {
|
||||
long = Long.fromString(n);
|
||||
}
|
||||
|
||||
this.seed = long.xor(this.multiplier).and(this.mask);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import Minecraft from './js/net/minecraft/client/Minecraft.js';
|
||||
|
||||
let resources = [];
|
||||
|
||||
// Script loader
|
||||
function loadScripts(scripts) {
|
||||
let total = scripts.length;
|
||||
let index = 0;
|
||||
|
||||
return scripts.reduce((currentPromise, scriptUrl) => {
|
||||
return currentPromise.then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Update status message
|
||||
updatePreStatus("Loading scripts... " + index + "/" + total);
|
||||
|
||||
// Load script
|
||||
let script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = scriptUrl;
|
||||
script.onload = () => resolve();
|
||||
document.getElementsByTagName('head')[0].appendChild(script);
|
||||
|
||||
index++;
|
||||
});
|
||||
});
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
// Texture loader
|
||||
function loadTexture(textures) {
|
||||
let total = textures.length;
|
||||
let index = 0;
|
||||
|
||||
return textures.reduce((currentPromise, texturePath) => {
|
||||
return currentPromise.then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Update status message
|
||||
updatePreStatus("Loading texture... " + index + "/" + total);
|
||||
|
||||
// Load texture
|
||||
let image = new Image();
|
||||
image.src = "src/resources/" + texturePath;
|
||||
image.onload = () => resolve();
|
||||
resources[texturePath] = image;
|
||||
|
||||
index++;
|
||||
});
|
||||
});
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
|
||||
function updatePreStatus(message) {
|
||||
document.getElementById("pre-status").innerText = message;
|
||||
}
|
||||
|
||||
// Load textures
|
||||
loadTexture([
|
||||
"misc/grasscolor.png",
|
||||
"gui/font.png",
|
||||
"gui/gui.png",
|
||||
"gui/background.png",
|
||||
"gui/icons.png",
|
||||
"terrain/terrain.png",
|
||||
"terrain/sun.png",
|
||||
"terrain/moon.png",
|
||||
"char.png"
|
||||
]).then(() => {
|
||||
// Load scripts
|
||||
loadScripts([
|
||||
// Dependencies
|
||||
"libraries/three.min.js",
|
||||
"libraries/stats.min.js",
|
||||
"libraries/context-filter-polyfill.min.js"
|
||||
]).then(() => {
|
||||
// Remove pre status
|
||||
document.getElementById("pre-status").remove();
|
||||
|
||||
// Start Minecraft
|
||||
window.app = new Minecraft("canvas-container", resources);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user