From 5c47dd65993bdf7ee73e8492c14b465c0f942884 Mon Sep 17 00:00:00 2001 From: LabyStudio Date: Thu, 14 Apr 2022 20:50:18 +0200 Subject: [PATCH] implement block in hand (cherry picked from commit 75fd4edd9f67b2cbf5abffc1ea417920106b1353) --- src/js/net/minecraft/client/Minecraft.js | 9 ++- .../minecraft/client/entity/EntityLiving.js | 46 ++++++---------- .../minecraft/client/entity/PlayerEntity.js | 9 ++- .../net/minecraft/client/gui/IngameOverlay.js | 4 +- .../minecraft/client/render/BlockRenderer.js | 55 ++++++++++++++----- .../minecraft/client/render/WorldRenderer.js | 6 +- .../render/entity/EntityRenderManager.js | 6 +- .../client/render/entity/EntityRenderer.js | 38 ++++++++++--- .../render/entity/entity/PlayerRenderer.js | 21 ++++++- .../client/render/model/model/ModelPlayer.js | 11 ++++ .../render/model/renderer/ModelRenderer.js | 2 + .../net/minecraft/util/MetadataChunkBlock.js | 2 +- src/js/net/minecraft/util/Random.js | 4 +- 13 files changed, 145 insertions(+), 68 deletions(-) diff --git a/src/js/net/minecraft/client/Minecraft.js b/src/js/net/minecraft/client/Minecraft.js index 0d89ee5..69769ae 100644 --- a/src/js/net/minecraft/client/Minecraft.js +++ b/src/js/net/minecraft/client/Minecraft.js @@ -51,7 +51,6 @@ window.Minecraft = class { // Create player this.player = new PlayerEntity(this, this.world); this.world.addEntity(this.player); - this.inventory = new Inventory(); this.displayScreen(this.loadingScreen); @@ -192,7 +191,7 @@ window.Minecraft = class { onKeyPressed(button) { for (let i = 1; i <= 9; i++) { if (button === 'Digit' + i) { - this.inventory.selectedSlotIndex = i - 1; + this.player.inventory.selectedSlotIndex = i - 1; } } @@ -238,7 +237,7 @@ window.Minecraft = class { if (hitResult != null) { let typeId = this.world.getBlockAt(hitResult.x, hitResult.y, hitResult.z); if (typeId !== 0) { - this.inventory.setItemInSelectedSlot(typeId); + this.player.inventory.setItemInSelectedSlot(typeId); } } } @@ -254,7 +253,7 @@ window.Minecraft = class { // Don't place blocks if the player is standing there if (!placedBoundingBox.intersects(this.player.boundingBox)) { - let typeId = this.inventory.getItemInSelectedSlot(); + let typeId = this.player.inventory.getItemInSelectedSlot(); // Get previous block let prevTypeId = this.world.getBlockAt(x, y, z); @@ -286,7 +285,7 @@ window.Minecraft = class { } onMouseScroll(delta) { - this.inventory.shiftSelectedSlot(delta); + this.player.inventory.shiftSelectedSlot(delta); } isPaused() { diff --git a/src/js/net/minecraft/client/entity/EntityLiving.js b/src/js/net/minecraft/client/entity/EntityLiving.js index e889abb..20b3114 100644 --- a/src/js/net/minecraft/client/entity/EntityLiving.js +++ b/src/js/net/minecraft/client/entity/EntityLiving.js @@ -13,7 +13,7 @@ window.EntityLiving = class extends Entity { this.swingProgress = 0; this.prevSwingProgress = 0; this.swingProgressInt = 0; - this.swingInProgress = false; + this.isSwingInProgress = false; this.renderYawOffset = 0; this.rotationYawHead = 0; @@ -29,26 +29,7 @@ window.EntityLiving = class extends Entity { onUpdate() { super.onUpdate(); this.onLivingUpdate(); - - let motionX = this.x - this.prevX; - let motionZ = this.z - this.prevZ; - - let bodyRotation = this.renderYawOffset; - - let distanceTravelled = motionX * motionX + motionZ * motionZ; - let distanceTravelledSqrt = 0.0; - - if (distanceTravelled > 0.0025000002) { - distanceTravelledSqrt = Math.sqrt(distanceTravelled) * 3.0; - bodyRotation = Math.atan2(motionZ, motionX) * 180.0 / Math.PI - 90.0; - } - - if (this.swingProgress > 0.0) { - bodyRotation = this.rotationYaw; - } - - // TODO handle travel distance - distanceTravelledSqrt = this.updateBodyRotation(bodyRotation, distanceTravelledSqrt); + this.updateBodyRotation(); while (this.rotationYaw - this.prevRotationYaw < -180.0) { this.prevRotationYaw -= 360.0; @@ -151,13 +132,25 @@ window.EntityLiving = class extends Entity { super.onEntityUpdate(); } - updateBodyRotation(bodyRotation, distanceTravelledSqrt) { + updateBodyRotation() { + let motionX = this.x - this.prevX; + let motionZ = this.z - this.prevZ; + + let bodyRotation = this.renderYawOffset; + + let distanceTravelled = motionX * motionX + motionZ * motionZ; + if (distanceTravelled > 0.0025000002) { + bodyRotation = Math.atan2(motionZ, motionX) * 180.0 / Math.PI - 90.0; + } + + if (this.swingProgress > 0.0) { + bodyRotation = this.rotationYaw; + } + let bodyRotationDifference = MathHelper.wrapAngleTo180(bodyRotation - this.renderYawOffset); this.renderYawOffset += bodyRotationDifference * 0.3; let yaw = MathHelper.wrapAngleTo180(this.rotationYaw - this.renderYawOffset); - let turn = yaw < -90.0 || yaw >= 90.0; - if (yaw < -75.0) { yaw = -75.0; } @@ -169,10 +162,6 @@ window.EntityLiving = class extends Entity { if (yaw * yaw > 2500.0) { this.renderYawOffset += yaw * 0.2; } - if (turn) { - distanceTravelledSqrt *= -1.0; - } - return distanceTravelledSqrt; } swingArm() { @@ -185,7 +174,6 @@ window.EntityLiving = class extends Entity { updateArmSwingProgress() { let swingAnimationEnd = 6; - if (this.isSwingInProgress) { ++this.swingProgressInt; diff --git a/src/js/net/minecraft/client/entity/PlayerEntity.js b/src/js/net/minecraft/client/entity/PlayerEntity.js index 2cfb67f..7d26171 100644 --- a/src/js/net/minecraft/client/entity/PlayerEntity.js +++ b/src/js/net/minecraft/client/entity/PlayerEntity.js @@ -5,6 +5,8 @@ window.PlayerEntity = class extends EntityLiving { constructor(minecraft, world) { super(minecraft, world); + this.inventory = new Inventory(); + this.collision = false; this.jumpMovementFactor = 0.02; @@ -124,7 +126,12 @@ window.PlayerEntity = class extends EntityLiving { } isHeadInWater() { - return this.world.getBlockAt(this.getBlockPosX(), Math.floor(this.y + this.getEyeHeight() + 0.12), this.getBlockPosZ()) === Block.WATER.getId(); + let cameraPosition = this.world.minecraft.worldRenderer.camera.position; + return this.world.getBlockAt( + Math.floor(cameraPosition.x), + Math.floor(cameraPosition.y + 0.12), + Math.floor(cameraPosition.z) + ) === Block.WATER.getId() } jump() { diff --git a/src/js/net/minecraft/client/gui/IngameOverlay.js b/src/js/net/minecraft/client/gui/IngameOverlay.js index b1f2313..71bf065 100644 --- a/src/js/net/minecraft/client/gui/IngameOverlay.js +++ b/src/js/net/minecraft/client/gui/IngameOverlay.js @@ -37,13 +37,13 @@ window.IngameOverlay = class extends Gui { this.textureHotbar, 0, 22, 24, 24, - x + this.minecraft.inventory.selectedSlotIndex * 20 - 1, y - 1, + x + this.minecraft.player.inventory.selectedSlotIndex * 20 - 1, y - 1, 24, 24 ) // Render items for (let i = 0; i < 9; i++) { - let typeId = this.minecraft.inventory.getItemInSlot(i); + let typeId = this.minecraft.player.inventory.getItemInSlot(i); if (typeId !== 0) { let renderId = "hotbar" + i; let block = Block.getById(typeId); diff --git a/src/js/net/minecraft/client/render/BlockRenderer.js b/src/js/net/minecraft/client/render/BlockRenderer.js index 1e52b4c..97246ec 100644 --- a/src/js/net/minecraft/client/render/BlockRenderer.js +++ b/src/js/net/minecraft/client/render/BlockRenderer.js @@ -165,19 +165,21 @@ window.BlockRenderer = class { let distortZ = 0; // Attach torch at wall - switch (world.getBlockDataAt(x, y, z)) { - case 1: - distortX = -0.2; - break; - case 2: - distortX = 0.2; - break; - case 3: - distortZ = -0.2; - break; - case 4: - distortZ = 0.2; - break; + if (world != null) { + switch (world.getBlockDataAt(x, y, z)) { + case 1: + distortX = -0.2; + break; + case 2: + distortX = 0.2; + break; + case 3: + distortZ = -0.2; + break; + case 4: + distortZ = 0.2; + break; + } } // Model type @@ -252,6 +254,33 @@ window.BlockRenderer = class { } } + renderBlockInHand(group, block, brightness) { + this.tessellator.startDrawing(); + + // Change brightness + this.tessellator.transformBrightness(brightness); + + // Render block + this.renderBlock(null, block, 0, 0, 0); + + // Create mesh + let mesh = this.tessellator.draw(group); + mesh.geometry.center(); + + // Relative position + mesh.position.x = 0; + mesh.position.y = 9; + mesh.position.z = -5; + + // Rotation + mesh.rotation.y = Math.PI / 4; + + // Scale + mesh.scale.x = 6; + mesh.scale.y = -6; + mesh.scale.z = 6; + } + renderGuiBlock(group, block, x, y, size, brightness) { this.tessellator.startDrawing(); diff --git a/src/js/net/minecraft/client/render/WorldRenderer.js b/src/js/net/minecraft/client/render/WorldRenderer.js index e46c580..96ae66b 100644 --- a/src/js/net/minecraft/client/render/WorldRenderer.js +++ b/src/js/net/minecraft/client/render/WorldRenderer.js @@ -27,7 +27,7 @@ window.WorldRenderer = class { this.blockRenderer = new BlockRenderer(this); // Entity render manager - this.entityRenderManager = new EntityRenderManager(); + this.entityRenderManager = new EntityRenderManager(this); this.initialize(); } @@ -92,8 +92,8 @@ window.WorldRenderer = class { // Render entities for (let entity of this.minecraft.world.entities) { if (entity === player && this.minecraft.settings.thirdPersonView === 0) { - entity.group.clear(); - entity.lastRenderedBrightness = -1; // TODO: Find a better way to trigger this + entity.group.clear(); // Remove entity from scene + delete entity.group.buildMeta; // To trigger a rebuild on the next render continue; } this.renderEntity(entity, partialTicks); diff --git a/src/js/net/minecraft/client/render/entity/EntityRenderManager.js b/src/js/net/minecraft/client/render/entity/EntityRenderManager.js index d0f2640..5116008 100644 --- a/src/js/net/minecraft/client/render/entity/EntityRenderManager.js +++ b/src/js/net/minecraft/client/render/entity/EntityRenderManager.js @@ -1,8 +1,10 @@ window.EntityRenderManager = class { - constructor() { + constructor(worldRenderer) { + this.worldRenderer = worldRenderer; + this.renderers = []; - this.push(PlayerEntity, new PlayerRenderer()); + this.push(PlayerEntity, new PlayerRenderer(worldRenderer)); } push(entityType, entityRenderer) { diff --git a/src/js/net/minecraft/client/render/entity/EntityRenderer.js b/src/js/net/minecraft/client/render/entity/EntityRenderer.js index dd0c3b7..867f9a9 100644 --- a/src/js/net/minecraft/client/render/entity/EntityRenderer.js +++ b/src/js/net/minecraft/client/render/entity/EntityRenderer.js @@ -6,19 +6,41 @@ window.EntityRenderer = class { } rebuild(entity) { - let brightness = entity.getEntityBrightness(); - entity.lastRenderedBrightness = brightness; + // Create meta for group + let group = entity.group; + let meta = {}; + this.fillMeta(entity, meta); + group.buildMeta = meta; - // Apply brightness + // Clear meshes + group.clear(); + + // Apply brightness and rebuild + let brightness = group.buildMeta.brightness; this.tessellator.setColor(brightness, brightness, brightness); + this.model.rebuild(this.tessellator, group); + } - // Rebuild - this.model.rebuild(this.tessellator, entity.group); + fillMeta(entity, meta) { + meta.brightness = entity.getEntityBrightness(); + meta.itemInHand = entity.inventory.getItemInSelectedSlot(); + } + + isRebuildRequired(entity) { + let group = entity.group; + if (typeof group.buildMeta === "undefined") { + return true; + } + + // Compare meta of group + let currentMeta = {}; + this.fillMeta(entity, currentMeta); + let previousMeta = group.buildMeta; + return JSON.stringify(currentMeta) !== JSON.stringify(previousMeta); } render(entity, partialTicks) { - let brightness = entity.getEntityBrightness(); - if (entity.lastRenderedBrightness !== brightness) { + if (this.isRebuildRequired(entity)) { this.rebuild(entity); } @@ -45,7 +67,7 @@ window.EntityRenderer = class { // Actual size of the entity let scale = 7.0 / 120.0; - group.scale.set(-scale,- scale, scale); + group.scale.set(-scale, -scale, scale); // Rotate entity model group.rotation.y = MathHelper.toRadians(-rotationBody + 180); diff --git a/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js b/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js index 087ff25..4b3c861 100644 --- a/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js +++ b/src/js/net/minecraft/client/render/entity/entity/PlayerRenderer.js @@ -1,21 +1,36 @@ window.PlayerRenderer = class extends EntityRenderer { - constructor() { + constructor(worldRenderer) { super(new ModelPlayer()); + this.worldRenderer = worldRenderer; + // Load character texture this.textureCharacter = new THREE.TextureLoader().load('src/resources/char.png'); this.textureCharacter.magFilter = THREE.NearestFilter; this.textureCharacter.minFilter = THREE.NearestFilter; } - rebuild(tessellator, entity) { + rebuild(entity) { this.tessellator.bindTexture(this.textureCharacter); - super.rebuild(tessellator, entity); + super.rebuild(entity); + + // Render item in hand + let group = this.model.rightArm.bone; + let id = entity.inventory.getItemInSelectedSlot(); + if (id !== 0) { + let block = Block.getById(id); + this.worldRenderer.blockRenderer.renderBlockInHand(group, block, 1); + } } render(entity, partialTicks) { super.render(entity, partialTicks); } + fillMeta(entity, meta) { + super.fillMeta(entity, meta); + meta.itemInHand = entity.inventory.getItemInSelectedSlot(); + } + } \ No newline at end of file diff --git a/src/js/net/minecraft/client/render/model/model/ModelPlayer.js b/src/js/net/minecraft/client/render/model/model/ModelPlayer.js index 7bae055..df82733 100644 --- a/src/js/net/minecraft/client/render/model/model/ModelPlayer.js +++ b/src/js/net/minecraft/client/render/model/model/ModelPlayer.js @@ -58,8 +58,11 @@ window.ModelPlayer = class extends ModelBase { render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch, partialTicks) { let group = entity.group; + // Head rotation this.head.rotateAngleY = MathHelper.toRadians(yaw); this.head.rotateAngleX = MathHelper.toRadians(pitch); + + // Limb swing leg animation this.rightArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662 + Math.PI) * 2.0 * limbSwing * 0.5; this.leftArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662) * 2.0 * limbSwing * 0.5; this.rightArm.rotateAngleZ = 0.0; @@ -69,10 +72,16 @@ window.ModelPlayer = class extends ModelBase { this.rightLeg.rotateAngleY = 0.0; this.leftLeg.rotateAngleY = 0.0; + // Reset arms for swing progress this.rightArm.rotateAngleY = 0.0; this.rightArm.rotateAngleZ = 0.0; this.leftArm.rotateAngleY = 0.0; + // Held item animation + if (entity.inventory.getItemInSelectedSlot() !== 0) { + this.rightArm.rotateAngleX = this.rightArm.rotateAngleX * 0.5 - (Math.PI / 10); + } + // Swing progress let swingProgress = entity.swingProgress - entity.prevSwingProgress; if (swingProgress < 0.0) { @@ -106,6 +115,7 @@ window.ModelPlayer = class extends ModelBase { this.rightArm.rotateAngleZ += Math.sin(interpolatedSwingProgress * Math.PI) * -0.4; } + // Sneaking animation if (entity.sneaking) { this.body.rotateAngleX = 0.5; this.rightArm.rotateAngleX += 0.4; @@ -126,6 +136,7 @@ window.ModelPlayer = class extends ModelBase { this.head.rotationPointY = 0.0; } + // Limb swing arm animation this.rightArm.rotateAngleZ += Math.cos(timeAlive * 0.09) * 0.05 + 0.05; this.leftArm.rotateAngleZ -= Math.cos(timeAlive * 0.09) * 0.05 + 0.05; this.rightArm.rotateAngleX += Math.sin(timeAlive * 0.067) * 0.05; diff --git a/src/js/net/minecraft/client/render/model/renderer/ModelRenderer.js b/src/js/net/minecraft/client/render/model/renderer/ModelRenderer.js index 06167e5..c7699eb 100644 --- a/src/js/net/minecraft/client/render/model/renderer/ModelRenderer.js +++ b/src/js/net/minecraft/client/render/model/renderer/ModelRenderer.js @@ -136,6 +136,8 @@ window.ModelRenderer = class { } rebuild(tessellator, group) { + this.bone.clear(); + // Start drawing tessellator.startDrawing(); diff --git a/src/js/net/minecraft/util/MetadataChunkBlock.js b/src/js/net/minecraft/util/MetadataChunkBlock.js index a52af31..bb7fd99 100644 --- a/src/js/net/minecraft/util/MetadataChunkBlock.js +++ b/src/js/net/minecraft/util/MetadataChunkBlock.js @@ -33,7 +33,7 @@ window.MetadataChunkBlock = class { let newLevel = 0; let typeId = world.getBlockAt(x, y, z); let block = Block.getById(typeId); - let opacity = typeId === 0 ? 0 : block.getOpacity() * 255; + let opacity = typeId === 0 ? 0 : Math.round(block.getOpacity() * 255); if (opacity === 0) { opacity = 1; diff --git a/src/js/net/minecraft/util/Random.js b/src/js/net/minecraft/util/Random.js index 11b7c68..ca8e88d 100644 --- a/src/js/net/minecraft/util/Random.js +++ b/src/js/net/minecraft/util/Random.js @@ -1,6 +1,8 @@ window.Random = class { - constructor(seed) { + static instances = 0; + + constructor(seed = Date.now() % 1000000000 ^ Random.instances++ * 1000) { this.mask = 0xffffffff; this.m_w = (123456789 + seed) & this.mask; this.m_z = (987654321 - seed) & this.mask;