Files
GameStarter/src/js/net/minecraft/client/Minecraft.js
T
2022-02-13 04:17:03 +01:00

248 lines
6.9 KiB
JavaScript

window.Minecraft = class {
/**
* Create Minecraft instance and render it on a canvas
*/
constructor(canvasWrapperId) {
this.currentScreen = null;
this.loadingScreen = null;
this.fps = 0;
// Tick timer
this.timer = new Timer(20);
this.settings = new GameSettings();
this.settings.load();
// Create window and world renderer
this.window = new GameWindow(this, canvasWrapperId);
// Create renderers
this.worldRenderer = new WorldRenderer(this, this.window);
this.screenRenderer = new ScreenRenderer(this, this.window);
this.itemRenderer = new ItemRenderer(this, this.window);
// Create current screen and overlay
this.ingameOverlay = new IngameOverlay(this, this.window);
// Display loading screen
this.loadingScreen = new GuiLoadingScreen();
this.loadingScreen.setTitle("Building terrain...");
this.frames = 0;
this.lastTime = Date.now();
// Create all blocks
Block.create();
this.itemRenderer.initialize();
// Update window size
this.window.updateWindowSize();
// Create world
this.world = new World(this);
this.worldRenderer.scene.add(this.world.group);
// Create player
this.player = new Player(this, this.world);
this.inventory = new Inventory();
this.displayScreen(this.loadingScreen);
// Initialize
this.init();
}
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();
}
hasInGameFocus() {
return this.window.mouseLocked && this.currentScreen === null;
}
requestNextFrame() {
let scope = this;
requestAnimationFrame(function () {
if (scope.running) {
scope.requestNextFrame();
scope.onLoop();
}
});
}
onLoop() {
this.window.statsFps.begin();
this.window.statsMs.begin();
// Update the timer
this.timer.advanceTime();
// Call the tick to reach updates 20 per seconds
for (let i = 0; i < this.timer.ticks; i++) {
this.onTick();
}
// Render the game
this.onRender(this.timer.partialTicks);
// Increase rendered frame
this.frames++;
// Loop if a second passed
while (Date.now() >= this.lastTime + 1000) {
this.fps = this.frames;
this.lastTime += 1000;
this.frames = 0;
}
this.window.statsFps.end();
this.window.statsMs.end();
}
onRender(partialTicks) {
// Player rotation
if (!this.isPaused()) {
this.player.turn(this.window.mouseMotionX, this.window.mouseMotionY);
this.window.mouseMotionX = 0;
this.window.mouseMotionY = 0;
}
// Update lights
while (this.world.updateLights()) {
// Empty
}
// Render the game
if (this.hasInGameFocus()) {
this.worldRenderer.render(partialTicks);
}
this.screenRenderer.render(partialTicks);
this.itemRenderer.render(partialTicks);
}
displayScreen(screen) {
if (typeof screen === "undefined") {
console.log("Tried to display an undefined screen");
return;
}
// Close previous screen
if (!(this.currentScreen === null)) {
this.currentScreen.onClose();
}
// Switch screen
this.currentScreen = screen;
// Update window size
this.window.updateWindowSize();
// Initialize new screen
if (screen === null) {
this.window.requestFocus();
} else {
this.window.exitFocus();
screen.setup(this, this.window.width, this.window.height);
}
}
onTick() {
if (!this.isPaused()) {
// Tick world
this.world.onTick();
// Tick the player
this.player.onTick();
}
// Update loading progress
if (!(this.loadingScreen === null)) {
let progress = Math.max(0, 1 - this.world.lightUpdateQueue.length / 10000);
this.loadingScreen.setProgress(progress);
// Finish loading
if (progress >= 1) {
this.loadingScreen = null;
this.displayScreen(null);
}
}
}
onKeyPressed(button) {
for (let i = 1; i <= 9; i++) {
if (button === 'Digit' + i) {
this.inventory.selectedSlotIndex = i - 1;
}
}
}
onMouseClicked(button) {
if (this.window.mouseLocked) {
let hitResult = this.player.rayTrace(5, this.timer.partialTicks);
// Destroy block
if (button === 0) {
if (hitResult != null) {
this.world.setBlockAt(hitResult.x, hitResult.y, hitResult.z, 0);
}
}
// Pick block
if (button === 1) {
if (hitResult != null) {
let typeId = this.world.getBlockAt(hitResult.x, hitResult.y, hitResult.z);
if (typeId !== 0) {
this.inventory.setItemInSelectedSlot(typeId);
}
}
}
// Place block
if (button === 2) {
if (hitResult != null) {
let x = hitResult.x + hitResult.face.x;
let y = hitResult.y + hitResult.face.y;
let z = hitResult.z + hitResult.face.z;
let placedBoundingBox = new BoundingBox(x, y, z, x + 1, y + 1, z + 1);
// Don't place blocks if the player is standing there
if (!placedBoundingBox.intersects(this.player.boundingBox)) {
let typeId = this.inventory.getItemInSelectedSlot();
if (typeId !== 0) {
// Place block
this.world.setBlockAt(x, y, z, typeId);
// Handle block abilities
let block = Block.getById(typeId);
block.onBlockPlaced(this.world, x, y, z, hitResult.face);
}
}
}
}
}
}
onMouseScroll(delta) {
this.inventory.shiftSelectedSlot(delta);
}
isPaused() {
return !this.hasInGameFocus() && this.loadingScreen === null;
}
}