Skip to content

Commit

Permalink
Redesigned dynamic model update handling
Browse files Browse the repository at this point in the history
- Instead of forcing the game to synchronously update chunks to avoid flashing, the block entity renderer override will continue to render until the updated chunk mesh has been uploaded
- This means the game will not freeze when block entities go from static to animated or vice versa, unless fully blocking chunk updates are specified in the game options
- Soft-failing mixins to Sodium have been added to allow this change to work with Sodium installed, also eliminating the long-standing issue of block entity animations flashing when using EBE with Sodium
  • Loading branch information
FoundationGames committed Jun 3, 2024
1 parent 9329310 commit 686cdbe
Show file tree
Hide file tree
Showing 28 changed files with 315 additions and 126 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ dependencies {
// Mod Menu because config screen access from another place
modApi "com.terraformersmc:modmenu:${project.modmenu_version}"

// Sodium for compatibility
modCompileOnlyApi "maven.modrinth:sodium:${project.sodium_version}"

// a bit less load time
modLocalRuntime "maven.modrinth:lazydfu:0.1.3"
}
Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ archives_base_name = enhancedblockentities

arrp_version=0.8.1
modmenu_version=9.2.0-beta.2

sodium_version=mc1.20.4-0.5.8
indium_version=1.0.30+mc1.20.4
28 changes: 14 additions & 14 deletions src/main/java/foundationgames/enhancedblockentities/EBESetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -332,32 +332,32 @@ public static void setupChests() {
new ChestBlockEntityRendererOverride(() -> {
BakedModelManagerAccess manager = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] {
manager.getModel(ModelIdentifiers.CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHEST_RIGHT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
manager.enhanced_bes$getModel(ModelIdentifiers.CHEST_CENTER_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHEST_LEFT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHEST_RIGHT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
};
}, christmasChestSelector)
);
EnhancedBlockEntityRegistry.register(Blocks.TRAPPED_CHEST, BlockEntityType.TRAPPED_CHEST, BlockEntityRenderCondition.CHEST,
new ChestBlockEntityRendererOverride(() -> {
BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] {
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_RIGHT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
manager.enhanced_bes$getModel(ModelIdentifiers.TRAPPED_CHEST_CENTER_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.TRAPPED_CHEST_LEFT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.TRAPPED_CHEST_RIGHT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.enhanced_bes$getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
};
}, christmasChestSelector)
);
EnhancedBlockEntityRegistry.register(Blocks.ENDER_CHEST, BlockEntityType.ENDER_CHEST, BlockEntityRenderCondition.CHEST,
new ChestBlockEntityRendererOverride(() -> {
BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] { manager.getModel(ModelIdentifiers.ENDER_CHEST_CENTER_LID) };
return new BakedModel[] { manager.enhanced_bes$getModel(ModelIdentifiers.ENDER_CHEST_CENTER_LID) };
}, entity -> 0)
);
}
Expand Down Expand Up @@ -434,7 +434,7 @@ public static void setupShulkerBoxes() {
new ShulkerBoxBlockEntityRendererOverride((map) -> {
var models = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager();
for (DyeColor dc : EBEUtil.DEFAULTED_DYE_COLORS) {
map.put(dc, models.getModel(ModelIdentifiers.SHULKER_BOX_LIDS.get(dc)));
map.put(dc, models.enhanced_bes$getModel(ModelIdentifiers.SHULKER_BOX_LIDS.get(dc)));
}
})
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package foundationgames.enhancedblockentities.client.model;

import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelResolver;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;

import java.util.function.Supplier;

public class DynamicModelProvidingPlugin implements ModelLoadingPlugin, ModelModifier.BeforeBake {
public class DynamicModelProvidingPlugin implements ModelLoadingPlugin, ModelResolver {
private final Supplier<DynamicUnbakedModel> model;
private final Identifier id;

Expand All @@ -18,12 +19,12 @@ public DynamicModelProvidingPlugin(Identifier id, Supplier<DynamicUnbakedModel>

@Override
public void onInitializeModelLoader(ModelLoadingPlugin.Context ctx) {
ctx.modifyModelBeforeBake().register(this);
ctx.resolveModel().register(this);
}

@Override
public UnbakedModel modifyModelBeforeBake(UnbakedModel model, ModelModifier.BeforeBake.Context ctx) {
public @Nullable UnbakedModel resolveModel(ModelResolver.Context ctx) {
if(ctx.id().equals(this.id)) return this.model.get();
return model;
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package foundationgames.enhancedblockentities.client.model;

import foundationgames.enhancedblockentities.util.DateUtil;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
Expand All @@ -19,7 +19,7 @@ public abstract class ModelSelector {
public static final ModelSelector STATE_HOLDER_SELECTOR = new ModelSelector() {
@Override
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, @Nullable RenderContext ctx, int[] indices) {
if(view.getBlockEntity(pos) instanceof ModelStateHolder stateHolder) {
if(view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) {
indices[0] = stateHolder.getModelState();
return;
}
Expand All @@ -37,7 +37,7 @@ public int getParticleModelIndex() {

@Override
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, @Nullable RenderContext ctx, int[] indices) {
if(view.getBlockEntity(pos) instanceof ModelStateHolder stateHolder) {
if(view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) {
indices[0] = stateHolder.getModelState() + this.getParticleModelIndex();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.model.ModelSelector;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.block.DecoratedPotPatterns;
Expand Down Expand Up @@ -61,7 +61,7 @@ public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos p

indices[0] = IDX_BASE_POT;
if (view.getBlockEntity(pos) instanceof DecoratedPotBlockEntity pot) {
if (pot instanceof ModelStateHolder ms && ms.getModelState() > 0) {
if (pot instanceof AppearanceStateHolder ms && ms.getModelState() > 0) {
Arrays.fill(indices, IDX_EMPTY);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.mixin.SignBlockEntityRenderAccessor;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.Vec3d;

@FunctionalInterface
public interface BlockEntityRenderCondition {
BlockEntityRenderCondition NON_ZERO_STATE = entity -> {
if(entity instanceof ModelStateHolder stateHolder) {
return stateHolder.getModelState() > 0;
if(entity instanceof AppearanceStateHolder stateHolder) {
return stateHolder.getRenderState() > 0;
}
return false;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockE

private BakedModel getBellModel() {
BakedModelManagerAccess manager = (BakedModelManagerAccess)MinecraftClient.getInstance().getBakedModelManager();
return manager.getModel(ModelIdentifiers.BELL_BODY);
return manager.enhanced_bes$getModel(ModelIdentifiers.BELL_BODY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockE
if (blockEntity instanceof LidOpenable) {
matrices.push();

LidOpenable chest = getAnimationProgress(blockEntity, tickDelta);
LidOpenable chest = getLidAnimationHolder(blockEntity, tickDelta);
matrices.translate(0.5f, 0, 0.5f);
Direction dir = blockEntity.getCachedState().get(ChestBlock.FACING);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - dir.asRotation()));
Expand All @@ -53,7 +53,7 @@ public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockE
}
}

public static LidOpenable getAnimationProgress(BlockEntity blockEntity, float tickDelta) {
public static LidOpenable getLidAnimationHolder(BlockEntity blockEntity, float tickDelta) {
LidOpenable chest = (LidOpenable)blockEntity;

BlockState state = blockEntity.getCachedState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private void tryGetModels() {
var models = (BakedModelManagerAccess) MinecraftClient.getInstance().getBakedModelManager();

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

if (this.potPatternModels == null) {
Expand All @@ -41,7 +41,7 @@ private void tryGetModels() {
BakedModel[] patternPerFaceModels = new BakedModel[patternModelIDs.length];

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

builder.put(k, patternPerFaceModels);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class BakedModelManagerMixin implements BakedModelManagerAccess {
@Shadow private Map<Identifier, BakedModel> models;

@Override
public BakedModel getModel(Identifier id) {
public BakedModel enhanced_bes$getModel(Identifier id) {
return this.models.get(id);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package foundationgames.enhancedblockentities.mixin;

import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BellBlockEntity;
import net.minecraft.block.entity.BlockEntity;
Expand All @@ -14,8 +14,9 @@
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(BellBlockEntity.class)
public class BellBlockEntityMixin extends BlockEntity implements ModelStateHolder {
public class BellBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;

public BellBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
Expand All @@ -28,8 +29,8 @@ public BellBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState st
), index = 3)
private static BellBlockEntity enhanced_bes$listenForStopRinging(BellBlockEntity blockEntity) {
int mState = blockEntity.ringTicks > 0 ? 1 : 0;
if (EnhancedBlockEntities.CONFIG.renderEnhancedBells && ((ModelStateHolder)blockEntity).getModelState() != mState) {
((ModelStateHolder)blockEntity).setModelState(mState, blockEntity.getWorld(), blockEntity.getPos());
if (EnhancedBlockEntities.CONFIG.renderEnhancedBells && ((AppearanceStateHolder)blockEntity).getModelState() != mState) {
((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, blockEntity.getWorld(), blockEntity.getPos());
}
return blockEntity;
}
Expand All @@ -40,7 +41,17 @@ public int getModelState() {
}

@Override
public void applyModelState(int state) {
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}

@Override
public int getRenderState() {
return enhanced_bes$renderState;
}

@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package foundationgames.enhancedblockentities.mixin;

import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess;
import net.minecraft.client.render.chunk.ChunkBuilder;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;

@Mixin(ChunkBuilder.BuiltChunk.class)
public class BuiltChunkMixin implements ChunkRebuildTaskAccess {
private @Unique
@Nullable Runnable enhanced_bes$taskAfterRebuild = null;

@Override
public Runnable enhanced_bes$getTaskAfterRebuild() {
return enhanced_bes$taskAfterRebuild;
}

@Override
public void enhanced_bes$setTaskAfterRebuild(Runnable task) {
enhanced_bes$taskAfterRebuild = task;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.duck.ModelStateHolder;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
Expand All @@ -16,19 +16,21 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(ChestBlockEntity.class)
public abstract class ChestBlockEntityMixin extends BlockEntity implements ModelStateHolder {
public abstract class ChestBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;

private ChestBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}

@Inject(method = "clientTick", at = @At(value = "TAIL"))
private static void enhanced_bes$listenForOpenClose(World world, BlockPos pos, BlockState state, ChestBlockEntity blockEntity, CallbackInfo ci) {
int mState = ChestBlockEntityRendererOverride.getAnimationProgress(blockEntity, 0)
.getAnimationProgress(0) > 0 ? 1 : 0;
if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((ModelStateHolder)blockEntity).getModelState() != mState) {
((ModelStateHolder)blockEntity).setModelState(mState, world, pos);
var lid = ChestBlockEntityRendererOverride.getLidAnimationHolder(blockEntity, 0.5f);
int mState = lid.getAnimationProgress(0.5f) > 0 ? 1 : 0;

if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((AppearanceStateHolder)blockEntity).getModelState() != mState) {
((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, world, pos);
}
}

Expand All @@ -38,7 +40,17 @@ public int getModelState() {
}

@Override
public void applyModelState(int state) {
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}

@Override
public int getRenderState() {
return enhanced_bes$renderState;
}

@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
Loading

0 comments on commit 686cdbe

Please sign in to comment.