Skip to content

Commit

Permalink
feat: Begin printer fancy rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
BlayTheNinth committed Dec 31, 2023
1 parent 83e0533 commit 1fc6913
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@

public class ForbiddenSmoothies {

// TODO fancy in-world rendering
// TODO fancy in-world rendering for printer
// TODO better textures for the models
// TODO Slightly different blender UI?
// TODO JEI/REI support

public static final String MOD_ID = "forbiddensmoothies";
public static final Logger logger = LogManager.getLogger(MOD_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
Expand All @@ -26,6 +27,9 @@
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;

public class PrinterBlock extends BaseEntityBlock {
Expand Down Expand Up @@ -111,4 +115,19 @@ public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, Block
(level, pos, state2, blockEntity) -> blockEntity.serverTick());
}


@Override
public VoxelShape getVisualShape(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext) {
return Shapes.empty();
}

@Override
public float getShadeBrightness(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos) {
return 1F;
}

@Override
public boolean propagatesSkylightDown(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos) {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.blay09.mods.forbiddensmoothies.ForbiddenSmoothiesConfig;
import net.blay09.mods.forbiddensmoothies.crafting.BlenderRecipe;
import net.blay09.mods.forbiddensmoothies.crafting.ModRecipes;
import net.blay09.mods.forbiddensmoothies.crafting.PrinterRecipe;
import net.blay09.mods.forbiddensmoothies.menu.BlenderMenu;
import net.blay09.mods.forbiddensmoothies.menu.ModMenus;
import net.minecraft.core.BlockPos;
Expand All @@ -36,7 +37,7 @@

public class BlenderBlockEntity extends BalmBlockEntity implements BalmMenuProvider, BalmContainerProvider, BalmEnergyStorageProvider {

private static final int SYNC_INTERVAL = 20;
private static final int SYNC_INTERVAL = 10;

public static final int DATA_PROGRESS = 0;
public static final int DATA_MAX_PROGRESS = 1;
Expand Down Expand Up @@ -100,8 +101,12 @@ public void setEnergy(int energy) {
private int progress;
private int maxProgress;
private int energyCostPerTick;

private BlenderRecipe currentRecipe;

private boolean dirtyForSync;
private int ticksSinceLastSync;

private float animationTicks;
private float animationEndingTicks;

Expand Down Expand Up @@ -192,7 +197,7 @@ public Container getContainer(Direction side) {
}

public void serverTick() {
if (ticksSinceLastSync >= 10 && dirtyForSync) {
if (ticksSinceLastSync >= SYNC_INTERVAL && dirtyForSync) {
sync();
dirtyForSync = false;
ticksSinceLastSync = 0;
Expand All @@ -202,21 +207,23 @@ public void serverTick() {

transferOutputs();

final var recipe = selectRecipe(randomSource).orElse(null);
maxProgress = getTotalProcessingTicks();
currentRecipe = selectRecipe(randomSource, this.currentRecipe).orElse(null);

final var lastEnergyCostPerTick = energyCostPerTick;
energyCostPerTick = recipe != null ? determineEnergyCostPerTick() : 0;
energyCostPerTick = currentRecipe != null ? determineEnergyCostPerTick() : 0;
if (lastEnergyCostPerTick != energyCostPerTick) {
dirtyForSync = true;
}
if (recipe != null && canFitRecipeResults(recipe) && energyStorage.drain(energyCostPerTick, true) >= energyCostPerTick) {

if (currentRecipe != null && canFitRecipeResults(currentRecipe) && energyStorage.drain(energyCostPerTick, true) >= energyCostPerTick) {
progress++;
energyStorage.drain(energyCostPerTick, false);

if (progress >= maxProgress) {
progress = 0;
final var output = recipe.assemble(recipeInputContainer, RegistryAccess.EMPTY);
for (final var ingredient : recipe.getIngredients()) {
final var output = currentRecipe.assemble(recipeInputContainer, level.registryAccess());
for (final var ingredient : currentRecipe.getIngredients()) {
for (int i = 0; i < recipeInputContainer.getContainerSize(); i++) {
final var slotStack = recipeInputContainer.getItem(i);
if (ingredient.test(slotStack)) {
Expand All @@ -226,6 +233,7 @@ public void serverTick() {
}
}
ContainerUtils.insertItemStacked(outputContainer, output, false);
currentRecipe = null;
}
} else {
progress = 0;
Expand Down Expand Up @@ -270,11 +278,15 @@ private boolean canFitRecipeResults(BlenderRecipe recipe) {
return rest.isEmpty();
}

private Optional<BlenderRecipe> selectRecipe(RandomSource random) {
private Optional<BlenderRecipe> selectRecipe(RandomSource random, @Nullable BlenderRecipe currentRecipe) {
if (level == null) {
return Optional.empty();
}

if (currentRecipe != null && currentRecipe.matches(recipeInputContainer, level)) {
return Optional.of(currentRecipe);
}

final var availableRecipes = level.getRecipeManager().getRecipesFor(ModRecipes.blenderRecipeType, recipeInputContainer, level);
return WeightedRandom.getRandomItem(random, availableRecipes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import net.blay09.mods.forbiddensmoothies.menu.PrinterMenu;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
Expand All @@ -36,6 +35,8 @@

public class PrinterBlockEntity extends BalmBlockEntity implements BalmMenuProvider, BalmContainerProvider, BalmEnergyStorageProvider {

private static final int SYNC_INTERVAL = 10;

public static final int DATA_PROGRESS = 0;
public static final int DATA_MAX_PROGRESS = 1;
public static final int DATA_LOCKED_INPUTS = 2;
Expand Down Expand Up @@ -99,6 +100,12 @@ public void setEnergy(int energy) {
private int maxProgress;
private int energyCostPerTick;

private boolean dirtyForSync;
private int ticksSinceLastSync;

private PrinterRecipe currentRecipe;
private ItemStack currentResultItem = ItemStack.EMPTY;

protected final ContainerData dataAccess = new ContainerData() {
public int get(int i) {
return switch (i) {
Expand Down Expand Up @@ -150,10 +157,16 @@ public void load(CompoundTag tag) {
super.load(tag);

container.deserialize(tag.getCompound("Items"));
energyStorage.deserialize(tag.get("Energy"));
if (tag.contains("Energy")) {
energyStorage.deserialize(tag.get("Energy"));
}
progress = tag.getInt("Progress");
maxProgress = tag.getInt("MaxProgress");
lockedInputs = tag.getBoolean("LockedInputs");

if (tag.contains("CurrentResultItem")) {
currentResultItem = ItemStack.of(tag.getCompound("CurrentResultItem"));
}
}

protected void saveAdditional(CompoundTag tag) {
Expand All @@ -165,6 +178,11 @@ protected void saveAdditional(CompoundTag tag) {
tag.putBoolean("LockedInputs", this.lockedInputs);
}

@Override
protected void writeUpdateTag(CompoundTag tag) {
tag.put("CurrentResultItem", currentResultItem.save(new CompoundTag()));
}

@Override
public Container getContainer() {
return container;
Expand All @@ -176,16 +194,38 @@ public Container getContainer(Direction side) {
}

public void serverTick() {
final var recipe = selectRecipe(randomSource).orElse(null);
if (ticksSinceLastSync >= SYNC_INTERVAL && dirtyForSync) {
sync();
dirtyForSync = false;
ticksSinceLastSync = 0;
} else {
ticksSinceLastSync++;
}

maxProgress = getTotalProcessingTicks();

final var lastRecipe = currentRecipe;
final var recipe = selectRecipe(randomSource, currentRecipe).orElse(null);
if (lastRecipe != recipe) {
dirtyForSync = true;
}

currentRecipe = recipe;
currentResultItem = recipe != null ? recipe.getResultItem(level.registryAccess()) : ItemStack.EMPTY;

final var lastEnergyCostPerTick = energyCostPerTick;
energyCostPerTick = recipe != null ? determineEnergyCostPerTick() : 0;
if (lastEnergyCostPerTick != energyCostPerTick) {
dirtyForSync = true;
}

if (recipe != null && canFitRecipeResults(recipe) && energyStorage.drain(energyCostPerTick, true) >= energyCostPerTick) {
progress++;
energyStorage.drain(energyCostPerTick, false);

if (progress >= maxProgress) {
progress = 0;
final var output = recipe.assemble(recipeInputContainer, RegistryAccess.EMPTY);
final var output = recipe.assemble(recipeInputContainer, level.registryAccess());
for (final var ingredient : recipe.getIngredients()) {
for (int i = 0; i < recipeInputContainer.getContainerSize(); i++) {
final var slotStack = recipeInputContainer.getItem(i);
Expand All @@ -196,6 +236,8 @@ public void serverTick() {
}
}
ContainerUtils.insertItemStacked(outputContainer, output, false);
currentRecipe = null;
currentResultItem = ItemStack.EMPTY;
}
} else {
progress = 0;
Expand All @@ -220,11 +262,15 @@ private boolean canFitRecipeResults(PrinterRecipe recipe) {
return rest.isEmpty();
}

private Optional<PrinterRecipe> selectRecipe(RandomSource random) {
private Optional<PrinterRecipe> selectRecipe(RandomSource random, @Nullable PrinterRecipe currentRecipe) {
if (level == null) {
return Optional.empty();
}

if (currentRecipe != null && currentRecipe.matches(recipeInputContainer, level)) {
return Optional.of(currentRecipe);
}

final var availableRecipes = level.getRecipeManager().getRecipesFor(ModRecipes.printerRecipeType, recipeInputContainer, level);
return WeightedRandom.getRandomItem(random, availableRecipes);
}
Expand All @@ -237,4 +283,14 @@ public EnergyStorage getEnergyStorage() {
public Container getInputContainer() {
return inputContainer;
}

public ItemStack getCurrentResultItem() {
return currentResultItem;
}

@Override
public void setChanged() {
super.setChanged();
dirtyForSync = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@

public class ModModels {
public static DeferredObject<BakedModel> blenderBlade;
public static DeferredObject<BakedModel> printerEasel;
public static DeferredObject<BakedModel> printerEaselPanel;

public static void initialize(BalmModels models) {
blenderBlade = models.loadModel(id("block/blender_blade"));
printerEasel = models.loadModel(id("block/printer_easel"));
printerEaselPanel = models.loadModel(id("block/printer_easel_panel"));
}

private static ResourceLocation id(String path) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,68 @@
package net.blay09.mods.forbiddensmoothies.client.render;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.blay09.mods.forbiddensmoothies.block.CustomBlockStateProperties;
import net.blay09.mods.forbiddensmoothies.block.entity.PrinterBlockEntity;
import net.blay09.mods.forbiddensmoothies.client.ModModels;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemDisplayContext;
import org.joml.AxisAngle4f;
import org.joml.Quaternionf;

public class PrinterRenderer implements BlockEntityRenderer<PrinterBlockEntity> {

private static final RandomSource random = RandomSource.create();

public PrinterRenderer(BlockEntityRendererProvider.Context context) {
}

@Override
public void render(PrinterBlockEntity blockEntity, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) {
public void render(PrinterBlockEntity blockEntity, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int combinedLight, int combinedOverlayIn) {
final var level = blockEntity.getLevel();
if (level == null) {
return;
}

final var state = blockEntity.getBlockState();
if (state.hasProperty(CustomBlockStateProperties.UGLY) && state.getValue(CustomBlockStateProperties.UGLY)) {
return;
}

final var dispatcher = Minecraft.getInstance().getBlockRenderer();
poseStack.pushPose();
poseStack.translate(-0.05f, 0f, 0.1f);
dispatcher.getModelRenderer()
.tesselateBlock(level,
ModModels.printerEasel.get(),
blockEntity.getBlockState(),
blockEntity.getBlockPos(),
poseStack,
buffer.getBuffer(RenderType.solid()),
false,
random,
0,
0);
poseStack.popPose();

final var itemStack = blockEntity.getCurrentResultItem();
poseStack.pushPose();
poseStack.translate(0.5f, 0f, 0.5f);
final var itemScale = 0.3f;
poseStack.translate(-0.08f, 0.425f, 0.115f);
poseStack.mulPose(new Quaternionf(new AxisAngle4f((float) Math.toRadians(22.5f), 1f, 0f, 0f)));
poseStack.scale(itemScale, itemScale, 0.1f);
final var itemRenderer = Minecraft.getInstance().getItemRenderer();
final var model = itemRenderer.getModel(itemStack, level, null, combinedLight);
RenderSystem.enableBlend();
itemRenderer.render(itemStack, ItemDisplayContext.FIXED, false, poseStack, buffer, LightTexture.FULL_BLOCK, combinedOverlayIn, model);
poseStack.popPose();
}

}
Loading

0 comments on commit 1fc6913

Please sign in to comment.