mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-30 23:05: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;
|
package com.simibubi.create;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
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 com.simibubi.create.content.trains.bogey.BogeySizes;
|
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||||
import com.simibubi.create.content.trains.bogey.BogeyStyle;
|
import com.simibubi.create.content.trains.bogey.BogeyStyle;
|
||||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.CommonStandardBogeyRenderer;
|
import com.simibubi.create.content.trains.bogey.BogeyStyle.SizeRenderer;
|
||||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.LargeStandardBogeyRenderer;
|
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer;
|
||||||
import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.SmallStandardBogeyRenderer;
|
import com.simibubi.create.content.trains.bogey.StandardBogeyVisual;
|
||||||
import com.simibubi.create.foundation.utility.Components;
|
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.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
|
||||||
|
|
||||||
public class AllBogeyStyles {
|
public class AllBogeyStyles {
|
||||||
public static final Map<ResourceLocation, BogeyStyle> BOGEY_STYLES = new HashMap<>();
|
public static final Map<ResourceLocation, BogeyStyle> BOGEY_STYLES = new HashMap<>();
|
||||||
public static final Map<ResourceLocation, Map<ResourceLocation, BogeyStyle>> CYCLE_GROUPS = 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) {
|
public static Map<ResourceLocation, BogeyStyle> getCycleGroup(ResourceLocation cycleGroup) {
|
||||||
return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP);
|
return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String STANDARD_CYCLE_GROUP = "standard";
|
private static BogeyStyle.Builder builder(String name, ResourceLocation cycleGroup) {
|
||||||
|
return new BogeyStyle.Builder(Create.asResource(name), cycleGroup);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BogeyStyleBuilder create(ResourceLocation name, ResourceLocation cycleGroup) {
|
@ApiStatus.Internal
|
||||||
return new BogeyStyleBuilder(name, cycleGroup);
|
public static void init() {
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class Create {
|
||||||
AllFanProcessingTypes.register();
|
AllFanProcessingTypes.register();
|
||||||
BlockSpoutingBehaviour.registerDefaults();
|
BlockSpoutingBehaviour.registerDefaults();
|
||||||
BogeySizes.init();
|
BogeySizes.init();
|
||||||
AllBogeyStyles.register();
|
AllBogeyStyles.init();
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
ComputerCraftProxy.register();
|
ComputerCraftProxy.register();
|
||||||
|
|
|
@ -4,18 +4,15 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
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.AllBlocks;
|
||||||
import com.simibubi.create.AllBogeyStyles;
|
import com.simibubi.create.AllBogeyStyles;
|
||||||
import com.simibubi.create.AllItems;
|
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.Lang;
|
||||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
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.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
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.level.material.FluidState;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> extends Block implements IBE<T>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
|
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<>();
|
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
||||||
public BogeySizes.BogeySize size;
|
public BogeySizes.BogeySize size;
|
||||||
|
|
||||||
|
|
||||||
public AbstractBogeyBlock(Properties pProperties, BogeySizes.BogeySize size) {
|
public AbstractBogeyBlock(Properties pProperties, BogeySizes.BogeySize size) {
|
||||||
super(pProperties);
|
super(pProperties);
|
||||||
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));
|
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
|
* 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) {
|
public static void registerStandardBogey(ResourceLocation block) {
|
||||||
BOGEYS.add(block);
|
BOGEYS.add(block);
|
||||||
}
|
}
|
||||||
|
@ -147,30 +139,6 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
||||||
return false;
|
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() {
|
public BogeySizes.BogeySize getSize() {
|
||||||
return this.size;
|
return this.size;
|
||||||
}
|
}
|
||||||
|
@ -216,9 +184,9 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
||||||
|
|
||||||
Set<BogeySizes.BogeySize> validSizes = style.validSizes();
|
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;
|
if (validSizes.contains(size)) break;
|
||||||
size = size.increment();
|
size = size.nextBySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
sbbe.setBogeyStyle(style);
|
sbbe.setBogeyStyle(style);
|
||||||
|
@ -227,7 +195,7 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
|
||||||
sbbe.setBogeyData(sbbe.getBogeyData().merge(defaultData));
|
sbbe.setBogeyData(sbbe.getBogeyData().merge(defaultData));
|
||||||
|
|
||||||
if (size == getSize()) {
|
if (size == getSize()) {
|
||||||
if (state.getBlock() != style.getBlockOfSize(size)) {
|
if (state.getBlock() != style.getBlockForSize(size)) {
|
||||||
CompoundTag oldData = sbbe.getBogeyData();
|
CompoundTag oldData = sbbe.getBogeyData();
|
||||||
level.setBlock(pos, copyProperties(state, getStateOfSize(sbbe, size)), Block.UPDATE_ALL);
|
level.setBlock(pos, copyProperties(state, getStateOfSize(sbbe, size)), Block.UPDATE_ALL);
|
||||||
if (!(level.getBlockEntity(pos) instanceof AbstractBogeyBlockEntity bogeyBlockEntity))
|
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) {
|
public BlockState getStateOfSize(AbstractBogeyBlockEntity sbbe, BogeySizes.BogeySize size) {
|
||||||
BogeyStyle style = sbbe.getStyle();
|
BogeyStyle style = sbbe.getStyle();
|
||||||
BlockState state = style.getBlockOfSize(size).defaultBlockState();
|
BlockState state = style.getBlockForSize(size).defaultBlockState();
|
||||||
return copyProperties(sbbe.getBlockState(), state);
|
return copyProperties(sbbe.getBlockState(), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,14 @@ public abstract class AbstractBogeyBlockEntity extends CachedRenderBBBlockEntity
|
||||||
|
|
||||||
public void setBogeyData(@NotNull CompoundTag newData) {
|
public void setBogeyData(@NotNull CompoundTag newData) {
|
||||||
if (!newData.contains(BOGEY_STYLE_KEY)) {
|
if (!newData.contains(BOGEY_STYLE_KEY)) {
|
||||||
ResourceLocation style = getDefaultStyle().name;
|
ResourceLocation style = getDefaultStyle().id;
|
||||||
NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style);
|
NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style);
|
||||||
}
|
}
|
||||||
this.bogeyData = newData;
|
this.bogeyData = newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBogeyStyle(@NotNull BogeyStyle style) {
|
public void setBogeyStyle(@NotNull BogeyStyle style) {
|
||||||
ResourceLocation location = style.name;
|
ResourceLocation location = style.id;
|
||||||
CompoundTag data = this.getBogeyData();
|
CompoundTag data = this.getBogeyData();
|
||||||
NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location);
|
NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location);
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
@ -80,7 +80,7 @@ public abstract class AbstractBogeyBlockEntity extends CachedRenderBBBlockEntity
|
||||||
|
|
||||||
private CompoundTag createBogeyData() {
|
private CompoundTag createBogeyData() {
|
||||||
CompoundTag nbt = new CompoundTag();
|
CompoundTag nbt = new CompoundTag();
|
||||||
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().name);
|
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().id);
|
||||||
boolean upsideDown = false;
|
boolean upsideDown = false;
|
||||||
if (getBlockState().getBlock() instanceof AbstractBogeyBlock<?> bogeyBlock)
|
if (getBlockState().getBlock() instanceof AbstractBogeyBlock<?> bogeyBlock)
|
||||||
upsideDown = bogeyBlock.isUpsideDown(getBlockState());
|
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;
|
package com.simibubi.create.content.trains.bogey;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.math.Axis;
|
||||||
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
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.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
public class BogeyBlockEntityRenderer<T extends BlockEntity> extends SafeBlockEntityRenderer<T> {
|
public class BogeyBlockEntityRenderer<T extends BlockEntity> extends SafeBlockEntityRenderer<T> {
|
||||||
|
public BogeyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
|
||||||
public BogeyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
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();
|
BlockState blockState = be.getBlockState();
|
||||||
if (be instanceof AbstractBogeyBlockEntity sbbe) {
|
if (be instanceof AbstractBogeyBlockEntity sbbe) {
|
||||||
float angle = sbbe.getVirtualAngle(partialTicks);
|
float angle = sbbe.getVirtualAngle(partialTicks);
|
||||||
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey)
|
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey) {
|
||||||
bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbbe.getStyle(), sbbe.getBogeyData());
|
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;
|
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.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 net.minecraft.client.renderer.MultiBufferSource;
|
||||||
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.nbt.CompoundTag;
|
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;
|
|
||||||
|
|
||||||
/**
|
public interface BogeyRenderer {
|
||||||
* 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:
|
void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay, boolean inContraption);
|
||||||
* <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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,78 @@
|
||||||
package com.simibubi.create.content.trains.bogey;
|
package com.simibubi.create.content.trains.bogey;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
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 com.simibubi.create.Create;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class BogeySizes {
|
public final class BogeySizes {
|
||||||
private static final Collection<BogeySize> BOGEY_SIZES = new HashSet<>();
|
private static final Map<ResourceLocation, BogeySize> BOGEY_SIZES = new HashMap<>();
|
||||||
public static final BogeySize SMALL = new BogeySize(Create.ID, "small", 6.5f / 16f);
|
private static final List<BogeySize> SORTED_INCREASING = new ArrayList<>();
|
||||||
public static final BogeySize LARGE = new BogeySize(Create.ID, "large", 12.5f / 16f);
|
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 {
|
static {
|
||||||
BOGEY_SIZES.add(SMALL);
|
register(SMALL);
|
||||||
BOGEY_SIZES.add(LARGE);
|
register(LARGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BogeySize addSize(String modId, String name, float size) {
|
private BogeySizes() {
|
||||||
ResourceLocation location = new ResourceLocation(modId, name);
|
|
||||||
return addSize(location, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BogeySize addSize(ResourceLocation location, float size) {
|
public static void register(BogeySize size) {
|
||||||
BogeySize customSize = new BogeySize(location, size);
|
ResourceLocation id = size.id();
|
||||||
BOGEY_SIZES.add(customSize);
|
if (BOGEY_SIZES.containsKey(id)) {
|
||||||
return customSize;
|
throw new IllegalArgumentException();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
BOGEY_SIZES.put(id, size);
|
||||||
|
|
||||||
public BogeySize increment() {
|
SORTED_INCREASING.add(size);
|
||||||
List<BogeySize> values = getAllSizesSmallToLarge();
|
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);
|
int ordinal = values.indexOf(this);
|
||||||
return values.get((ordinal + 1) % values.size());
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
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.AllBogeyStyles;
|
||||||
import com.simibubi.create.AllSoundEvents;
|
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.content.trains.entity.CarriageBogey;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
import dev.engine_room.flywheel.api.visualization.VisualizationContext;
|
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.ParticleOptions;
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.DistExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
|
||||||
|
|
||||||
|
|
||||||
public class BogeyStyle {
|
public class BogeyStyle {
|
||||||
|
public final ResourceLocation id;
|
||||||
public final ResourceLocation name;
|
|
||||||
public final ResourceLocation cycleGroup;
|
public final ResourceLocation cycleGroup;
|
||||||
public final Component displayName;
|
public final Component displayName;
|
||||||
public final ResourceLocation soundType;
|
public final Supplier<SoundEvent> soundEvent;
|
||||||
public final ParticleOptions contactParticle;
|
public final ParticleOptions contactParticle;
|
||||||
public final ParticleOptions smokeParticle;
|
public final ParticleOptions smokeParticle;
|
||||||
public final CompoundTag defaultData;
|
public final CompoundTag defaultData;
|
||||||
|
private final Map<BogeySizes.BogeySize, Supplier<? extends AbstractBogeyBlock<?>>> sizes;
|
||||||
private Optional<Supplier<? extends CommonRenderer>> commonRendererFactory;
|
|
||||||
private Map<BogeySizes.BogeySize, ResourceLocation> sizes;
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private Map<BogeySizes.BogeySize, SizeRenderData> sizeRenderers;
|
private Map<BogeySizes.BogeySize, SizeRenderer> sizeRenderers;
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
public BogeyStyle(ResourceLocation id, ResourceLocation cycleGroup, Component displayName,
|
||||||
private Optional<CommonRenderer> commonRenderer;
|
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,
|
this.id = id;
|
||||||
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.cycleGroup = cycleGroup;
|
this.cycleGroup = cycleGroup;
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.soundType = soundType;
|
this.soundEvent = soundEvent;
|
||||||
this.contactParticle = contactParticle;
|
this.contactParticle = contactParticle;
|
||||||
this.smokeParticle = smokeParticle;
|
this.smokeParticle = smokeParticle;
|
||||||
this.defaultData = defaultData;
|
this.defaultData = defaultData;
|
||||||
|
@ -64,9 +57,6 @@ public class BogeyStyle {
|
||||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
this.sizeRenderers = new HashMap<>();
|
this.sizeRenderers = new HashMap<>();
|
||||||
sizeRenderers.forEach((k, v) -> this.sizeRenderers.put(k, v.get()));
|
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);
|
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() {
|
public Set<BogeySizes.BogeySize> validSizes() {
|
||||||
return sizes.keySet();
|
return sizes.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public AbstractBogeyBlock<?> getBlockForSize(BogeySizes.BogeySize size) {
|
||||||
public SoundEvent getSoundType() {
|
return sizes.get(size).get();
|
||||||
AllSoundEvents.SoundEntry entry = AllSoundEvents.ALL.get(this.soundType);
|
}
|
||||||
if (entry == null || entry.getMainEvent() == null) entry = AllSoundEvents.TRAIN2;
|
|
||||||
return entry.getMainEvent();
|
@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)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public BogeyRenderer createRendererInstance(BogeySizes.BogeySize size) {
|
public void render(BogeySize size, float partialTick, PoseStack poseStack, MultiBufferSource buffers, int light, int overlay, float wheelAngle, @Nullable CompoundTag bogeyData, boolean inContraption) {
|
||||||
return this.sizeRenderers.get(size).createRenderInstance();
|
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)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public BogeyRenderer getInWorldRenderInstance(BogeySizes.BogeySize size) {
|
@Nullable
|
||||||
SizeRenderData sizeData = this.sizeRenderers.get(size);
|
public BogeyVisual createVisual(VisualizationContext ctx, CarriageBogey bogey, float partialTick) {
|
||||||
return sizeData != null ? sizeData.getInWorldInstance() : BackupBogeyRenderer.INSTANCE;
|
SizeRenderer renderer = sizeRenderers.get(bogey.getSize());
|
||||||
}
|
if (renderer != null) {
|
||||||
|
return renderer.visualizer.createVisual(ctx, bogey, partialTick);
|
||||||
public Optional<CommonRenderer> getInWorldCommonRenderInstance() {
|
}
|
||||||
return this.commonRenderer;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public record SizeRenderData(Supplier<? extends BogeyRenderer> rendererFactory, BogeyRenderer instance) {
|
public record SizeRenderer(BogeyRenderer renderer, BogeyVisualizer visualizer) {
|
||||||
public BogeyRenderer createRenderInstance() {
|
}
|
||||||
return rendererFactory.get();
|
|
||||||
|
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() {
|
public Builder displayName(Component displayName) {
|
||||||
return instance;
|
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;
|
package com.simibubi.create.content.trains.bogey;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
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;
|
public interface BogeyVisual {
|
||||||
import net.minecraft.core.BlockPos;
|
void update(float wheelAngle, PoseStack poseStack);
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
|
||||||
import net.minecraft.world.level.LightLayer;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
|
|
||||||
public final class BogeyVisual {
|
void hide();
|
||||||
private final BogeySizes.BogeySize size;
|
|
||||||
private final BogeyStyle style;
|
|
||||||
|
|
||||||
public final CarriageBogey bogey;
|
void updateLight(int packedLight);
|
||||||
public final BogeyRenderer renderer;
|
|
||||||
public final Optional<BogeyRenderer.CommonRenderer> commonRenderer;
|
|
||||||
|
|
||||||
public BogeyVisual(CarriageBogey bogey, BogeyStyle style, BogeySizes.BogeySize size,
|
void delete();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
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.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllPartialModels;
|
||||||
import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock;
|
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.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
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.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
|
||||||
public class StandardBogeyRenderer {
|
public class StandardBogeyRenderer implements BogeyRenderer {
|
||||||
public static class CommonStandardBogeyRenderer extends BogeyRenderer.CommonRenderer {
|
@Override
|
||||||
@Override
|
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||||
createModelInstance(context, AllBlocks.SHAFT.getDefaultState()
|
|
||||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
SuperByteBuffer shaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()
|
||||||
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
.setValue(ShaftBlock.AXIS, Direction.Axis.Z));
|
||||||
boolean inInstancedContraption = vb == null;
|
for (int i : Iterate.zeroAndOne) {
|
||||||
BogeyModelData[] shafts = getTransform(AllBlocks.SHAFT.getDefaultState()
|
shaft.translate(-.5f, .25f, i * -1)
|
||||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inInstancedContraption, 2);
|
.center()
|
||||||
for (int i : Iterate.zeroAndOne) {
|
.rotateZDegrees(wheelAngle)
|
||||||
shafts[i].translate(-.5f, .25f, i * -1)
|
.uncenter()
|
||||||
.center()
|
.light(light)
|
||||||
.rotateZDegrees(wheelAngle)
|
.overlay(overlay)
|
||||||
.uncenter()
|
.renderInto(poseStack, buffer);
|
||||||
.render(ms, light, vb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Small extends StandardBogeyRenderer {
|
||||||
public static class SmallStandardBogeyRenderer extends BogeyRenderer {
|
|
||||||
@Override
|
@Override
|
||||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||||
createModelInstance(context, SMALL_BOGEY_WHEELS, 2);
|
super.render(bogeyData, wheelAngle, partialTick, poseStack, bufferSource, light, overlay, inContraption);
|
||||||
createModelInstance(context, BOGEY_FRAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||||
|
|
||||||
@Override
|
CachedBufferer.partial(AllPartialModels.BOGEY_FRAME, Blocks.AIR.defaultBlockState())
|
||||||
public BogeySizes.BogeySize getSize() {
|
.scale(1 - 1 / 512f)
|
||||||
return BogeySizes.SMALL;
|
.light(light)
|
||||||
}
|
.overlay(overlay)
|
||||||
|
.renderInto(poseStack, buffer);
|
||||||
|
|
||||||
@Override
|
SuperByteBuffer wheels = CachedBufferer.partial(AllPartialModels.SMALL_BOGEY_WHEELS, Blocks.AIR.defaultBlockState());
|
||||||
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);
|
|
||||||
for (int side : Iterate.positiveAndNegative) {
|
for (int side : Iterate.positiveAndNegative) {
|
||||||
if (!inInstancedContraption)
|
wheels.translate(0, 12 / 16f, side)
|
||||||
ms.pushPose();
|
|
||||||
wheels[(side + 1)/2]
|
|
||||||
.translate(0, 12 / 16f, side)
|
|
||||||
.rotateXDegrees(wheelAngle)
|
.rotateXDegrees(wheelAngle)
|
||||||
.render(ms, light, vb);
|
.light(light)
|
||||||
if (!inInstancedContraption)
|
.overlay(overlay)
|
||||||
ms.popPose();
|
.renderInto(poseStack, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LargeStandardBogeyRenderer extends BogeyRenderer {
|
public static class Large extends StandardBogeyRenderer {
|
||||||
@Override
|
@Override
|
||||||
public void initialiseContraptionModelData(VisualizationContext context, CarriageBogey carriageBogey) {
|
public void render(CompoundTag bogeyData, float wheelAngle, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int light, int overlay, boolean inContraption) {
|
||||||
createModelInstance(context, LARGE_BOGEY_WHEELS, BOGEY_DRIVE, BOGEY_PISTON, BOGEY_PIN);
|
super.render(bogeyData, wheelAngle, partialTick, poseStack, bufferSource, light, overlay, inContraption);
|
||||||
createModelInstance(context, AllBlocks.SHAFT.getDefaultState()
|
|
||||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
VertexConsumer buffer = bufferSource.getBuffer(RenderType.cutoutMipped());
|
||||||
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);
|
|
||||||
|
|
||||||
|
SuperByteBuffer secondaryShaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()
|
||||||
|
.setValue(ShaftBlock.AXIS, Direction.Axis.X));
|
||||||
for (int i : Iterate.zeroAndOne) {
|
for (int i : Iterate.zeroAndOne) {
|
||||||
secondaryShafts[i]
|
secondaryShaft.translate(-.5f, .25f, .5f + i * -2)
|
||||||
.translate(-.5f, .25f, .5f + i * -2)
|
|
||||||
.center()
|
.center()
|
||||||
.rotateXDegrees(wheelAngle)
|
.rotateXDegrees(wheelAngle)
|
||||||
.uncenter()
|
.uncenter()
|
||||||
.render(ms, light, vb);
|
.light(light)
|
||||||
|
.overlay(overlay)
|
||||||
|
.renderInto(poseStack, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransform(BOGEY_DRIVE, ms, inInstancedContraption)
|
CachedBufferer.partial(AllPartialModels.BOGEY_DRIVE, Blocks.AIR.defaultBlockState())
|
||||||
.render(ms, light, vb);
|
.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)))
|
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)))
|
||||||
.render(ms, light, vb);
|
.light(light)
|
||||||
|
.overlay(overlay)
|
||||||
|
.renderInto(poseStack, buffer);
|
||||||
|
|
||||||
if (!inInstancedContraption)
|
CachedBufferer.partial(AllPartialModels.LARGE_BOGEY_WHEELS, Blocks.AIR.defaultBlockState())
|
||||||
ms.pushPose();
|
|
||||||
|
|
||||||
getTransform(LARGE_BOGEY_WHEELS, ms, inInstancedContraption)
|
|
||||||
.translate(0, 1, 0)
|
.translate(0, 1, 0)
|
||||||
.rotateXDegrees(wheelAngle)
|
.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)
|
.translate(0, 1, 0)
|
||||||
.rotateXDegrees(wheelAngle)
|
.rotateXDegrees(wheelAngle)
|
||||||
.translate(0, 1 / 4f, 0)
|
.translate(0, 1 / 4f, 0)
|
||||||
.rotateXDegrees(-wheelAngle)
|
.rotateXDegrees(-wheelAngle)
|
||||||
.render(ms, light, vb);
|
.light(light)
|
||||||
|
.overlay(overlay)
|
||||||
if (!inInstancedContraption)
|
.renderInto(poseStack, buffer);
|
||||||
ms.popPose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.Create;
|
||||||
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock;
|
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock;
|
||||||
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity;
|
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.BogeyStyle;
|
||||||
import com.simibubi.create.content.trains.bogey.BogeyVisual;
|
|
||||||
import com.simibubi.create.content.trains.graph.DimensionPalette;
|
import com.simibubi.create.content.trains.graph.DimensionPalette;
|
||||||
import com.simibubi.create.content.trains.graph.TrackGraph;
|
import com.simibubi.create.content.trains.graph.TrackGraph;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
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.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
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.core.Direction.Axis;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
@ -184,7 +183,7 @@ public class CarriageBogey {
|
||||||
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
|
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
|
||||||
tag.putBoolean("UpsideDown", upsideDown);
|
tag.putBoolean("UpsideDown", upsideDown);
|
||||||
bogeyData.putBoolean(UPSIDE_DOWN_KEY, 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);
|
tag.put(BOGEY_DATA_KEY, bogeyData);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
@ -199,20 +198,20 @@ public class CarriageBogey {
|
||||||
return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond());
|
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() {
|
public BogeyStyle getStyle() {
|
||||||
ResourceLocation location = NBTHelper.readResourceLocation(this.bogeyData, BOGEY_STYLE_KEY);
|
ResourceLocation location = NBTHelper.readResourceLocation(this.bogeyData, BOGEY_STYLE_KEY);
|
||||||
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(location);
|
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(location);
|
||||||
return style != null ? style : AllBogeyStyles.STANDARD; // just for safety
|
return style != null ? style : AllBogeyStyles.STANDARD; // just for safety
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BogeySize getSize() {
|
||||||
|
return type.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
private CompoundTag createBogeyData() {
|
private CompoundTag createBogeyData() {
|
||||||
BogeyStyle style = type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD;
|
BogeyStyle style = type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD;
|
||||||
CompoundTag nbt = style.defaultData != null ? style.defaultData : new CompoundTag();
|
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());
|
nbt.putBoolean(UPSIDE_DOWN_KEY, isUpsideDown());
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -736,6 +736,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
||||||
dimensional.updateRenderedCutoff();
|
dimensional.updateRenderedCutoff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: entities should not reference their visual in any way
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private WeakReference<CarriageContraptionVisual> instanceHolder;
|
private WeakReference<CarriageContraptionVisual> instanceHolder;
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
||||||
|
|
||||||
int light = getBogeyLightCoords(entity, bogey, partialTicks);
|
int light = getBogeyLightCoords(entity, bogey, partialTicks);
|
||||||
|
|
||||||
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light,
|
bogey.getStyle().render(bogey.getSize(), partialTicks, ms, buffers, light,
|
||||||
overlay, bogey.getStyle(), bogey.bogeyData);
|
overlay, bogey.wheelAngle.getValue(partialTicks), bogey.bogeyData, true);
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,6 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
||||||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, bogey.isLeading);
|
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, bogey.isLeading);
|
||||||
if (!carriage.isOnTwoBogeys())
|
if (!carriage.isOnTwoBogeys())
|
||||||
bogey.updateCouplingAnchor(position, viewXRot, viewYRot, bogeySpacing, partialTicks, !bogey.isLeading);
|
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) {
|
public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) {
|
||||||
|
|
||||||
var lightPos = BlockPos.containing(
|
var lightPos = BlockPos.containing(
|
||||||
Objects.requireNonNullElseGet(bogey.getAnchorPosition(), () -> entity.getLightProbePosition(partialTicks)));
|
Objects.requireNonNullElseGet(bogey.getAnchorPosition(), () -> entity.getLightProbePosition(partialTicks)));
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package com.simibubi.create.content.trains.entity;
|
package com.simibubi.create.content.trains.entity;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.content.contraptions.render.ContraptionVisual;
|
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.content.trains.bogey.BogeyVisual;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
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;
|
import dev.engine_room.flywheel.lib.transform.TransformStack;
|
||||||
|
|
||||||
public class CarriageContraptionVisual extends ContraptionVisual<CarriageContraptionEntity> {
|
public class CarriageContraptionVisual extends ContraptionVisual<CarriageContraptionEntity> {
|
||||||
|
|
||||||
private final PoseStack ms = new PoseStack();
|
private final PoseStack ms = new PoseStack();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private Carriage carriage;
|
private Carriage carriage;
|
||||||
private Couple<BogeyVisual> bogeys;
|
@Nullable
|
||||||
private Couple<Boolean> bogeyHidden;
|
private Couple<@Nullable VisualizedBogey> bogeys;
|
||||||
|
private Couple<Boolean> bogeyHidden = Couple.create(() -> false);
|
||||||
|
|
||||||
public CarriageContraptionVisual(VisualizationContext context, CarriageContraptionEntity entity, float partialTick) {
|
public CarriageContraptionVisual(VisualizationContext context, CarriageContraptionEntity entity, float partialTick) {
|
||||||
super(context, entity, partialTick);
|
super(context, entity, partialTick);
|
||||||
bogeyHidden = Couple.create(() -> false);
|
|
||||||
entity.bindInstance(this);
|
entity.bindInstance(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,13 +31,12 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
||||||
protected void init(float pt) {
|
protected void init(float pt) {
|
||||||
carriage = entity.getCarriage();
|
carriage = entity.getCarriage();
|
||||||
|
|
||||||
if (carriage != null) {
|
if (carriage != null) {
|
||||||
bogeys = carriage.bogeys.mapNotNullWithParam((bogey, manager) -> bogey.getStyle()
|
bogeys = carriage.bogeys.mapNotNull(bogey -> VisualizedBogey.of(visualizationContext, bogey, pt));
|
||||||
.createVisual(bogey, bogey.type.getSize(), manager), visualizationContext);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
super.init(pt);
|
super.init(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBogeyVisibility(boolean first, boolean visible) {
|
public void setBogeyVisibility(boolean first, boolean visible) {
|
||||||
bogeyHidden.set(first, !visible);
|
bogeyHidden.set(first, !visible);
|
||||||
|
@ -62,26 +61,27 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
|
|
||||||
Vector3f instancePosition = getVisualPosition(partialTick);
|
Vector3f visualPosition = getVisualPosition(partialTick);
|
||||||
TransformStack.of(ms)
|
TransformStack.of(ms)
|
||||||
.translate(instancePosition);
|
.translate(visualPosition);
|
||||||
|
|
||||||
for (boolean current : Iterate.trueAndFalse) {
|
for (boolean current : Iterate.trueAndFalse) {
|
||||||
BogeyVisual instance = bogeys.get(current);
|
VisualizedBogey visualizedBogey = bogeys.get(current);
|
||||||
if (instance == null)
|
if (visualizedBogey == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (bogeyHidden.get(current)) {
|
if (bogeyHidden.get(current)) {
|
||||||
instance.beginFrame(0, null);
|
visualizedBogey.visual.hide();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
CarriageBogey bogey = instance.bogey;
|
CarriageBogey bogey = visualizedBogey.bogey;
|
||||||
|
|
||||||
CarriageContraptionEntityRenderer.translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTick);
|
CarriageContraptionEntityRenderer.translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTick);
|
||||||
ms.translate(0, -1.5 - 1 / 128f, 0);
|
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();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +95,11 @@ public class CarriageContraptionVisual extends ContraptionVisual<CarriageContrap
|
||||||
if (bogeys == null)
|
if (bogeys == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bogeys.forEach(instance -> {
|
bogeys.forEach(bogey -> {
|
||||||
if (instance != null)
|
if (bogey != null) {
|
||||||
instance.updateLight(level, entity);
|
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)
|
if (bogeys == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bogeys.forEach(instance -> {
|
bogeys.forEach(bogey -> {
|
||||||
if (instance != null) {
|
if (bogey != null) {
|
||||||
instance.commonRenderer.ifPresent(BogeyRenderer::remove);
|
bogey.visual.delete();
|
||||||
instance.renderer.remove();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
public CarriageSounds(CarriageContraptionEntity entity) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
bogeySounds = entity.getCarriage().bogeys.map(bogey ->
|
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());
|
: AllSoundEvents.TRAIN2.getMainEvent());
|
||||||
closestBogeySound = bogeySounds.getFirst();
|
closestBogeySound = bogeySounds.getFirst();
|
||||||
distanceFactor = LerpedFloat.linear();
|
distanceFactor = LerpedFloat.linear();
|
||||||
|
@ -94,7 +94,7 @@ public class CarriageSounds {
|
||||||
relevantBogey = bogeys.getFirst();
|
relevantBogey = bogeys.getFirst();
|
||||||
}
|
}
|
||||||
if (relevantBogey != null) {
|
if (relevantBogey != null) {
|
||||||
closestBogeySound = relevantBogey.getStyle().getSoundType();
|
closestBogeySound = relevantBogey.getStyle().soundEvent.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
|
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));
|
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) {
|
public <S> Couple<S> mapWithContext(BiFunction<T, Boolean, S> function) {
|
||||||
return Couple.create(function.apply(first, true), function.apply(second, false));
|
return Couple.create(function.apply(first, true), function.apply(second, false));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue