Skip to content

Commit

Permalink
Add 1.20.4 decorated pot animations for inserting items
Browse files Browse the repository at this point in the history
  • Loading branch information
FoundationGames committed May 30, 2024
1 parent e3fb4fc commit 9329310
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.BellBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.DecoratedPotBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.ShulkerBoxBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.SignBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.resource.EBEPack;
Expand Down Expand Up @@ -441,6 +442,7 @@ public static void setupShulkerBoxes() {
}

public static void setupDecoratedPots() {
EnhancedBlockEntityRegistry.register(Blocks.DECORATED_POT, BlockEntityType.DECORATED_POT, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.DECORATED_POT, BlockEntityType.DECORATED_POT,
BlockEntityRenderCondition.DECORATED_POT, new DecoratedPotBlockEntityRendererOverride());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import foundationgames.enhancedblockentities.util.DateUtil;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.ResourceUtil;
import foundationgames.enhancedblockentities.util.WorldUtil;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.item.ModelPredicateProviderRegistry;
Expand All @@ -22,6 +24,7 @@ public final class EnhancedBlockEntities implements ClientModInitializer {
@Override
public void onInitializeClient() {
WorldRenderEvents.END.register(SignRenderManager::endFrame);
ClientTickEvents.END_WORLD_TICK.register(WorldUtil.EVENT_LISTENER);

ModelIdentifiers.init();
EBESetup.setupResourceProviders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public final class ModelIdentifiers implements ModelLoadingPlugin {
public static final Identifier BELL_BODY = of("block/bell_body", BELL_PREDICATE);

public static final Identifier DECORATED_POT_BASE = of("block/decorated_pot_base", DECORATED_POT_PREDICATE);
public static final Identifier DECORATED_POT_SHAKING = of("block/decorated_pot_shaking", DECORATED_POT_PREDICATE);

public static final Map<DyeColor, Identifier> SHULKER_BOXES = new HashMap<>();
public static final Map<DyeColor, Identifier> SHULKER_BOX_BOTTOMS = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.model.ModelSelector;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.DecoratedPotPatterns;
Expand All @@ -17,10 +18,16 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

public class DecoratedPotModelSelector extends ModelSelector {
public static final int BUILTIN_MODEL_COUNT = 2;

public static final int IDX_EMPTY = 0;
public static final int IDX_BASE_POT = 1;

private final List<RegistryKey<String>> potteryPatterns;

public DecoratedPotModelSelector() {
Expand All @@ -32,10 +39,11 @@ public DecoratedPotModelSelector() {
public Identifier[] createModelIDs() {
ModelIdentifiers.refreshPotteryPatterns();

var ids = new Identifier[1 + potteryPatterns.size() * 4];
ids[0] = ModelIdentifiers.DECORATED_POT_BASE;
var ids = new Identifier[BUILTIN_MODEL_COUNT + potteryPatterns.size() * 4];
ids[IDX_EMPTY] = ModelIdentifiers.DECORATED_POT_SHAKING;
ids[IDX_BASE_POT] = ModelIdentifiers.DECORATED_POT_BASE;

int idIndex = 1;
int idIndex = BUILTIN_MODEL_COUNT;
for (int dirIndex = 0; dirIndex < 4; dirIndex++) {
for (var pattern : this.potteryPatterns) {
ids[idIndex] = ModelIdentifiers.POTTERY_PATTERNS.get(pattern)[dirIndex];
Expand All @@ -51,20 +59,25 @@ public Identifier[] createModelIDs() {
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, @Nullable RenderContext ctx, int[] indices) {
final int patternCount = potteryPatterns.size();

indices[0] = 0;
indices[0] = IDX_BASE_POT;
if (view.getBlockEntity(pos) instanceof DecoratedPotBlockEntity pot) {
if (pot instanceof ModelStateHolder ms && ms.getModelState() > 0) {
Arrays.fill(indices, IDX_EMPTY);
return;
}

var sherds = pot.getSherds();

indices[1] = 1 + getPatternIndex(sherds.back(), patternCount);
indices[2] = 1 + getPatternIndex(sherds.left(), patternCount) + patternCount;
indices[3] = 1 + getPatternIndex(sherds.right(), patternCount) + patternCount * 2;
indices[4] = 1 + getPatternIndex(sherds.front(), patternCount) + patternCount * 3;
indices[1] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.back(), patternCount);
indices[2] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.left(), patternCount) + patternCount;
indices[3] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.right(), patternCount) + patternCount * 2;
indices[4] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.front(), patternCount) + patternCount * 3;

return;
}

for (int i = 0; i < 4; i++) {
indices[1 + i] = 1 + patternCount * i;
indices[1 + i] = BUILTIN_MODEL_COUNT + patternCount * i;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@

@FunctionalInterface
public interface BlockEntityRenderCondition {
BlockEntityRenderCondition STATE_GREATER_THAN_1 = entity -> {
BlockEntityRenderCondition NON_ZERO_STATE = entity -> {
if(entity instanceof ModelStateHolder stateHolder) {
return stateHolder.getModelState() > 0;
}
return false;
};

BlockEntityRenderCondition CHEST = STATE_GREATER_THAN_1;
BlockEntityRenderCondition CHEST = NON_ZERO_STATE;

BlockEntityRenderCondition BELL = STATE_GREATER_THAN_1;
BlockEntityRenderCondition BELL = NON_ZERO_STATE;

BlockEntityRenderCondition SHULKER_BOX = STATE_GREATER_THAN_1;
BlockEntityRenderCondition SHULKER_BOX = NON_ZERO_STATE;

BlockEntityRenderCondition SIGN = entity -> {
EBEConfig config = EnhancedBlockEntities.CONFIG;
Expand All @@ -48,6 +48,8 @@ public interface BlockEntityRenderCondition {
return false;
};

BlockEntityRenderCondition DECORATED_POT = NON_ZERO_STATE;

BlockEntityRenderCondition NEVER = entity -> false;

BlockEntityRenderCondition ALWAYS = entity -> true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package foundationgames.enhancedblockentities.client.render.entity;

import com.google.common.collect.ImmutableMap;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.duck.BakedModelManagerAccess;
import net.minecraft.block.DecoratedPotPatterns;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;

import java.util.Map;

public class DecoratedPotBlockEntityRendererOverride extends BlockEntityRendererOverride {
public static final float WOBBLE_STRENGTH = 1f / 64;

private BakedModel baseModel = null;
private Map<RegistryKey<String>, BakedModel[]> potPatternModels = null;

private void tryGetModels() {
var models = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager();

if (this.baseModel == null) {
this.baseModel = models.getModel(ModelIdentifiers.DECORATED_POT_BASE);
}

if (this.potPatternModels == null) {
var builder = ImmutableMap.<RegistryKey<String>, BakedModel[]>builder();

Registries.DECORATED_POT_PATTERN.getKeys().forEach(k -> {
var patternModelIDs = ModelIdentifiers.POTTERY_PATTERNS.get(k);
BakedModel[] patternPerFaceModels = new BakedModel[patternModelIDs.length];

for (int i = 0; i < patternModelIDs.length; i++) {
patternPerFaceModels[i] = models.getModel(patternModelIDs[i]);
}

builder.put(k, patternPerFaceModels);
});

this.potPatternModels = builder.build();
}
}

@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
tryGetModels();

if (blockEntity instanceof DecoratedPotBlockEntity pot) {
matrices.push();

var dir = pot.getHorizontalFacing();

matrices.translate(0.5f, 0, 0.5f);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - dir.asRotation()));
matrices.translate(-0.5f, 0, -0.5f);

var wobbleType = pot.lastWobbleType;
if (wobbleType != null && pot.getWorld() != null) {
float tilt = ((float)(pot.getWorld().getTime() - pot.lastWobbleTime) + tickDelta) / (float)wobbleType.lengthInTicks;
if (tilt >= 0.0F && tilt <= 1.0F) {
if (wobbleType == DecoratedPotBlockEntity.WobbleType.POSITIVE) {
float animPeriod = tilt * MathHelper.TAU;

float tiltX = -1.5f * (MathHelper.cos(animPeriod) + 0.5f) * MathHelper.sin(animPeriod * 0.5f);
matrices.multiply(RotationAxis.POSITIVE_X.rotation(tiltX * WOBBLE_STRENGTH), 0.5f, 0f, 0.5f);

float tiltZ = MathHelper.sin(animPeriod);
matrices.multiply(RotationAxis.POSITIVE_Z.rotation(tiltZ * WOBBLE_STRENGTH), 0.5f, 0f, 0.5f);
} else {
float yaw = (1f - tilt) * MathHelper.sin(-tilt * 3 * MathHelper.PI) * 0.125f;
matrices.multiply(RotationAxis.POSITIVE_Y.rotation(yaw), 0.5f, 0f, 0.5f);
}
}
}

var sherds = pot.getSherds();
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices, this.baseModel, light, overlay);

EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(DecoratedPotPatterns.fromSherd(sherds.back()))[0], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(DecoratedPotPatterns.fromSherd(sherds.left()))[1], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(DecoratedPotPatterns.fromSherd(sherds.right()))[2], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(DecoratedPotPatterns.fromSherd(sherds.front()))[3], light, overlay);

matrices.pop();
}
}

@Override
public void onModelsReload() {
this.baseModel = null;
this.potPatternModels = null;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package foundationgames.enhancedblockentities.mixin;

import foundationgames.enhancedblockentities.util.WorldUtil;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.nbt.NbtCompound;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(DecoratedPotBlockEntity.class)
public class DecoratedPotBlockEntityMixin {
public class DecoratedPotBlockEntityMixin implements ModelStateHolder {
@Unique private int enhanced_bes$modelState = 0;

@Inject(method = "readNbt", at = @At("TAIL"))
private void enhanced_bes$updateChunkOnPatternsLoaded(NbtCompound nbt, CallbackInfo ci) {
var self = (DecoratedPotBlockEntity)(Object)this;
Expand All @@ -18,4 +23,33 @@ public class DecoratedPotBlockEntityMixin {
WorldUtil.rebuildChunkSynchronously(self.getWorld(), self.getPos(), false);
}
}

@Inject(method = "onSyncedBlockEvent", at = @At(value = "RETURN", shift = At.Shift.BEFORE, ordinal = 0))
private void enhanced_bes$updateOnWobble(int type, int data, CallbackInfoReturnable<Boolean> cir) {
var self = (DecoratedPotBlockEntity)(Object)this;
var world = self.getWorld();

if (self.lastWobbleType == null) {
return;
}

this.setModelState(1, world, self.getPos());

WorldUtil.schedule(world, self.lastWobbleTime + self.lastWobbleType.lengthInTicks,
() -> {
if (self.getWorld().getTime() >= self.lastWobbleTime + self.lastWobbleType.lengthInTicks) {
this.setModelState(0, world, self.getPos());
}
});
}

@Override
public int getModelState() {
return enhanced_bes$modelState;
}

@Override
public void applyModelState(int state) {
this.enhanced_bes$modelState = state;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package foundationgames.enhancedblockentities.util;

import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.world.World;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public enum WorldUtil {;
public enum WorldUtil implements ClientTickEvents.EndWorldTick {
EVENT_LISTENER;

public static Set<ChunkSectionPos> FORCE_SYNCHRONOUS_CHUNK_REBUILD = new HashSet<>();
private static Map<RegistryKey<World>, Long2ObjectMap<Runnable>> SCHEDULED_TASKS = new HashMap<>();

public static void rebuildChunkSynchronously(World world, BlockPos pos, boolean forceSync) {
var bState = world.getBlockState(pos);
Expand All @@ -23,4 +33,24 @@ public static void rebuildChunkSynchronously(World world, BlockPos pos, boolean
EnhancedBlockEntities.LOG.warn("Error rebuilding chunk at block pos "+pos);
}
}

public static void schedule(World world, long time, Runnable action) {
SCHEDULED_TASKS.computeIfAbsent(world.getRegistryKey(), k -> new Long2ObjectOpenHashMap<>()).put(time, action);
}

@Override
public void onEndTick(ClientWorld world) {
var key = world.getRegistryKey();

if (SCHEDULED_TASKS.containsKey(key)) {
SCHEDULED_TASKS.get(key).long2ObjectEntrySet().removeIf(entry -> {
if (world.getTime() >= entry.getLongKey()) {
entry.getValue().run();
return true;
}

return false;
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"textures": {
"particle": "minecraft:block/terracotta"
}
}

0 comments on commit 9329310

Please sign in to comment.