Skip to content

Commit 1a3686e

Browse files
committed
Completed new placement renderer. Closes #36.
1 parent 4cb6ad4 commit 1a3686e

File tree

5 files changed

+111
-34
lines changed

5 files changed

+111
-34
lines changed

src/main/java/dev/compactmods/crafting/client/ClientConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ public class ClientConfig {
1414

1515
private static ForgeConfigSpec.ConfigValue<String> PROJECTOR_COLOR;
1616
private static ForgeConfigSpec.ConfigValue<String> PROJECTOR_OFF_COLOR;
17+
private static ForgeConfigSpec.IntValue PLACEMENT_TIME;
1718

1819
public static ForgeConfigSpec.BooleanValue ENABLE_DEBUG_ON_F3;
1920

2021
public static int projectorColor = 0xFFFFFFFF;
2122
public static int projectorOffColor = 0xFFFFFFFF;
23+
public static int placementTime = 60;
2224

2325
static {
2426
generateConfig();
@@ -50,6 +52,10 @@ private static void generateConfig() {
5052
.comment("Whether or not activating F3 will enable debug renderers.")
5153
.define("projectorDebugger", false);
5254

55+
PLACEMENT_TIME = builder
56+
.comment("How long (ticks) the placement helper will show on right-clicking a projector.")
57+
.defineInRange("placementTime", 160, 60, 240);
58+
5359
builder.pop();
5460

5561
CONFIG = builder.build();
@@ -59,6 +65,7 @@ private static void generateConfig() {
5965
public static void onLoad(final ModConfig.ModConfigEvent configEvent) {
6066
projectorColor = extractHexColor(PROJECTOR_COLOR.get(), 0x00FF6A00);
6167
projectorOffColor = extractHexColor(PROJECTOR_OFF_COLOR.get(), 0x00898989);
68+
placementTime = PLACEMENT_TIME.get();
6269
}
6370

6471
private static int extractHexColor(String hex, int def) {

src/main/java/dev/compactmods/crafting/client/ClientEventHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,7 @@ public static void onWorldRender(final RenderWorldLastEvent event) {
8686
stack.popPose();
8787
});
8888
});
89+
90+
buffers.endBatch();
8991
}
9092
}
Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
package dev.compactmods.crafting.client.render;
22

3+
import java.util.HashMap;
4+
import java.util.Optional;
35
import java.util.Set;
4-
import java.util.stream.Collectors;
56
import com.mojang.blaze3d.matrix.MatrixStack;
67
import dev.compactmods.crafting.Registration;
8+
import dev.compactmods.crafting.api.field.MiniaturizationFieldSize;
79
import dev.compactmods.crafting.capability.IProjectorRenderInfo;
10+
import dev.compactmods.crafting.client.ClientConfig;
811
import dev.compactmods.crafting.projector.FieldProjectorBlock;
912
import dev.compactmods.crafting.projector.ProjectorHelper;
13+
import net.minecraft.block.AbstractBlock;
1014
import net.minecraft.block.BlockState;
15+
import net.minecraft.block.Blocks;
1116
import net.minecraft.client.Minecraft;
1217
import net.minecraft.client.renderer.ActiveRenderInfo;
1318
import net.minecraft.client.renderer.IRenderTypeBuffer;
19+
import net.minecraft.client.world.ClientWorld;
1420
import net.minecraft.util.Direction;
1521
import net.minecraft.util.math.BlockPos;
1622
import net.minecraft.util.math.vector.Vector3d;
@@ -19,17 +25,18 @@
1925
public class ClientProjectorRenderInfo implements IProjectorRenderInfo {
2026

2127
private final BlockState baseState;
22-
private Set<BlockPos> remainingProjectors;
28+
private final HashMap<BlockPos, Direction> remainingProjectors;
2329
private int renderTime;
2430

2531

2632
public ClientProjectorRenderInfo() {
33+
this.remainingProjectors = new HashMap<>(4);
2734
this.baseState = Registration.FIELD_PROJECTOR_BLOCK.get().defaultBlockState();
2835
}
2936

3037
@Override
3138
public Set<BlockPos> getMissingProjectors() {
32-
return remainingProjectors;
39+
return remainingProjectors.keySet();
3340
}
3441

3542
@Override
@@ -39,48 +46,82 @@ public int getRenderTimeLeft() {
3946

4047
@Override
4148
public void render(MatrixStack matrixStack) {
42-
if(this.renderTime == 0) return;
43-
if(this.remainingProjectors.isEmpty()) return;
49+
if (this.renderTime == 0) return;
50+
if (this.remainingProjectors.isEmpty()) return;
4451

45-
final IRenderTypeBuffer.Impl buffers = Minecraft.getInstance().renderBuffers().bufferSource();
46-
final ActiveRenderInfo mainCamera = Minecraft.getInstance().gameRenderer.getMainCamera();
52+
final Minecraft mc = Minecraft.getInstance();
53+
final IRenderTypeBuffer.Impl buffers = mc.renderBuffers().bufferSource();
54+
final ActiveRenderInfo mainCamera = mc.gameRenderer.getMainCamera();
55+
final ClientWorld level = mc.level;
4756

4857
matrixStack.pushPose();
4958
Vector3d projectedView = mainCamera.getPosition();
5059
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
5160

52-
remainingProjectors.forEach(pos -> {
61+
remainingProjectors.forEach((pos, dir) -> {
5362
matrixStack.pushPose();
5463
matrixStack.translate(
55-
(double) pos.getX(),
56-
(double) pos.getY(),
57-
(double) pos.getZ()
64+
(double) pos.getX() + 0.05,
65+
(double) pos.getY() + 0.05,
66+
(double) pos.getZ() + 0.05
5867
);
5968

60-
GhostRenderer.renderTransparentBlock(baseState, matrixStack, buffers);
69+
matrixStack.scale(0.9f, 0.9f, 0.9f);
70+
71+
GhostRenderer.renderTransparentBlock(baseState.setValue(FieldProjectorBlock.FACING, dir), pos, matrixStack, buffers, renderTime);
6172
matrixStack.popPose();
73+
74+
for (int y = -1; y > -10; y--) {
75+
BlockPos realPos = new BlockPos(pos.getX(), pos.getY() + y, pos.getZ());
76+
if(!level.isStateAtPosition(realPos, AbstractBlock.AbstractBlockState::isAir))
77+
break;
78+
79+
matrixStack.pushPose();
80+
matrixStack.translate(
81+
(double) pos.getX() + 0.15,
82+
(double) pos.getY() + 0.15 + y,
83+
(double) pos.getZ() + 0.15
84+
);
85+
86+
matrixStack.scale(0.6f, 0.6f, 0.6f);
87+
GhostRenderer.renderTransparentBlock(Blocks.BLACK_STAINED_GLASS.defaultBlockState(), null, matrixStack, buffers, renderTime);
88+
matrixStack.popPose();
89+
}
6290
});
6391

6492
matrixStack.popPose();
93+
buffers.endBatch();
6594
}
6695

6796
@Override
6897
public void tick() {
69-
if(renderTime > 0)
70-
this.renderTime--;
71-
if(renderTime < 0)
72-
this.renderTime = 0;
98+
if (renderTime > 0) this.renderTime--;
99+
if (renderTime < 0) this.renderTime = 0;
73100
}
74101

75102
@Override
76103
public void resetRenderTime() {
77-
this.renderTime = 20 * 10;
104+
this.renderTime = ClientConfig.placementTime;
78105
}
79106

80107
@Override
81108
public void setProjector(World level, BlockPos initial) {
82-
this.remainingProjectors = ProjectorHelper.getMissingProjectors(level, initial,
83-
FieldProjectorBlock.getDirection(level, initial).orElse(Direction.UP))
84-
.collect(Collectors.toSet());
109+
remainingProjectors.clear();
110+
111+
Optional<MiniaturizationFieldSize> fieldSize = ProjectorHelper.getClosestOppositeSize(level, initial);
112+
final Direction initialFacing = FieldProjectorBlock.getDirection(level, initial).orElse(Direction.UP);
113+
if(fieldSize.isPresent()) {
114+
final BlockPos center = fieldSize.get().getCenterFromProjector(initial, initialFacing);
115+
Direction.Plane.HORIZONTAL.stream()
116+
.forEach(dir -> {
117+
if(dir == initialFacing) return;
118+
119+
final BlockPos location = fieldSize.get().getProjectorLocationForDirection(center, dir);
120+
remainingProjectors.put(location, dir.getOpposite());
121+
});
122+
} else {
123+
ProjectorHelper.getValidOppositePositions(initial, initialFacing)
124+
.forEach(pos -> this.remainingProjectors.put(pos, initialFacing.getOpposite()));
125+
}
85126
}
86127
}
Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,61 @@
11
package dev.compactmods.crafting.client.render;
22

3-
import java.util.Arrays;
3+
import javax.annotation.Nullable;
44
import java.util.Random;
55
import com.mojang.blaze3d.matrix.MatrixStack;
66
import com.mojang.blaze3d.vertex.IVertexBuilder;
77
import net.minecraft.block.BlockState;
88
import net.minecraft.client.Minecraft;
99
import net.minecraft.client.renderer.IRenderTypeBuffer;
1010
import net.minecraft.client.renderer.LightTexture;
11+
import net.minecraft.client.renderer.color.BlockColors;
12+
import net.minecraft.client.renderer.model.BakedQuad;
1113
import net.minecraft.client.renderer.model.IBakedModel;
1214
import net.minecraft.client.renderer.texture.OverlayTexture;
15+
import net.minecraft.util.ColorHelper;
1316
import net.minecraft.util.Direction;
17+
import net.minecraft.util.math.BlockPos;
18+
import net.minecraft.util.math.MathHelper;
1419
import net.minecraftforge.client.model.data.EmptyModelData;
1520

1621
public class GhostRenderer {
17-
public static void renderTransparentBlock(BlockState state, MatrixStack matrix, IRenderTypeBuffer buffer) {
22+
public static void renderTransparentBlock(BlockState state, @Nullable BlockPos pos, MatrixStack matrix, IRenderTypeBuffer buffer) {
23+
renderTransparentBlock(state, pos, matrix, buffer, 100);
24+
}
25+
26+
public static void renderTransparentBlock(BlockState state, @Nullable BlockPos pos, MatrixStack matrix, IRenderTypeBuffer buffer, int ticksLeft) {
27+
final Minecraft mc = Minecraft.getInstance();
28+
final BlockColors colors = mc.getBlockColors();
29+
30+
// clamp b/n 0-100, effective range 0 - 0.9f
31+
final float alpha = ticksLeft >= 100 ? 0.9f : 0.9f * Math.max(ticksLeft / 100f, .1f);
32+
1833
IVertexBuilder builder = buffer.getBuffer(CCRenderTypes.PHANTOM);
19-
matrix.translate(0.1F, 0.1F, 0.1F);
20-
matrix.scale(0.8F, 0.8F, 0.8F);
21-
IBakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state.getBlockState());
22-
if(model != Minecraft.getInstance().getModelManager().getMissingModel()) {
23-
Arrays.stream(Direction.values())
24-
.flatMap(direction -> model.getQuads(state.getBlockState(), direction, new Random(42L), EmptyModelData.INSTANCE).stream())
25-
.forEach(quad -> builder.addVertexData(matrix.last(), quad, 1.0F, 1.0F, 1.0F, 0.8F, LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY));
34+
IBakedModel model = mc.getBlockRenderer().getBlockModel(state.getBlockState());
35+
if (model != mc.getModelManager().getMissingModel()) {
36+
for(Direction dir : Direction.values())
37+
model.getQuads(state.getBlockState(), dir, new Random(42L), EmptyModelData.INSTANCE)
38+
.forEach(quad -> addQuad(state, pos, matrix, mc, colors, builder, quad, alpha));
39+
2640
model.getQuads(state.getBlockState(), null, new Random(42L), EmptyModelData.INSTANCE)
27-
.forEach(quad -> builder.addVertexData(matrix.last(), quad, 1.0F, 1.0F, 1.0F, 0.8F, LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY));
41+
.forEach(quad -> addQuad(state, pos, matrix, mc, colors, builder, quad, alpha));
2842
}
2943
}
44+
45+
private static void addQuad(BlockState state, @Nullable BlockPos pos, MatrixStack matrix, Minecraft mc, BlockColors colors, IVertexBuilder builder, BakedQuad quad, float alpha) {
46+
int color = quad.isTinted() ? colors.getColor(state, mc.level, pos, quad.getTintIndex()) :
47+
ColorHelper.PackedColor.color(255, 255, 255, 255);
48+
49+
final float red = ColorHelper.PackedColor.red(color) / 255f;
50+
final float green = ColorHelper.PackedColor.green(color) / 255f;
51+
final float blue = ColorHelper.PackedColor.blue(color) / 255f;
52+
53+
final float trueAlpha = MathHelper.clamp(0.01f, alpha, 0.06f);
54+
builder.addVertexData(matrix.last(), quad,
55+
red,
56+
green,
57+
blue,
58+
trueAlpha,
59+
LightTexture.pack(15, 15), OverlayTexture.NO_OVERLAY);
60+
}
3061
}

src/main/java/dev/compactmods/crafting/projector/FieldProjectorBlock.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import net.minecraft.entity.player.PlayerEntity;
1717
import net.minecraft.item.BlockItemUseContext;
1818
import net.minecraft.particles.IParticleData;
19-
import net.minecraft.particles.ParticleTypes;
2019
import net.minecraft.server.MinecraftServer;
2120
import net.minecraft.state.DirectionProperty;
2221
import net.minecraft.state.EnumProperty;
@@ -169,9 +168,6 @@ public ActionResultType use(BlockState state, World world, BlockPos pos, PlayerE
169168
return ActionResultType.SUCCESS;
170169
}
171170

172-
ProjectorHelper.getMissingProjectors(world, pos, state.getValue(FACING))
173-
.forEach(projPos -> spawnPlacementParticle((ServerWorld) world, projPos, ParticleTypes.BARRIER));
174-
175171
// Uncomment for debug block placement
176172
// Arrays.stream(FieldProjectionSize.values()).forEach(size -> {
177173
// BlockPos center = size.getCenterFromProjector(pos, projectorFacing);

0 commit comments

Comments
 (0)