working on upside down bogeys in nether portals

This commit is contained in:
techno-sam 2023-05-04 09:32:53 -07:00
parent 2f285b6eb7
commit da26c0ccbf
29 changed files with 483 additions and 241 deletions

3
.gitignore vendored
View file

@ -42,4 +42,5 @@ local.properties
# PDT-specific # PDT-specific
.buildpath .buildpath
.DS_Store .DS_Store
/libs/

View file

@ -135,6 +135,9 @@ repositories {
includeGroup "maven.modrinth" includeGroup "maven.modrinth"
} }
} }
flatDir {
dirs 'libs'
}
} }
dependencies { dependencies {
@ -169,6 +172,7 @@ dependencies {
// runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.115") // runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.115")
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252") // runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3") // runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3")
implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false }
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings

View file

@ -7,6 +7,7 @@ import com.simibubi.create.content.logistics.trains.BogeySizes;
import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.*; import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.*;
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle; import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.BlockEntry;
@ -30,7 +31,7 @@ public class AllBogeyStyles {
public static BogeyStyle STANDARD = create("standard") public static BogeyStyle STANDARD = create("standard")
.commonRenderer(CommonStandardBogeyRenderer::new) .commonRenderer(CommonStandardBogeyRenderer::new)
.displayName(new TranslatableComponent("create.bogeys.styles.standard")) .displayName(Components.translatable("create.bogeys.styles.standard"))
.size(BogeySizes.SMALL, SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY) .size(BogeySizes.SMALL, SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY)
.size(BogeySizes.LARGE, LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY) .size(BogeySizes.LARGE, LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY)
.build(); .build();

View file

@ -192,6 +192,7 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
import com.simibubi.create.content.logistics.trains.track.FakeTrackTileEntity; import com.simibubi.create.content.logistics.trains.track.FakeTrackTileEntity;
import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity;
import com.simibubi.create.content.logistics.trains.track.TrackBlock; import com.simibubi.create.content.logistics.trains.track.TrackBlock;
import com.simibubi.create.content.logistics.trains.track.TrackInstance; import com.simibubi.create.content.logistics.trains.track.TrackInstance;
@ -203,12 +204,9 @@ import com.simibubi.create.content.schematics.block.SchematicannonRenderer;
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
import com.tterrag.registrate.util.entry.BlockEntityEntry; import com.tterrag.registrate.util.entry.BlockEntityEntry;
import com.tterrag.registrate.util.entry.BlockEntry;
import com.tterrag.registrate.util.nullness.NonNullSupplier; import com.tterrag.registrate.util.nullness.NonNullSupplier;
import net.minecraft.world.level.block.Block;
public class AllTileEntities { public class AllTileEntities {
// Schematics // Schematics

View file

@ -342,7 +342,7 @@ public abstract class Contraption {
} }
// Bogeys tend to have sticky sides // Bogeys tend to have sticky sides
if (state.getBlock()instanceof AbstractBogeyBlock bogey) if (state.getBlock()instanceof AbstractBogeyBlock<?> bogey)
for (Direction d : bogey.getStickySurfaces(world, pos, state)) for (Direction d : bogey.getStickySurfaces(world, pos, state))
if (!visited.contains(pos.relative(d))) if (!visited.contains(pos.relative(d)))
frontier.add(pos.relative(d)); frontier.add(pos.relative(d));

View file

@ -17,7 +17,7 @@ import com.simibubi.create.AllBogeyStyles;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle; import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
@ -55,7 +55,7 @@ import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBogeyTileEntity>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable { public abstract class AbstractBogeyBlock<T extends AbstractBogeyTileEntity> extends Block implements ITE<T>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS; public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS;
static final List<ResourceLocation> BOGEYS = new ArrayList<>(); static final List<ResourceLocation> BOGEYS = new ArrayList<>();
public BogeySizes.BogeySize size; public BogeySizes.BogeySize size;
@ -100,16 +100,37 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
public abstract double getWheelRadius(); public abstract double getWheelRadius();
public abstract Vec3 getConnectorAnchorOffset(); public Vec3 getConnectorAnchorOffset(boolean upsideDown) {
return getConnectorAnchorOffset();
}
/**
* This should be implemented, but not called directly
*/
protected abstract Vec3 getConnectorAnchorOffset();
public boolean allowsSingleBogeyCarriage() { public boolean allowsSingleBogeyCarriage() {
return true; return true;
} }
public abstract BogeyStyle getDefaultStyle();
/**
* Legacy system doesn't capture bogey tile entities when constructing a train
*/
public boolean captureTileEntityForTrain() {
return false;
}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks, public void render(@Nullable BlockState state, boolean upsideDown, float wheelAngle, PoseStack ms, float partialTicks,
MultiBufferSource buffers, int light, int overlay, StandardBogeyTileEntity sbte) { MultiBufferSource buffers, int light, int overlay, AbstractBogeyTileEntity sbte) {
BogeyStyle style = sbte.getStyle(); BogeyStyle style;
if (sbte != null) { // on trains, sbte can be null.
style = sbte.getStyle();
} else {
style = getDefaultStyle();
}
final Optional<BogeyRenderer.CommonRenderer> commonRenderer final Optional<BogeyRenderer.CommonRenderer> commonRenderer
= style.getNewCommonRenderInstance(); = style.getNewCommonRenderInstance();
final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize()); final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize());
@ -120,9 +141,10 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
} }
ms.translate(0, -1.5 - 1 / 128f, 0); ms.translate(0, -1.5 - 1 / 128f, 0);
VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped()); VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped());
renderer.render(sbte.getBogeyData(), wheelAngle, ms, light, vb); CompoundTag bogeyData = sbte != null ? sbte.getBogeyData() : new CompoundTag();
renderer.render(upsideDown, bogeyData, wheelAngle, ms, light, vb, state == null);
commonRenderer.ifPresent(common -> commonRenderer.ifPresent(common ->
common.render(sbte.getBogeyData(), wheelAngle, ms, light, vb)); common.render(upsideDown, bogeyData, wheelAngle, ms, light, vb, state == null));
} }
public BogeySizes.BogeySize getSize() { public BogeySizes.BogeySize getSize() {
@ -160,7 +182,7 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
BlockEntity be = level.getBlockEntity(pos); BlockEntity be = level.getBlockEntity(pos);
if (!(be instanceof StandardBogeyTileEntity sbte)) if (!(be instanceof AbstractBogeyTileEntity sbte))
return InteractionResult.FAIL; return InteractionResult.FAIL;
player.getCooldowns().addCooldown(stack.getItem(), 20); player.getCooldowns().addCooldown(stack.getItem(), 20);
@ -187,7 +209,7 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
CompoundTag oldData = sbte.getBogeyData(); CompoundTag oldData = sbte.getBogeyData();
level.setBlock(pos, this.getStateOfSize(sbte, size), 3); level.setBlock(pos, this.getStateOfSize(sbte, size), 3);
BlockEntity newBlockEntity = level.getBlockEntity(pos); BlockEntity newBlockEntity = level.getBlockEntity(pos);
if (!(newBlockEntity instanceof StandardBogeyTileEntity newTileEntity)) if (!(newBlockEntity instanceof AbstractBogeyTileEntity newTileEntity))
return InteractionResult.FAIL; return InteractionResult.FAIL;
newTileEntity.setBogeyData(oldData); newTileEntity.setBogeyData(oldData);
player.displayClientMessage(Lang.translateDirect("create.bogey.style.updated_style_and_size") player.displayClientMessage(Lang.translateDirect("create.bogey.style.updated_style_and_size")
@ -229,12 +251,12 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
public BlockState getNextSize(Level level, BlockPos pos) { public BlockState getNextSize(Level level, BlockPos pos) {
BlockEntity te = level.getBlockEntity(pos); BlockEntity te = level.getBlockEntity(pos);
if (te instanceof StandardBogeyTileEntity sbte) if (te instanceof AbstractBogeyTileEntity sbte)
return this.getNextSize(sbte); return this.getNextSize(sbte);
return level.getBlockState(pos); return level.getBlockState(pos);
} }
public BlockState getNextSize(StandardBogeyTileEntity sbte) { public BlockState getNextSize(AbstractBogeyTileEntity sbte) {
BogeySizes.BogeySize size = this.getSize(); BogeySizes.BogeySize size = this.getSize();
BogeyStyle style = sbte.getStyle(); BogeyStyle style = sbte.getStyle();
BlockState nextBlock = style.getNextBlock(size).defaultBlockState(); BlockState nextBlock = style.getNextBlock(size).defaultBlockState();
@ -243,7 +265,7 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
: nextBlock; : nextBlock;
} }
public BlockState getStateOfSize(StandardBogeyTileEntity sbte, BogeySizes.BogeySize size) { public BlockState getStateOfSize(AbstractBogeyTileEntity sbte, BogeySizes.BogeySize size) {
BogeyStyle style = sbte.getStyle(); BogeyStyle style = sbte.getStyle();
BlockState state = style.getBlockOfSize(size).defaultBlockState(); BlockState state = style.getBlockOfSize(size).defaultBlockState();
return state.hasProperty(WATERLOGGED) return state.hasProperty(WATERLOGGED)
@ -253,9 +275,9 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
public BogeyStyle getNextStyle(Level level, BlockPos pos) { public BogeyStyle getNextStyle(Level level, BlockPos pos) {
BlockEntity te = level.getBlockEntity(pos); BlockEntity te = level.getBlockEntity(pos);
if (te instanceof StandardBogeyTileEntity sbte) if (te instanceof AbstractBogeyTileEntity sbte)
return this.getNextStyle(sbte.getStyle()); return this.getNextStyle(sbte.getStyle());
return AllBogeyStyles.STANDARD; return getDefaultStyle();
} }
public BogeyStyle getNextStyle(BogeyStyle style) { public BogeyStyle getNextStyle(BogeyStyle style) {
@ -279,4 +301,16 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack()); return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack());
} }
public boolean canBeUpsideDown() {
return false;
}
public boolean isUpsideDown(BlockState state) {
return false;
}
public BlockState getVersion(BlockState base, boolean upsideDown) {
return base;
}
} }

View file

@ -37,12 +37,12 @@ public abstract class BogeyRenderer {
* *
* @param model The key for the model data to instantiate or retrieve * @param model The key for the model data to instantiate or retrieve
* @param ms The posestack used for contraption model data * @param ms The posestack used for contraption model data
* @param inContraption The type of model needed * @param inInstancedContraption The type of model needed
* @param size The amount of models needed * @param size The amount of models needed
* @return A generic transform which can be used for both in-world and in-contraption models * @return A generic transform which can be used for both in-world and in-contraption models
*/ */
public Transform<?>[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inContraption, int size) { public Transform<?>[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption, int size) {
return (inContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size); return (inInstancedContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size);
} }
/** /**
@ -69,7 +69,7 @@ public abstract class BogeyRenderer {
* @param vb (Optional) Vertex Consumer used for in-world rendering * @param vb (Optional) Vertex Consumer used for in-world rendering
*/ */
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public abstract void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb); public abstract void render(boolean upsideDown, 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 * Used for calling in-contraption rendering ensuring that falsey data is handled correctly
@ -79,8 +79,8 @@ public abstract class BogeyRenderer {
* @param ms The posestack to render to * @param ms The posestack to render to
*/ */
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms) { public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms) {
this.render(bogeyData, wheelAngle, ms, 0, null); this.render(upsideDown, bogeyData, wheelAngle, ms, 0, null, true);
} }
public abstract BogeySizes.BogeySize getSize(); public abstract BogeySizes.BogeySize getSize();
@ -147,12 +147,12 @@ public abstract class BogeyRenderer {
* *
* @param model The key of the model to be collected or instantiated * @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 ms Posestack to bind the model to if it is within a contraption
* @param inContraption Type of rendering required * @param inInstancedContraption Type of rendering required
* @return A generic transform which can be used for both in-world and in-contraption models * @return A generic transform which can be used for both in-world and in-contraption models
*/ */
public Transform<?> getTransformFromPartial(PartialModel model, PoseStack ms, boolean inContraption) { public Transform<?> getTransformFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption) {
BlockState air = Blocks.AIR.defaultBlockState(); BlockState air = Blocks.AIR.defaultBlockState();
return inContraption ? contraptionModelData.get(keyFromModel(model))[0].setTransform(ms) return inInstancedContraption ? contraptionModelData.get(keyFromModel(model))[0].setTransform(ms)
: CachedBufferer.partial(model, air); : CachedBufferer.partial(model, air);
} }

View file

@ -21,14 +21,15 @@ public class BogeySizes {
BOGEY_SIZES.add(LARGE); BOGEY_SIZES.add(LARGE);
} }
public static void addSize(String modId, String name, float size) { public static BogeySize addSize(String modId, String name, float size) {
ResourceLocation location = new ResourceLocation(modId, name); ResourceLocation location = new ResourceLocation(modId, name);
addSize(location, size); return addSize(location, size);
} }
public static void addSize(ResourceLocation location, float size) { public static BogeySize addSize(ResourceLocation location, float size) {
BogeySize customSize = new BogeySize(location, size); BogeySize customSize = new BogeySize(location, size);
BOGEY_SIZES.add(customSize); BOGEY_SIZES.add(customSize);
return customSize;
} }
public static List<BogeySize> getAllSizesSmallToLarge() { public static List<BogeySize> getAllSizesSmallToLarge() {

View file

@ -1,7 +1,7 @@
package com.simibubi.create.content.logistics.trains; package com.simibubi.create.content.logistics.trains;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
@ -17,10 +17,10 @@ public class BogeyTileEntityRenderer<T extends BlockEntity> extends SafeTileEnti
protected void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, protected void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
int overlay) { int overlay) {
BlockState blockState = te.getBlockState(); BlockState blockState = te.getBlockState();
if (te instanceof StandardBogeyTileEntity sbte) { if (te instanceof AbstractBogeyTileEntity sbte) {
float angle = sbte.getVirtualAngle(partialTicks); float angle = sbte.getVirtualAngle(partialTicks);
if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) if (blockState.getBlock() instanceof AbstractBogeyBlock bogey)
bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbte); bogey.render(blockState, bogey.isUpsideDown(blockState), angle, ms, partialTicks, buffer, light, overlay, sbte);
} }
} }

View file

@ -36,10 +36,10 @@ public class StandardBogeyRenderer {
} }
@Override @Override
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
boolean inContraption = vb == null; boolean inInstancedContraption = vb == null;
Transform<?>[] shafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState() Transform<?>[] shafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState()
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inContraption, 2); .setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inInstancedContraption, 2);
for (int i : Iterate.zeroAndOne) { for (int i : Iterate.zeroAndOne) {
shafts[i].translate(-.5f, .25f, i * -1) shafts[i].translate(-.5f, .25f, i * -1)
.centre() .centre()
@ -69,20 +69,20 @@ public class StandardBogeyRenderer {
} }
@Override @Override
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
boolean inContraption = vb == null; boolean inInstancedContraption = vb == null;
Transform<?> transform = getTransformFromPartial(BOGEY_FRAME, ms, inContraption); Transform<?> transform = getTransformFromPartial(BOGEY_FRAME, ms, inInstancedContraption);
finalize(transform, ms, light, vb); finalize(transform, ms, light, vb);
Transform<?>[] wheels = getTransformsFromPartial(SMALL_BOGEY_WHEELS, ms, inContraption, 2); Transform<?>[] wheels = getTransformsFromPartial(SMALL_BOGEY_WHEELS, ms, inInstancedContraption, 2);
for (int side : Iterate.positiveAndNegative) { for (int side : Iterate.positiveAndNegative) {
if (!inContraption) if (!inInstancedContraption)
ms.pushPose(); ms.pushPose();
Transform<?> wheel = wheels[(side + 1)/2]; Transform<?> wheel = wheels[(side + 1)/2];
wheel.translate(0, 12 / 16f, side) wheel.translate(0, 12 / 16f, side)
.rotateX(wheelAngle); .rotateX(wheelAngle);
finalize(wheel, ms, light, vb); finalize(wheel, ms, light, vb);
if (!inContraption) if (!inInstancedContraption)
ms.popPose(); ms.popPose();
} }
} }
@ -107,11 +107,11 @@ public class StandardBogeyRenderer {
} }
@Override @Override
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
boolean inContraption = vb == null; boolean inInstancedContraption = vb == null;
Transform<?>[] secondaryShafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState() Transform<?>[] secondaryShafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState()
.setValue(ShaftBlock.AXIS, Direction.Axis.X), ms, inContraption, 2); .setValue(ShaftBlock.AXIS, Direction.Axis.X), ms, inInstancedContraption, 2);
for (int i : Iterate.zeroAndOne) { for (int i : Iterate.zeroAndOne) {
Transform<?> secondShaft = secondaryShafts[i]; Transform<?> secondShaft = secondaryShafts[i];
@ -122,29 +122,29 @@ public class StandardBogeyRenderer {
finalize(secondShaft, ms, light, vb); finalize(secondShaft, ms, light, vb);
} }
Transform<?> bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inContraption); Transform<?> bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inInstancedContraption);
finalize(bogeyDrive, ms, light, vb); finalize(bogeyDrive, ms, light, vb);
Transform<?> bogeyPiston = getTransformFromPartial(BOGEY_PISTON, ms, inContraption) Transform<?> bogeyPiston = getTransformFromPartial(BOGEY_PISTON, ms, inInstancedContraption)
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))); .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)));
finalize(bogeyPiston, ms, light, vb); finalize(bogeyPiston, ms, light, vb);
if (!inContraption) if (!inInstancedContraption)
ms.pushPose(); ms.pushPose();
Transform<?> bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inContraption) Transform<?> bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inInstancedContraption)
.translate(0, 1, 0) .translate(0, 1, 0)
.rotateX(wheelAngle); .rotateX(wheelAngle);
finalize(bogeyWheels, ms, light, vb); finalize(bogeyWheels, ms, light, vb);
Transform<?> bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inContraption) Transform<?> bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inInstancedContraption)
.translate(0, 1, 0) .translate(0, 1, 0)
.rotateX(wheelAngle) .rotateX(wheelAngle)
.translate(0, 1 / 4f, 0) .translate(0, 1 / 4f, 0)
.rotateX(-wheelAngle); .rotateX(-wheelAngle);
finalize(bogeyPin, ms, light, vb); finalize(bogeyPin, ms, light, vb);
if (!inContraption) if (!inInstancedContraption)
ms.popPose(); ms.popPose();
} }
} }

View file

@ -11,7 +11,7 @@ public class BackupBogeyRenderer extends BogeyRenderer.CommonRenderer {
public static BackupBogeyRenderer INSTANCE = new BackupBogeyRenderer(); public static BackupBogeyRenderer INSTANCE = new BackupBogeyRenderer();
@Override @Override
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
} }

View file

@ -46,8 +46,8 @@ public final class BogeyInstance {
} }
commonRenderer.ifPresent(bogeyRenderer -> commonRenderer.ifPresent(bogeyRenderer ->
bogeyRenderer.render(bogey.bogeyData, wheelAngle, ms)); bogeyRenderer.render(bogey.isUpsideDown(), bogey.bogeyData, wheelAngle, ms));
renderer.render(bogey.bogeyData, wheelAngle, ms); renderer.render(bogey.isUpsideDown(), bogey.bogeyData, wheelAngle, ms);
} }
public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) { public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) {

View file

@ -16,6 +16,8 @@ import java.util.function.Function;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.simibubi.create.foundation.command.DebugValueCommand;
import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
@ -306,6 +308,9 @@ public class Carriage {
double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing(); double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing();
double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing(); double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing();
boolean leadingUpsideDown = leadingBogey.isUpsideDown();
boolean trailingUpsideDown = trailingBogey.isUpsideDown();
for (boolean leading : Iterate.trueAndFalse) { for (boolean leading : Iterate.trueAndFalse) {
TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint(); TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint();
TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint(); TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint();
@ -321,24 +326,31 @@ public class Carriage {
dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
: pivoted(dce, dimension, point, : pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2); leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
leadingUpsideDown, trailingUpsideDown, leading);
boolean backAnchorFlip = trailingBogey.isUpsideDown() ^ leadingBogey.isUpsideDown();
if (isOnTwoBogeys()) { if (isOnTwoBogeys()) {
dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
: pivoted(dce, dimension, point, : pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2)); leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition() leadingUpsideDown, trailingUpsideDown, leading));
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition(backAnchorFlip)
: pivoted(dce, dimension, point, : pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2)); leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2,
leadingUpsideDown, trailingUpsideDown, leading));
} else { } else {
if (dimension.equals(otherDimension)) { if (dimension.equals(otherDimension)) {
dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition); dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition);
} else { } else {
dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition() dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition()
: pivoted(dce, dimension, point, leadingWheelSpacing)); : pivoted(dce, dimension, point, leadingWheelSpacing,
leadingUpsideDown, trailingUpsideDown, leading));
dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition() dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition()
: pivoted(dce, dimension, point, leadingWheelSpacing)); : pivoted(dce, dimension, point, leadingWheelSpacing,
leadingUpsideDown, trailingUpsideDown, leading));
} }
} }
@ -356,15 +368,20 @@ public class Carriage {
} }
private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey<Level> dimension, TravellingPoint start, private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey<Level> dimension, TravellingPoint start,
double offset) { double offset, boolean leadingUpsideDown, boolean trailingUpsideDown, boolean isLeading) {
if (train.graph == null) if (train.graph == null)
return dce.pivot == null ? null : dce.pivot.getLocation(); return dce.pivot == null ? null : dce.pivot.getLocation();
TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint()); TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint());
if (pivot == null) if (pivot == null)
return null; return null;
Vec3 startVec = start.getPosition(); Vec3 startVec = start.getPosition(start != getLeadingPoint() && (leadingBogey().isUpsideDown() != trailingBogey().isUpsideDown()));
Vec3 portalVec = pivot.getLocation() Vec3 portalVec = pivot.getLocation()
.add(0, 1, 0); .add(0, DebugValueCommand.tmpPortalOffset(leadingUpsideDown, trailingUpsideDown, isLeading), 0);
// same side - other side
// n(ormal)-n(ormal)
// u(pside down)-u(pside down) what about un ? not tested yet un doesn't work with + 1 or -1. HALP
// 1 works for: nn n nu
//-1 works for: uu u
return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec); return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec);
} }

View file

@ -8,7 +8,7 @@ import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.DimensionPalette; import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock; import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
import com.simibubi.create.content.logistics.trains.TrackGraph; import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
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;
@ -28,7 +28,7 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import static com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity.BOGEY_STYLE_KEY; import static com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity.BOGEY_STYLE_KEY;
public class CarriageBogey { public class CarriageBogey {
@ -38,6 +38,7 @@ public class CarriageBogey {
public CompoundTag bogeyData; public CompoundTag bogeyData;
AbstractBogeyBlock type; AbstractBogeyBlock type;
boolean upsideDown;
Couple<TravellingPoint> points; Couple<TravellingPoint> points;
LerpedFloat wheelAngle; LerpedFloat wheelAngle;
@ -48,11 +49,14 @@ public class CarriageBogey {
int derailAngle; int derailAngle;
public CarriageBogey(AbstractBogeyBlock type, CompoundTag bogeyData, TravellingPoint point, TravellingPoint point2) { public CarriageBogey(AbstractBogeyBlock type, boolean upsideDown, CompoundTag bogeyData, TravellingPoint point, TravellingPoint point2) {
this.type = type;
if (bogeyData == null || bogeyData.isEmpty()) if (bogeyData == null || bogeyData.isEmpty())
bogeyData = this.createBogeyData(); // Prevent Crash When Updating bogeyData = this.createBogeyData(); // Prevent Crash When Updating
this.bogeyData = bogeyData; this.bogeyData = bogeyData;
this.type = type; this.upsideDown = type.canBeUpsideDown() && upsideDown;
point.upsideDown = this.upsideDown;
point2.upsideDown = this.upsideDown;
points = Couple.create(point, point2); points = Couple.create(point, point2);
wheelAngle = LerpedFloat.angular(); wheelAngle = LerpedFloat.angular();
yaw = LerpedFloat.angular(); yaw = LerpedFloat.angular();
@ -109,11 +113,15 @@ public class CarriageBogey {
} }
public TravellingPoint leading() { public TravellingPoint leading() {
return points.getFirst(); TravellingPoint point = points.getFirst();
point.upsideDown = isUpsideDown();
return point;
} }
public TravellingPoint trailing() { public TravellingPoint trailing() {
return points.getSecond(); TravellingPoint point = points.getSecond();
point.upsideDown = isUpsideDown();
return point;
} }
public double getStress() { public double getStress() {
@ -127,18 +135,23 @@ public class CarriageBogey {
@Nullable @Nullable
public Vec3 getAnchorPosition() { public Vec3 getAnchorPosition() {
return getAnchorPosition(false);
}
@Nullable
public Vec3 getAnchorPosition(boolean flipUpsideDown) {
if (leading().edge == null) if (leading().edge == null)
return null; return null;
return points.getFirst() return points.getFirst()
.getPosition() .getPosition(flipUpsideDown)
.add(points.getSecond() .add(points.getSecond()
.getPosition()) .getPosition(flipUpsideDown))
.scale(.5); .scale(.5);
} }
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing, public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
float partialTicks, boolean leading) { float partialTicks, boolean leading) {
Vec3 thisOffset = type.getConnectorAnchorOffset(); Vec3 thisOffset = type.getConnectorAnchorOffset(isUpsideDown());
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1); thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X); thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
@ -159,6 +172,7 @@ public class CarriageBogey {
tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type) tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type)
.toString()); .toString());
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions))); tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
tag.putBoolean("UpsideDown", upsideDown);
tag.put(BOGEY_STYLE_KEY, bogeyData); tag.put(BOGEY_STYLE_KEY, bogeyData);
return tag; return tag;
} }
@ -166,10 +180,11 @@ public class CarriageBogey {
public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
ResourceLocation location = new ResourceLocation(tag.getString("Type")); ResourceLocation location = new ResourceLocation(tag.getString("Type"));
AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(location); AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(location);
boolean upsideDown = tag.getBoolean("UpsideDown");
Couple<TravellingPoint> points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND), Couple<TravellingPoint> points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND),
c -> TravellingPoint.read(c, graph, dimensions)); c -> TravellingPoint.read(c, graph, dimensions));
CompoundTag data = tag.getCompound(StandardBogeyTileEntity.BOGEY_DATA_KEY); CompoundTag data = tag.getCompound(AbstractBogeyTileEntity.BOGEY_DATA_KEY);
return new CarriageBogey(type, data, points.getFirst(), points.getSecond()); return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond());
} }
public BogeyInstance createInstance(MaterialManager materialManager) { public BogeyInstance createInstance(MaterialManager materialManager) {
@ -183,11 +198,15 @@ public class CarriageBogey {
private CompoundTag createBogeyData() { private CompoundTag createBogeyData() {
CompoundTag nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, AllBogeyStyles.STANDARD.name); NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, (type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD).name);
return nbt; return nbt;
} }
void setLeading() { void setLeading() {
isLeading = true; isLeading = true;
} }
public boolean isUpsideDown() {
return type.canBeUpsideDown() && upsideDown;
}
} }

View file

@ -162,11 +162,12 @@ public class CarriageContraption extends Contraption {
.getStep(), toLocalPos(pos)); .getStep(), toLocalPos(pos));
} }
if (blockState.getBlock() instanceof AbstractBogeyBlock) { if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) {
boolean captureTE = bogey.captureTileEntityForTrain();
bogeys++; bogeys++;
if (bogeys == 2) if (bogeys == 2)
secondBogeyPos = pos; secondBogeyPos = pos;
return Pair.of(new StructureBlockInfo(pos, blockState, null), null); return Pair.of(new StructureBlockInfo(pos, blockState, captureTE ? getTileEntityNBT(world, pos) : null), captureTE ? world.getBlockEntity(pos) : null);
} }
if (AllBlocks.BLAZE_BURNER.has(blockState) if (AllBlocks.BLAZE_BURNER.has(blockState)

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
@ -70,8 +70,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
int light = getBogeyLightCoords(entity, bogey, partialTicks); int light = getBogeyLightCoords(entity, bogey, partialTicks);
BlockEntity be = entity.getContraption().presentTileEntities.get(bogeyPos); BlockEntity be = entity.getContraption().presentTileEntities.get(bogeyPos);
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light, bogey.type.render(null, bogey.isUpsideDown(), bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light,
overlay, (StandardBogeyTileEntity) be); overlay, (AbstractBogeyTileEntity) be);
ms.popPose(); ms.popPose();
} }
@ -85,6 +85,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot, public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot,
float viewXRot, float partialTicks) { float viewXRot, float partialTicks) {
boolean selfUpsideDown = bogey.isUpsideDown();
boolean leadingUpsideDown = bogey.carriage.leadingBogey().isUpsideDown();
TransformStack.cast(ms) TransformStack.cast(ms)
.rotateY(viewYRot + 90) .rotateY(viewYRot + 90)
.rotateX(-viewXRot) .rotateX(-viewXRot)
@ -95,7 +97,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
.rotateY(-viewYRot - 90) .rotateY(-viewYRot - 90)
.rotateY(bogey.yaw.getValue(partialTicks)) .rotateY(bogey.yaw.getValue(partialTicks))
.rotateX(bogey.pitch.getValue(partialTicks)) .rotateX(bogey.pitch.getValue(partialTicks))
.translate(0, .5f, 0); .translate(0, .5f, 0)
.rotateZ(selfUpsideDown ? 180 : 0)
.translateY(selfUpsideDown != leadingUpsideDown ? 2 : 0);
} }
public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) { public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) {

View file

@ -82,7 +82,7 @@ public class CarriageCouplingRenderer {
float margin = 3 / 16f; float margin = 3 / 16f;
double couplingDistance = train.carriageSpacing.get(i) - 2 * margin double couplingDistance = train.carriageSpacing.get(i) - 2 * margin
- bogey1.type.getConnectorAnchorOffset().z - bogey2.type.getConnectorAnchorOffset().z; - bogey1.type.getConnectorAnchorOffset(bogey1.isUpsideDown()).z - bogey2.type.getConnectorAnchorOffset(bogey1.isUpsideDown()).z;
int couplingSegments = (int) Math.round(couplingDistance * 4); int couplingSegments = (int) Math.round(couplingDistance * 4);
double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments; double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments;
for (int j = 0; j < couplingSegments; j++) { for (int j = 0; j < couplingSegments; j++) {

View file

@ -88,7 +88,13 @@ public class CarriageSounds {
double distance2 = toBogey2.length(); double distance2 = toBogey2.length();
Couple<CarriageBogey> bogeys = entity.getCarriage().bogeys; Couple<CarriageBogey> bogeys = entity.getCarriage().bogeys;
closestBogeySound = bogeys.get(distance1 > distance2).getStyle().getSoundType(); CarriageBogey relevantBogey = bogeys.get(distance1 > distance2);
if (relevantBogey == null) {
relevantBogey = bogeys.getFirst();
}
if (relevantBogey != null) {
closestBogeySound = relevantBogey.getStyle().getSoundType();
}
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1; Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
double distance = Math.min(distance1, distance2); double distance = Math.min(distance1, distance2);

View file

@ -17,7 +17,7 @@ import java.util.function.Consumer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@ -317,7 +317,13 @@ public class Train {
if (leadingAnchor == null || trailingAnchor == null) if (leadingAnchor == null || trailingAnchor == null)
continue; continue;
total += leadingAnchor.distanceTo(trailingAnchor); double distanceTo = leadingAnchor.distanceToSqr(trailingAnchor);
if (carriage.leadingBogey().isUpsideDown() != previousCarriage.trailingBogey().isUpsideDown()) {
distanceTo = Math.sqrt(distanceTo - 4);
} else {
distanceTo = Math.sqrt(distanceTo);
}
total += distanceTo;
entries++; entries++;
} }
} }
@ -726,14 +732,16 @@ public class Train {
if (entity.getContraption()instanceof CarriageContraption cc) if (entity.getContraption()instanceof CarriageContraption cc)
cc.returnStorageForDisassembly(carriage.storage); cc.returnStorageForDisassembly(carriage.storage);
entity.setPos(Vec3 entity.setPos(Vec3
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset))); .atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset).below(carriage.leadingBogey().isUpsideDown() ? 2 : 0)));
entity.disassemble(); entity.disassemble();
for (CarriageBogey bogey : carriage.bogeys) { for (CarriageBogey bogey : carriage.bogeys) {
if (bogey == null)
continue;
Vec3 bogeyPosition = bogey.getAnchorPosition(); Vec3 bogeyPosition = bogey.getAnchorPosition();
if (bogeyPosition == null) continue; if (bogeyPosition == null) continue;
BlockEntity be = level.getBlockEntity(new BlockPos(bogeyPosition)); BlockEntity be = level.getBlockEntity(new BlockPos(bogeyPosition));
if (!(be instanceof StandardBogeyTileEntity sbte)) if (!(be instanceof AbstractBogeyTileEntity sbte))
continue; continue;
sbte.setBogeyData(bogey.bogeyData); sbte.setBogeyData(bogey.bogeyData);
} }
@ -957,7 +965,7 @@ public class Train {
occupiedObservers.clear(); occupiedObservers.clear();
cachedObserverFiltering.clear(); cachedObserverFiltering.clear();
TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position); TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position, false);
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups; Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
MutableObject<UUID> prevGroup = new MutableObject<>(null); MutableObject<UUID> prevGroup = new MutableObject<>(null);

View file

@ -49,8 +49,9 @@ public class TrainPacket extends SimplePacketBase {
if (!isFirst && !buffer.readBoolean()) if (!isFirst && !buffer.readBoolean())
continue; continue;
AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation()); AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation());
boolean upsideDown = buffer.readBoolean();
CompoundTag data = buffer.readNbt(); CompoundTag data = buffer.readNbt();
bogies.set(isFirst, new CarriageBogey(type, data, new TravellingPoint(), new TravellingPoint())); bogies.set(isFirst, new CarriageBogey(type, upsideDown, data, new TravellingPoint(), new TravellingPoint()));
} }
int spacing = buffer.readVarInt(); int spacing = buffer.readVarInt();
carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing)); carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing));
@ -88,6 +89,7 @@ public class TrainPacket extends SimplePacketBase {
} }
CarriageBogey bogey = carriage.bogeys.get(first); CarriageBogey bogey = carriage.bogeys.get(first);
buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type)); buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type));
buffer.writeBoolean(bogey.upsideDown);
buffer.writeNbt(bogey.bogeyData); buffer.writeNbt(bogey.bogeyData);
} }
buffer.writeVarInt(carriage.bogeySpacing); buffer.writeVarInt(carriage.bogeySpacing);

View file

@ -115,10 +115,13 @@ public class TrainRelocator {
BlockPos blockPos = blockhit.getBlockPos(); BlockPos blockPos = blockhit.getBlockPos();
BezierTrackPointLocation hoveredBezier = null; BezierTrackPointLocation hoveredBezier = null;
boolean upsideDown = relocating.carriages.get(0).leadingBogey().isUpsideDown();
Vec3 offset = upsideDown ? new Vec3(0, -0.5, 0) : Vec3.ZERO;
if (simulate && toVisualise != null && lastHoveredResult != null) { if (simulate && toVisualise != null && lastHoveredResult != null) {
for (int i = 0; i < toVisualise.size() - 1; i++) { for (int i = 0; i < toVisualise.size() - 1; i++) {
Vec3 vec1 = toVisualise.get(i); Vec3 vec1 = toVisualise.get(i).add(offset);
Vec3 vec2 = toVisualise.get(i + 1); Vec3 vec2 = toVisualise.get(i + 1).add(offset);
CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0))
.colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B)
.disableLineNormals() .disableLineNormals()
@ -150,7 +153,7 @@ public class TrainRelocator {
boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0; boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0;
boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true); boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true);
if (!simulate && result) { if (!simulate && result) {
relocating.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10)); relocating.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10));
AllPackets.channel.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier, AllPackets.channel.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier,
direction, lookAngle, relocatingEntityId)); direction, lookAngle, relocatingEntityId));
} }
@ -182,7 +185,7 @@ public class TrainRelocator {
if (edge == null) if (edge == null)
return false; return false;
TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position); TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position, false);
IEdgePointListener ignoreSignals = probe.ignoreEdgePoints(); IEdgePointListener ignoreSignals = probe.ignoreEdgePoints();
ITurnListener ignoreTurns = probe.ignoreTurns(); ITurnListener ignoreTurns = probe.ignoreTurns();
List<Pair<Couple<TrackNode>, Double>> recordedLocations = new ArrayList<>(); List<Pair<Couple<TrackNode>, Double>> recordedLocations = new ArrayList<>();

View file

@ -38,6 +38,7 @@ public class TravellingPoint {
public TrackEdge edge; public TrackEdge edge;
public double position; public double position;
public boolean blocked; public boolean blocked;
public boolean upsideDown;
public static enum SteerDirection { public static enum SteerDirection {
NONE(0), LEFT(-1), RIGHT(1); NONE(0), LEFT(-1), RIGHT(1);
@ -64,11 +65,12 @@ public class TravellingPoint {
public TravellingPoint() {} public TravellingPoint() {}
public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position) { public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position, boolean upsideDown) {
this.node1 = node1; this.node1 = node1;
this.node2 = node2; this.node2 = node2;
this.edge = edge; this.edge = edge;
this.position = position; this.position = position;
this.upsideDown = upsideDown;
} }
public IEdgePointListener ignoreEdgePoints() { public IEdgePointListener ignoreEdgePoints() {
@ -395,14 +397,22 @@ public class TravellingPoint {
} }
public Vec3 getPosition() { public Vec3 getPosition() {
return getPositionWithOffset(0); return getPosition(false);
}
public Vec3 getPosition(boolean flipped) {
return getPositionWithOffset(0, flipped);
} }
public Vec3 getPositionWithOffset(double offset) { public Vec3 getPositionWithOffset(double offset) {
return getPositionWithOffset(offset, false);
}
public Vec3 getPositionWithOffset(double offset, boolean flipUpsideDown) {
double t = (position + offset) / edge.getLength(); double t = (position + offset) / edge.getLength();
return edge.getPosition(t) return edge.getPosition(t)
.add(edge.getNormal(node1, node2, t) .add(edge.getNormal(node1, node2, t)
.scale(1)); .scale(upsideDown^flipUpsideDown ? -1 : 1));
} }
public void migrateTo(List<GraphLocation> locations) { public void migrateTo(List<GraphLocation> locations) {
@ -423,12 +433,13 @@ public class TravellingPoint {
tag.put("Nodes", nodes.map(TrackNode::getLocation) tag.put("Nodes", nodes.map(TrackNode::getLocation)
.serializeEach(loc -> loc.write(dimensions))); .serializeEach(loc -> loc.write(dimensions)));
tag.putDouble("Position", position); tag.putDouble("Position", position);
tag.putBoolean("UpsideDown", upsideDown);
return tag; return tag;
} }
public static TravellingPoint read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { public static TravellingPoint read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
if (graph == null) if (graph == null)
return new TravellingPoint(null, null, null, 0); return new TravellingPoint(null, null, null, 0, false);
Couple<TrackNode> locs = tag.contains("Nodes") Couple<TrackNode> locs = tag.contains("Nodes")
? Couple.deserializeEach(tag.getList("Nodes", Tag.TAG_COMPOUND), c -> TrackNodeLocation.read(c, dimensions)) ? Couple.deserializeEach(tag.getList("Nodes", Tag.TAG_COMPOUND), c -> TrackNodeLocation.read(c, dimensions))
@ -436,11 +447,11 @@ public class TravellingPoint {
: Couple.create(null, null); : Couple.create(null, null);
if (locs.either(Objects::isNull)) if (locs.either(Objects::isNull))
return new TravellingPoint(null, null, null, 0); return new TravellingPoint(null, null, null, 0, false);
double position = tag.getDouble("Position"); double position = tag.getDouble("Position");
return new TravellingPoint(locs.getFirst(), locs.getSecond(), graph.getConnectionsFrom(locs.getFirst()) return new TravellingPoint(locs.getFirst(), locs.getSecond(), graph.getConnectionsFrom(locs.getFirst())
.get(locs.getSecond()), position); .get(locs.getSecond()), position, tag.getBoolean("UpsideDown"));
} }
} }

View file

@ -38,7 +38,7 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePoi
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem; import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
@ -67,7 +67,6 @@ import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
@ -194,6 +193,7 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
int assemblyLength; int assemblyLength;
int[] bogeyLocations; int[] bogeyLocations;
AbstractBogeyBlock[] bogeyTypes; AbstractBogeyBlock[] bogeyTypes;
boolean[] upsideDownBogeys;
int bogeyCount; int bogeyCount;
@Override @Override
@ -270,28 +270,31 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
return false; return false;
BlockPos up = new BlockPos(track.getUpNormal(level, pos, state)); BlockPos up = new BlockPos(track.getUpNormal(level, pos, state));
BlockPos down = new BlockPos(track.getUpNormal(level, pos, state).multiply(-1, -1, -1));
int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1; int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1;
if (!isValidBogeyOffset(bogeyOffset)) { if (!isValidBogeyOffset(bogeyOffset)) {
for (int i = -1; i <= 1; i++) { for (boolean upsideDown : Iterate.falseAndTrue) {
BlockPos bogeyPos = pos.relative(assemblyDirection, i) for (int i = -1; i <= 1; i++) {
.offset(up); BlockPos bogeyPos = pos.relative(assemblyDirection, i)
BlockState blockState = level.getBlockState(bogeyPos); .offset(upsideDown ? down : up);
if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) { BlockState blockState = level.getBlockState(bogeyPos);
BlockEntity be = level.getBlockEntity(bogeyPos); if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey) {
if (!(be instanceof StandardBogeyTileEntity oldTE)) BlockEntity be = level.getBlockEntity(bogeyPos);
continue; if (!(be instanceof AbstractBogeyTileEntity oldTE))
CompoundTag oldData = oldTE.getBogeyData(); continue;
BlockState newBlock = bogey.getNextSize(oldTE); CompoundTag oldData = oldTE.getBogeyData();
if (newBlock.getBlock() == bogey) BlockState newBlock = bogey.getNextSize(oldTE);
player.displayClientMessage(Lang.translateDirect("create.bogey.style.no_other_sizes") if (newBlock.getBlock() == bogey)
.withStyle(ChatFormatting.RED), true); player.displayClientMessage(Lang.translateDirect("create.bogey.style.no_other_sizes")
level.setBlock(bogeyPos, newBlock, 3); .withStyle(ChatFormatting.RED), true);
BlockEntity newEntity = level.getBlockEntity(bogeyPos); level.setBlock(bogeyPos, newBlock, 3);
if (!(newEntity instanceof StandardBogeyTileEntity newTE)) BlockEntity newEntity = level.getBlockEntity(bogeyPos);
continue; if (!(newEntity instanceof AbstractBogeyTileEntity newTE))
newTE.setBogeyData(oldData); continue;
bogey.playRotateSound(level, bogeyPos); newTE.setBogeyData(oldData);
return true; bogey.playRotateSound(level, bogeyPos);
return true;
}
} }
} }
@ -304,7 +307,9 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
return false; return false;
} }
BlockPos targetPos = pos.offset(up); boolean upsideDown = (player.getViewXRot(1.0F) < 0 && (track.getBogeyAnchor(level, pos, state)).getBlock() instanceof AbstractBogeyBlock bogey && bogey.canBeUpsideDown());
BlockPos targetPos = upsideDown ? pos.offset(down) : pos.offset(up);
if (level.getBlockState(targetPos) if (level.getBlockState(targetPos)
.getDestroySpeed(level, targetPos) == -1) { .getDestroySpeed(level, targetPos) == -1) {
return false; return false;
@ -312,7 +317,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
level.destroyBlock(targetPos, true); level.destroyBlock(targetPos, true);
BlockState bogeyAnchor = ProperWaterloggedBlock.withWater(level, track.getBogeyAnchor(level, pos, state), pos); BlockState bogeyAnchor = track.getBogeyAnchor(level, pos, state);
if (bogeyAnchor.getBlock() instanceof AbstractBogeyBlock bogey) {
bogeyAnchor = bogey.getVersion(bogeyAnchor, upsideDown);
}
bogeyAnchor = ProperWaterloggedBlock.withWater(level, bogeyAnchor, pos);
level.setBlock(targetPos, bogeyAnchor, 3); level.setBlock(targetPos, bogeyAnchor, 3);
player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true); player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true);
SoundType soundtype = bogeyAnchor.getBlock() SoundType soundtype = bogeyAnchor.getBlock()
@ -387,8 +396,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
bogeyLocations = new int[maxBogeyCount]; bogeyLocations = new int[maxBogeyCount];
if (bogeyTypes == null) if (bogeyTypes == null)
bogeyTypes = new AbstractBogeyBlock[maxBogeyCount]; bogeyTypes = new AbstractBogeyBlock[maxBogeyCount];
if (upsideDownBogeys == null)
upsideDownBogeys = new boolean[maxBogeyCount];
Arrays.fill(bogeyLocations, -1); Arrays.fill(bogeyLocations, -1);
Arrays.fill(bogeyTypes, null); Arrays.fill(bogeyTypes, null);
Arrays.fill(upsideDownBogeys, false);
for (int i = 0; i < MAX_LENGTH; i++) { for (int i = 0; i < MAX_LENGTH; i++) {
if (i == MAX_LENGTH - 1) { if (i == MAX_LENGTH - 1) {
@ -401,10 +413,19 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
} }
BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos)); BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos));
if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && bogeyIndex < bogeyLocations.length) { BlockPos upsideDownBogeyOffset = new BlockPos(bogeyOffset.getX(), bogeyOffset.getY()*-1, bogeyOffset.getZ());
bogeyTypes[bogeyIndex] = bogey; if (bogeyIndex < bogeyLocations.length) {
bogeyLocations[bogeyIndex] = i; if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && !bogey.isUpsideDown(potentialBogeyState)) {
bogeyIndex++; bogeyTypes[bogeyIndex] = bogey;
bogeyLocations[bogeyIndex] = i;
upsideDownBogeys[bogeyIndex] = false;
bogeyIndex++;
} else if ((potentialBogeyState = level.getBlockState(upsideDownBogeyOffset.offset(currentPos))).getBlock() instanceof AbstractBogeyBlock bogey && bogey.isUpsideDown(potentialBogeyState)) {
bogeyTypes[bogeyIndex] = bogey;
bogeyLocations[bogeyIndex] = i;
upsideDownBogeys[bogeyIndex] = true;
bogeyIndex++;
}
} }
currentPos.move(assemblyDirection); currentPos.move(assemblyDirection);
@ -564,7 +585,7 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
return; return;
} }
points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge)); points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge, false));
} }
secondNode = node; secondNode = node;
@ -591,10 +612,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]); spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]);
CarriageContraption contraption = new CarriageContraption(assemblyDirection); CarriageContraption contraption = new CarriageContraption(assemblyDirection);
BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset); BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset);
BlockPos upsideDownBogeyPosOffset = trackPosition.offset(new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ()));
try { try {
int offset = bogeyLocations[bogeyIndex] + 1; int offset = bogeyLocations[bogeyIndex] + 1;
boolean success = contraption.assemble(level, bogeyPosOffset.relative(assemblyDirection, offset)); boolean success = contraption.assemble(level, upsideDownBogeys[bogeyIndex] ? upsideDownBogeyPosOffset.relative(assemblyDirection, offset) : bogeyPosOffset.relative(assemblyDirection, offset));
atLeastOneForwardControls |= contraption.hasForwardControls(); atLeastOneForwardControls |= contraption.hasForwardControls();
contraption.setSoundQueueOffset(offset); contraption.setSoundQueueOffset(offset);
if (!success) { if (!success) {
@ -608,25 +630,29 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable
} }
AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex];
boolean firstBogeyIsUpsideDown = upsideDownBogeys[bogeyIndex];
BlockPos firstBogeyPos = contraption.anchor; BlockPos firstBogeyPos = contraption.anchor;
StandardBogeyTileEntity firstBogeyTileEntity = (StandardBogeyTileEntity) level.getBlockEntity(firstBogeyPos); AbstractBogeyTileEntity firstBogeyTileEntity = (AbstractBogeyTileEntity) level.getBlockEntity(firstBogeyPos);
CarriageBogey firstBogey = CarriageBogey firstBogey =
new CarriageBogey(typeOfFirstBogey, firstBogeyTileEntity.getBogeyData(), points.get(pointIndex), points.get(pointIndex + 1)); new CarriageBogey(typeOfFirstBogey, firstBogeyIsUpsideDown, firstBogeyTileEntity.getBogeyData(), points.get(pointIndex), points.get(pointIndex + 1));
CarriageBogey secondBogey = null; CarriageBogey secondBogey = null;
BlockPos secondBogeyPos = contraption.getSecondBogeyPos(); BlockPos secondBogeyPos = contraption.getSecondBogeyPos();
/*if (secondBogeyPos != null && (bogeyIndex + 1 < upsideDownBogeys.length && upsideDownBogeys[bogeyIndex + 1])) {
secondBogeyPos = secondBogeyPos.above(2);
}*/
int bogeySpacing = 0; int bogeySpacing = 0;
if (secondBogeyPos != null) { if (secondBogeyPos != null) {
if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos
.equals(bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) { .equals((upsideDownBogeys[bogeyIndex + 1] ? upsideDownBogeyPosOffset : bogeyPosOffset).relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) {
exception(new AssemblyException(Lang.translateDirect("train_assembly.not_connected_in_order")), exception(new AssemblyException(Lang.translateDirect("train_assembly.not_connected_in_order")),
contraptions.size() + 1); contraptions.size() + 1);
return; return;
} }
StandardBogeyTileEntity secondBogeyTileEntity = AbstractBogeyTileEntity secondBogeyTileEntity =
(StandardBogeyTileEntity) level.getBlockEntity(secondBogeyPos); (AbstractBogeyTileEntity) level.getBlockEntity(secondBogeyPos);
bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex]; bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex];
secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], secondBogeyTileEntity.getBogeyData(), secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], upsideDownBogeys[bogeyIndex + 1], secondBogeyTileEntity.getBogeyData(),
points.get(pointIndex + 2), points.get(pointIndex + 3)); points.get(pointIndex + 2), points.get(pointIndex + 3));
bogeyIndex++; bogeyIndex++;

View file

@ -0,0 +1,114 @@
package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllBogeyStyles;
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
import com.simibubi.create.foundation.tileEntity.CachedRenderBBTileEntity;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractBogeyTileEntity extends CachedRenderBBTileEntity {
public static String BOGEY_STYLE_KEY = "BogeyStyle";
public static String BOGEY_DATA_KEY = "BogeyData";
private CompoundTag bogeyData;
public AbstractBogeyTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
public abstract BogeyStyle getDefaultStyle();
public CompoundTag getBogeyData() {
if (this.bogeyData == null || !this.bogeyData.contains(BOGEY_STYLE_KEY))
this.bogeyData = this.createBogeyData();
return this.bogeyData;
}
public void setBogeyData(@NotNull CompoundTag newData) {
if (!newData.contains(BOGEY_STYLE_KEY)) {
ResourceLocation style = getDefaultStyle().name;
NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style);
}
this.bogeyData = newData;
}
public void setBogeyStyle(@NotNull BogeyStyle style) {
ResourceLocation location = style.name;
CompoundTag data = this.getBogeyData();
NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location);
markUpdated();
}
@NotNull
public BogeyStyle getStyle() {
CompoundTag data = this.getBogeyData();
ResourceLocation currentStyle = NBTHelper.readResourceLocation(data, BOGEY_STYLE_KEY);
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(currentStyle);
if (style == null) {
setBogeyStyle(getDefaultStyle());
return getStyle();
}
return style;
}
@Override
protected void saveAdditional(@NotNull CompoundTag pTag) {
CompoundTag data = this.getBogeyData();
if (data != null) pTag.put(BOGEY_DATA_KEY, data); // Now contains style
super.saveAdditional(pTag);
}
@Override
public void load(CompoundTag pTag) {
if (pTag.contains(BOGEY_DATA_KEY))
this.bogeyData = pTag.getCompound(BOGEY_DATA_KEY);
else
this.bogeyData = this.createBogeyData();
super.load(pTag);
}
private CompoundTag createBogeyData() {
CompoundTag nbt = new CompoundTag();
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().name);
return nbt;
}
@Override
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(2);
}
// Ponder
LerpedFloat virtualAnimation = LerpedFloat.angular();
public float getVirtualAngle(float partialTicks) {
return virtualAnimation.getValue(partialTicks);
}
public void animate(float distanceMoved) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof AbstractBogeyBlock type))
return;
double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius());
double newWheelAngle = (virtualAnimation.getValue() - angleDiff) % 360;
virtualAnimation.setValue(newWheelAngle);
}
private void markUpdated() {
setChanged();
Level level = getLevel();
if (level != null)
getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
}

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.logistics.trains.track; package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllBogeyStyles;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock; import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
import com.simibubi.create.content.logistics.trains.BogeySizes; import com.simibubi.create.content.logistics.trains.BogeySizes;
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
@ -18,7 +19,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public class StandardBogeyBlock extends AbstractBogeyBlock implements ITE<StandardBogeyTileEntity>, ProperWaterloggedBlock, ISpecialBlockItemRequirement { public class StandardBogeyBlock extends AbstractBogeyBlock<StandardBogeyTileEntity> implements ITE<StandardBogeyTileEntity>, ProperWaterloggedBlock, ISpecialBlockItemRequirement {
public StandardBogeyBlock(Properties props, BogeySizes.BogeySize size) { public StandardBogeyBlock(Properties props, BogeySizes.BogeySize size) {
super(props, size); super(props, size);
@ -40,6 +41,11 @@ public class StandardBogeyBlock extends AbstractBogeyBlock implements ITE<Standa
return new Vec3(0, 7 / 32f, 1); return new Vec3(0, 7 / 32f, 1);
} }
@Override
public BogeyStyle getDefaultStyle() {
return AllBogeyStyles.STANDARD;
}
@Override @Override
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
Player player) { Player player) {

View file

@ -1,112 +1,19 @@
package com.simibubi.create.content.logistics.trains.track; package com.simibubi.create.content.logistics.trains.track;
import com.simibubi.create.AllBogeyStyles; import com.simibubi.create.AllBogeyStyles;
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle; import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
import com.simibubi.create.foundation.tileEntity.CachedRenderBBTileEntity;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
;
import org.jetbrains.annotations.NotNull;
public class StandardBogeyTileEntity extends CachedRenderBBTileEntity {
public static String BOGEY_STYLE_KEY = "BogeyStyle";
public static String BOGEY_DATA_KEY = "BogeyData";
private CompoundTag bogeyData;
public class StandardBogeyTileEntity extends AbstractBogeyTileEntity {
public StandardBogeyTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public StandardBogeyTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
} }
public CompoundTag getBogeyData() {
if (this.bogeyData == null || !this.bogeyData.contains(BOGEY_STYLE_KEY))
this.bogeyData = this.createBogeyData();
return this.bogeyData;
}
public void setBogeyData(@NotNull CompoundTag newData) {
if (!newData.contains(BOGEY_STYLE_KEY)) {
ResourceLocation style = AllBogeyStyles.STANDARD.name;
NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style);
}
this.bogeyData = newData;
}
public void setBogeyStyle(@NotNull BogeyStyle style) {
ResourceLocation location = style.name;
CompoundTag data = this.getBogeyData();
NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location);
markUpdated();
}
@NotNull
public BogeyStyle getStyle() {
CompoundTag data = this.getBogeyData();
ResourceLocation currentStyle = NBTHelper.readResourceLocation(data, BOGEY_STYLE_KEY);
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(currentStyle);
if (style == null) {
setBogeyStyle(AllBogeyStyles.STANDARD);
return getStyle();
}
return style;
}
@Override @Override
protected void saveAdditional(@NotNull CompoundTag pTag) { public BogeyStyle getDefaultStyle() {
CompoundTag data = this.getBogeyData(); return AllBogeyStyles.STANDARD;
if (data != null) pTag.put(BOGEY_DATA_KEY, data); // Now contains style
super.saveAdditional(pTag);
}
@Override
public void load(CompoundTag pTag) {
if (pTag.contains(BOGEY_DATA_KEY))
this.bogeyData = pTag.getCompound(BOGEY_DATA_KEY);
else
this.bogeyData = this.createBogeyData();
super.load(pTag);
}
private CompoundTag createBogeyData() {
CompoundTag nbt = new CompoundTag();
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, AllBogeyStyles.STANDARD.name);
return nbt;
}
@Override
protected AABB createRenderBoundingBox() {
return super.createRenderBoundingBox().inflate(2);
}
// Ponder
LerpedFloat virtualAnimation = LerpedFloat.angular();
public float getVirtualAngle(float partialTicks) {
return virtualAnimation.getValue(partialTicks);
}
public void animate(float distanceMoved) {
BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof AbstractBogeyBlock type))
return;
double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius());
double newWheelAngle = (virtualAnimation.getValue() - angleDiff) % 360;
virtualAnimation.setValue(newWheelAngle);
}
private void markUpdated() {
setChanged();
Level level = getLevel();
if (level != null)
getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
} }
} }

View file

@ -60,6 +60,7 @@ public class AllCommands {
.then(CameraDistanceCommand.register()) .then(CameraDistanceCommand.register())
.then(CameraAngleCommand.register()) .then(CameraAngleCommand.register())
.then(FlySpeedCommand.register()) .then(FlySpeedCommand.register())
.then(DebugValueCommand.register())
//.then(KillTPSCommand.register()) //.then(KillTPSCommand.register())
.build(); .build();

View file

@ -0,0 +1,78 @@
package com.simibubi.create.foundation.command;
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.simibubi.create.Create;
import net.minecraft.SharedConstants;
import org.apache.commons.lang3.mutable.MutableInt;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.foundation.utility.Components;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.world.level.block.CommandBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
public class DebugValueCommand {
public static float value = 0;
public static ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal("debugValue")
.requires(cs -> cs.hasPermission(4))
.then(Commands.argument("value", FloatArgumentType.floatArg())
.executes((ctx) -> {
value = FloatArgumentType.getFloat(ctx, "value");
ctx.getSource().sendSuccess(Components.literal("Set value to: "+value), true);
return 1;
}));
}
// same side - other side
// n(ormal)-n(ormal)
// u(pside down)-u(pside down) what about un ? not tested yet un doesn't work with + 1 or -1. HALP
// 1 works for: nn n nu
//-1 works for: uu u
public static double tmpPortalOffset(boolean leadingUpsideDown, boolean trailingUpsideDown, boolean isLeading) {
double portalOffset = 0.0;
if (!leadingUpsideDown && !trailingUpsideDown) { // nn
return 1.0;
} else if (leadingUpsideDown && trailingUpsideDown) { // uu
return -1.0;
} else if (leadingUpsideDown && !trailingUpsideDown) { // un
if (isLeading) {
return 0.1;
} else {
return 0.2;
}
} else if (!leadingUpsideDown && trailingUpsideDown) { // nu
if (isLeading) {
return 1.0;
} else {
return 1.0;
}
}
Create.LOGGER.error("Theoretically unreachable code just got reached. HALP me please");
return 0.0; // this is actually unreachable but yay
/*if (!leadingUpsideDown) { // leading up
portalOffset = 1.0;
} else if (trailingUpsideDown) { // leading down, trailing down
portalOffset = -1.0;
} else { // leading down, trailing up - ahh
portalOffset = DebugValueCommand.value;
}
return portalOffset;*/
}
}

View file

@ -7,7 +7,7 @@ import java.util.function.Function;
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.IBearingTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.IBearingTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity;
import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.ponder.PonderWorld;
@ -34,7 +34,7 @@ public class AnimateTileEntityInstruction extends TickingInstruction {
public static AnimateTileEntityInstruction bogey(BlockPos location, float totalDelta, int ticks) { public static AnimateTileEntityInstruction bogey(BlockPos location, float totalDelta, int ticks) {
float movedPerTick = totalDelta / ticks; float movedPerTick = totalDelta / ticks;
return new AnimateTileEntityInstruction(location, totalDelta, ticks, return new AnimateTileEntityInstruction(location, totalDelta, ticks,
(w, f) -> castIfPresent(w, location, StandardBogeyTileEntity.class) (w, f) -> castIfPresent(w, location, AbstractBogeyTileEntity.class)
.ifPresent(bte -> bte.animate(f.equals(totalDelta) ? 0 : movedPerTick)), .ifPresent(bte -> bte.animate(f.equals(totalDelta) ? 0 : movedPerTick)),
(w) -> 0f); (w) -> 0f);
} }