fixed small cube and caching for dynamic models items because items rerender often
This commit is contained in:
parent
bd412bfccd
commit
5fcb983592
@ -30,7 +30,7 @@ import static fr.adrien1106.reframed.util.blocks.BlockProperties.LIGHT;
|
||||
* TODO add Hammer from framed ( removes theme ) for sure
|
||||
* TODO add screwdriver ( iterate over theme states ) ?
|
||||
* TODO add blueprint for survival friendly copy paste of a theme.
|
||||
* TODO fix other models ( + half stair )
|
||||
* TODO fix other models ( + half stair + layers )
|
||||
* TODO get better naming for the shapes (will break a lot of already placed blocks)
|
||||
* TODO put more coherence in the double theme orders / directions
|
||||
* TODO better connected textures
|
||||
|
@ -28,6 +28,7 @@ import static fr.adrien1106.reframed.block.ReFramedStepBlock.getStepShape;
|
||||
import static fr.adrien1106.reframed.util.blocks.BlockProperties.EDGE;
|
||||
import static fr.adrien1106.reframed.util.blocks.Edge.*;
|
||||
import static net.minecraft.data.client.VariantSettings.Rotation.*;
|
||||
import static net.minecraft.util.shape.VoxelShapes.empty;
|
||||
|
||||
public class ReFramedDoubleSmallBlock extends WaterloggableReFramedDoubleBlock implements BlockStateProvider {
|
||||
|
||||
@ -57,22 +58,27 @@ public class ReFramedDoubleSmallBlock extends WaterloggableReFramedDoubleBlock i
|
||||
return super.getPlacementState(ctx).with(EDGE, BlockHelper.getPlacementEdge(ctx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCullingShape(BlockState state, BlockView view, BlockPos pos) {
|
||||
return isGhost(view, pos) ? empty(): getStepShape(state.get(EDGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
return getStepShape(state.get(EDGE));
|
||||
}
|
||||
|
||||
@Override // TODO
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, int i) {
|
||||
return switch (state.get(EDGE)) {
|
||||
case NORTH_DOWN -> SMALL_CUBE_VOXELS.get(i == 1 ? 0 : 3);
|
||||
case NORTH_DOWN -> SMALL_CUBE_VOXELS.get(i == 1 ? 3 : 0);
|
||||
case DOWN_SOUTH -> SMALL_CUBE_VOXELS.get(i == 1 ? 1 : 2);
|
||||
case SOUTH_UP -> SMALL_CUBE_VOXELS.get(i == 1 ? 5 : 6);
|
||||
case SOUTH_UP -> SMALL_CUBE_VOXELS.get(i == 1 ? 6 : 5);
|
||||
case UP_NORTH -> SMALL_CUBE_VOXELS.get(i == 1 ? 4 : 7);
|
||||
case WEST_DOWN -> SMALL_CUBE_VOXELS.get(i == 1 ? 2 : 3);
|
||||
case DOWN_EAST -> SMALL_CUBE_VOXELS.get(i == 1 ? 0 : 1);
|
||||
case EAST_UP -> SMALL_CUBE_VOXELS.get(i == 1 ? 4 : 5);
|
||||
case UP_WEST -> SMALL_CUBE_VOXELS.get(i == 1 ? 6 : 7);
|
||||
case EAST_UP -> SMALL_CUBE_VOXELS.get(i == 1 ? 5 : 4);
|
||||
case UP_WEST -> SMALL_CUBE_VOXELS.get(i == 1 ? 7 : 6);
|
||||
case WEST_NORTH -> SMALL_CUBE_VOXELS.get(i == 1 ? 3 : 7);
|
||||
case NORTH_EAST -> SMALL_CUBE_VOXELS.get(i == 1 ? 0 : 4);
|
||||
case EAST_SOUTH -> SMALL_CUBE_VOXELS.get(i == 1 ? 1 : 5);
|
||||
@ -82,10 +88,10 @@ public class ReFramedDoubleSmallBlock extends WaterloggableReFramedDoubleBlock i
|
||||
|
||||
@Override
|
||||
public int getTopThemeIndex(BlockState state) {
|
||||
return super.getTopThemeIndex(state); // TODO
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override // TODO
|
||||
@Override
|
||||
public BlockStateSupplier getMultipart() {
|
||||
Identifier small_cube_id = ReFramed.id("double_small_cube_special");
|
||||
return MultipartBlockStateSupplier.create(this)
|
||||
|
@ -108,7 +108,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
|
||||
}
|
||||
if(theme.getBlock() == Blocks.BARRIER) return;
|
||||
|
||||
CamoAppearance camo = appearance_manager.getCamoAppearance(world, theme, pos, theme_index);
|
||||
CamoAppearance camo = appearance_manager.getCamoAppearance(world, theme, pos, theme_index, false);
|
||||
long seed = theme.getRenderingSeed(pos);
|
||||
int model_id = 0;
|
||||
if (camo instanceof WeightedComputedAppearance wca) model_id = wca.getAppearanceIndex(seed);
|
||||
@ -135,7 +135,7 @@ public abstract class RetexturingBakedModel extends ForwardingBakedModel {
|
||||
int tint;
|
||||
BlockState theme = ReFramedEntity.readStateFromItem(stack, theme_index);
|
||||
if(!theme.isAir()) {
|
||||
appearance = appearance_manager.getCamoAppearance(null, theme, null, theme_index);
|
||||
appearance = appearance_manager.getCamoAppearance(null, theme, null, theme_index, true);
|
||||
tint = 0xFF000000 | ((MinecraftAccessor) MinecraftClient.getInstance()).getItemColors().getColor(new ItemStack(theme.getBlock()), 0);
|
||||
} else {
|
||||
appearance = appearance_manager.getDefaultAppearance(theme_index);
|
||||
|
@ -1,11 +1,12 @@
|
||||
package fr.adrien1106.reframed.client.model.apperance;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import fr.adrien1106.reframed.ReFramed;
|
||||
import fr.adrien1106.reframed.client.ReFramedClient;
|
||||
import fr.adrien1106.reframed.client.model.DynamicBakedModel;
|
||||
import fr.adrien1106.reframed.client.model.QuadPosBounds;
|
||||
import fr.adrien1106.reframed.mixin.model.WeightedBakedModelAccessor;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
@ -67,11 +68,8 @@ public class CamoAppearanceManager {
|
||||
private final CamoAppearance accent_appearance;
|
||||
private final CamoAppearance barrierItemAppearance;
|
||||
|
||||
private static final Object2ObjectLinkedOpenHashMap<BlockState, CamoAppearance> APPEARANCE_CACHE =
|
||||
new Object2ObjectLinkedOpenHashMap<>(2048, 0.25f) {
|
||||
@Override
|
||||
protected void rehash(int n) {}
|
||||
};
|
||||
private static final Cache<BlockState, CamoAppearance> APPEARANCE_CACHE = CacheBuilder.newBuilder().maximumSize(2048).build();
|
||||
|
||||
private final AtomicInteger serial_number = new AtomicInteger(0); //Mutable
|
||||
|
||||
private final EnumMap<BlendMode, RenderMaterial> ao_materials = new EnumMap<>(BlendMode.class);
|
||||
@ -81,19 +79,24 @@ public class CamoAppearanceManager {
|
||||
return appearance == 2 ? accent_appearance: default_appearance;
|
||||
}
|
||||
|
||||
public CamoAppearance getCamoAppearance(BlockRenderView world, BlockState state, BlockPos pos, int theme_index) {
|
||||
public CamoAppearance getCamoAppearance(BlockRenderView world, BlockState state, BlockPos pos, int theme_index, boolean item) {
|
||||
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager().getModel(state);
|
||||
|
||||
// add support for connected textures and more generally any compatible models injected so that they return baked quads
|
||||
if (model instanceof DynamicBakedModel dynamic_model) {
|
||||
return computeAppearance(dynamic_model.computeQuads(world, state, pos, theme_index), state);
|
||||
// cache items as they get rendered more often
|
||||
if (item && APPEARANCE_CACHE.asMap().containsKey(state)) return APPEARANCE_CACHE.getIfPresent(state);
|
||||
|
||||
CamoAppearance appearance = computeAppearance(dynamic_model.computeQuads(world, state, pos, theme_index), state);
|
||||
if (item) APPEARANCE_CACHE.put(state, appearance);
|
||||
return appearance;
|
||||
}
|
||||
|
||||
// refresh cache
|
||||
if (APPEARANCE_CACHE.containsKey(state)) return APPEARANCE_CACHE.getAndMoveToFirst(state);
|
||||
if (APPEARANCE_CACHE.asMap().containsKey(state)) return APPEARANCE_CACHE.getIfPresent(state);
|
||||
|
||||
CamoAppearance appearance = computeAppearance(model, state);
|
||||
APPEARANCE_CACHE.putAndMoveToFirst(state, appearance);
|
||||
APPEARANCE_CACHE.put(state, appearance);
|
||||
return appearance;
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,7 @@ public abstract class AthenaBakedModelMixin implements DynamicBakedModel, BakedM
|
||||
level.getBlockEntity(pos) instanceof ThemeableBlockEntity framed_entity
|
||||
? framed_entity.getTheme(theme_index)
|
||||
: state, pos, direction)
|
||||
)
|
||||
.forEach(sprite -> face_quads.computeIfPresent(direction, (d, quads) -> {
|
||||
).forEach(sprite -> face_quads.computeIfPresent(direction, (d, quads) -> {
|
||||
Sprite texture = textures.get(sprite.sprite());
|
||||
if (texture == null) return quads;
|
||||
emitter.square(direction, sprite.left(), sprite.bottom(), sprite.right(), sprite.top(), sprite.depth());
|
||||
|
@ -48,7 +48,7 @@ public class BlockHelper {
|
||||
|
||||
// self culling cache of the models not made thread local so that it is only computed once
|
||||
private static final Cache<CullElement, Integer[]> INNER_CULL_MAP = CacheBuilder.newBuilder().maximumSize(1024).build();
|
||||
private record CullElement(Object state_key, int model) {}
|
||||
private record CullElement(Block block, Object state_key, int model) {}
|
||||
|
||||
public static Corner getPlacementCorner(ItemPlacementContext ctx) {
|
||||
Direction side = ctx.getSide().getOpposite();
|
||||
@ -172,17 +172,18 @@ public class BlockHelper {
|
||||
|
||||
// check for default light emission
|
||||
if (placement_state.getLuminance() > 0
|
||||
&& themes.stream().noneMatch(theme -> theme.getLuminance() > 0))
|
||||
if (block_entity.emitsLight()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
|
||||
else block_entity.toggleLight();
|
||||
&& themes.stream().noneMatch(theme -> theme.getLuminance() > 0)
|
||||
&& !block_entity.emitsLight()
|
||||
)
|
||||
block_entity.toggleLight();
|
||||
|
||||
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
|
||||
|
||||
// check for default redstone emission
|
||||
if (placement_state.getWeakRedstonePower(world, pos, Direction.NORTH) > 0
|
||||
&& themes.stream().noneMatch(theme -> theme.getWeakRedstonePower(world, pos, Direction.NORTH) > 0))
|
||||
if (block_entity.emitsRedstone()) Block.dropStack(world, pos, new ItemStack(Items.GLOWSTONE_DUST));
|
||||
else block_entity.toggleRedstone();
|
||||
&& themes.stream().noneMatch(theme -> theme.getWeakRedstonePower(world, pos, Direction.NORTH) > 0)
|
||||
&& !block_entity.emitsRedstone()
|
||||
) block_entity.toggleRedstone();
|
||||
|
||||
if(!player.isCreative()) held.decrement(1);
|
||||
world.playSound(player, pos, placement_state.getSoundGroup().getPlaceSound(), SoundCategory.BLOCKS, 1f, 1.1f);
|
||||
@ -203,10 +204,6 @@ public class BlockHelper {
|
||||
if(state.contains(LIGHT) && held.getItem() == Items.GLOWSTONE_DUST) {
|
||||
block_entity.toggleLight();
|
||||
world.setBlockState(pos, state.with(LIGHT, block_entity.emitsLight()));
|
||||
|
||||
if(!player.isCreative())
|
||||
if (block_entity.emitsLight()) held.decrement(1);
|
||||
else held.increment(1);
|
||||
world.playSound(player, pos, SoundEvents.BLOCK_GLASS_HIT, SoundCategory.BLOCKS, 1f, 1f);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
@ -214,10 +211,6 @@ public class BlockHelper {
|
||||
// frame will emit redstone if applied with redstone torch can deactivate redstone block camo emission
|
||||
if(held.getItem() == Items.REDSTONE_TORCH && ext.canAddRedstoneEmission(state, world, pos)) {
|
||||
block_entity.toggleRedstone();
|
||||
|
||||
if(!player.isCreative())
|
||||
if (block_entity.emitsRedstone()) held.decrement(1);
|
||||
else held.increment(1);
|
||||
world.playSound(player, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 1f, 1f);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
@ -225,10 +218,6 @@ public class BlockHelper {
|
||||
// Frame will lose its collision if applied with popped chorus fruit
|
||||
if(held.getItem() == Items.POPPED_CHORUS_FRUIT && ext.canRemoveCollision(state, world, pos)) {
|
||||
block_entity.toggleSolidity();
|
||||
|
||||
if(!player.isCreative())
|
||||
if (!block_entity.isSolid()) held.decrement(1);
|
||||
else held.increment(1);
|
||||
world.playSound(player, pos, SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.BLOCKS, 1f, 1f);
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
@ -245,7 +234,7 @@ public class BlockHelper {
|
||||
public static void computeInnerCull(BlockState state, List<ForwardingBakedModel> models) {
|
||||
if (!(state.getBlock() instanceof ReFramedBlock frame_block)) return;
|
||||
Object key = frame_block.getModelCacheKey(state);
|
||||
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(key, 1))) return;
|
||||
if (INNER_CULL_MAP.asMap().containsKey(new CullElement(frame_block, key, 1))) return;
|
||||
|
||||
Renderer r = ReFramedClient.HELPER.getFabricRenderer();
|
||||
QuadEmitter quad_emitter = r.meshBuilder().getEmitter();
|
||||
@ -275,7 +264,7 @@ public class BlockHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
INNER_CULL_MAP.put(new CullElement(key, self_id), cull_array);
|
||||
INNER_CULL_MAP.put(new CullElement(frame_block, key, self_id), cull_array);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +273,7 @@ public class BlockHelper {
|
||||
if ( !(state.getBlock() instanceof ReFramedBlock frame_block)
|
||||
|| !(view.getBlockEntity(pos) instanceof ThemeableBlockEntity frame_entity)
|
||||
) return true;
|
||||
CullElement key = new CullElement(frame_block.getModelCacheKey(state), theme_index);
|
||||
CullElement key = new CullElement(frame_block, frame_block.getModelCacheKey(state), theme_index);
|
||||
if (!INNER_CULL_MAP.asMap().containsKey(key)) return true;
|
||||
|
||||
// needs to be Integer object because array is initialized with null not 0
|
||||
|
Loading…
Reference in New Issue
Block a user