Skip to content

Commit

Permalink
Add fancy effect for fusion reactor (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
gateguardian523 authored Jun 26, 2024
1 parent 5ef9d8e commit 0a2f28a
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 28 deletions.
4 changes: 4 additions & 0 deletions src/main/java/com/gregtechceu/gtceu/GTCEu.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public static boolean isAlmostUnifiedLoaded() {
return LDLib.isModLoaded(GTValues.MODID_ALMOSTUNIFIED);
}

public static boolean isShimmerLoaded() {
return LDLib.isModLoaded(GTValues.MODID_SHIMMER);
}

@Deprecated(forRemoval = true, since = "1.0.21")
public static boolean isHighTier() {
return GTCEuAPI.isHighTier();
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/gregtechceu/gtceu/api/GTValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ public static int[] tiersBetween(int minInclusive, int maxInclusive) {
MODID_REBORN_ENERGY = "team_reborn_energy",
MODID_ALMOSTUNIFIED = "almostunified",
MODID_CURIOS = "curios",
MODID_AE2WTLIB = "ae2wtlib";
MODID_AE2WTLIB = "ae2wtlib",
MODID_SHIMMER = "shimmer";

/**
* Spray painting compat modids
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.gregtechceu.gtceu.client.renderer;

import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;

@OnlyIn(Dist.CLIENT)
public class GTRenderTypes extends RenderType {

private static final RenderType LIGHT_RING = RenderType.create("light_ring",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP, 256, false, false,
RenderType.CompositeState.builder()
.setCullState(NO_CULL)
.setShaderState(RenderStateShard.POSITION_COLOR_SHADER)
.createCompositeState(false));

private GTRenderTypes(String name, VertexFormat format, VertexFormat.Mode mode, int bufferSize,
boolean affectsCrumbling, boolean sortOnUpload, Runnable setupState, Runnable clearState) {
super(name, format, mode, bufferSize, affectsCrumbling, sortOnUpload, setupState, clearState);
}

public static RenderType getLightRing() {
return LIGHT_RING;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.gregtechceu.gtceu.client.renderer.machine;

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity;
import com.gregtechceu.gtceu.api.pattern.util.RelativeDirection;
import com.gregtechceu.gtceu.client.renderer.GTRenderTypes;
import com.gregtechceu.gtceu.client.util.BloomUtils;
import com.gregtechceu.gtceu.client.util.RenderBufferHelper;
import com.gregtechceu.gtceu.common.machine.multiblock.electric.FusionReactorMachine;

import com.lowdragmc.lowdraglib.utils.ColorUtils;
import com.lowdragmc.lowdraglib.utils.interpolate.Eases;
import com.lowdragmc.shimmer.client.shader.RenderUtils;

import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

import com.mojang.blaze3d.vertex.PoseStack;

public class FusionReactorRenderer extends WorkableCasingMachineRenderer {

public FusionReactorRenderer(ResourceLocation baseCasing, ResourceLocation workableModel, boolean tint) {
super(baseCasing, workableModel, tint);
}

@Override
@OnlyIn(Dist.CLIENT)
public void render(BlockEntity blockEntity, float partialTicks, PoseStack stack, MultiBufferSource buffer,
int combinedLight, int combinedOverlay) {
if (blockEntity instanceof IMachineBlockEntity machineBlockEntity &&
machineBlockEntity.getMetaMachine() instanceof FusionReactorMachine machine) {
if (GTCEu.isShimmerLoaded()) {
PoseStack finalStack = RenderUtils.copyPoseStack(stack);
BloomUtils.entityBloom(source -> renderLightRing(machine, partialTicks, finalStack, source));
} else {
renderLightRing(machine, partialTicks, stack, buffer);
}
}
}

@OnlyIn(Dist.CLIENT)
private void renderLightRing(FusionReactorMachine machine, float partialTicks, PoseStack stack,
MultiBufferSource buffer) {
var color = machine.getColor();
if (color == -1) return;
int ringColor = ColorUtils.blendColor(color, -1, Eases.EaseQuadIn.getInterpolation(
Math.abs((Math.abs(machine.getOffsetTimer() % 50) + partialTicks) - 25) / 25));
var front = machine.getFrontFacing();
var upwards = machine.getUpwardsFacing();
var flipped = machine.isFlipped();
Direction relativeBack = RelativeDirection.BACK.getRelativeFacing(front, upwards, flipped);
Direction.Axis axis = RelativeDirection.UP.getRelativeFacing(front, upwards, flipped).getAxis();
float a = ColorUtils.alpha(ringColor);
float r = ColorUtils.red(ringColor);
float g = ColorUtils.green(ringColor);
float b = ColorUtils.blue(ringColor);
RenderBufferHelper.renderRing(stack, buffer.getBuffer(GTRenderTypes.getLightRing()),
relativeBack.getStepX() * 7 + 0.5F,
relativeBack.getStepY() * 7 + 0.5F,
relativeBack.getStepZ() * 7 + 0.5F,
6, 0.2F, 10, 20,
r, g, b, a, axis);
}

@Override
@OnlyIn(Dist.CLIENT)
public boolean hasTESR(BlockEntity blockEntity) {
return true;
}

@Override
@OnlyIn(Dist.CLIENT)
public boolean isGlobalRenderer(BlockEntity blockEntity) {
return true;
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/gregtechceu/gtceu/client/util/BloomUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gregtechceu.gtceu.client.util;

import com.lowdragmc.shimmer.client.postprocessing.PostProcessing;

import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

import java.util.function.Consumer;

@OnlyIn(Dist.CLIENT)
public class BloomUtils {

public static void entityBloom(Consumer<MultiBufferSource> sourceConsumer) {
// Shimmer will call PostProcessing.BLOOM_UNREAL.renderEntityPost in LevelRenderer#renderLevel
// We probably don't need to call it ourselves
PostProcessing.BLOOM_UNREAL.postEntity(sourceConsumer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.gregtechceu.gtceu.client.util;

import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import org.joml.Matrix4f;

@OnlyIn(Dist.CLIENT)
public class RenderBufferHelper {

/**
*
* Draw a ring torus
*
* @param poseStack The stack used to store the transformation matrix.
* @param buffer Vertex consumer, which is used to cache vertex data.
* @param x The coordinates of the center
* @param y The coordinates of the center
* @param z The coordinates of the center
* @param r The large radius of the torus, that is, the distance from the center of the torus to center of
* the "pipe".
* @param tubeRadius The small radius of the "pipe", i.e. the thickness of the "pipe".
* @param sides The number of subdivisions of the "pipe".
* @param segments The number of subdivisions for the ring.
* @param red color
* @param green color
* @param blue color
* @param alpha transparency
* @param axis The axial direction of the "ring pipe" determines which axis the "ring pipe" rotates around.
*/
public static void renderRing(PoseStack poseStack, VertexConsumer buffer, float x, float y, float z, float r,
float tubeRadius,
int sides, int segments, float red, float green, float blue, float alpha,
Direction.Axis axis) {
Matrix4f mat = poseStack.last().pose();
float sideDelta = (float) (2.0 * Math.PI / sides); // Subdivision angle of the "pipe"
float ringDelta = (float) (2.0 * Math.PI / segments); // Subdivision angle of the ring
float theta = 0; // θ, sin(θ), cos(θ) Main angle
float cosTheta = 1.0F;
float sinTheta = 0.0F;

float phi, sinPhi, cosPhi; // φ, sin(φ), cos(φ) Side angle
float dist; // The distance from the point to the center of the ring pipe

// Iterate through each subdivision of the ring
for (int i = 0; i < segments; i++) {
float theta1 = theta + ringDelta;
float cosTheta1 = Mth.cos(theta1);
float sinTheta1 = Mth.sin(theta1);

// Iterate through each subdivision of the "pipe"
phi = 0;
for (int j = 0; j <= sides; j++) {
phi = phi + sideDelta;
cosPhi = Mth.cos(phi);
sinPhi = Mth.sin(phi);
dist = r + (tubeRadius * cosPhi);

switch (axis) {
case Y:
buffer.vertex(mat, x + sinTheta * dist, y + tubeRadius * sinPhi, z + cosTheta * dist)
.color(red, green, blue, alpha).endVertex();
buffer.vertex(mat, x + sinTheta1 * dist, y + tubeRadius * sinPhi, z + cosTheta1 * dist)
.color(red, green, blue, alpha).endVertex();
break;
case X:
buffer.vertex(mat, x + tubeRadius * sinPhi, y + sinTheta * dist, z + cosTheta * dist)
.color(red, green, blue, alpha).endVertex();
buffer.vertex(mat, x + tubeRadius * sinPhi, y + sinTheta1 * dist, z + cosTheta1 * dist)
.color(red, green, blue, alpha).endVertex();
break;
case Z:
buffer.vertex(mat, x + cosTheta * dist, y + sinTheta * dist, z + tubeRadius * sinPhi)
.color(red, green, blue, alpha).endVertex();
buffer.vertex(mat, x + cosTheta1 * dist, y + sinTheta1 * dist, z + tubeRadius * sinPhi)
.color(red, green, blue, alpha).endVertex();
break;
}

}
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1730,8 +1730,9 @@ public static BiConsumer<ItemStack, List<Component>> createTankTooltips(String n
shapeInfos.add(baseBuilder.build());
return shapeInfos;
})
.workableCasingRenderer(FusionReactorMachine.getCasingType(tier).getTexture(),
GTCEu.id("block/multiblock/fusion_reactor"), false)
.renderer(() -> new FusionReactorRenderer(FusionReactorMachine.getCasingType(tier).getTexture(),
GTCEu.id("block/multiblock/fusion_reactor"), false))
.hasTESR(true)
.compassSections(GTCompassSections.TIER[LuV])
.compassNodeSelf()
.register(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.gregtechceu.gtceu.api.block.IFusionCasingType;
import com.gregtechceu.gtceu.api.capability.IEnergyContainer;
import com.gregtechceu.gtceu.api.capability.recipe.EURecipeCapability;
import com.gregtechceu.gtceu.api.capability.recipe.FluidRecipeCapability;
import com.gregtechceu.gtceu.api.capability.recipe.IO;
import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
Expand All @@ -19,6 +20,8 @@
import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
import com.gregtechceu.gtceu.common.block.FusionCasingBlock;

import com.lowdragmc.lowdraglib.side.fluid.FluidHelper;
import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced;
import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted;
import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder;

Expand Down Expand Up @@ -56,10 +59,9 @@ public class FusionReactorMachine extends WorkableElectricMultiblockMachine impl
protected long heat = 0;
@Persisted
protected final NotifiableEnergyContainer energyContainer;
// TODO implement it when we do fancy effect again.
// @Getter
// @DescSynced
// private Integer color = -1;
@Getter
@DescSynced
private Integer color = -1;
@Nullable
protected TickableSubscription preHeatSubs;

Expand Down Expand Up @@ -196,6 +198,18 @@ public boolean onWorking() {
this.updatePreHeatSubscription();
}
}

if (color == -1) {
if (!recipe.getOutputContents(FluidRecipeCapability.CAP).isEmpty()) {
int newColor = 0xFF000000 |
FluidHelper.getColor(FluidRecipeCapability.CAP
.of(recipe.getOutputContents(FluidRecipeCapability.CAP).get(0).getContent())
.getStacks()[0]);
if (!Objects.equals(color, newColor)) {
color = newColor;
}
}
}
return super.onWorking();
}

Expand All @@ -217,31 +231,16 @@ public void updateHeat() {
updatePreHeatSubscription();
}

// @Override
// public void onWorking() {
// super.onWorking();
// if (color == -1) {
// var lastRecipe = recipeLogic.getLastRecipe();
// if (lastRecipe != null && !lastRecipe.getOutputContents(FluidRecipeCapability.CAP).isEmpty()) {
// int newColor = 0xFF000000 |
// FluidHelper.getColor(FluidRecipeCapability.CAP.of(lastRecipe.getOutputContents(FluidRecipeCapability.CAP).get(0).getContent()));
// if (!Objects.equals(color, newColor)) {
// color = newColor;
// }
// }
// }
// }

// @Override
// public void onWaiting() {
// super.onWaiting();
// color = -1;
// }
@Override
public void onWaiting() {
super.onWaiting();
color = -1;
}

@Override
public void afterWorking() {
super.afterWorking();
// color = -1;
color = -1;
}

@Override
Expand Down

0 comments on commit 0a2f28a

Please sign in to comment.