mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-30 06:45:03 +01:00
Refactor bogey rendering
This commit is contained in:
parent
eb2f1fecdc
commit
03a94dd74d
19 changed files with 544 additions and 863 deletions
|
@ -1,132 +1,42 @@
|
|||
package com.simibubi.create;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyRenderer.CommonRenderer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyStyle;
|
||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.CommonStandardBogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.LargeStandardBogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.SmallStandardBogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyStyle.SizeRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.StandardBogeyVisual;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class AllBogeyStyles {
|
||||
public static final Map<ResourceLocation, BogeyStyle> BOGEY_STYLES = new HashMap<>();
|
||||
public static final Map<ResourceLocation, Map<ResourceLocation, BogeyStyle>> CYCLE_GROUPS = new HashMap<>();
|
||||
private static final Map<ResourceLocation, BogeyStyle> EMPTY_GROUP = ImmutableMap.of();
|
||||
private static final Map<ResourceLocation, BogeyStyle> EMPTY_GROUP = Collections.emptyMap();
|
||||
|
||||
public static final ResourceLocation STANDARD_CYCLE_GROUP = Create.asResource("standard");
|
||||
|
||||
public static final BogeyStyle STANDARD =
|
||||
builder("standard", STANDARD_CYCLE_GROUP).displayName(Components.translatable("create.bogey.style.standard"))
|
||||
.size(BogeySizes.SMALL, AllBlocks.SMALL_BOGEY, () -> new SizeRenderer(new StandardBogeyRenderer.Small(), StandardBogeyVisual.Small::new))
|
||||
.size(BogeySizes.LARGE, AllBlocks.LARGE_BOGEY, () -> new SizeRenderer(new StandardBogeyRenderer.Large(), StandardBogeyVisual.Large::new))
|
||||
.build();
|
||||
|
||||
public static Map<ResourceLocation, BogeyStyle> getCycleGroup(ResourceLocation cycleGroup) {
|
||||
return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP);
|
||||
}
|
||||
|
||||
public static final String STANDARD_CYCLE_GROUP = "standard";
|
||||
|
||||
public static final BogeyStyle STANDARD =
|
||||
create("standard", STANDARD_CYCLE_GROUP).commonRenderer(() -> CommonStandardBogeyRenderer::new)
|
||||
.displayName(Components.translatable("create.bogey.style.standard"))
|
||||
.size(BogeySizes.SMALL, () -> SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY)
|
||||
.size(BogeySizes.LARGE, () -> LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY)
|
||||
.build();
|
||||
|
||||
private static BogeyStyleBuilder create(String name, String cycleGroup) {
|
||||
return create(Create.asResource(name), Create.asResource(cycleGroup));
|
||||
private static BogeyStyle.Builder builder(String name, ResourceLocation cycleGroup) {
|
||||
return new BogeyStyle.Builder(Create.asResource(name), cycleGroup);
|
||||
}
|
||||
|
||||
public static BogeyStyleBuilder create(ResourceLocation name, ResourceLocation cycleGroup) {
|
||||
return new BogeyStyleBuilder(name, cycleGroup);
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
|
||||
public static class BogeyStyleBuilder {
|
||||
protected final Map<BogeySizes.BogeySize, Supplier<BogeyStyle.SizeRenderData>> sizeRenderers = new HashMap<>();
|
||||
protected final Map<BogeySizes.BogeySize, ResourceLocation> sizes = new HashMap<>();
|
||||
protected final ResourceLocation name;
|
||||
protected final ResourceLocation cycleGroup;
|
||||
|
||||
protected Component displayName = Lang.translateDirect("bogey.style.invalid");
|
||||
protected ResourceLocation soundType = AllSoundEvents.TRAIN2.getId();
|
||||
protected CompoundTag defaultData = new CompoundTag();
|
||||
protected ParticleOptions contactParticle = ParticleTypes.CRIT;
|
||||
protected ParticleOptions smokeParticle = ParticleTypes.POOF;
|
||||
protected Optional<Supplier<? extends CommonRenderer>> commonRenderer = Optional.empty();
|
||||
|
||||
public BogeyStyleBuilder(ResourceLocation name, ResourceLocation cycleGroup) {
|
||||
this.name = name;
|
||||
this.cycleGroup = cycleGroup;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder displayName(Component displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder soundType(ResourceLocation soundType) {
|
||||
this.soundType = soundType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder defaultData(CompoundTag defaultData) {
|
||||
this.defaultData = defaultData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier<Supplier<? extends BogeyRenderer>> renderer,
|
||||
BlockEntry<? extends AbstractBogeyBlock<?>> blockEntry) {
|
||||
this.size(size, renderer, blockEntry.getId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier<Supplier<? extends BogeyRenderer>> renderer,
|
||||
ResourceLocation location) {
|
||||
this.sizes.put(size, location);
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
this.sizeRenderers.put(size, () -> new BogeyStyle.SizeRenderData(renderer.get(), renderer.get()
|
||||
.get()));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder contactParticle(ParticleOptions contactParticle) {
|
||||
this.contactParticle = contactParticle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder smokeParticle(ParticleOptions smokeParticle) {
|
||||
this.smokeParticle = smokeParticle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyleBuilder commonRenderer(Supplier<Supplier<? extends CommonRenderer>> commonRenderer) {
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
this.commonRenderer = Optional.of(commonRenderer.get());
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyle build() {
|
||||
BogeyStyle entry = new BogeyStyle(name, cycleGroup, displayName, soundType, contactParticle, smokeParticle,
|
||||
defaultData, sizes, sizeRenderers, commonRenderer);
|
||||
BOGEY_STYLES.put(name, entry);
|
||||
CYCLE_GROUPS.computeIfAbsent(cycleGroup, l -> new HashMap<>())
|
||||
.put(name, entry);
|
||||
return entry;
|
||||
}
|
||||
@ApiStatus.Internal
|
||||
public static void init() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class Create {
|
|||
AllFanProcessingTypes.register();
|
||||
BlockSpoutingBehaviour.registerDefaults();
|
||||
BogeySizes.init();
|
||||
AllBogeyStyles.register();
|
||||
AllBogeyStyles.init();
|
||||
// ----
|
||||
|
||||
ComputerCraftProxy.register();
|
||||
|
|
|
@ -4,18 +4,15 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllBogeyStyles;
|
||||
import com.simibubi.create.AllItems;
|
||||
|
@ -33,8 +30,6 @@ import com.simibubi.create.foundation.utility.Iterate;
|
|||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -57,8 +52,6 @@ import net.minecraft.world.level.block.state.properties.Property;
|
|||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> extends Block implements IBE<T>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
|
||||
|
@ -66,7 +59,6 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
||||
public BogeySizes.BogeySize size;
|
||||
|
||||
|
||||
public AbstractBogeyBlock(Properties pProperties, BogeySizes.BogeySize size) {
|
||||
super(pProperties);
|
||||
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));
|
||||
|
@ -91,7 +83,7 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
/**
|
||||
* Only for internal Create use. If you have your own style set, do not call this method
|
||||
*/
|
||||
@Deprecated
|
||||
@ApiStatus.Internal
|
||||
public static void registerStandardBogey(ResourceLocation block) {
|
||||
BOGEYS.add(block);
|
||||
}
|
||||
|
@ -147,30 +139,6 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
return false;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks,
|
||||
MultiBufferSource buffers, int light, int overlay, BogeyStyle style, CompoundTag bogeyData) {
|
||||
if (style == null)
|
||||
style = getDefaultStyle();
|
||||
|
||||
final Optional<BogeyRenderer.CommonRenderer> commonRenderer
|
||||
= style.getInWorldCommonRenderInstance();
|
||||
final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize());
|
||||
if (state != null) {
|
||||
ms.translate(.5f, .5f, .5f);
|
||||
if (state.getValue(AXIS) == Direction.Axis.X)
|
||||
ms.mulPose(Axis.YP.rotationDegrees(90));
|
||||
}
|
||||
ms.translate(0, -1.5 - 1 / 128f, 0);
|
||||
VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped());
|
||||
if (bogeyData == null)
|
||||
bogeyData = new CompoundTag();
|
||||
renderer.render(bogeyData, wheelAngle, ms, light, vb, state == null);
|
||||
CompoundTag finalBogeyData = bogeyData;
|
||||
commonRenderer.ifPresent(common ->
|
||||
common.render(finalBogeyData, wheelAngle, ms, light, vb, state == null));
|
||||
}
|
||||
|
||||
public BogeySizes.BogeySize getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
@ -216,9 +184,9 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
|
||||
Set<BogeySizes.BogeySize> validSizes = style.validSizes();
|
||||
|
||||
for (int i = 0; i < BogeySizes.count(); i++) {
|
||||
for (int i = 0; i < BogeySizes.all().size(); i++) {
|
||||
if (validSizes.contains(size)) break;
|
||||
size = size.increment();
|
||||
size = size.nextBySize();
|
||||
}
|
||||
|
||||
sbbe.setBogeyStyle(style);
|
||||
|
@ -227,7 +195,7 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
sbbe.setBogeyData(sbbe.getBogeyData().merge(defaultData));
|
||||
|
||||
if (size == getSize()) {
|
||||
if (state.getBlock() != style.getBlockOfSize(size)) {
|
||||
if (state.getBlock() != style.getBlockForSize(size)) {
|
||||
CompoundTag oldData = sbbe.getBogeyData();
|
||||
level.setBlock(pos, copyProperties(state, getStateOfSize(sbbe, size)), Block.UPDATE_ALL);
|
||||
if (!(level.getBlockEntity(pos) instanceof AbstractBogeyBlockEntity bogeyBlockEntity))
|
||||
|
@ -328,7 +296,7 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
|||
|
||||
public BlockState getStateOfSize(AbstractBogeyBlockEntity sbbe, BogeySizes.BogeySize size) {
|
||||
BogeyStyle style = sbbe.getStyle();
|
||||
BlockState state = style.getBlockOfSize(size).defaultBlockState();
|
||||
BlockState state = style.getBlockForSize(size).defaultBlockState();
|
||||
return copyProperties(sbbe.getBlockState(), state);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,14 +37,14 @@ public abstract class AbstractBogeyBlockEntity extends CachedRenderBBBlockEntity
|
|||
|
||||
public void setBogeyData(@NotNull CompoundTag newData) {
|
||||
if (!newData.contains(BOGEY_STYLE_KEY)) {
|
||||
ResourceLocation style = getDefaultStyle().name;
|
||||
ResourceLocation style = getDefaultStyle().id;
|
||||
NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style);
|
||||
}
|
||||
this.bogeyData = newData;
|
||||
}
|
||||
|
||||
public void setBogeyStyle(@NotNull BogeyStyle style) {
|
||||
ResourceLocation location = style.name;
|
||||
ResourceLocation location = style.id;
|
||||
CompoundTag data = this.getBogeyData();
|
||||
NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location);
|
||||
markUpdated();
|
||||
|
@ -80,7 +80,7 @@ public abstract class AbstractBogeyBlockEntity extends CachedRenderBBBlockEntity
|
|||
|
||||
private CompoundTag createBogeyData() {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().name);
|
||||
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().id);
|
||||
boolean upsideDown = false;
|
||||
if (getBlockState().getBlock() instanceof AbstractBogeyBlock<?> bogeyBlock)
|
||||
upsideDown = bogeyBlock.isUpsideDown(getBlockState());
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
||||
public class BackupBogeyRenderer extends BogeyRenderer.CommonRenderer {
|
||||
public static BackupBogeyRenderer INSTANCE = new BackupBogeyRenderer();
|
||||
|
||||
@Override
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class BogeyBlockEntityRenderer<T extends BlockEntity> extends SafeBlockEntityRenderer<T> {
|
||||
|
||||
public BogeyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {}
|
||||
public BogeyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||
|
@ -18,9 +20,12 @@ public class BogeyBlockEntityRenderer<T extends BlockEntity> extends SafeBlockEn
|
|||
BlockState blockState = be.getBlockState();
|
||||
if (be instanceof AbstractBogeyBlockEntity sbbe) {
|
||||
float angle = sbbe.getVirtualAngle(partialTicks);
|
||||
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey)
|
||||
bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbbe.getStyle(), sbbe.getBogeyData());
|
||||
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey) {
|
||||
ms.translate(.5f, .5f, .5f);
|
||||
if (blockState.getValue(AbstractBogeyBlock.AXIS) == Direction.Axis.X)
|
||||
ms.mulPose(Axis.YP.rotationDegrees(90));
|
||||
sbbe.getStyle().render(bogey.getSize(), partialTicks, ms, buffer, light, overlay, angle, sbbe.getBogeyData(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,399 +1,10 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3fc;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Quaternionfc;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.VirtualRenderHelper;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
|
||||
import dev.engine_room.flywheel.lib.instance.PosedInstance;
|
||||
import dev.engine_room.flywheel.lib.model.Models;
|
||||
import dev.engine_room.flywheel.lib.model.baked.PartialModel;
|
||||
import dev.engine_room.flywheel.lib.transform.Transform;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
/**
|
||||
* This is a port of the bogey api from Extended Bogeys, If you are looking to implement your own bogeys you can find some helpful resources below:
|
||||
* <p>
|
||||
* - <a href="https://github.com/Rabbitminers/Extended-Bogeys/tree/1.18/multiloader/dev/common/src/main/java/com/rabbitminers/extendedbogeys/bogeys/styles">Extended Bogeys (Examples)</a>
|
||||
* - <a href="https://github.com/Rabbitminers/Extended-Bogeys/blob/1.18/multiloader/dev/API_DOCS.md">Extended Bogeys (API documentation)</a>
|
||||
* - <a href="https://github.com/Layers-of-Railways/Railway/tree/93e318d1e922b1e992b89b0aceef85a2d545f370/common/src/main/java/com/railwayteam/railways/content/custom_bogeys">Steam n' Rails (Examples)</a>
|
||||
*/
|
||||
public abstract class BogeyRenderer {
|
||||
Map<String, BogeyModelData[]> contraptionModelData = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A common interface for getting transform data for both in-world and in-contraption model data safely from a
|
||||
* partial model
|
||||
*
|
||||
* @param model The key for the model data to instantiate or retrieve
|
||||
* @param ms The posestack used for contraption model data
|
||||
* @param inInstancedContraption The type of model needed
|
||||
* @param size The amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
public BogeyModelData[] getTransform(PartialModel model, PoseStack ms, boolean inInstancedContraption, int size) {
|
||||
return (inInstancedContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* A common interface for getting transform data for both in-world and in-contraption model data safely from a
|
||||
* blockstate
|
||||
*
|
||||
* @param state The key for the model data to instantiate or retrieve
|
||||
* @param ms The posestack used for contraption model data
|
||||
* @param inContraption The type of model needed
|
||||
* @param size The amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
public BogeyModelData[] getTransform(BlockState state, PoseStack ms, boolean inContraption, int size) {
|
||||
return inContraption ? transformContraptionModelData(keyFromModel(state), ms) : createModelData(state, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to collect or create a single model from a partial model used for both in-world and
|
||||
* in-contraption rendering
|
||||
*
|
||||
* @param model The key of the model to be collected or instantiated
|
||||
* @param ms Posestack to bind the model to if it is within a contraption
|
||||
* @param inInstancedContraption Type of rendering required
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
public BogeyModelData getTransform(PartialModel model, PoseStack ms, boolean inInstancedContraption) {
|
||||
return inInstancedContraption ? contraptionModelData.get(keyFromModel(model))[0].setTransform(ms)
|
||||
: BogeyModelData.from(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* A common interface for getting transform data for blockstates, for a single model
|
||||
*
|
||||
* @param state The state of the model to be collected or instantiated
|
||||
* @param ms Posestack to bind the model to if it is within a contraption
|
||||
* @param inContraption Type of model required
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
public BogeyModelData getTransform(BlockState state, PoseStack ms, boolean inContraption) {
|
||||
return (inContraption) ? contraptionModelData.get(keyFromModel(state))[0].setTransform(ms)
|
||||
: BogeyModelData.from(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for calling both in-world and in-contraption rendering
|
||||
*
|
||||
* @param bogeyData Custom data stored on the bogey able to be used for rendering
|
||||
* @param wheelAngle The angle of the wheel
|
||||
* @param ms The posestack to render to
|
||||
* @param light (Optional) Light used for in-world rendering
|
||||
* @param vb (Optional) Vertex Consumer used for in-world rendering
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public abstract void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light,
|
||||
VertexConsumer vb, boolean inContraption);
|
||||
|
||||
/**
|
||||
* Used for calling in-contraption rendering ensuring that falsey data is handled correctly
|
||||
*
|
||||
* @param bogeyData Custom data stored on the bogey able to be used for rendering
|
||||
* @param wheelAngle The angle of the wheel
|
||||
* @param ms The posestack to render to
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms) {
|
||||
this.render(bogeyData, wheelAngle, ms, 0, null, true);
|
||||
}
|
||||
|
||||
public abstract BogeySizes.BogeySize getSize();
|
||||
|
||||
/**
|
||||
* Used to collect Contraption Model Data for in-contraption rendering, should not be utilised directly when
|
||||
* rendering to prevent render type mismatch
|
||||
*
|
||||
* @param key The key used to access the model
|
||||
* @param ms Posestack of the contraption to bind the model data to
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
private BogeyModelData[] transformContraptionModelData(String key, PoseStack ms) {
|
||||
BogeyModelData[] modelData = contraptionModelData.get(key);
|
||||
Arrays.stream(modelData).forEach(modelDataElement -> modelDataElement.setTransform(ms));
|
||||
return modelData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response
|
||||
* when rendering multiple models both in-world and in-contraption for example, with wheels
|
||||
*
|
||||
* @param model The partial model of the model data ot be made
|
||||
* @param size The Amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
private BogeyModelData[] createModelData(PartialModel model, int size) {
|
||||
BogeyModelData[] data = { BogeyModelData.from(model) };
|
||||
return expandArrayToLength(data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response
|
||||
* when rendering multiple models both in-world and in-contraption for example, with wheels
|
||||
*
|
||||
* @param state The state of the model data to be made
|
||||
* @param size Amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
private BogeyModelData[] createModelData(BlockState state, int size) {
|
||||
BogeyModelData[] data = { BogeyModelData.from(state) };
|
||||
return expandArrayToLength(data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to clone in-world models to a set size to allow for common handling of rendering with multiple
|
||||
* instances of the same model for example with wheels
|
||||
*
|
||||
* @param data An in-world model to be replicated
|
||||
* @param size Amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
private BogeyModelData[] expandArrayToLength(BogeyModelData[] data, int size) {
|
||||
return Arrays.stream(Collections.nCopies(size, data).toArray())
|
||||
.flatMap(inner -> Arrays.stream((BogeyModelData[]) inner))
|
||||
.toArray(BogeyModelData[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides render implementations a point in setup to instantiate all model data to be needed
|
||||
*
|
||||
* @param context The visualization context
|
||||
* @param carriageBogey The bogey to create data for
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public abstract void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey);
|
||||
|
||||
/**
|
||||
* Creates instances of models for in-world rendering to a set length from a provided partial model
|
||||
*
|
||||
* @param context The visualization context
|
||||
* @param model Partial model to be instanced
|
||||
* @param count Amount of models neeeded
|
||||
*/
|
||||
public void createModelInstance(VisualizationContext context, PartialModel model, int count) {
|
||||
var instancer = context.instancerProvider()
|
||||
.instancer(InstanceTypes.POSED, Models.partial(model));
|
||||
BogeyModelData[] modelData = IntStream.range(0, count)
|
||||
.mapToObj(i -> instancer.createInstance())
|
||||
.map(BogeyModelData::new)
|
||||
.toArray(BogeyModelData[]::new);
|
||||
contraptionModelData.put(keyFromModel(model), modelData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instances of models for in-contraption rendering to a set length from a provided blockstate
|
||||
*
|
||||
* @param context The visualization context
|
||||
* @param state Blockstate of the model to be created
|
||||
* @param count Amount of models needed
|
||||
*/
|
||||
public void createModelInstance(VisualizationContext context, BlockState state, int count) {
|
||||
var instancer = context.instancerProvider()
|
||||
.instancer(InstanceTypes.POSED, VirtualRenderHelper.blockModel(state));
|
||||
BogeyModelData[] modelData = IntStream.range(0, count)
|
||||
.mapToObj(i -> instancer.createInstance())
|
||||
.map(BogeyModelData::new)
|
||||
.toArray(BogeyModelData[]::new);
|
||||
contraptionModelData.put(keyFromModel(state), modelData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single instance of models for in-contraption rendering from a provided blockstate
|
||||
*
|
||||
* @param context The visualization context
|
||||
* @param states Blockstates of the models to be created
|
||||
*/
|
||||
public void createModelInstance(VisualizationContext context, BlockState... states) {
|
||||
for (BlockState state : states)
|
||||
this.createModelInstance(context, state, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a single model instance for in-contraption rendering
|
||||
*
|
||||
* @param context The visualization context
|
||||
* @param models The type of model to create instances of
|
||||
*/
|
||||
public void createModelInstance(VisualizationContext context, PartialModel... models) {
|
||||
for (PartialModel model : models)
|
||||
createModelInstance(context, model, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated, use BogeyModelData#render instead, left in
|
||||
* to avoid existing usages from crashing
|
||||
*
|
||||
* @param b The model data itself
|
||||
* @param ms Pose stack to render to
|
||||
* @param light light level of the scene
|
||||
* @param vb Vertex Consumber to render to
|
||||
* @param <B> Generic alias for both contraption and in-world model data
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
public static <B extends Transform<?>> void finalize(B b, PoseStack ms, int light, @Nullable VertexConsumer vb) {
|
||||
b.scale(1 - 1/512f);
|
||||
if (b instanceof SuperByteBuffer byteBuf && vb != null)
|
||||
byteBuf.light(light).renderInto(ms, vb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic handling for setting empty transforms for all model data
|
||||
*
|
||||
*/
|
||||
|
||||
public void emptyTransforms() {
|
||||
for (BogeyModelData[] data : contraptionModelData.values())
|
||||
for (BogeyModelData model : data)
|
||||
model.setEmptyTransform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic handling for updating all model data's light
|
||||
*
|
||||
* @param blockLight the blocklight to be applied
|
||||
* @param skyLight the skylight to be applied
|
||||
*/
|
||||
|
||||
public void updateLight(int blockLight, int skyLight) {
|
||||
for (BogeyModelData[] data : contraptionModelData.values())
|
||||
for (BogeyModelData model : data)
|
||||
model.updateLight(blockLight, skyLight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic handling for clearing all model data of a contraption
|
||||
*
|
||||
*/
|
||||
|
||||
public void remove() {
|
||||
for (BogeyModelData[] data : contraptionModelData.values())
|
||||
for (BogeyModelData model : data)
|
||||
model.delete();
|
||||
contraptionModelData.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a model key from a partial model, so it can be easily accessed
|
||||
*
|
||||
* @param partialModel the model we want a unique key for
|
||||
* @return Key of the model
|
||||
*/
|
||||
|
||||
private String keyFromModel(PartialModel partialModel) {
|
||||
return partialModel.modelLocation().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a model key from a blockstate, so it can be easily accessed
|
||||
*
|
||||
* @param state Blockstate of the model
|
||||
* @return Key of the model
|
||||
*/
|
||||
|
||||
private String keyFromModel(BlockState state) {
|
||||
return state.toString();
|
||||
}
|
||||
|
||||
public static abstract class CommonRenderer extends BogeyRenderer {
|
||||
@Override
|
||||
public BogeySizes.BogeySize getSize() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public record BogeyModelData(Transform<?> transform) implements Transform<BogeyModelData> {
|
||||
public static BogeyModelData from(PartialModel model) {
|
||||
BlockState air = Blocks.AIR.defaultBlockState();
|
||||
return new BogeyModelData(CachedBufferer.partial(model, air));
|
||||
}
|
||||
public static BogeyModelData from(BlockState model) {
|
||||
return new BogeyModelData(CachedBufferer.block(model));
|
||||
}
|
||||
public void render(PoseStack ms, int light, @Nullable VertexConsumer vb) {
|
||||
transform.scale(1 - 1/512f);
|
||||
if (transform instanceof SuperByteBuffer byteBuf && vb != null)
|
||||
byteBuf.light(light).renderInto(ms, vb);
|
||||
}
|
||||
|
||||
public BogeyModelData setTransform(PoseStack ms) {
|
||||
if (this.transform instanceof PosedInstance model)
|
||||
model.setTransform(ms)
|
||||
.setChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyModelData setEmptyTransform() {
|
||||
if (this.transform instanceof PosedInstance model)
|
||||
model.setZeroTransform()
|
||||
.setChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyModelData delete() {
|
||||
if (this.transform instanceof PosedInstance model)
|
||||
model.delete();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyModelData updateLight(int blockLight, int skyLight) {
|
||||
if (this.transform instanceof PosedInstance model)
|
||||
model.light(blockLight, skyLight)
|
||||
.setChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyModelData mulPose(Matrix4fc pose) {
|
||||
this.transform.mulPose(pose);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyModelData mulNormal(Matrix3fc normal) {
|
||||
this.transform.mulNormal(normal);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyModelData rotate(Quaternionfc quaternion) {
|
||||
this.transform.rotate(quaternion);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyModelData scale(float factorX, float factorY, float factorZ) {
|
||||
this.transform.scale(factorX, factorY, factorZ);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyModelData translate(float x, float y, float z) {
|
||||
this.transform.translate(x, y, z);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public interface BogeyRenderer {
|
||||
void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, boolean inContraption);
|
||||
}
|
||||
|
|
|
@ -1,70 +1,78 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.UnmodifiableView;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class BogeySizes {
|
||||
private static final Collection<BogeySize> BOGEY_SIZES = new HashSet<>();
|
||||
public static final BogeySize SMALL = new BogeySize(Create.ID, "small", 6.5f / 16f);
|
||||
public static final BogeySize LARGE = new BogeySize(Create.ID, "large", 12.5f / 16f);
|
||||
public final class BogeySizes {
|
||||
private static final Map<ResourceLocation, BogeySize> BOGEY_SIZES = new HashMap<>();
|
||||
private static final List<BogeySize> SORTED_INCREASING = new ArrayList<>();
|
||||
private static final List<BogeySize> SORTED_DECREASING = new ArrayList<>();
|
||||
@UnmodifiableView
|
||||
private static final Map<ResourceLocation, BogeySize> BOGEY_SIZES_VIEW = Collections.unmodifiableMap(BOGEY_SIZES);
|
||||
@UnmodifiableView
|
||||
private static final List<BogeySize> SORTED_INCREASING_VIEW = Collections.unmodifiableList(SORTED_INCREASING);
|
||||
@UnmodifiableView
|
||||
private static final List<BogeySize> SORTED_DECREASING_VIEW = Collections.unmodifiableList(SORTED_DECREASING);
|
||||
|
||||
public static final BogeySize SMALL = new BogeySize(Create.asResource("small"), 6.5f / 16f);
|
||||
public static final BogeySize LARGE = new BogeySize(Create.asResource("large"), 12.5f / 16f);
|
||||
|
||||
static {
|
||||
BOGEY_SIZES.add(SMALL);
|
||||
BOGEY_SIZES.add(LARGE);
|
||||
register(SMALL);
|
||||
register(LARGE);
|
||||
}
|
||||
|
||||
public static BogeySize addSize(String modId, String name, float size) {
|
||||
ResourceLocation location = new ResourceLocation(modId, name);
|
||||
return addSize(location, size);
|
||||
private BogeySizes() {
|
||||
}
|
||||
|
||||
public static BogeySize addSize(ResourceLocation location, float size) {
|
||||
BogeySize customSize = new BogeySize(location, size);
|
||||
BOGEY_SIZES.add(customSize);
|
||||
return customSize;
|
||||
}
|
||||
|
||||
public static List<BogeySize> getAllSizesSmallToLarge() {
|
||||
return BOGEY_SIZES.stream()
|
||||
.sorted(Comparator.comparing(BogeySize::wheelRadius))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<BogeySize> getAllSizesLargeToSmall() {
|
||||
List<BogeySize> sizes = getAllSizesSmallToLarge();
|
||||
Collections.reverse(sizes);
|
||||
return sizes;
|
||||
}
|
||||
|
||||
public static int count() {
|
||||
return BOGEY_SIZES.size();
|
||||
}
|
||||
|
||||
public record BogeySize(ResourceLocation location, float wheelRadius) {
|
||||
public BogeySize(String modId, String name, float wheelRadius) {
|
||||
this(new ResourceLocation(modId, name), wheelRadius);
|
||||
public static void register(BogeySize size) {
|
||||
ResourceLocation id = size.id();
|
||||
if (BOGEY_SIZES.containsKey(id)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
BOGEY_SIZES.put(id, size);
|
||||
|
||||
public BogeySize increment() {
|
||||
List<BogeySize> values = getAllSizesSmallToLarge();
|
||||
SORTED_INCREASING.add(size);
|
||||
SORTED_DECREASING.add(size);
|
||||
SORTED_INCREASING.sort(Comparator.comparing(BogeySize::wheelRadius));
|
||||
SORTED_DECREASING.sort(Comparator.comparing(BogeySize::wheelRadius).reversed());
|
||||
}
|
||||
|
||||
@UnmodifiableView
|
||||
public static Map<ResourceLocation, BogeySize> all() {
|
||||
return BOGEY_SIZES_VIEW;
|
||||
}
|
||||
|
||||
@UnmodifiableView
|
||||
public static List<BogeySize> allSortedIncreasing() {
|
||||
return SORTED_INCREASING_VIEW;
|
||||
}
|
||||
|
||||
@UnmodifiableView
|
||||
public static List<BogeySize> allSortedDecreasing() {
|
||||
return SORTED_DECREASING_VIEW;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public record BogeySize(ResourceLocation id, float wheelRadius) {
|
||||
public BogeySize nextBySize() {
|
||||
List<BogeySize> values = allSortedIncreasing();
|
||||
int ordinal = values.indexOf(this);
|
||||
return values.get((ordinal + 1) % values.size());
|
||||
}
|
||||
|
||||
public boolean is(BogeySize size) {
|
||||
return size.location == this.location;
|
||||
}
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,60 +2,53 @@ package com.simibubi.create.content.trains.bogey;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBogeyStyles;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyRenderer.CommonRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.BogeySizes.BogeySize;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
|
||||
public class BogeyStyle {
|
||||
|
||||
public final ResourceLocation name;
|
||||
public final ResourceLocation id;
|
||||
public final ResourceLocation cycleGroup;
|
||||
public final Component displayName;
|
||||
public final ResourceLocation soundType;
|
||||
public final Supplier<SoundEvent> soundEvent;
|
||||
public final ParticleOptions contactParticle;
|
||||
public final ParticleOptions smokeParticle;
|
||||
public final CompoundTag defaultData;
|
||||
|
||||
private Optional<Supplier<? extends CommonRenderer>> commonRendererFactory;
|
||||
private Map<BogeySizes.BogeySize, ResourceLocation> sizes;
|
||||
private final Map<BogeySizes.BogeySize, Supplier<? extends AbstractBogeyBlock<?>>> sizes;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private Map<BogeySizes.BogeySize, SizeRenderData> sizeRenderers;
|
||||
private Map<BogeySizes.BogeySize, SizeRenderer> sizeRenderers;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private Optional<CommonRenderer> commonRenderer;
|
||||
public BogeyStyle(ResourceLocation id, ResourceLocation cycleGroup, Component displayName,
|
||||
Supplier<SoundEvent> soundEvent, ParticleOptions contactParticle, ParticleOptions smokeParticle,
|
||||
CompoundTag defaultData, Map<BogeySizes.BogeySize, Supplier<? extends AbstractBogeyBlock<?>>> sizes,
|
||||
Map<BogeySizes.BogeySize, Supplier<? extends SizeRenderer>> sizeRenderers) {
|
||||
|
||||
public BogeyStyle(ResourceLocation name, ResourceLocation cycleGroup, Component displayName,
|
||||
ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle,
|
||||
CompoundTag defaultData, Map<BogeySizes.BogeySize, ResourceLocation> sizes,
|
||||
Map<BogeySizes.BogeySize, Supplier<SizeRenderData>> sizeRenderers,
|
||||
Optional<Supplier<? extends CommonRenderer>> commonRenderer) {
|
||||
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.cycleGroup = cycleGroup;
|
||||
this.displayName = displayName;
|
||||
this.soundType = soundType;
|
||||
this.soundEvent = soundEvent;
|
||||
this.contactParticle = contactParticle;
|
||||
this.smokeParticle = smokeParticle;
|
||||
this.defaultData = defaultData;
|
||||
|
@ -64,9 +57,6 @@ public class BogeyStyle {
|
|||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
this.sizeRenderers = new HashMap<>();
|
||||
sizeRenderers.forEach((k, v) -> this.sizeRenderers.put(k, v.get()));
|
||||
|
||||
this.commonRendererFactory = commonRenderer;
|
||||
this.commonRenderer = commonRenderer.map(Supplier::get);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -74,60 +64,109 @@ public class BogeyStyle {
|
|||
return AllBogeyStyles.getCycleGroup(cycleGroup);
|
||||
}
|
||||
|
||||
public Block getNextBlock(BogeySizes.BogeySize currentSize) {
|
||||
return Stream.iterate(currentSize.increment(), BogeySizes.BogeySize::increment)
|
||||
.filter(sizes::containsKey)
|
||||
.findFirst()
|
||||
.map(this::getBlockOfSize)
|
||||
.orElse(getBlockOfSize(currentSize));
|
||||
}
|
||||
|
||||
public Block getBlockOfSize(BogeySizes.BogeySize size) {
|
||||
return ForgeRegistries.BLOCKS.getValue(sizes.get(size));
|
||||
}
|
||||
|
||||
public Set<BogeySizes.BogeySize> validSizes() {
|
||||
return sizes.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SoundEvent getSoundType() {
|
||||
AllSoundEvents.SoundEntry entry = AllSoundEvents.ALL.get(this.soundType);
|
||||
if (entry == null || entry.getMainEvent() == null) entry = AllSoundEvents.TRAIN2;
|
||||
return entry.getMainEvent();
|
||||
public AbstractBogeyBlock<?> getBlockForSize(BogeySizes.BogeySize size) {
|
||||
return sizes.get(size).get();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public AbstractBogeyBlock<?> getNextBlock(BogeySizes.BogeySize currentSize) {
|
||||
return Stream.iterate(currentSize.nextBySize(), BogeySizes.BogeySize::nextBySize)
|
||||
.filter(sizes::containsKey)
|
||||
.findFirst()
|
||||
.map(this::getBlockForSize)
|
||||
.orElse((AbstractBogeyBlock) getBlockForSize(currentSize));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public BogeyRenderer createRendererInstance(BogeySizes.BogeySize size) {
|
||||
return this.sizeRenderers.get(size).createRenderInstance();
|
||||
public void render(BogeySize size, float partialTick, PoseStack poseStack, MultiBufferSource buffers, int light, int overlay, float wheelAngle, @Nullable CompoundTag bogeyData, boolean inContraption) {
|
||||
if (bogeyData == null)
|
||||
bogeyData = new CompoundTag();
|
||||
|
||||
poseStack.translate(0, -1.5 - 1 / 128f, 0);
|
||||
|
||||
SizeRenderer renderer = sizeRenderers.get(size);
|
||||
if (renderer != null) {
|
||||
renderer.renderer.render(bogeyData, wheelAngle, partialTick, poseStack, buffers, light, overlay, inContraption);
|
||||
}
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public BogeyRenderer getInWorldRenderInstance(BogeySizes.BogeySize size) {
|
||||
SizeRenderData sizeData = this.sizeRenderers.get(size);
|
||||
return sizeData != null ? sizeData.getInWorldInstance() : BackupBogeyRenderer.INSTANCE;
|
||||
}
|
||||
|
||||
public Optional<CommonRenderer> getInWorldCommonRenderInstance() {
|
||||
return this.commonRenderer;
|
||||
}
|
||||
|
||||
public Optional<CommonRenderer> getNewCommonRenderInstance() {
|
||||
return this.commonRendererFactory.map(Supplier::get);
|
||||
}
|
||||
|
||||
public BogeyVisual createVisual(CarriageBogey bogey, BogeySizes.BogeySize size, VisualizationContext context) {
|
||||
return new BogeyVisual(bogey, this, size, context);
|
||||
@Nullable
|
||||
public BogeyVisual createVisual(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||
SizeRenderer renderer = sizeRenderers.get(bogey.getSize());
|
||||
if (renderer != null) {
|
||||
return renderer.visualizer.createVisual(ctx, bogey, partialTick);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public record SizeRenderData(Supplier<? extends BogeyRenderer> rendererFactory, BogeyRenderer instance) {
|
||||
public BogeyRenderer createRenderInstance() {
|
||||
return rendererFactory.get();
|
||||
public record SizeRenderer(BogeyRenderer renderer, BogeyVisualizer visualizer) {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
protected final ResourceLocation id;
|
||||
protected final ResourceLocation cycleGroup;
|
||||
protected final Map<BogeySizes.BogeySize, Supplier<? extends AbstractBogeyBlock<?>>> sizes = new HashMap<>();
|
||||
|
||||
protected Component displayName = Lang.translateDirect("bogey.style.invalid");
|
||||
protected Supplier<SoundEvent> soundEvent = AllSoundEvents.TRAIN2::getMainEvent;
|
||||
protected ParticleOptions contactParticle = ParticleTypes.CRIT;
|
||||
protected ParticleOptions smokeParticle = ParticleTypes.POOF;
|
||||
protected CompoundTag defaultData = new CompoundTag();
|
||||
|
||||
protected final Map<BogeySizes.BogeySize, Supplier<? extends SizeRenderer>> sizeRenderers = new HashMap<>();
|
||||
|
||||
public Builder(ResourceLocation id, ResourceLocation cycleGroup) {
|
||||
this.id = id;
|
||||
this.cycleGroup = cycleGroup;
|
||||
}
|
||||
|
||||
public BogeyRenderer getInWorldInstance() {
|
||||
return instance;
|
||||
public Builder displayName(Component displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder soundEvent(Supplier<SoundEvent> soundEvent) {
|
||||
this.soundEvent = soundEvent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder contactParticle(ParticleOptions contactParticle) {
|
||||
this.contactParticle = contactParticle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder smokeParticle(ParticleOptions smokeParticle) {
|
||||
this.smokeParticle = smokeParticle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder defaultData(CompoundTag defaultData) {
|
||||
this.defaultData = defaultData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder size(BogeySizes.BogeySize size, Supplier<? extends AbstractBogeyBlock<?>> block,
|
||||
Supplier<? extends SizeRenderer> renderer) {
|
||||
this.sizes.put(size, block);
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||
this.sizeRenderers.put(size, renderer);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public BogeyStyle build() {
|
||||
BogeyStyle entry = new BogeyStyle(id, cycleGroup, displayName, soundEvent, contactParticle, smokeParticle,
|
||||
defaultData, sizes, sizeRenderers);
|
||||
AllBogeyStyles.BOGEY_STYLES.put(id, entry);
|
||||
AllBogeyStyles.CYCLE_GROUPS.computeIfAbsent(cycleGroup, l -> new HashMap<>())
|
||||
.put(id, entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,13 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
import com.simibubi.create.content.trains.entity.CarriageContraptionEntity;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
public interface BogeyVisual {
|
||||
void update(float wheelAngle, PoseStack poseStack);
|
||||
|
||||
public final class BogeyVisual {
|
||||
private final BogeySizes.BogeySize size;
|
||||
private final BogeyStyle style;
|
||||
void hide();
|
||||
|
||||
public final CarriageBogey bogey;
|
||||
public final BogeyRenderer renderer;
|
||||
public final Optional<BogeyRenderer.CommonRenderer> commonRenderer;
|
||||
void updateLight(int packedLight);
|
||||
|
||||
public BogeyVisual(CarriageBogey bogey, BogeyStyle style, BogeySizes.BogeySize size,
|
||||
VisualizationContext context) {
|
||||
this.bogey = bogey;
|
||||
this.size = size;
|
||||
this.style = style;
|
||||
|
||||
this.renderer = this.style.createRendererInstance(this.size);
|
||||
this.commonRenderer = this.style.getNewCommonRenderInstance();
|
||||
|
||||
commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.initialiseContraptionModelData(context, bogey));
|
||||
renderer.initialiseContraptionModelData(context, bogey);
|
||||
}
|
||||
|
||||
public void beginFrame(float wheelAngle, PoseStack ms) {
|
||||
if (ms == null) {
|
||||
renderer.emptyTransforms();
|
||||
return;
|
||||
}
|
||||
|
||||
commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.render(bogey.bogeyData, wheelAngle, ms));
|
||||
renderer.render(bogey.bogeyData, wheelAngle, ms);
|
||||
}
|
||||
|
||||
public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) {
|
||||
var lightPos = BlockPos.containing(getLightPos(entity));
|
||||
commonRenderer
|
||||
.ifPresent(bogeyRenderer -> bogeyRenderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos),
|
||||
world.getBrightness(LightLayer.SKY, lightPos)));
|
||||
renderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos),
|
||||
world.getBrightness(LightLayer.SKY, lightPos));
|
||||
}
|
||||
|
||||
private Vec3 getLightPos(CarriageContraptionEntity entity) {
|
||||
return bogey.getAnchorPosition() != null ? bogey.getAnchorPosition()
|
||||
: entity.getLightProbePosition(AnimationTickHolder.getPartialTicks());
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface BogeyVisualFactory {
|
||||
BogeyVisual create(CarriageBogey bogey, BogeySizes.BogeySize size, VisualizationContext context);
|
||||
}
|
||||
void delete();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BogeyVisualizer {
|
||||
BogeyVisual createVisual(VisualizationContext ctx, CarriageBogey bogey, float partialTick);
|
||||
}
|
|
@ -1,134 +1,109 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import static com.simibubi.create.AllPartialModels.BOGEY_DRIVE;
|
||||
import static com.simibubi.create.AllPartialModels.BOGEY_FRAME;
|
||||
import static com.simibubi.create.AllPartialModels.BOGEY_PIN;
|
||||
import static com.simibubi.create.AllPartialModels.BOGEY_PISTON;
|
||||
import static com.simibubi.create.AllPartialModels.LARGE_BOGEY_WHEELS;
|
||||
import static com.simibubi.create.AllPartialModels.SMALL_BOGEY_WHEELS;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
public class StandardBogeyRenderer {
|
||||
public static class CommonStandardBogeyRenderer extends BogeyRenderer.CommonRenderer {
|
||||
@Override
|
||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
||||
createModelInstance(context, AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), 2);
|
||||
}
|
||||
public class StandardBogeyRenderer implements BogeyRenderer {
|
||||
@Override
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||
|
||||
@Override
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||
boolean inInstancedContraption = vb == null;
|
||||
BogeyModelData[] shafts = getTransform(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inInstancedContraption, 2);
|
||||
for (int i : Iterate.zeroAndOne) {
|
||||
shafts[i].translate(-.5f, .25f, i * -1)
|
||||
.center()
|
||||
.rotateZDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.render(ms, light, vb);
|
||||
}
|
||||
SuperByteBuffer shaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z));
|
||||
for (int i : Iterate.zeroAndOne) {
|
||||
shaft.translate(-.5f, .25f, i * -1)
|
||||
.center()
|
||||
.rotateZDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SmallStandardBogeyRenderer extends BogeyRenderer {
|
||||
public static class Small extends StandardBogeyRenderer {
|
||||
@Override
|
||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
||||
createModelInstance(context, SMALL_BOGEY_WHEELS, 2);
|
||||
createModelInstance(context, BOGEY_FRAME);
|
||||
}
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||
super.render(bogeyData, wheelAngle, partialTick, poseStack, bufferSource, light, overlay, inContraption);
|
||||
|
||||
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||
|
||||
@Override
|
||||
public BogeySizes.BogeySize getSize() {
|
||||
return BogeySizes.SMALL;
|
||||
}
|
||||
CachedBufferer.partial(AllPartialModels.BOGEY_FRAME, Blocks.AIR.defaultBlockState())
|
||||
.scale(1 - 1 / 512f)
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
|
||||
@Override
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||
boolean inInstancedContraption = vb == null;
|
||||
getTransform(BOGEY_FRAME, ms, inInstancedContraption)
|
||||
.render(ms, light, vb);
|
||||
|
||||
BogeyModelData[] wheels = getTransform(SMALL_BOGEY_WHEELS, ms, inInstancedContraption, 2);
|
||||
SuperByteBuffer wheels = CachedBufferer.partial(AllPartialModels.SMALL_BOGEY_WHEELS, Blocks.AIR.defaultBlockState());
|
||||
for (int side : Iterate.positiveAndNegative) {
|
||||
if (!inInstancedContraption)
|
||||
ms.pushPose();
|
||||
wheels[(side + 1)/2]
|
||||
.translate(0, 12 / 16f, side)
|
||||
wheels.translate(0, 12 / 16f, side)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.render(ms, light, vb);
|
||||
if (!inInstancedContraption)
|
||||
ms.popPose();
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LargeStandardBogeyRenderer extends BogeyRenderer {
|
||||
public static class Large extends StandardBogeyRenderer {
|
||||
@Override
|
||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
||||
createModelInstance(context, LARGE_BOGEY_WHEELS, BOGEY_DRIVE, BOGEY_PISTON, BOGEY_PIN);
|
||||
createModelInstance(context, AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X), 2);
|
||||
}
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||
super.render(bogeyData, wheelAngle, partialTick, poseStack, bufferSource, light, overlay, inContraption);
|
||||
|
||||
@Override
|
||||
public BogeySizes.BogeySize getSize() {
|
||||
return BogeySizes.LARGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||
boolean inInstancedContraption = vb == null;
|
||||
|
||||
BogeyModelData[] secondaryShafts = getTransform(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X), ms, inInstancedContraption, 2);
|
||||
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||
|
||||
SuperByteBuffer secondaryShaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X));
|
||||
for (int i : Iterate.zeroAndOne) {
|
||||
secondaryShafts[i]
|
||||
.translate(-.5f, .25f, .5f + i * -2)
|
||||
secondaryShaft.translate(-.5f, .25f, .5f + i * -2)
|
||||
.center()
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.render(ms, light, vb);
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
}
|
||||
|
||||
getTransform(BOGEY_DRIVE, ms, inInstancedContraption)
|
||||
.render(ms, light, vb);
|
||||
CachedBufferer.partial(AllPartialModels.BOGEY_DRIVE, Blocks.AIR.defaultBlockState())
|
||||
.scale(1 - 1 / 512f)
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
|
||||
getTransform(BOGEY_PISTON, ms, inInstancedContraption)
|
||||
CachedBufferer.partial(AllPartialModels.BOGEY_PISTON, Blocks.AIR.defaultBlockState())
|
||||
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)))
|
||||
.render(ms, light, vb);
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
|
||||
if (!inInstancedContraption)
|
||||
ms.pushPose();
|
||||
|
||||
getTransform(LARGE_BOGEY_WHEELS, ms, inInstancedContraption)
|
||||
CachedBufferer.partial(AllPartialModels.LARGE_BOGEY_WHEELS, Blocks.AIR.defaultBlockState())
|
||||
.translate(0, 1, 0)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.render(ms, light, vb);
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
|
||||
getTransform(BOGEY_PIN, ms, inInstancedContraption)
|
||||
CachedBufferer.partial(AllPartialModels.BOGEY_PIN, Blocks.AIR.defaultBlockState())
|
||||
.translate(0, 1, 0)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.translate(0, 1 / 4f, 0)
|
||||
.rotateXDegrees(-wheelAngle)
|
||||
.render(ms, light, vb);
|
||||
|
||||
if (!inInstancedContraption)
|
||||
ms.popPose();
|
||||
.light(light)
|
||||
.overlay(overlay)
|
||||
.renderInto(poseStack, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
package com.simibubi.create.content.trains.bogey;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllPartialModels;
|
||||
import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock;
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
import com.simibubi.create.foundation.render.VirtualRenderHelper;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import dev.engine_room.flywheel.lib.instance.InstanceTypes;
|
||||
import dev.engine_room.flywheel.lib.instance.TransformedInstance;
|
||||
import dev.engine_room.flywheel.lib.model.Models;
|
||||
import net.minecraft.core.Direction;
|
||||
|
||||
public class StandardBogeyVisual implements BogeyVisual {
|
||||
private final TransformedInstance shaft1;
|
||||
private final TransformedInstance shaft2;
|
||||
|
||||
public StandardBogeyVisual(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||
var shaftInstancer = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z)));
|
||||
shaft1 = shaftInstancer.createInstance();
|
||||
shaft2 = shaftInstancer.createInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float wheelAngle, PoseStack poseStack) {
|
||||
shaft1.setTransform(poseStack)
|
||||
.translate(-.5f, .25f, 0)
|
||||
.center()
|
||||
.rotateZDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.setChanged();
|
||||
shaft2.setTransform(poseStack)
|
||||
.translate(-.5f, .25f, -1)
|
||||
.center()
|
||||
.rotateZDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
shaft1.setZeroTransform().setChanged();
|
||||
shaft2.setZeroTransform().setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight(int packedLight) {
|
||||
shaft1.light(packedLight).setChanged();
|
||||
shaft2.light(packedLight).setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
shaft1.delete();
|
||||
shaft2.delete();
|
||||
}
|
||||
|
||||
public static class Small extends StandardBogeyVisual {
|
||||
private final TransformedInstance frame;
|
||||
private final TransformedInstance wheel1;
|
||||
private final TransformedInstance wheel2;
|
||||
|
||||
public Small(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||
super(ctx, bogey, partialTick);
|
||||
var wheelInstancer = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.SMALL_BOGEY_WHEELS));
|
||||
frame = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_FRAME))
|
||||
.createInstance();
|
||||
wheel1 = wheelInstancer.createInstance();
|
||||
wheel2 = wheelInstancer.createInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float wheelAngle, PoseStack poseStack) {
|
||||
super.update(wheelAngle, poseStack);
|
||||
wheel1.setTransform(poseStack)
|
||||
.translate(0, 12 / 16f, -1)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.setChanged();
|
||||
wheel2.setTransform(poseStack)
|
||||
.translate(0, 12 / 16f, 1)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.setChanged();
|
||||
frame.setTransform(poseStack)
|
||||
.scale(1 - 1 / 512f)
|
||||
.setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
super.hide();
|
||||
frame.setZeroTransform().setChanged();
|
||||
wheel1.setZeroTransform().setChanged();
|
||||
wheel2.setZeroTransform().setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight(int packedLight) {
|
||||
super.updateLight(packedLight);
|
||||
frame.light(packedLight).setChanged();
|
||||
wheel1.light(packedLight).setChanged();
|
||||
wheel2.light(packedLight).setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
super.delete();
|
||||
frame.delete();
|
||||
wheel1.delete();
|
||||
wheel2.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Large extends StandardBogeyVisual {
|
||||
private final TransformedInstance secondaryShaft1;
|
||||
private final TransformedInstance secondaryShaft2;
|
||||
private final TransformedInstance drive;
|
||||
private final TransformedInstance piston;
|
||||
private final TransformedInstance wheels;
|
||||
private final TransformedInstance pin;
|
||||
|
||||
public Large(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||
super(ctx, bogey, partialTick);
|
||||
var secondaryShaftInstancer = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, VirtualRenderHelper.blockModel(AllBlocks.SHAFT.getDefaultState()
|
||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X)));
|
||||
secondaryShaft1 = secondaryShaftInstancer.createInstance();
|
||||
secondaryShaft2 = secondaryShaftInstancer.createInstance();
|
||||
drive = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_DRIVE))
|
||||
.createInstance();
|
||||
piston = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_PISTON))
|
||||
.createInstance();
|
||||
wheels = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.LARGE_BOGEY_WHEELS))
|
||||
.createInstance();
|
||||
pin = ctx.instancerProvider()
|
||||
.instancer(InstanceTypes.TRANSFORMED, Models.partial(AllPartialModels.BOGEY_PIN))
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float wheelAngle, PoseStack poseStack) {
|
||||
super.update(wheelAngle, poseStack);
|
||||
secondaryShaft1.setTransform(poseStack)
|
||||
.translate(-.5f, .25f, .5f)
|
||||
.center()
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.setChanged();
|
||||
secondaryShaft2.setTransform(poseStack)
|
||||
.translate(-.5f, .25f, -1.5f)
|
||||
.center()
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.uncenter()
|
||||
.setChanged();
|
||||
drive.setTransform(poseStack)
|
||||
.scale(1 - 1/512f)
|
||||
.setChanged();
|
||||
piston.setTransform(poseStack)
|
||||
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)))
|
||||
.setChanged();
|
||||
wheels.setTransform(poseStack)
|
||||
.translate(0, 1, 0)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.setChanged();
|
||||
pin.setTransform(poseStack)
|
||||
.translate(0, 1, 0)
|
||||
.rotateXDegrees(wheelAngle)
|
||||
.translate(0, 1 / 4f, 0)
|
||||
.rotateXDegrees(-wheelAngle)
|
||||
.setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
super.hide();
|
||||
secondaryShaft1.setZeroTransform().setChanged();
|
||||
secondaryShaft2.setZeroTransform().setChanged();
|
||||
wheels.setZeroTransform().setChanged();
|
||||
drive.setZeroTransform().setChanged();
|
||||
piston.setZeroTransform().setChanged();
|
||||
pin.setZeroTransform().setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight(int packedLight) {
|
||||
super.updateLight(packedLight);
|
||||
secondaryShaft1.light(packedLight).setChanged();
|
||||
secondaryShaft2.light(packedLight).setChanged();
|
||||
wheels.light(packedLight).setChanged();
|
||||
drive.light(packedLight).setChanged();
|
||||
piston.light(packedLight).setChanged();
|
||||
pin.light(packedLight).setChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
super.delete();
|
||||
secondaryShaft1.delete();
|
||||
secondaryShaft2.delete();
|
||||
wheels.delete();
|
||||
drive.delete();
|
||||
piston.delete();
|
||||
pin.delete();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,8 @@ import com.simibubi.create.AllBogeyStyles;
|
|||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock;
|
||||
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity;
|
||||
import com.simibubi.create.content.trains.bogey.BogeySizes.BogeySize;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyStyle;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyVisual;
|
||||
import com.simibubi.create.content.trains.graph.DimensionPalette;
|
||||
import com.simibubi.create.content.trains.graph.TrackGraph;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
|
@ -21,7 +21,6 @@ import com.simibubi.create.foundation.utility.RegisteredObjects;
|
|||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
|
||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
@ -184,7 +183,7 @@ public class CarriageBogey {
|
|||
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
|
||||
tag.putBoolean("UpsideDown", upsideDown);
|
||||
bogeyData.putBoolean(UPSIDE_DOWN_KEY, upsideDown);
|
||||
NBTHelper.writeResourceLocation(bogeyData, BOGEY_STYLE_KEY, getStyle().name);
|
||||
NBTHelper.writeResourceLocation(bogeyData, BOGEY_STYLE_KEY, getStyle().id);
|
||||
tag.put(BOGEY_DATA_KEY, bogeyData);
|
||||
return tag;
|
||||
}
|
||||
|
@ -199,20 +198,20 @@ public class CarriageBogey {
|
|||
return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond());
|
||||
}
|
||||
|
||||
public BogeyVisual createVisual(VisualizationContext context) {
|
||||
return this.getStyle().createVisual(this, type.getSize(), context);
|
||||
}
|
||||
|
||||
public BogeyStyle getStyle() {
|
||||
ResourceLocation location = NBTHelper.readResourceLocation(this.bogeyData, BOGEY_STYLE_KEY);
|
||||
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(location);
|
||||
return style != null ? style : AllBogeyStyles.STANDARD; // just for safety
|
||||
}
|
||||
|
||||
public BogeySize getSize() {
|
||||
return type.getSize();
|
||||
}
|
||||
|
||||
private CompoundTag createBogeyData() {
|
||||
BogeyStyle style = type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD;
|
||||
CompoundTag nbt = style.defaultData != null ? style.defaultData : new CompoundTag();
|
||||
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, style.name);
|
||||
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, style.id);
|
||||
nbt.putBoolean(UPSIDE_DOWN_KEY, isUpsideDown());
|
||||
return nbt;
|
||||
}
|
||||
|
|
|
@ -736,6 +736,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
dimensional.updateRenderedCutoff();
|
||||
}
|
||||
|
||||
// FIXME: entities should not reference their visual in any way
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private WeakReference<CarriageContraptionVisual> instanceHolder;
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
|||
|
||||
int light = getBogeyLightCoords(entity, bogey, partialTicks);
|
||||
|
||||
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light,
|
||||
overlay, bogey.getStyle(), bogey.bogeyData);
|
||||
bogey.getStyle().render(bogey.getSize(), partialTicks, ms, buffers, light,
|
||||
overlay, bogey.wheelAngle.getValue(partialTicks), bogey.bogeyData, true);
|
||||
|
||||
ms.popPose();
|
||||
}
|
||||
|
@ -75,7 +75,6 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
|||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, bogey.isLeading);
|
||||
if (!carriage.isOnTwoBogeys())
|
||||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, !bogey.isLeading);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -99,7 +98,6 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
|||
}
|
||||
|
||||
public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) {
|
||||
|
||||
var lightPos = BlockPos.containing(
|
||||
Objects.requireNonNullElseGet(bogey.getAnchorPosition(), () -> entity.getLightProbePosition(partialTicks)));
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package com.simibubi.create.content.trains.entity;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.contraptions.render.ContraptionVisual;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyRenderer;
|
||||
import com.simibubi.create.content.trains.bogey.BogeyVisual;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
@ -14,16 +14,16 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
|||
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||
|
||||
public class CarriageContraptionVisual extends ContraptionVisual<CarriageContraptionEntity> {
|
||||
|
||||
private final PoseStack ms = new PoseStack();
|
||||
|
||||
@Nullable
|
||||
private Carriage carriage;
|
||||
private Couple<BogeyVisual> bogeys;
|
||||
private Couple<Boolean> bogeyHidden;
|
||||
@Nullable
|
||||
private Couple<@Nullable VisualizedBogey> bogeys;
|
||||
private Couple<Boolean> bogeyHidden = Couple.create(() -> false);
|
||||
|
||||
public CarriageContraptionVisual(VisualizationContext context, CarriageContraptionEntity entity, float partialTick) {
|
||||
super(context, entity, partialTick);
|
||||
bogeyHidden = Couple.create(() -> false);
|
||||
entity.bindInstance(this);
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,12 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
|||
protected void init(float pt) {
|
||||
carriage = entity.getCarriage();
|
||||
|
||||
if (carriage != null) {
|
||||
bogeys = carriage.bogeys.mapNotNullWithParam((bogey, manager) -> bogey.getStyle()
|
||||
.createVisual(bogey, bogey.type.getSize(), manager), visualizationContext);
|
||||
}
|
||||
if (carriage != null) {
|
||||
bogeys = carriage.bogeys.mapNotNull(bogey -> VisualizedBogey.of(visualizationContext, bogey, pt));
|
||||
}
|
||||
|
||||
super.init(pt);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBogeyVisibility(boolean first, boolean visible) {
|
||||
bogeyHidden.set(first, !visible);
|
||||
|
@ -62,26 +61,27 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
|||
|
||||
ms.pushPose();
|
||||
|
||||
Vector3f instancePosition = getVisualPosition(partialTick);
|
||||
Vector3f visualPosition = getVisualPosition(partialTick);
|
||||
TransformStack.of(ms)
|
||||
.translate(instancePosition);
|
||||
.translate(visualPosition);
|
||||
|
||||
for (boolean current : Iterate.trueAndFalse) {
|
||||
BogeyVisual instance = bogeys.get(current);
|
||||
if (instance == null)
|
||||
VisualizedBogey visualizedBogey = bogeys.get(current);
|
||||
if (visualizedBogey == null)
|
||||
continue;
|
||||
|
||||
if (bogeyHidden.get(current)) {
|
||||
instance.beginFrame(0, null);
|
||||
visualizedBogey.visual.hide();
|
||||
continue;
|
||||
}
|
||||
|
||||
ms.pushPose();
|
||||
CarriageBogey bogey = instance.bogey;
|
||||
CarriageBogey bogey = visualizedBogey.bogey;
|
||||
|
||||
CarriageContraptionEntityRenderer.translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTick);
|
||||
ms.translate(0, -1.5 - 1 / 128f, 0);
|
||||
|
||||
instance.beginFrame(bogey.wheelAngle.getValue(partialTick), ms);
|
||||
visualizedBogey.visual.update(bogey.wheelAngle.getValue(partialTick), ms);
|
||||
ms.popPose();
|
||||
}
|
||||
|
||||
|
@ -95,9 +95,11 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
|||
if (bogeys == null)
|
||||
return;
|
||||
|
||||
bogeys.forEach(instance -> {
|
||||
if (instance != null)
|
||||
instance.updateLight(level, entity);
|
||||
bogeys.forEach(bogey -> {
|
||||
if (bogey != null) {
|
||||
int packedLight = CarriageContraptionEntityRenderer.getBogeyLightCoords(entity, bogey.bogey, partialTick);
|
||||
bogey.visual.updateLight(packedLight);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -108,11 +110,21 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
|||
if (bogeys == null)
|
||||
return;
|
||||
|
||||
bogeys.forEach(instance -> {
|
||||
if (instance != null) {
|
||||
instance.commonRenderer.ifPresent(BogeyRenderer::remove);
|
||||
instance.renderer.remove();
|
||||
bogeys.forEach(bogey -> {
|
||||
if (bogey != null) {
|
||||
bogey.visual.delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private record VisualizedBogey(CarriageBogey bogey, BogeyVisual visual) {
|
||||
@Nullable
|
||||
static VisualizedBogey of(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||
BogeyVisual visual = bogey.getStyle().createVisual(ctx, bogey, partialTick);
|
||||
if (visual == null) {
|
||||
return null;
|
||||
}
|
||||
return new VisualizedBogey(bogey, visual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class CarriageSounds {
|
|||
public CarriageSounds(CarriageContraptionEntity entity) {
|
||||
this.entity = entity;
|
||||
bogeySounds = entity.getCarriage().bogeys.map(bogey ->
|
||||
bogey != null && bogey.getStyle() != null ? bogey.getStyle().getSoundType()
|
||||
bogey != null && bogey.getStyle() != null ? bogey.getStyle().soundEvent.get()
|
||||
: AllSoundEvents.TRAIN2.getMainEvent());
|
||||
closestBogeySound = bogeySounds.getFirst();
|
||||
distanceFactor = LerpedFloat.linear();
|
||||
|
@ -94,7 +94,7 @@ public class CarriageSounds {
|
|||
relevantBogey = bogeys.getFirst();
|
||||
}
|
||||
if (relevantBogey != null) {
|
||||
closestBogeySound = relevantBogey.getStyle().getSoundType();
|
||||
closestBogeySound = relevantBogey.getStyle().soundEvent.get();
|
||||
}
|
||||
|
||||
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
|
||||
|
|
|
@ -55,6 +55,10 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
|||
return Couple.create(function.apply(first), function.apply(second));
|
||||
}
|
||||
|
||||
public <S> Couple<S> mapNotNull(Function<T, S> function) {
|
||||
return Couple.create(first != null ? function.apply(first) : null, second != null ? function.apply(second) : null);
|
||||
}
|
||||
|
||||
public <S> Couple<S> mapWithContext(BiFunction<T, Boolean, S> function) {
|
||||
return Couple.create(function.apply(first, true), function.apply(second, false));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue