Flywheel/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java

205 lines
5.7 KiB
Java
Raw Normal View History

package com.jozufozu.flywheel.vanilla;
2021-07-13 00:02:08 +02:00
import java.util.Calendar;
import javax.annotation.Nonnull;
2021-12-10 00:27:56 +01:00
import com.jozufozu.flywheel.api.instance.IDynamicInstance;
import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance;
2021-12-10 00:27:56 +01:00
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
import com.jozufozu.flywheel.core.model.ModelPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.resources.model.Material;
import net.minecraft.world.level.block.AbstractChestBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.DoubleBlockCombiner;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.entity.LidBlockEntity;
import net.minecraft.world.level.block.state.properties.ChestType;
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends TileEntityInstance<T> implements IDynamicInstance {
private final OrientedData body;
private final ModelData lid;
private final Float2FloatFunction lidProgress;
private final Material renderMaterial;
@Nonnull
private final ChestType chestType;
private final Quaternion baseRotation;
private float lastProgress = Float.NaN;
public ChestInstance(MaterialManager materialManager, T tile) {
super(materialManager, tile);
Block block = blockState.getBlock();
2021-07-15 20:36:24 +02:00
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
renderMaterial = Sheets.chooseMaterial(tile, chestType, isChristmas());
body = baseInstance()
.setPosition(getInstancePosition());
lid = lidInstance();
2021-12-08 21:48:18 +01:00
if (block instanceof AbstractChestBlock<?> chestBlock) {
2021-07-15 20:36:24 +02:00
float horizontalAngle = blockState.getValue(ChestBlock.FACING).toYRot();
2021-07-15 20:36:24 +02:00
baseRotation = Vector3f.YP.rotationDegrees(-horizontalAngle);
body.setRotation(baseRotation);
DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, world, getWorldPosition(), true);
2021-07-15 20:36:24 +02:00
this.lidProgress = wrapper.apply(ChestBlock.opennessCombiner(tile));
} else {
2021-07-15 20:36:24 +02:00
baseRotation = Quaternion.ONE;
lidProgress = $ -> 0f;
}
}
@Override
public void beginFrame() {
float progress = lidProgress.get(AnimationTickHolder.getPartialTicks());
if (lastProgress == progress) return;
lastProgress = progress;
progress = 1.0F - progress;
progress = 1.0F - progress * progress * progress;
float angleX = -(progress * ((float) Math.PI / 2F));
lid.loadIdentity()
.translate(getInstancePosition())
.translate(0, 9f/16f, 0)
.centre()
.multiply(baseRotation)
.unCentre()
.translate(0, 0, 1f / 16f)
2021-07-15 20:36:24 +02:00
.multiply(Vector3f.XP.rotation(angleX))
.translate(0, 0, -1f / 16f);
}
@Override
public void updateLight() {
relight(getWorldPosition(), body, lid);
}
@Override
public void remove() {
body.delete();
lid.delete();
}
private OrientedData baseInstance() {
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.ORIENTED)
.model("base_" + renderMaterial.texture(), this::getBaseModel)
.createInstance();
}
private ModelData lidInstance() {
return materialManager.solid(RenderType.entitySolid(renderMaterial.atlasLocation()))
.material(Materials.TRANSFORMED)
.model("lid_" + renderMaterial.texture(), this::getLidModel)
.createInstance();
}
private ModelPart getBaseModel() {
return switch (chestType) {
case LEFT -> ModelPart.builder("chest_base_left", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 19)
.start(0, 0, 1)
.size(15, 10, 14)
.endCuboid()
.build();
case RIGHT -> ModelPart.builder("chest_base_right", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
.size(15, 10, 14)
.endCuboid()
.build();
default -> ModelPart.builder("chest_base", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 19)
.start(1, 0, 1)
.end(15, 10, 15)
.endCuboid()
.build();
};
}
private ModelPart getLidModel() {
return switch (chestType) {
case LEFT -> ModelPart.builder("chest_lid_left", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 0)
.start(0, 0, 1)
.size(15, 5, 14)
.endCuboid()
.cuboid()
.start(0, -2, 15)
.size(1, 4, 1)
.endCuboid()
.build();
case RIGHT -> ModelPart.builder("chest_lid_right", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)
.size(15, 5, 14)
.endCuboid()
.cuboid()
.start(15, -2, 15)
.size(1, 4, 1)
.endCuboid()
.build();
default -> ModelPart.builder("chest_lid", 64, 64)
.sprite(renderMaterial.sprite())
.cuboid()
.textureOffset(0, 0)
.start(1, 0, 1)
.size(14, 5, 14)
.endCuboid()
.cuboid()
.start(7, -2, 15)
.size(2, 4, 1)
.endCuboid()
.build();
};
}
public static boolean isChristmas() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DATE) >= 24 && calendar.get(Calendar.DATE) <= 26;
}
}