Using Create outlines and ghost blocks for block previews.

Fixed item names.
This commit is contained in:
Christian Knaapen
2023-01-16 01:53:09 +01:00
parent c2d413fad0
commit fa1aadcd86
9 changed files with 158 additions and 81 deletions

View File

@@ -0,0 +1,31 @@
package nl.requios.effortlessbuilding.create;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class CreateClientTest {
@SubscribeEvent
public static void onTick(TickEvent.ClientTickEvent event) {
CreateClient.GHOST_BLOCKS.showGhostState(1, Blocks.SPRUCE_LOG.defaultBlockState())
.at(0, 120, 0)
.breathingAlpha();
CreateClient.GHOST_BLOCKS.showGhostState(2, Blocks.SPRUCE_LOG.defaultBlockState())
.at(1, 120, 0)
.breathingAlpha();
CreateClient.OUTLINER.showAABB(1, new AABB(0, 0, 0, 10, 2, 6)
.move(10, 120, 0))
.withFaceTexture(AllSpecialTextures.CHECKERED)
.colored(new Color(0.11f, 0.49f, 0.7f, 1f))
// .colored(0xbfbfbf)
.disableNormals()
.lineWidth(1 / 32f);
}
}

View File

@@ -35,8 +35,8 @@ public class ClientEvents {
Level world = Minecraft.getInstance().level; Level world = Minecraft.getInstance().level;
AnimationTickHolder.tick(); AnimationTickHolder.tick();
CreateClient.OUTLINER.tickOutlines();
CreateClient.GHOST_BLOCKS.tickGhosts(); CreateClient.GHOST_BLOCKS.tickGhosts();
CreateClient.OUTLINER.tickOutlines();
CameraAngleAnimationService.tick(); CameraAngleAnimationService.tick();
} }
@@ -89,7 +89,7 @@ public class ClientEvents {
event.setPitch(CameraAngleAnimationService.getPitch(partialTicks)); event.setPitch(CameraAngleAnimationService.getPitch(partialTicks));
} }
protected static boolean isGameActive() { public static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
} }

View File

@@ -75,7 +75,7 @@ public abstract class GhostBlockRenderer {
BlockState state = params.state; BlockState state = params.state;
BlockPos pos = params.pos; BlockPos pos = params.pos;
float alpha = params.alphaSupplier.get() * .75f/* * PlacementHelpers.getCurrentAlpha()*/; float alpha = params.alphaSupplier.get()/* * .75f* PlacementHelpers.getCurrentAlpha()*/;
BakedModel model = dispatcher.getBlockModel(state); BakedModel model = dispatcher.getBlockModel(state);
RenderType layer = RenderType.translucent(); RenderType layer = RenderType.translucent();
@@ -88,7 +88,7 @@ public abstract class GhostBlockRenderer {
ms.scale(.85f, .85f, .85f); ms.scale(.85f, .85f, .85f);
ms.translate(-.5, -.5, -.5); ms.translate(-.5, -.5, -.5);
renderModel(ms.last(), vb, state, model, 1f, 1f, 1f, alpha, renderModel(ms.last(), vb, state, model, 0f, 1f, 1f, alpha,
LevelRenderer.getLightColor(mc.level, pos), OverlayTexture.NO_OVERLAY, LevelRenderer.getLightColor(mc.level, pos), OverlayTexture.NO_OVERLAY,
ModelUtil.VIRTUAL_DATA, layer); ModelUtil.VIRTUAL_DATA, layer);

View File

@@ -33,7 +33,7 @@ public class DiamondRandomizerBagItem extends AbstractRandomizerBagItem{
@Override @Override
public Component getDisplayName() { public Component getDisplayName() {
return Component.translatable("effortlessbuilding:diamond_randomizer_bag"); return Component.translatable("item.effortlessbuilding.diamond_randomizer_bag");
} }
@Nullable @Nullable

View File

@@ -33,7 +33,7 @@ public class GoldenRandomizerBagItem extends AbstractRandomizerBagItem{
@Override @Override
public Component getDisplayName() { public Component getDisplayName() {
return Component.translatable("effortlessbuilding:golden_randomizer_bag"); return Component.translatable("item.effortlessbuilding.golden_randomizer_bag");
} }
@Nullable @Nullable

View File

@@ -33,7 +33,7 @@ public class RandomizerBagItem extends AbstractRandomizerBagItem {
@Override @Override
public Component getDisplayName() { public Component getDisplayName() {
return Component.translatable("effortlessbuilding:randomizer_bag"); return Component.translatable("item.effortlessbuilding.randomizer_bag");
} }
@Nullable @Nullable

View File

@@ -32,6 +32,9 @@ import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.create.AllSpecialTextures;
import nl.requios.effortlessbuilding.create.CreateClient;
import nl.requios.effortlessbuilding.create.foundation.utility.Color;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
@@ -51,7 +54,7 @@ public class BlockPreviewRenderer {
private static BlockPos previousSecondPos; private static BlockPos previousSecondPos;
private static int soundTime = 0; private static int soundTime = 0;
public static void render(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Player player, ModifierSettings modifierSettings, ModeSettings modeSettings) { public static void render(PoseStack ms, MultiBufferSource.BufferSource buffer, Player player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect //Render placed blocks with dissolve effect
//Use fancy shader if config allows, otherwise no dissolve //Use fancy shader if config allows, otherwise no dissolve
@@ -62,7 +65,7 @@ public class BlockPreviewRenderer {
double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get(); double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime; float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(matrixStack, renderTypeBuffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking); renderBlockPreviews(ms, buffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
} }
} }
} }
@@ -188,22 +191,45 @@ public class BlockPreviewRenderer {
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount; int blockCount;
if (!breaking) {
//Use fancy shader if config allows, otherwise outlines //Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderThreshold.get()) { if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
blockCount = renderBlockPreviews(matrixStack, renderTypeBuffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); blockCount = renderBlockPreviews(ms, buffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates)
.withFaceTexture(AllSpecialTextures.CHECKERED)
.disableNormals()
.lineWidth(1 / 32f)
.colored(new Color(1f, 1f, 1f, 1f));
} else { } else {
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer); // VertexConsumer vc = RenderHandler.beginLines(buffer);
//
// Vec3 color = new Vec3(1f, 1f, 1f);
// if (breaking) color = new Vec3(1f, 0f, 0f);
//
// for (int i = newCoordinates.size() - 1; i >= 0; i--) {
// VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.level, newCoordinates.get(i));
// RenderHandler.renderBlockOutline(ms, vc, newCoordinates.get(i), collisionShape, color);
// }
//
// RenderHandler.endLines(buffer);
Vec3 color = new Vec3(1f, 1f, 1f); CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates)
if (breaking) color = new Vec3(1f, 0f, 0f); .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED)
.disableNormals()
.lineWidth(1 / 16f)
.colored(new Color(1f, 1f, 1f, 1f));
for (int i = newCoordinates.size() - 1; i >= 0; i--) { blockCount = newCoordinates.size();
VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.level, newCoordinates.get(i));
RenderHandler.renderBlockOutline(matrixStack, buffer, newCoordinates.get(i), collisionShape, color);
} }
RenderHandler.endLines(renderTypeBuffer); } else {
//Breaking
CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates)
.withFaceTexture(AllSpecialTextures.THIN_CHECKERED)
.disableNormals()
.lineWidth(1 / 16f)
.colored(new Color(0.8f, 0.1f, 0.1f, 1f));
blockCount = newCoordinates.size(); blockCount = newCoordinates.size();
} }
@@ -240,29 +266,29 @@ public class BlockPreviewRenderer {
//Draw outlines if no block in hand //Draw outlines if no block in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar //Find proper raytrace: either normal range or increased range depending on canBreakFar
VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer); // VertexConsumer vc = RenderHandler.beginLines(buffer);
HitResult objectMouseOver = Minecraft.getInstance().hitResult; // HitResult objectMouseOver = Minecraft.getInstance().hitResult;
HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; // HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
//
if (player.isCreative() && noBlockInHand && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) { // if (player.isCreative() && noBlockInHand && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace; // BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace;
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos()); // List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos());
//
//Only render first outline if further than normal reach // //Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK; // boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) { // for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i); // BlockPos coordinate = breakCoordinates.get(i);
//
BlockState blockState = player.level.getBlockState(coordinate); // BlockState blockState = player.level.getBlockState(coordinate);
if (!blockState.isAir()) { // if (!blockState.isAir()) {
if (SurvivalHelper.canBreak(player.level, player, coordinate) || i == 0) { // if (SurvivalHelper.canBreak(player.level, player, coordinate) || i == 0) {
VoxelShape collisionShape = blockState.getCollisionShape(player.level, coordinate); // VoxelShape collisionShape = blockState.getCollisionShape(player.level, coordinate);
RenderHandler.renderBlockOutline(matrixStack, buffer, coordinate, collisionShape, new Vec3(0f, 0f, 0f)); // RenderHandler.renderBlockOutline(ms, vc, coordinate, collisionShape, new Vec3(0f, 0f, 0f));
} // }
} // }
} // }
} // }
RenderHandler.endLines(renderTypeBuffer); // RenderHandler.endLines(buffer);
} }
} }
@@ -290,9 +316,9 @@ public class BlockPreviewRenderer {
if (CompatHelper.isItemBlockProxy(itemstack)) if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place //Check if we can place
//If check is turned off, check if blockstate is the same (for dissolve effect) //If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks the breaking shader) if ((!checkCanPlace && player.level.getBlockState(blockPos) == blockState) || //TODO enable (breaks the breaking shader)
SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) { SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) {
RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red); RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red);

View File

@@ -14,6 +14,7 @@ import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -22,11 +23,14 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderLevelLastEvent; import net.minecraftforge.client.event.RenderLevelLastEvent;
import net.minecraftforge.client.event.RenderLevelStageEvent; import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.create.CreateClient;
import nl.requios.effortlessbuilding.create.events.ClientEvents;
/*** /***
* Main render class for Effortless Building * Main render class for Effortless Building
@@ -34,6 +38,17 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
@EventBusSubscriber(Dist.CLIENT) @EventBusSubscriber(Dist.CLIENT)
public class RenderHandler { public class RenderHandler {
@SubscribeEvent
public static void onTick(TickEvent.ClientTickEvent event) {
if (!ClientEvents.isGameActive()) return;
Player player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockPreviewRenderer.render(null, null, player, modifierSettings, modeSettings);
}
@SubscribeEvent @SubscribeEvent
public static void onRender(RenderLevelLastEvent event) { public static void onRender(RenderLevelLastEvent event) {
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
@@ -83,39 +98,44 @@ public class RenderHandler {
renderTypeBuffer.endBatch(); renderTypeBuffer.endBatch();
} }
protected static void renderBlockPreview(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, BlockRenderDispatcher dispatcher, protected static void renderBlockPreview(PoseStack ms, MultiBufferSource.BufferSource buffer, BlockRenderDispatcher dispatcher,
BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) { BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) {
if (blockState == null) return; if (blockState == null) return;
matrixStack.pushPose(); CreateClient.GHOST_BLOCKS.showGhostState(blockPos.toShortString(), blockState)
matrixStack.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); // .breathingAlpha()
// matrixStack.rotate(Vector3f.YP.rotationDegrees(-90f)); .alpha(0.7f)
matrixStack.translate(-0.01f, -0.01f, -0.01f); .at(blockPos);
matrixStack.scale(1.02f, 1.02f, 1.02f);
//Begin block preview rendering // ms.pushPose();
RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red); // ms.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
VertexConsumer buffer = renderTypeBuffer.getBuffer(blockPreviewRenderType); //// ms.rotate(Vector3f.YP.rotationDegrees(-90f));
// ms.translate(-0.01f, -0.01f, -0.01f);
try { // ms.scale(1.02f, 1.02f, 1.02f);
BakedModel model = dispatcher.getBlockModel(blockState); //
dispatcher.getModelRenderer().renderModel(matrixStack.last(), buffer, blockState, model, // //Begin block preview rendering
1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, blockPreviewRenderType); // RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red);
} catch (NullPointerException e) { // VertexConsumer vc = buffer.getBuffer(blockPreviewRenderType);
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString()); //
// try {
//Render outline as backup, escape out of the current renderstack // BakedModel model = dispatcher.getBlockModel(blockState);
matrixStack.popPose(); // dispatcher.getModelRenderer().renderModel(ms.last(), vc, blockState, model,
renderTypeBuffer.endBatch(); // 1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, blockPreviewRenderType);
VertexConsumer lineBuffer = beginLines(renderTypeBuffer); // } catch (NullPointerException e) {
renderBlockOutline(matrixStack, lineBuffer, blockPos, new Vec3(1f, 1f, 1f)); // EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString());
endLines(renderTypeBuffer); //
buffer = renderTypeBuffer.getBuffer(Sheets.translucentCullBlockSheet()); //any type will do, as long as we have something on the stack // //Render outline as backup, escape out of the current renderstack
matrixStack.pushPose(); // ms.popPose();
} // buffer.endBatch();
// VertexConsumer lineBuffer = beginLines(buffer);
renderTypeBuffer.endBatch(); // renderBlockOutline(ms, lineBuffer, blockPos, new Vec3(1f, 1f, 1f));
matrixStack.popPose(); // endLines(buffer);
// vc = buffer.getBuffer(Sheets.translucentCullBlockSheet()); //any type will do, as long as we have something on the stack
// ms.pushPose();
// }
//
// buffer.endBatch();
// ms.popPose();
} }
protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, Vec3 color) { protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, Vec3 color) {

View File

@@ -11,12 +11,12 @@
"key.effortlessbuilding.redo.desc": "Redo", "key.effortlessbuilding.redo.desc": "Redo",
"key.effortlessbuilding.altplacement.desc": "Alternative placement", "key.effortlessbuilding.altplacement.desc": "Alternative placement",
"effortlessbuilding:randomizer_bag": "Leather Randomizer Bag", "item.effortlessbuilding.randomizer_bag": "Leather Randomizer Bag",
"effortlessbuilding:golden_randomizer_bag": "Golden Randomizer Bag", "item.effortlessbuilding.golden_randomizer_bag": "Golden Randomizer Bag",
"effortlessbuilding:diamond_randomizer_bag": "Diamond Randomizer Bag", "item.effortlessbuilding.diamond_randomizer_bag": "Diamond Randomizer Bag",
"effortlessbuilding:reach_upgrade1": "Reach Upgrade 1", "item.effortlessbuilding.reach_upgrade1": "Reach Upgrade 1",
"effortlessbuilding:reach_upgrade2": "Reach Upgrade 2", "item.effortlessbuilding.reach_upgrade2": "Reach Upgrade 2",
"effortlessbuilding:reach_upgrade3": "Reach Upgrade 3", "item.effortlessbuilding.reach_upgrade3": "Reach Upgrade 3",
"effortlessbuilding.mode.normal": "Disable", "effortlessbuilding.mode.normal": "Disable",
"effortlessbuilding.mode.normal_plus": "Single", "effortlessbuilding.mode.normal_plus": "Single",