diff --git a/.gitignore b/.gitignore index 4afb35865..b9a3321f8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ local.properties # PDT-specific .buildpath -.DS_Store \ No newline at end of file +.DS_Store +/libs/ diff --git a/build.gradle b/build.gradle index d8e3a2d87..02e7769a0 100644 --- a/build.gradle +++ b/build.gradle @@ -135,6 +135,9 @@ repositories { includeGroup "maven.modrinth" } } + flatDir { + dirs 'libs' + } } dependencies { @@ -169,6 +172,7 @@ dependencies { // 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("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 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index d50c09db9..9ee732055 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -559,7 +559,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json f85edc574ee6de0de7693ffb031266643db6724a assets/create/lang/en_ud.json -eb624aafc91b284143c3a0cc7d9bbb8de66e8950 assets/create/lang/en_us.json +c0b485449804a49390ef01491350a2878b2b57bd assets/create/lang/en_us.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -5611,6 +5611,7 @@ ac265a674626e0e832330086fd18fe0be37fc327 data/create/recipes/weathered_copper_ti 2a2700b43614f86d3294726595cb28ed7dca4387 data/create/tags/blocks/brittle.json d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json 2b4c93e5a752ebf54217594766f30d8d60cb4343 data/create/tags/blocks/fan_transparent.json +ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/create/tags/blocks/girdable_tracks.json ee6d2b53d81f2bed492662b6c06f46c4f2b9ef9b data/create/tags/blocks/movable_empty_collider.json 6e5d3b2123fbb00e7f439c091623619502551bca data/create/tags/blocks/non_movable.json 10781e8cfcbb3486327aace3aa00e437fb44b331 data/create/tags/blocks/ore_override_stone.json @@ -5618,6 +5619,7 @@ ee6d2b53d81f2bed492662b6c06f46c4f2b9ef9b data/create/tags/blocks/movable_empty_c 23eb7cf8abff36f85320c35c69b98fdb775c8ec9 data/create/tags/blocks/safe_nbt.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json +ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/create/tags/blocks/tracks.json 9460e92c8e483446318b849abe7e6f52dcd4a269 data/create/tags/blocks/tree_attachments.json 50936b211d94167a35ec78c89954082a336b6269 data/create/tags/blocks/valve_handles.json eac71740fb12bdb38b5dfaa2268613d7ba82b809 data/create/tags/blocks/windmill_sails.json diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 2603c07fc..dcee7c629 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1754,6 +1754,12 @@ "enchantment.create.capacity.desc": "Increases Backtank air capacity.", "enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.", + "create.bogey.style.updated_style": "Updated style", + "create.bogey.style.updated_style_and_size": "Updated style and size", + "create.bogey.style.no_other_sizes": "No other sizes", + "create.bogey.style.invalid": "Unnamed style", + "create.bogey.style.standard": "Standard", + "_": "->------------------------] Subtitles [------------------------<-", diff --git a/src/main/java/com/simibubi/create/AllBogeyStyles.java b/src/main/java/com/simibubi/create/AllBogeyStyles.java index f15e7bd4d..1d5358bd1 100644 --- a/src/main/java/com/simibubi/create/AllBogeyStyles.java +++ b/src/main/java/com/simibubi/create/AllBogeyStyles.java @@ -1,5 +1,6 @@ package com.simibubi.create; +import com.google.common.collect.ImmutableMap; import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock; import com.simibubi.create.content.logistics.trains.BogeyRenderer; import com.simibubi.create.content.logistics.trains.BogeyRenderer.CommonRenderer; @@ -7,6 +8,7 @@ import com.simibubi.create.content.logistics.trains.BogeySizes; import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.*; 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.tterrag.registrate.util.entry.BlockEntry; @@ -26,20 +28,26 @@ import static com.simibubi.create.Create.LOGGER; public class AllBogeyStyles { public static final Map BOGEY_STYLES = new HashMap<>(); + public static final Map> STYLE_GROUPS = new HashMap<>(); // each set of styles that should be cycled through + private static final Map EMPTY_GROUP = ImmutableMap.of(); - public static BogeyStyle STANDARD = create("standard") + public static Map getCycleGroup(ResourceLocation cycleGroup) { + return STYLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP); + } + + public static BogeyStyle STANDARD = create("standard", "standard") .commonRenderer(CommonStandardBogeyRenderer::new) - .displayName(Lang.translateDirect("create.bogeys.styles.standard")) + .displayName(Components.translatable("create.bogey.style.standard")) .size(BogeySizes.SMALL, SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY) .size(BogeySizes.LARGE, LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY) .build(); - public static BogeyStyleBuilder create(String name) { - return create(Create.asResource(name)); + public static BogeyStyleBuilder create(String name, String cycleGroup) { + return create(Create.asResource(name), Create.asResource(cycleGroup)); } - public static BogeyStyleBuilder create(ResourceLocation name) { - return new BogeyStyleBuilder(name); + public static BogeyStyleBuilder create(ResourceLocation name, ResourceLocation cycleGroup) { + return new BogeyStyleBuilder(name, cycleGroup); } public static void register() { @@ -49,16 +57,18 @@ public class AllBogeyStyles { public static class BogeyStyleBuilder { protected final Map sizes = new HashMap<>(); protected final ResourceLocation name; + protected final ResourceLocation cycleGroup; - protected Component displayName = Lang.translateDirect("create.bogeys.invalid"); + 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> commonRenderer = Optional.empty(); - public BogeyStyleBuilder(ResourceLocation name) { + public BogeyStyleBuilder(ResourceLocation name, ResourceLocation cycleGroup) { this.name = name; + this.cycleGroup = cycleGroup; } public BogeyStyleBuilder displayName(Component displayName) { @@ -105,8 +115,9 @@ public class AllBogeyStyles { public BogeyStyle build() { BogeyStyle entry = - new BogeyStyle(name, displayName, soundType, contactParticle, smokeParticle, defaultData, sizes, commonRenderer); + new BogeyStyle(name, cycleGroup, displayName, soundType, contactParticle, smokeParticle, defaultData, sizes, commonRenderer); BOGEY_STYLES.put(name, entry); + STYLE_GROUPS.computeIfAbsent(cycleGroup, l -> new HashMap<>()).put(name, entry); return entry; } } diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index ba342d0f8..a6f0f7456 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -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.StationTileEntity; 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.TrackBlock; 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.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.tterrag.registrate.util.entry.BlockEntityEntry; -import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonNullSupplier; -import net.minecraft.world.level.block.Block; - public class AllTileEntities { // Schematics diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index 7a74a69c4..12807830f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -342,7 +342,7 @@ public abstract class Contraption { } // 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)) if (!visited.contains(pos.relative(d))) frontier.add(pos.relative(d)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java index 28aa93eaa..26a1ca324 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java @@ -37,7 +37,7 @@ public class ChassisRangeDisplay { timer = DISPLAY_TIME; CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te)) .colored(0xFFFFFF) - .disableLineNormals() + .disableNormals() .lineWidth(1 / 16f) .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java index fd9659dfe..b6ecc76de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java @@ -100,7 +100,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox()) .colored(h ? HIGHLIGHT : PASSIVE) .withFaceTextures(faceTex, faceTex) - .disableLineNormals() + .disableNormals() .lineWidth(h ? 1 / 16f : 1 / 64f); } } @@ -155,12 +155,12 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox) .colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE) - .disableLineNormals() + .disableNormals() .lineWidth(1 / 16f); CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0x4D9162) - .disableLineNormals() + .disableNormals() .lineWidth(1 / 64f); } @@ -259,7 +259,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0xB5F2C6) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED) - .disableLineNormals() + .disableNormals() .lineWidth(1 / 24f); discard(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java index 7d25a0443..9028abdaa 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java @@ -39,7 +39,7 @@ public class ZapperRenderHandler extends ShootableGadgetRenderHandler { cachedBeams.forEach(beam -> { CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) - .disableLineNormals() + .disableNormals() .colored(0xffffff) .lineWidth(beam.itensity * 1 / 8f); }); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java index 888a706b5..b5e8ed028 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java @@ -33,7 +33,7 @@ public class WorldshaperRenderHandler { CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) .colored(0xbfbfbf) - .disableLineNormals() + .disableNormals() .lineWidth(1 / 32f) .withFaceTexture(AllSpecialTextures.CHECKERED); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/AbstractBogeyBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/AbstractBogeyBlock.java index 040cdd599..61110f849 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/AbstractBogeyBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/AbstractBogeyBlock.java @@ -9,6 +9,8 @@ import java.util.Set; import javax.annotation.Nullable; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Vector3f; @@ -17,7 +19,10 @@ import com.simibubi.create.AllBogeyStyles; import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.wrench.IWrenchable; 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.entity.Carriage; +import com.simibubi.create.content.logistics.trains.entity.CarriageBogey; +import com.simibubi.create.content.logistics.trains.entity.TravellingPoint; +import com.simibubi.create.content.logistics.trains.track.AbstractBogeyTileEntity; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.block.ITE; @@ -46,6 +51,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -55,7 +61,7 @@ import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.NotNull; -public abstract class AbstractBogeyBlock extends Block implements ITE, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable { +public abstract class AbstractBogeyBlock extends Block implements ITE, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable { public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; static final List BOGEYS = new ArrayList<>(); public BogeySizes.BogeySize size; @@ -67,7 +73,23 @@ public abstract class AbstractBogeyBlock extends Block implements ITE getValidPathfindingTypes(BogeyStyle style) { + return ImmutableSet.of(getTrackType(style)); + } + + public abstract TrackMaterial.TrackType getTrackType(BogeyStyle style); + + /** + * Only for internal Create use. If you have your own style set, do not call this method + */ + @Deprecated + public static void registerStandardBogey(ResourceLocation block) { BOGEYS.add(block); } @@ -100,16 +122,34 @@ public abstract class AbstractBogeyBlock extends Block implements ITE commonRenderer = style.getInWorldCommonRenderInstance(); final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize()); @@ -120,14 +160,17 @@ public abstract class AbstractBogeyBlock extends Block implements ITE - common.render(sbte.getBogeyData(), wheelAngle, ms, light, vb)); + common.render(upsideDown, finalBogeyData, wheelAngle, ms, light, vb, state == null)); } public BogeySizes.BogeySize getSize() { return this.size; - }; + } public Direction getBogeyUpDirection() { return Direction.UP; @@ -153,21 +196,21 @@ public abstract class AbstractBogeyBlock extends Block implements ITE 1) { - Collection styles = AllBogeyStyles.BOGEY_STYLES.values(); - - if (styles.size() <= 1) - return InteractionResult.PASS; BlockEntity be = level.getBlockEntity(pos); - if (!(be instanceof StandardBogeyTileEntity sbte)) + if (!(be instanceof AbstractBogeyTileEntity sbte)) return InteractionResult.FAIL; player.getCooldowns().addCooldown(stack.getItem(), 20); BogeyStyle currentStyle = sbte.getStyle(); + BogeySizes.BogeySize size = getSize(); BogeyStyle style = this.getNextStyle(currentStyle); + if (style == currentStyle) + return InteractionResult.PASS; + Set validSizes = style.validSizes(); for (int i = 0; i < BogeySizes.count(); i++) { @@ -181,17 +224,17 @@ public abstract class AbstractBogeyBlock extends Block implements ITE getBogeyBlockCycle() { + return BOGEYS; + } + @Override public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) { Block block = state.getBlock(); - int indexOf = BOGEYS.indexOf(RegisteredObjects.getKeyOrThrow(block)); + List bogeyCycle = getBogeyBlockCycle(); + int indexOf = bogeyCycle.indexOf(RegisteredObjects.getKeyOrThrow(block)); if (indexOf == -1) return state; - int index = (indexOf + 1) % BOGEYS.size(); + int index = (indexOf + 1) % bogeyCycle.size(); Direction bogeyUpDirection = getBogeyUpDirection(); boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state); while (index != indexOf) { - ResourceLocation id = BOGEYS.get(index); + ResourceLocation id = bogeyCycle.get(index); Block newBlock = ForgeRegistries.BLOCKS.getValue(id); - if (newBlock instanceof AbstractBogeyBlock bogey) { + if (newBlock instanceof AbstractBogeyBlock bogey) { BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate); if (matchingBogey != null) - return matchingBogey.hasProperty(WATERLOGGED) - ? matchingBogey.setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - : matchingBogey; + return copyProperties(state, matchingBogey); } - index = (index + 1) % BOGEYS.size(); + index = (index + 1) % bogeyCycle.size(); } return state; @@ -229,37 +278,55 @@ public abstract class AbstractBogeyBlock extends Block implements ITE> propertiesToCopy() { + return ImmutableList.of(WATERLOGGED, AXIS); + } + + // generic method needed to satisfy Property and BlockState's generic requirements + private > BlockState copyProperty(BlockState source, BlockState target, Property property) { + if (source.hasProperty(property) && target.hasProperty(property)) { + return target.setValue(property, source.getValue(property)); + } + return target; + } + + private BlockState copyProperties(BlockState source, BlockState target) { + for (Property property : propertiesToCopy()) + target = copyProperty(source, target, property); + return target; + } + + public BlockState getNextSize(AbstractBogeyTileEntity sbte) { BogeySizes.BogeySize size = this.getSize(); BogeyStyle style = sbte.getStyle(); BlockState nextBlock = style.getNextBlock(size).defaultBlockState(); - return nextBlock.hasProperty(WATERLOGGED) - ? nextBlock.setValue(WATERLOGGED, sbte.getBlockState().getValue(WATERLOGGED)) - : nextBlock; + nextBlock = copyProperties(sbte.getBlockState(), nextBlock); + return nextBlock; } - public BlockState getStateOfSize(StandardBogeyTileEntity sbte, BogeySizes.BogeySize size) { + public BlockState getStateOfSize(AbstractBogeyTileEntity sbte, BogeySizes.BogeySize size) { BogeyStyle style = sbte.getStyle(); BlockState state = style.getBlockOfSize(size).defaultBlockState(); - return state.hasProperty(WATERLOGGED) - ? state.setValue(WATERLOGGED, sbte.getBlockState().getValue(WATERLOGGED)) - : state; + return copyProperties(sbte.getBlockState(), state); } public BogeyStyle getNextStyle(Level level, BlockPos pos) { BlockEntity te = level.getBlockEntity(pos); - if (te instanceof StandardBogeyTileEntity sbte) + if (te instanceof AbstractBogeyTileEntity sbte) return this.getNextStyle(sbte.getStyle()); - return AllBogeyStyles.STANDARD; + return getDefaultStyle(); } public BogeyStyle getNextStyle(BogeyStyle style) { - Collection allStyles = AllBogeyStyles.BOGEY_STYLES.values(); + Collection allStyles = style.getCycleGroup().values(); if (allStyles.size() <= 1) return style; List list = new ArrayList<>(allStyles); @@ -279,4 +346,16 @@ public abstract class AbstractBogeyBlock extends Block implements ITE[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inContraption, int size) { - return (inContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size); + public Transform[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption, int 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 */ @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 @@ -79,8 +79,8 @@ public abstract class BogeyRenderer { * @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); + public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms) { + this.render(upsideDown, bogeyData, wheelAngle, ms, 0, null, true); } 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 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 */ - public Transform getTransformFromPartial(PartialModel model, PoseStack ms, boolean inContraption) { + public Transform getTransformFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption) { 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); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java index 547df8b1b..ee8795ddd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.logistics.trains; 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 net.minecraft.client.renderer.MultiBufferSource; @@ -17,10 +17,10 @@ public class BogeyTileEntityRenderer extends SafeTileEnti protected void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { BlockState blockState = te.getBlockState(); - if (te instanceof StandardBogeyTileEntity sbte) { + if (te instanceof AbstractBogeyTileEntity sbte) { float angle = sbte.getVirtualAngle(partialTicks); - if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) - bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbte); + if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) + bogey.render(blockState, bogey.isUpsideDown(blockState), angle, ms, partialTicks, buffer, light, overlay, sbte.getStyle(), sbte.getBogeyData()); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java index 990e876cb..4dda3fb56 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java @@ -265,13 +265,17 @@ public class GlobalRailwayManager { public void clientTick() { if (isTrackGraphDebugActive()) for (TrackGraph trackGraph : trackNetworks.values()) - TrackGraphVisualizer.debugViewGraph(trackGraph); + TrackGraphVisualizer.debugViewGraph(trackGraph, isTrackGraphDebugExtended()); } - + private static boolean isTrackGraphDebugActive() { return KineticDebugger.isF3DebugModeActive() && AllConfigs.CLIENT.showTrackGraphOnF3.get(); } + private static boolean isTrackGraphDebugExtended() { + return AllConfigs.CLIENT.showExtendedTrackGraphOnF3.get(); + } + public GlobalRailwayManager sided(LevelAccessor level) { if (level != null && !level.isClientSide()) return this; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java index ad3f7c99b..f0ef234d9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java @@ -25,6 +25,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; @@ -74,22 +75,42 @@ public interface ITrackBlock { getTrackAxes(world, pos, state).forEach(axis -> { addToListIfConnected(connectedTo, list, (d, b) -> axis.scale(b ? d : -d) .add(center), b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, - axis, null); + axis, null, (b, v) -> getMaterialSimple(world, v)); }); return list; } + public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos) { + return getMaterialSimple(world, pos, TrackMaterial.ANDESITE); + } + + public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos, TrackMaterial defaultMaterial) { + if (defaultMaterial == null) + defaultMaterial = TrackMaterial.ANDESITE; + if (world != null) { + Block block = world.getBlockState(new BlockPos(pos)).getBlock(); + if (block instanceof ITrackBlock track) { + return track.getMaterial(); + } + } + return defaultMaterial; + } + public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection list, BiFunction offsetFactory, Function normalFactory, - Function> dimensionFactory, Vec3 axis, BezierConnection viaTurn) { + Function> dimensionFactory, Vec3 axis, BezierConnection viaTurn, BiFunction materialFactory) { DiscoveredLocation firstLocation = new DiscoveredLocation(dimensionFactory.apply(true), offsetFactory.apply(0.5d, true)).viaTurn(viaTurn) + .materialA(materialFactory.apply(true, offsetFactory.apply(0.0d, true))) + .materialB(materialFactory.apply(true, offsetFactory.apply(1.0d, true))) .withNormal(normalFactory.apply(true)) .withDirection(axis); DiscoveredLocation secondLocation = new DiscoveredLocation(dimensionFactory.apply(false), offsetFactory.apply(0.5d, false)).viaTurn(viaTurn) + .materialA(materialFactory.apply(false, offsetFactory.apply(0.0d, false))) + .materialB(materialFactory.apply(false, offsetFactory.apply(1.0d, false))) .withNormal(normalFactory.apply(false)) .withDirection(axis); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java index c3ece1c78..10d14fdad 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java @@ -31,10 +31,10 @@ public class StandardBogeyRenderer { } @Override - public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { - boolean inContraption = vb == null; + public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; 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) { shafts[i].translate(-.5f, .25f, i * -1) .centre() @@ -60,20 +60,20 @@ public class StandardBogeyRenderer { } @Override - public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { - boolean inContraption = vb == null; - Transform transform = getTransformFromPartial(BOGEY_FRAME, ms, inContraption); + public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; + Transform transform = getTransformFromPartial(BOGEY_FRAME, ms, inInstancedContraption); 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) { - if (!inContraption) + if (!inInstancedContraption) ms.pushPose(); Transform wheel = wheels[(side + 1)/2]; wheel.translate(0, 12 / 16f, side) .rotateX(wheelAngle); finalize(wheel, ms, light, vb); - if (!inContraption) + if (!inInstancedContraption) ms.popPose(); } } @@ -93,11 +93,11 @@ public class StandardBogeyRenderer { } @Override - public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb) { - boolean inContraption = vb == null; + public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; 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) { Transform secondShaft = secondaryShafts[i]; @@ -108,29 +108,29 @@ public class StandardBogeyRenderer { finalize(secondShaft, ms, light, vb); } - Transform bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inContraption); + Transform bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inInstancedContraption); 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))); finalize(bogeyPiston, ms, light, vb); - if (!inContraption) + if (!inInstancedContraption) ms.pushPose(); - Transform bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inContraption) + Transform bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inInstancedContraption) .translate(0, 1, 0) .rotateX(wheelAngle); finalize(bogeyWheels, ms, light, vb); - Transform bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inContraption) + Transform bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inInstancedContraption) .translate(0, 1, 0) .rotateX(wheelAngle) .translate(0, 1 / 4f, 0) .rotateX(-wheelAngle); finalize(bogeyPin, ms, light, vb); - if (!inContraption) + if (!inInstancedContraption) ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java index d5e3affe0..501b437bf 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java @@ -22,13 +22,19 @@ public class TrackEdge { BezierConnection turn; EdgeData edgeData; boolean interDimensional; + TrackMaterial trackMaterial; - public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn) { + public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn, TrackMaterial trackMaterial) { this.interDimensional = !node1.location.dimension.equals(node2.location.dimension); this.edgeData = new EdgeData(this); this.node1 = node1; this.node2 = node2; this.turn = turn; + this.trackMaterial = trackMaterial; + } + + public TrackMaterial getTrackMaterial() { + return trackMaterial; } public boolean isTurn() { @@ -181,13 +187,15 @@ public class TrackEdge { public CompoundTag write(DimensionPalette dimensions) { CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag(); baseCompound.put("Signals", edgeData.write(dimensions)); + baseCompound.putString("Material", getTrackMaterial().id.toString()); return baseCompound; } public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { TrackEdge trackEdge = - new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null); + new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null, + TrackMaterial.deserialize(tag.getString("Material"))); trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions); return trackEdge; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java index 897713e94..8bb92da9f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java @@ -393,14 +393,15 @@ public class TrackGraph { return connectionsFrom.get(nodes.getSecond()); } - public void connectNodes(LevelAccessor reader, TrackNodeLocation location, TrackNodeLocation location2, + public void connectNodes(LevelAccessor reader, DiscoveredLocation location, DiscoveredLocation location2, @Nullable BezierConnection turn) { TrackNode node1 = nodes.get(location); TrackNode node2 = nodes.get(location2); boolean bezier = turn != null; - TrackEdge edge = new TrackEdge(node1, node2, turn); - TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null); + TrackMaterial material = bezier ? turn.getMaterial() : location2.materialA; + TrackEdge edge = new TrackEdge(node1, node2, turn, material); + TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null, material); for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) { for (TrackNode otherNode1 : graph.nodes.values()) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java index dfd5d0e36..36e1fa5f4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java @@ -60,7 +60,7 @@ public class TrackGraphSync { public void edgeAdded(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) { flushGraphPacket(graph); currentGraphSyncPacket.addedEdges - .add(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTurn())); + .add(Pair.of(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTrackMaterial()), edge.getTurn())); currentPayload++; } @@ -82,7 +82,7 @@ public class TrackGraphSync { if (currentGraphSyncPacket.addedNodes.remove(nodeId) == null) currentGraphSyncPacket.removedNodes.add(nodeId); currentGraphSyncPacket.addedEdges.removeIf(pair -> { - Couple ids = pair.getFirst(); + Couple ids = pair.getFirst().getFirst(); return ids.getFirst() .intValue() == nodeId || ids.getSecond() @@ -156,7 +156,7 @@ public class TrackGraphSync { graph.connectionsByNode.get(node) .forEach((node2, edge) -> { Couple key = Couple.create(node.getNetId(), node2.getNetId()); - currentPacket.addedEdges.add(Pair.of(key, edge.getTurn())); + currentPacket.addedEdges.add(Pair.of(Pair.of(key, edge.getTrackMaterial()), edge.getTurn())); currentPacket.syncEdgeData(node, node2, edge); }); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java index 33e5e0790..7707db41b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java @@ -22,7 +22,7 @@ import net.minecraft.world.phys.Vec3; public class TrackGraphSyncPacket extends TrackGraphPacket { Map> addedNodes; - List, BezierConnection>> addedEdges; + List, TrackMaterial>, BezierConnection>> addedEdges; List removedNodes; List addedEdgePoints; List removedEdgePoints; @@ -79,7 +79,7 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { size = buffer.readVarInt(); for (int i = 0; i < size; i++) addedEdges.add( - Pair.of(Couple.create(buffer::readVarInt), buffer.readBoolean() ? new BezierConnection(buffer) : null)); + Pair.of(Pair.of(Couple.create(buffer::readVarInt), TrackMaterial.deserialize(buffer.readUtf())), buffer.readBoolean() ? new BezierConnection(buffer) : null)); size = buffer.readVarInt(); for (int i = 0; i < size; i++) @@ -134,8 +134,9 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { buffer.writeVarInt(addedEdges.size()); addedEdges.forEach(pair -> { - pair.getFirst() + pair.getFirst().getFirst() .forEach(buffer::writeVarInt); + buffer.writeUtf(pair.getFirst().getSecond().id.toString()); BezierConnection turn = pair.getSecond(); buffer.writeBoolean(turn != null); if (turn != null) @@ -192,13 +193,13 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { graph.loadNode(nodeLocation.getFirst(), nodeId, nodeLocation.getSecond()); } - for (Pair, BezierConnection> pair : addedEdges) { - Couple nodes = pair.getFirst() + for (Pair, TrackMaterial>, BezierConnection> pair : addedEdges) { + Couple nodes = pair.getFirst().getFirst() .map(graph::getNode); TrackNode node1 = nodes.getFirst(); TrackNode node2 = nodes.getSecond(); if (node1 != null && node2 != null) - graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond())); + graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond(), pair.getFirst().getSecond())); } for (TrackEdgePoint edgePoint : addedEdgePoints) @@ -268,4 +269,4 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { updatedEdgeData.put(key, Pair.of(groupType, list)); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java index 66988f041..bc2c24241 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java @@ -5,6 +5,15 @@ import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.world.item.ItemStack; + +import net.minecraft.world.item.Items; + +import net.minecraft.world.level.block.Blocks; + import org.lwjgl.glfw.GLFW; import com.simibubi.create.AllKeys; @@ -209,7 +218,7 @@ public class TrackGraphVisualizer { } } - public static void debugViewGraph(TrackGraph graph) { + public static void debugViewGraph(TrackGraph graph, boolean extended) { Minecraft mc = Minecraft.getInstance(); Entity cameraEntity = mc.cameraEntity; if (cameraEntity == null) @@ -262,6 +271,13 @@ public class TrackGraphVisualizer { yOffset = new Vec3(0, (other.hashCode() > hashCode ? 6 : 4) / 16f, 0); if (!edge.isTurn()) { + if (extended) { + Vec3 materialPos = edge.getPosition(0.5).add(0, 1, 0); + CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, + new ItemStack(edge.getTrackMaterial().trackBlock.get().get())); + CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, 1, 1, 1)) + .colored(graph.color); + } CreateClient.OUTLINER.showLine(edge, edge.getPosition(0) .add(yOffset), edge.getPosition(1) @@ -273,6 +289,13 @@ public class TrackGraphVisualizer { Vec3 previous = null; BezierConnection turn = edge.getTurn(); + if (extended) { + Vec3 materialPos = edge.getPosition(0.5).add(0, 1, 0); + CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, + new ItemStack(edge.getTrackMaterial().trackBlock.get().get())); + CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, 1, 1, 1)) + .colored(graph.color); + } for (int i = 0; i <= turn.getSegmentCount(); i++) { Vec3 current = edge.getPosition(i * 1f / turn.getSegmentCount()); if (previous != null) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java index 509eedd23..ad8c0e009 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java @@ -24,8 +24,8 @@ public class TrackNodeLocation extends Vec3i { this(vec.x, vec.y, vec.z); } - public TrackNodeLocation(double p_121865_, double p_121866_, double p_121867_) { - super(Math.round(p_121865_ * 2), Math.floor(p_121866_ * 2), Math.round(p_121867_ * 2)); + public TrackNodeLocation(double x, double y, double z) { + super(Math.round(x * 2), Math.floor(y * 2), Math.round(z * 2)); } public TrackNodeLocation in(Level level) { @@ -116,9 +116,11 @@ public class TrackNodeLocation extends Vec3i { boolean forceNode = false; Vec3 direction; Vec3 normal; + TrackMaterial materialA; + TrackMaterial materialB; - public DiscoveredLocation(Level level, double p_121865_, double p_121866_, double p_121867_) { - super(p_121865_, p_121866_, p_121867_); + public DiscoveredLocation(Level level, double x, double y, double z) { + super(x, y, z); in(level); } @@ -131,6 +133,22 @@ public class TrackNodeLocation extends Vec3i { this(level.dimension(), vec); } + public DiscoveredLocation materialA(TrackMaterial material) { + this.materialA = material; + return this; + } + + public DiscoveredLocation materialB(TrackMaterial material) { + this.materialB = material; + return this; + } + + public DiscoveredLocation materials(TrackMaterial materialA, TrackMaterial materialB) { + this.materialA = materialA; + this.materialB = materialB; + return this; + } + public DiscoveredLocation viaTurn(BezierConnection turn) { this.turn = turn; if (turn != null) @@ -165,6 +183,10 @@ public class TrackNodeLocation extends Vec3i { return forceNode; } + public boolean differentMaterials() { + return materialA != materialB; + } + public boolean notInLineWith(Vec3 direction) { return this.direction != null && Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java index 611787364..c755b4613 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java @@ -234,10 +234,12 @@ public class TrackPropagator { return true; if (location.shouldForceNode()) return true; + if (location.differentMaterials()) + return true; if (next.stream() .anyMatch(DiscoveredLocation::shouldForceNode)) return true; - + Vec3 direction = location.direction; if (direction != null && next.stream() .anyMatch(dl -> dl.notInLineWith(direction))) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BackupBogeyRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BackupBogeyRenderer.java index 41dc32e8b..45efd8cc9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BackupBogeyRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BackupBogeyRenderer.java @@ -11,7 +11,7 @@ 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) { + public void render(boolean upsideDown, CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java index a9b0ff8af..9e66664ce 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java @@ -46,8 +46,8 @@ public final class BogeyInstance { } commonRenderer.ifPresent(bogeyRenderer -> - bogeyRenderer.render(bogey.bogeyData, wheelAngle, ms)); - renderer.render(bogey.bogeyData, wheelAngle, ms); + bogeyRenderer.render(bogey.isUpsideDown(), bogey.bogeyData, wheelAngle, ms)); + renderer.render(bogey.isUpsideDown(), bogey.bogeyData, wheelAngle, ms); } public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java index 6d3bdbb12..c5667cd0d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.logistics.trains.entity; import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllBogeyStyles; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.logistics.trains.BogeyRenderer; @@ -28,6 +29,7 @@ public class BogeyStyle { private final Optional> commonRendererFactory; public final ResourceLocation name; + public final ResourceLocation cycleGroup; private final Optional commonRenderer; private final Map sizes; public final Component displayName; @@ -36,9 +38,10 @@ public class BogeyStyle { public final ParticleOptions smokeParticle; public final CompoundTag defaultData; - public BogeyStyle(ResourceLocation name, Component displayName, ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle, - CompoundTag defaultData, Map sizes, Optional> commonRenderer) { + public BogeyStyle(ResourceLocation name, ResourceLocation cycleGroup, Component displayName, ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle, + CompoundTag defaultData, Map sizes, Optional commonRenderer) { this.name = name; + this.cycleGroup = cycleGroup; this.displayName = displayName; this.soundType = soundType; this.contactParticle = contactParticle; @@ -51,6 +54,9 @@ public class BogeyStyle { this.commonRenderer = commonRenderer.map(Supplier::get); } + public Map getCycleGroup() { + return AllBogeyStyles.getCycleGroup(cycleGroup); + } public Block getNextBlock(BogeySizes.BogeySize currentSize) { return Stream.iterate(currentSize.increment(), BogeySizes.BogeySize::increment) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java index 12d25eea7..ec7e9f1d7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java @@ -85,6 +85,11 @@ public class Carriage { bogey2.carriage = this; } + public boolean isOnIncompatibleTrack() { + return leadingBogey().type.isOnIncompatibleTrack(this, true) + || trailingBogey().type.isOnIncompatibleTrack(this, false); + } + public void setTrain(Train train) { this.train = train; } @@ -306,6 +311,9 @@ public class Carriage { double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing(); double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing(); + boolean leadingUpsideDown = leadingBogey.isUpsideDown(); + boolean trailingUpsideDown = trailingBogey.isUpsideDown(); + for (boolean leading : Iterate.trueAndFalse) { TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint(); TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint(); @@ -321,24 +329,31 @@ public class Carriage { dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2); + leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown); + + boolean backAnchorFlip = trailingBogey.isUpsideDown() ^ leadingBogey.isUpsideDown(); if (isOnTwoBogeys()) { dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2)); - dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition() + leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown)); + dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition(backAnchorFlip) : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2)); + leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown)); } else { if (dimension.equals(otherDimension)) { dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition); } else { dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition() - : pivoted(dce, dimension, point, leadingWheelSpacing)); + : pivoted(dce, dimension, point, leadingWheelSpacing, + leadingUpsideDown, trailingUpsideDown)); dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition() - : pivoted(dce, dimension, point, leadingWheelSpacing)); + : pivoted(dce, dimension, point, leadingWheelSpacing, + leadingUpsideDown, trailingUpsideDown)); } } @@ -356,15 +371,16 @@ public class Carriage { } private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey dimension, TravellingPoint start, - double offset) { + double offset, boolean leadingUpsideDown, boolean trailingUpsideDown) { if (train.graph == null) return dce.pivot == null ? null : dce.pivot.getLocation(); TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint()); if (pivot == null) return null; - Vec3 startVec = start.getPosition(); + boolean flipped = start != getLeadingPoint() && (leadingUpsideDown != trailingUpsideDown); + Vec3 startVec = start.getPosition(flipped); Vec3 portalVec = pivot.getLocation() - .add(0, 1, 0); + .add(0, leadingUpsideDown ? -1.0 : 1.0, 0); return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java index 3ac7d3a43..0d0b224cb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java @@ -8,7 +8,7 @@ import com.simibubi.create.Create; import com.simibubi.create.content.logistics.trains.DimensionPalette; import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock; 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.Couple; 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.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 { @@ -37,7 +37,8 @@ public class CarriageBogey { public CompoundTag bogeyData; - AbstractBogeyBlock type; + AbstractBogeyBlock type; + boolean upsideDown; Couple points; LerpedFloat wheelAngle; @@ -48,11 +49,14 @@ public class CarriageBogey { 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()) bogeyData = this.createBogeyData(); // Prevent Crash When Updating this.bogeyData = bogeyData; - this.type = type; + this.upsideDown = type.canBeUpsideDown() && upsideDown; + point.upsideDown = this.upsideDown; + point2.upsideDown = this.upsideDown; points = Couple.create(point, point2); wheelAngle = LerpedFloat.angular(); yaw = LerpedFloat.angular(); @@ -109,11 +113,15 @@ public class CarriageBogey { } public TravellingPoint leading() { - return points.getFirst(); + TravellingPoint point = points.getFirst(); + point.upsideDown = isUpsideDown(); + return point; } public TravellingPoint trailing() { - return points.getSecond(); + TravellingPoint point = points.getSecond(); + point.upsideDown = isUpsideDown(); + return point; } public double getStress() { @@ -127,18 +135,25 @@ public class CarriageBogey { @Nullable public Vec3 getAnchorPosition() { + return getAnchorPosition(false); + } + + @Nullable + public Vec3 getAnchorPosition(boolean flipUpsideDown) { if (leading().edge == null) return null; return points.getFirst() - .getPosition() - .add(points.getSecond() - .getPosition()) - .scale(.5); + .getPosition(flipUpsideDown) + .add(points.getSecond() + .getPosition(flipUpsideDown)) + .scale(.5); } public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing, float partialTicks, boolean leading) { - Vec3 thisOffset = type.getConnectorAnchorOffset(); + boolean selfUpsideDown = isUpsideDown(); + boolean leadingUpsideDown = carriage.leadingBogey().isUpsideDown(); + Vec3 thisOffset = type.getConnectorAnchorOffset(selfUpsideDown); thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1); thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X); @@ -150,6 +165,8 @@ public class CarriageBogey { thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y); thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X); thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y); + if (selfUpsideDown != leadingUpsideDown) + thisOffset = thisOffset.add(0, selfUpsideDown ? -2 : 2, 0); couplingAnchors.set(leading, entityPos.add(thisOffset)); } @@ -159,6 +176,7 @@ public class CarriageBogey { tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type) .toString()); tag.put("Points", points.serializeEach(tp -> tp.write(dimensions))); + tag.putBoolean("UpsideDown", upsideDown); tag.put(BOGEY_STYLE_KEY, bogeyData); return tag; } @@ -166,10 +184,11 @@ public class CarriageBogey { public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { ResourceLocation location = new ResourceLocation(tag.getString("Type")); AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(location); + boolean upsideDown = tag.getBoolean("UpsideDown"); Couple points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND), c -> TravellingPoint.read(c, graph, dimensions)); - CompoundTag data = tag.getCompound(StandardBogeyTileEntity.BOGEY_DATA_KEY); - return new CarriageBogey(type, data, points.getFirst(), points.getSecond()); + CompoundTag data = tag.getCompound(AbstractBogeyTileEntity.BOGEY_DATA_KEY); + return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond()); } public BogeyInstance createInstance(MaterialManager materialManager) { @@ -183,11 +202,15 @@ public class CarriageBogey { private CompoundTag createBogeyData() { 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; } void setLeading() { isLeading = true; } + + public boolean isUpsideDown() { + return type.canBeUpsideDown() && upsideDown; + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java index 3d06b191b..f7a2be376 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java @@ -162,11 +162,12 @@ public class CarriageContraption extends Contraption { .getStep(), toLocalPos(pos)); } - if (blockState.getBlock() instanceof AbstractBogeyBlock) { + if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) { + boolean captureTE = bogey.captureTileEntityForTrain(); bogeys++; if (bogeys == 2) 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) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java index 06a9ce394..53469f4fb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java @@ -7,8 +7,6 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer; -import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; - import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.culling.Frustum; @@ -68,10 +66,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTicks); int light = getBogeyLightCoords(entity, bogey, partialTicks); - BlockEntity be = entity.getContraption().presentTileEntities.get(bogeyPos); - bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light, - overlay, (StandardBogeyTileEntity) be); + bogey.type.render(null, bogey.isUpsideDown(), bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light, + overlay, bogey.getStyle(), bogey.bogeyData); ms.popPose(); } @@ -85,6 +82,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot, float viewXRot, float partialTicks) { + boolean selfUpsideDown = bogey.isUpsideDown(); + boolean leadingUpsideDown = bogey.carriage.leadingBogey().isUpsideDown(); TransformStack.cast(ms) .rotateY(viewYRot + 90) .rotateX(-viewXRot) @@ -95,7 +94,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer .rotateY(-viewYRot - 90) .rotateY(bogey.yaw.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) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java index f67a86798..7f8f46f82 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java @@ -82,7 +82,7 @@ public class CarriageCouplingRenderer { float margin = 3 / 16f; 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(bogey2.isUpsideDown()).z; int couplingSegments = (int) Math.round(couplingDistance * 4); double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments; for (int j = 0; j < couplingSegments; j++) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java index 454cc406c..b9a59d58d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java @@ -88,7 +88,13 @@ public class CarriageSounds { double distance2 = toBogey2.length(); Couple 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; double distance = Math.min(distance1, distance2); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java index 258bc4da1..ba05808b6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java @@ -14,6 +14,9 @@ import java.util.UUID; import javax.annotation.Nullable; +import com.railwayteam.railways.Railways; +import com.simibubi.create.content.logistics.trains.TrackMaterial; + import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableObject; @@ -251,7 +254,7 @@ public class Navigation { return; } } - + topSpeed *= train.throttle; double turnTopSpeed = Math.min(topSpeed, train.maxTurnSpeed()); @@ -540,6 +543,23 @@ public class Navigation { if (graph == null) return; + // Cache the list of track types that the train can travel on + Set validTypes = new HashSet<>(); + for (int i = 0; i < train.carriages.size(); i++) { + Carriage carriage = train.carriages.get(i); + if (i == 0) { + validTypes.addAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle())); + } else { + validTypes.retainAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle())); + } + if (carriage.isOnTwoBogeys()) + validTypes.retainAll(carriage.trailingBogey().type.getValidPathfindingTypes(carriage.trailingBogey().getStyle())); + } + if (validTypes.isEmpty()) // if there are no valid track types, a route can't be found + return; + + Create.LOGGER.info("Valid types: "+validTypes); + Map penalties = new IdentityHashMap<>(); boolean costRelevant = maxCost >= 0; if (costRelevant) { @@ -579,7 +599,7 @@ public class Navigation { .get(initialNode2); if (initialEdge == null) return; - + double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position; frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge)); @@ -659,6 +679,8 @@ public class Navigation { continue; for (Entry target : validTargets) { + if (!validTypes.contains(target.getValue().getTrackMaterial().trackType)) + continue; TrackNode newNode = target.getKey(); TrackEdge newEdge = target.getValue(); double newDistance = newEdge.getLength() + distance; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java index c56137ff8..dea3d9782 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java @@ -17,7 +17,7 @@ import java.util.function.Consumer; 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; @@ -317,7 +317,13 @@ public class Train { if (leadingAnchor == null || trailingAnchor == null) 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++; } } @@ -379,7 +385,7 @@ public class Train { int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE; double actualDistance = carriage.travel(level, graph, distance + totalStress, toFollowForward, toFollowBackward, carriageType); - blocked |= carriage.blocked; + blocked |= carriage.blocked || carriage.isOnIncompatibleTrack(); boolean onTwoBogeys = carriage.isOnTwoBogeys(); maxStress = Math.max(maxStress, onTwoBogeys ? carriage.bogeySpacing - carriage.getAnchorDiff() : 0); @@ -726,14 +732,16 @@ public class Train { if (entity.getContraption()instanceof CarriageContraption cc) cc.returnStorageForDisassembly(carriage.storage); 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(); for (CarriageBogey bogey : carriage.bogeys) { + if (bogey == null) + continue; Vec3 bogeyPosition = bogey.getAnchorPosition(); if (bogeyPosition == null) continue; BlockEntity be = level.getBlockEntity(new BlockPos(bogeyPosition)); - if (!(be instanceof StandardBogeyTileEntity sbte)) + if (!(be instanceof AbstractBogeyTileEntity sbte)) continue; sbte.setBogeyData(bogey.bogeyData); } @@ -957,7 +965,7 @@ public class Train { occupiedObservers.clear(); cachedObserverFiltering.clear(); - TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position); + TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position, false); Map allGroups = Create.RAILWAYS.signalEdgeGroups; MutableObject prevGroup = new MutableObject<>(null); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java index 3d27c86cd..54bb6c107 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java @@ -49,8 +49,9 @@ public class TrainPacket extends SimplePacketBase { if (!isFirst && !buffer.readBoolean()) continue; AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation()); + boolean upsideDown = buffer.readBoolean(); 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(); carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing)); @@ -88,6 +89,7 @@ public class TrainPacket extends SimplePacketBase { } CarriageBogey bogey = carriage.bogeys.get(first); buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type)); + buffer.writeBoolean(bogey.upsideDown); buffer.writeNbt(bogey.bogeyData); } buffer.writeVarInt(carriage.bogeySpacing); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java index 149120c53..38ea9c94b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java @@ -115,13 +115,16 @@ public class TrainRelocator { BlockPos blockPos = blockhit.getBlockPos(); 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) { for (int i = 0; i < toVisualise.size() - 1; i++) { - Vec3 vec1 = toVisualise.get(i); - Vec3 vec2 = toVisualise.get(i + 1); + Vec3 vec1 = toVisualise.get(i).add(offset); + 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)) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B) - .disableLineNormals() + .disableNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } } @@ -150,7 +153,7 @@ public class TrainRelocator { boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0; boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true); 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, direction, lookAngle, relocatingEntityId)); } @@ -182,7 +185,7 @@ public class TrainRelocator { if (edge == null) 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(); ITurnListener ignoreTurns = probe.ignoreTurns(); List, Double>> recordedLocations = new ArrayList<>(); @@ -269,7 +272,7 @@ public class TrainRelocator { public static void visualise(Train train, int i, Vec3 v1, Vec3 v2, boolean valid) { CreateClient.OUTLINER.showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0)) .colored(valid ? 0x95CD41 : 0xEA5C2B) - .disableLineNormals() + .disableNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java index 194d926a6..827380139 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java @@ -38,6 +38,7 @@ public class TravellingPoint { public TrackEdge edge; public double position; public boolean blocked; + public boolean upsideDown; public static enum SteerDirection { NONE(0), LEFT(-1), RIGHT(1); @@ -64,11 +65,12 @@ public class 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.node2 = node2; this.edge = edge; this.position = position; + this.upsideDown = upsideDown; } public IEdgePointListener ignoreEdgePoints() { @@ -395,14 +397,22 @@ public class TravellingPoint { } public Vec3 getPosition() { - return getPositionWithOffset(0); + return getPosition(false); + } + + public Vec3 getPosition(boolean flipped) { + return getPositionWithOffset(0, flipped); } public Vec3 getPositionWithOffset(double offset) { + return getPositionWithOffset(offset, false); + } + + public Vec3 getPositionWithOffset(double offset, boolean flipUpsideDown) { double t = (position + offset) / edge.getLength(); return edge.getPosition(t) - .add(edge.getNormal(node1, node2, t) - .scale(1)); + .add(edge.getNormal(node1, node2, t) + .scale(upsideDown^flipUpsideDown ? -1 : 1)); } public void migrateTo(List locations) { @@ -423,12 +433,13 @@ public class TravellingPoint { tag.put("Nodes", nodes.map(TrackNode::getLocation) .serializeEach(loc -> loc.write(dimensions))); tag.putDouble("Position", position); + tag.putBoolean("UpsideDown", upsideDown); return tag; } public static TravellingPoint read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { if (graph == null) - return new TravellingPoint(null, null, null, 0); + return new TravellingPoint(null, null, null, 0, false); Couple locs = tag.contains("Nodes") ? Couple.deserializeEach(tag.getList("Nodes", Tag.TAG_COMPOUND), c -> TrackNodeLocation.read(c, dimensions)) @@ -436,11 +447,11 @@ public class TravellingPoint { : Couple.create(null, null); 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"); return new TravellingPoint(locs.getFirst(), locs.getSecond(), graph.getConnectionsFrom(locs.getFirst()) - .get(locs.getSecond()), position); + .get(locs.getSecond()), position, tag.getBoolean("UpsideDown")); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java index a045a4216..0bb323292 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java @@ -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.schedule.Schedule; 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.block.ProperWaterloggedBlock; 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.entity.player.Player; 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.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -193,7 +192,8 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable Direction assemblyDirection; int assemblyLength; int[] bogeyLocations; - AbstractBogeyBlock[] bogeyTypes; + AbstractBogeyBlock[] bogeyTypes; + boolean[] upsideDownBogeys; int bogeyCount; @Override @@ -270,28 +270,31 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable return false; 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; if (!isValidBogeyOffset(bogeyOffset)) { - for (int i = -1; i <= 1; i++) { - BlockPos bogeyPos = pos.relative(assemblyDirection, i) - .offset(up); - BlockState blockState = level.getBlockState(bogeyPos); - if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) { - BlockEntity be = level.getBlockEntity(bogeyPos); - if (!(be instanceof StandardBogeyTileEntity oldTE)) - continue; - CompoundTag oldData = oldTE.getBogeyData(); - BlockState newBlock = bogey.getNextSize(oldTE); - if (newBlock.getBlock() == bogey) - player.displayClientMessage(Lang.translateDirect("create.bogey.style.no_other_sizes") - .withStyle(ChatFormatting.RED), true); - level.setBlock(bogeyPos, newBlock, 3); - BlockEntity newEntity = level.getBlockEntity(bogeyPos); - if (!(newEntity instanceof StandardBogeyTileEntity newTE)) - continue; - newTE.setBogeyData(oldData); - bogey.playRotateSound(level, bogeyPos); - return true; + for (boolean upsideDown : Iterate.falseAndTrue) { + for (int i = -1; i <= 1; i++) { + BlockPos bogeyPos = pos.relative(assemblyDirection, i) + .offset(upsideDown ? down : up); + BlockState blockState = level.getBlockState(bogeyPos); + if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) { + BlockEntity be = level.getBlockEntity(bogeyPos); + if (!(be instanceof AbstractBogeyTileEntity oldTE)) + continue; + CompoundTag oldData = oldTE.getBogeyData(); + BlockState newBlock = bogey.getNextSize(oldTE); + if (newBlock.getBlock() == bogey) + player.displayClientMessage(Lang.translateDirect("bogey.style.no_other_sizes") + .withStyle(ChatFormatting.RED), true); + level.setBlock(bogeyPos, newBlock, 3); + BlockEntity newEntity = level.getBlockEntity(bogeyPos); + if (!(newEntity instanceof AbstractBogeyTileEntity newTE)) + continue; + newTE.setBogeyData(oldData); + bogey.playRotateSound(level, bogeyPos); + return true; + } } } @@ -304,7 +307,9 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable 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) .getDestroySpeed(level, targetPos) == -1) { return false; @@ -312,7 +317,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable 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); player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true); SoundType soundtype = bogeyAnchor.getBlock() @@ -387,8 +396,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable bogeyLocations = new int[maxBogeyCount]; if (bogeyTypes == null) bogeyTypes = new AbstractBogeyBlock[maxBogeyCount]; + if (upsideDownBogeys == null) + upsideDownBogeys = new boolean[maxBogeyCount]; Arrays.fill(bogeyLocations, -1); Arrays.fill(bogeyTypes, null); + Arrays.fill(upsideDownBogeys, false); for (int i = 0; i < MAX_LENGTH; i++) { if (i == MAX_LENGTH - 1) { @@ -401,10 +413,19 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable } BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos)); - if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && bogeyIndex < bogeyLocations.length) { - bogeyTypes[bogeyIndex] = bogey; - bogeyLocations[bogeyIndex] = i; - bogeyIndex++; + BlockPos upsideDownBogeyOffset = new BlockPos(bogeyOffset.getX(), bogeyOffset.getY()*-1, bogeyOffset.getZ()); + if (bogeyIndex < bogeyLocations.length) { + if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && !bogey.isUpsideDown(potentialBogeyState)) { + 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); @@ -564,7 +585,7 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable return; } - points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge)); + points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge, false)); } secondNode = node; @@ -591,10 +612,11 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]); CarriageContraption contraption = new CarriageContraption(assemblyDirection); BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset); + BlockPos upsideDownBogeyPosOffset = trackPosition.offset(new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ())); try { 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(); contraption.setSoundQueueOffset(offset); if (!success) { @@ -607,26 +629,27 @@ public class StationTileEntity extends SmartTileEntity implements ITransformable return; } - AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; + AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; + boolean firstBogeyIsUpsideDown = upsideDownBogeys[bogeyIndex]; BlockPos firstBogeyPos = contraption.anchor; - StandardBogeyTileEntity firstBogeyTileEntity = (StandardBogeyTileEntity) level.getBlockEntity(firstBogeyPos); + AbstractBogeyTileEntity firstBogeyTileEntity = (AbstractBogeyTileEntity) level.getBlockEntity(firstBogeyPos); 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; BlockPos secondBogeyPos = contraption.getSecondBogeyPos(); int bogeySpacing = 0; if (secondBogeyPos != null) { 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")), contraptions.size() + 1); return; } - StandardBogeyTileEntity secondBogeyTileEntity = - (StandardBogeyTileEntity) level.getBlockEntity(secondBogeyPos); + AbstractBogeyTileEntity secondBogeyTileEntity = + (AbstractBogeyTileEntity) level.getBlockEntity(secondBogeyPos); 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)); bogeyIndex++; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/AbstractBogeyTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/AbstractBogeyTileEntity.java new file mode 100644 index 000000000..f3b752b52 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/AbstractBogeyTileEntity.java @@ -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); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java index f569f093d..4e12babab 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java @@ -1,10 +1,12 @@ package com.simibubi.create.content.logistics.trains.track; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllBogeyStyles; 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.BogeySizes; +import com.simibubi.create.content.logistics.trains.TrackMaterial; +import com.simibubi.create.content.logistics.trains.entity.BogeyStyle; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; @@ -18,13 +20,18 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -public class StandardBogeyBlock extends AbstractBogeyBlock implements ITE, ProperWaterloggedBlock, ISpecialBlockItemRequirement { +public class StandardBogeyBlock extends AbstractBogeyBlock implements ITE, ProperWaterloggedBlock, ISpecialBlockItemRequirement { public StandardBogeyBlock(Properties props, BogeySizes.BogeySize size) { super(props, size); registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); } + @Override + public TrackMaterial.TrackType getTrackType(BogeyStyle style) { + return TrackMaterial.TrackType.STANDARD; + } + @Override public double getWheelPointSpacing() { return 2; @@ -40,6 +47,11 @@ public class StandardBogeyBlock extends AbstractBogeyBlock implements ITE type, BlockPos pos, BlockState 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 - 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, 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); + public BogeyStyle getDefaultStyle() { + return AllBogeyStyles.STANDARD; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java index c764f143f..78cc17b3b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java @@ -391,7 +391,7 @@ public class TrackBlock extends Block (d, b) -> axis.scale(b ? 0 : fromCenter ? -d : d) .add(center), b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, axis, - null); + null, (b, v) -> ITrackBlock.getMaterialSimple(world, v)); } else list = ITrackBlock.super.getConnected(world, pos, state, linear, connectedTo); @@ -407,7 +407,7 @@ public class TrackBlock extends Block Map connections = trackTE.getConnections(); connections.forEach((connectedPos, bc) -> ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get, - b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, null, bc)); + b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, null, bc, (b, v) -> ITrackBlock.getMaterialSimple(world, v, bc.getMaterial()))); if (trackTE.boundLocation == null || !(world instanceof ServerLevel level)) return list; @@ -433,7 +433,7 @@ public class TrackBlock extends Block getTrackAxes(world, pos, state).forEach(axis -> { ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> (b ? axis : boundAxis).scale(d) .add(b ? center : boundCenter), b -> (b ? shape : boundShape).getNormal(), - b -> b ? level.dimension() : otherLevel.dimension(), axis, null); + b -> b ? level.dimension() : otherLevel.dimension(), axis, null, (b, v) -> ITrackBlock.getMaterialSimple(b ? level : otherLevel, v)); }); return list; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java index adf3e9707..6ac278f3b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java @@ -748,13 +748,13 @@ public class TrackPlacement { .showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1), VecHelper.lerp(s, middle1, rail1)) .colored(railcolor) - .disableLineNormals() + .disableNormals() .lineWidth(lw); CreateClient.OUTLINER .showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2), VecHelper.lerp(s, middle2, rail2)) .colored(railcolor) - .disableLineNormals() + .disableNormals() .lineWidth(lw); } @@ -775,7 +775,7 @@ public class TrackPlacement { int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue()); CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) .lineWidth(1 / 8f) - .disableLineNormals() + .disableNormals() .colored(color); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java index fa653d28c..10ceb1547 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java @@ -72,7 +72,7 @@ public class FlipTool extends PlacementToolBase { AllSpecialTextures tex = AllSpecialTextures.CHECKERED; outline.getParams() .lineWidth(1 / 16f) - .disableLineNormals() + .disableNormals() .colored(0xdddddd) .withFaceTextures(tex, tex); outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java index 21dcda4ad..55b3e3dcc 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java @@ -32,7 +32,7 @@ public class RotateTool extends PlacementToolBase { line.getParams() .disableCull() - .disableLineNormals() + .disableNormals() .colored(0xdddddd) .lineWidth(1 / 16f); line.set(start, end) diff --git a/src/main/java/com/simibubi/create/foundation/command/AllCommands.java b/src/main/java/com/simibubi/create/foundation/command/AllCommands.java index 8664b0a5e..676a47d1f 100644 --- a/src/main/java/com/simibubi/create/foundation/command/AllCommands.java +++ b/src/main/java/com/simibubi/create/foundation/command/AllCommands.java @@ -60,6 +60,7 @@ public class AllCommands { .then(CameraDistanceCommand.register()) .then(CameraAngleCommand.register()) .then(FlySpeedCommand.register()) + //.then(DebugValueCommand.register()) //.then(KillTPSCommand.register()) .build(); diff --git a/src/main/java/com/simibubi/create/foundation/command/DebugValueCommand.java b/src/main/java/com/simibubi/create/foundation/command/DebugValueCommand.java new file mode 100644 index 000000000..5272bdc59 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/command/DebugValueCommand.java @@ -0,0 +1,41 @@ +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 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; + })); + + } +} diff --git a/src/main/java/com/simibubi/create/foundation/config/CClient.java b/src/main/java/com/simibubi/create/foundation/config/CClient.java index 4fffd25fe..449c10a3f 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CClient.java +++ b/src/main/java/com/simibubi/create/foundation/config/CClient.java @@ -77,6 +77,7 @@ public class CClient extends ConfigBase { public final ConfigGroup trains = group(1, "trains", Comments.trains); public final ConfigFloat mountedZoomMultiplier = f(3, 0, "mountedZoomMultiplier", Comments.mountedZoomMultiplier); public final ConfigBool showTrackGraphOnF3 = b(false, "showTrackGraphOnF3", Comments.showTrackGraphOnF3); + public final ConfigBool showExtendedTrackGraphOnF3 = b(false, "showExtendedTrackGraphOnF3", Comments.showExtendedTrackGraphOnF3); @Override public String getName() { @@ -147,6 +148,7 @@ public class CClient extends ConfigBase { static String trains = "Railway related settings"; static String mountedZoomMultiplier = "How far away the Camera should zoom when seated on a train"; static String showTrackGraphOnF3 = "Display nodes and edges of a Railway Network while f3 debug mode is active"; + static String showExtendedTrackGraphOnF3 = "Additionally display materials of a Rail Network while f3 debug mode is active"; } } diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index 5d8f5e49b..c9971fb76 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -80,6 +80,7 @@ public class BuilderTransformers { .build(); } + @SuppressWarnings("deprecation") public static NonNullUnaryOperator> bogey() { return b -> b.initialProperties(SharedProperties::softMetal) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -88,7 +89,7 @@ public class BuilderTransformers { .blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models() .getExistingFile(p.modLoc("block/track/bogey/top")))) .loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get())) - .onRegister(block -> AbstractBogeyBlock.register(RegisteredObjects.getKeyOrThrow(block))); + .onRegister(block -> AbstractBogeyBlock.registerStandardBogey(RegisteredObjects.getKeyOrThrow(block))); } public static NonNullUnaryOperator> trapdoor(boolean orientable) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java index 0c6321006..a4bfb3537 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java @@ -398,7 +398,7 @@ public class WorldSectionElement extends AnimatedSceneElement { aabbOutline.getParams() .lineWidth(1 / 64f) .colored(0xefefef) - .disableLineNormals(); + .disableNormals(); aabbOutline.render(ms, (SuperRenderTypeBuffer) buffer, pt); ms.popPose(); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instruction/AnimateTileEntityInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instruction/AnimateTileEntityInstruction.java index cd65b8a36..b11242d80 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instruction/AnimateTileEntityInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instruction/AnimateTileEntityInstruction.java @@ -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.structureMovement.bearing.IBearingTileEntity; 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.PonderWorld; @@ -34,7 +34,7 @@ public class AnimateTileEntityInstruction extends TickingInstruction { public static AnimateTileEntityInstruction bogey(BlockPos location, float totalDelta, int ticks) { float movedPerTick = 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)), (w) -> 0f); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java index 9f5b064ce..75d6367d2 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java @@ -87,6 +87,9 @@ public class ValueBox extends ChasingAABBOutline { ms.translate(pos.getX(), pos.getY(), pos.getZ()); if (hasTransform) transform.transform(blockState, ms); + transformNormals = ms.last() + .normal() + .copy(); params.colored(isPassive ? passiveColor : highlightColor); super.render(ms, buffer, pt); diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java index 81b34939e..12af40349 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java @@ -1,18 +1,15 @@ package com.simibubi.create.foundation.utility.outliner; -import java.util.Optional; - import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; -import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -20,212 +17,85 @@ public class AABBOutline extends Outline { protected AABB bb; - protected final Vector3f minPosTemp1 = new Vector3f(); - protected final Vector3f maxPosTemp1 = new Vector3f(); - - protected final Vector4f colorTemp1 = new Vector4f(); - protected final Vector3f pos0Temp = new Vector3f(); - protected final Vector3f pos1Temp = new Vector3f(); - protected final Vector3f pos2Temp = new Vector3f(); - protected final Vector3f pos3Temp = new Vector3f(); - protected final Vector3f normalTemp = new Vector3f(); - protected final Vector3f originTemp = new Vector3f(); - public AABBOutline(AABB bb) { - setBounds(bb); + this.setBounds(bb); } - public AABB getBounds() { - return bb; + @Override + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { + renderBB(ms, buffer, bb); + } + + public void renderBB(PoseStack ms, SuperRenderTypeBuffer buffer, AABB bb) { + Vec3 projectedView = Minecraft.getInstance().gameRenderer.getMainCamera() + .getPosition(); + boolean noCull = bb.contains(projectedView); + bb = bb.inflate(noCull ? -1 / 128d : 1 / 128d); + noCull |= params.disableCull; + + Vec3 xyz = new Vec3(bb.minX, bb.minY, bb.minZ); + Vec3 Xyz = new Vec3(bb.maxX, bb.minY, bb.minZ); + Vec3 xYz = new Vec3(bb.minX, bb.maxY, bb.minZ); + Vec3 XYz = new Vec3(bb.maxX, bb.maxY, bb.minZ); + Vec3 xyZ = new Vec3(bb.minX, bb.minY, bb.maxZ); + Vec3 XyZ = new Vec3(bb.maxX, bb.minY, bb.maxZ); + Vec3 xYZ = new Vec3(bb.minX, bb.maxY, bb.maxZ); + Vec3 XYZ = new Vec3(bb.maxX, bb.maxY, bb.maxZ); + + Vec3 start = xyz; + renderAACuboidLine(ms, buffer, start, Xyz); + renderAACuboidLine(ms, buffer, start, xYz); + renderAACuboidLine(ms, buffer, start, xyZ); + + start = XyZ; + renderAACuboidLine(ms, buffer, start, xyZ); + renderAACuboidLine(ms, buffer, start, XYZ); + renderAACuboidLine(ms, buffer, start, Xyz); + + start = XYz; + renderAACuboidLine(ms, buffer, start, xYz); + renderAACuboidLine(ms, buffer, start, Xyz); + renderAACuboidLine(ms, buffer, start, XYZ); + + start = xYZ; + renderAACuboidLine(ms, buffer, start, XYZ); + renderAACuboidLine(ms, buffer, start, xyZ); + renderAACuboidLine(ms, buffer, start, xYz); + + renderFace(ms, buffer, Direction.NORTH, xYz, XYz, Xyz, xyz, noCull); + renderFace(ms, buffer, Direction.SOUTH, XYZ, xYZ, xyZ, XyZ, noCull); + renderFace(ms, buffer, Direction.EAST, XYz, XYZ, XyZ, Xyz, noCull); + renderFace(ms, buffer, Direction.WEST, xYZ, xYz, xyz, xyZ, noCull); + renderFace(ms, buffer, Direction.UP, xYZ, XYZ, XYz, xYz, noCull); + renderFace(ms, buffer, Direction.DOWN, xyz, Xyz, XyZ, xyZ, noCull); + + } + + protected void renderFace(PoseStack ms, SuperRenderTypeBuffer buffer, Direction direction, Vec3 p1, Vec3 p2, + Vec3 p3, Vec3 p4, boolean noCull) { + if (!params.faceTexture.isPresent()) + return; + + ResourceLocation faceTexture = params.faceTexture.get() + .getLocation(); + float alphaBefore = params.alpha; + params.alpha = + (direction == params.getHighlightedFace() && params.hightlightedFaceTexture.isPresent()) ? 1 : 0.5f; + + RenderType translucentType = RenderTypes.getOutlineTranslucent(faceTexture, !noCull); + VertexConsumer builder = buffer.getLateBuffer(translucentType); + + Axis axis = direction.getAxis(); + Vec3 uDiff = p2.subtract(p1); + Vec3 vDiff = p4.subtract(p1); + float maxU = (float) Math.abs(axis == Axis.X ? uDiff.z : uDiff.x); + float maxV = (float) Math.abs(axis == Axis.Y ? vDiff.z : vDiff.y); + putQuadUV(ms, builder, p1, p2, p3, p4, 0, 0, maxU, maxV, Direction.UP); + params.alpha = alphaBefore; } public void setBounds(AABB bb) { this.bb = bb; } - @Override - public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - params.loadColor(colorTemp); - Vector4f color = colorTemp; - int lightmap = params.lightmap; - boolean disableLineNormals = params.disableLineNormals; - - renderBox(ms, buffer, bb, color, lightmap, disableLineNormals); - } - - protected void renderBox(PoseStack ms, SuperRenderTypeBuffer buffer, AABB box, Vector4f color, int lightmap, boolean disableLineNormals) { - Vector3f minPos = minPosTemp1; - Vector3f maxPos = maxPosTemp1; - - Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera() - .getPosition(); - boolean cameraInside = box.contains(cameraPos); - boolean cull = !cameraInside && !params.disableCull; - float inflate = cameraInside ? -1 / 128f : 1 / 128f; - minPos.set((float) box.minX - inflate, (float) box.minY - inflate, (float) box.minZ - inflate); - maxPos.set((float) box.maxX + inflate, (float) box.maxY + inflate, (float) box.maxZ + inflate); - - renderBoxFaces(ms, buffer, cull, params.getHighlightedFace(), minPos, maxPos, color, lightmap); - - float lineWidth = params.getLineWidth(); - if (lineWidth == 0) - return; - - VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); - renderBoxEdges(ms, consumer, minPos, maxPos, lineWidth, color, lightmap, disableLineNormals); - } - - protected void renderBoxFaces(PoseStack ms, SuperRenderTypeBuffer buffer, boolean cull, Direction highlightedFace, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap) { - PoseStack.Pose pose = ms.last(); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.DOWN, color, lightmap); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.UP, color, lightmap); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.NORTH, color, lightmap); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.SOUTH, color, lightmap); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.WEST, color, lightmap); - renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.EAST, color, lightmap); - } - - protected void renderBoxFace(PoseStack.Pose pose, SuperRenderTypeBuffer buffer, boolean cull, Direction highlightedFace, Vector3f minPos, Vector3f maxPos, Direction face, Vector4f color, int lightmap) { - boolean highlighted = face == highlightedFace; - - // TODO: Presumably, the other texture should be used, but this was not noticed before so fixing it may lead to suboptimal visuals. -// Optional optionalFaceTexture = highlighted ? params.hightlightedFaceTexture : params.faceTexture; - Optional optionalFaceTexture = params.faceTexture; - if (!optionalFaceTexture.isPresent()) - return; - AllSpecialTextures faceTexture = optionalFaceTexture.get(); - - RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), cull); - VertexConsumer consumer = buffer.getLateBuffer(renderType); - - float alphaMult = highlighted ? 1 : 0.5f; - colorTemp1.set(color.x(), color.y(), color.z(), color.w() * alphaMult); - color = colorTemp1; - - renderBoxFace(pose, consumer, minPos, maxPos, face, color, lightmap); - } - - protected void renderBoxFace(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Direction face, Vector4f color, int lightmap) { - Vector3f pos0 = pos0Temp; - Vector3f pos1 = pos1Temp; - Vector3f pos2 = pos2Temp; - Vector3f pos3 = pos3Temp; - Vector3f normal = normalTemp; - - float minX = minPos.x(); - float minY = minPos.y(); - float minZ = minPos.z(); - float maxX = maxPos.x(); - float maxY = maxPos.y(); - float maxZ = maxPos.z(); - - float maxU; - float maxV; - - switch (face) { - case DOWN -> { - // 0 1 2 3 - pos0.set(minX, minY, maxZ); - pos1.set(minX, minY, minZ); - pos2.set(maxX, minY, minZ); - pos3.set(maxX, minY, maxZ); - maxU = maxX - minX; - maxV = maxZ - minZ; - normal.set(0, -1, 0); - } - case UP -> { - // 4 5 6 7 - pos0.set(minX, maxY, minZ); - pos1.set(minX, maxY, maxZ); - pos2.set(maxX, maxY, maxZ); - pos3.set(maxX, maxY, minZ); - maxU = maxX - minX; - maxV = maxZ - minZ; - normal.set(0, 1, 0); - } - case NORTH -> { - // 7 2 1 4 - pos0.set(maxX, maxY, minZ); - pos1.set(maxX, minY, minZ); - pos2.set(minX, minY, minZ); - pos3.set(minX, maxY, minZ); - maxU = maxX - minX; - maxV = maxY - minY; - normal.set(0, 0, -1); - } - case SOUTH -> { - // 5 0 3 6 - pos0.set(minX, maxY, maxZ); - pos1.set(minX, minY, maxZ); - pos2.set(maxX, minY, maxZ); - pos3.set(maxX, maxY, maxZ); - maxU = maxX - minX; - maxV = maxY - minY; - normal.set(0, 0, 1); - } - case WEST -> { - // 4 1 0 5 - pos0.set(minX, maxY, minZ); - pos1.set(minX, minY, minZ); - pos2.set(minX, minY, maxZ); - pos3.set(minX, maxY, maxZ); - maxU = maxZ - minZ; - maxV = maxY - minY; - normal.set(-1, 0, 0); - } - case EAST -> { - // 6 3 2 7 - pos0.set(maxX, maxY, maxZ); - pos1.set(maxX, minY, maxZ); - pos2.set(maxX, minY, minZ); - pos3.set(maxX, maxY, minZ); - maxU = maxZ - minZ; - maxV = maxY - minY; - normal.set(1, 0, 0); - } - default -> { - maxU = 1; - maxV = 1; - } - } - - bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, 0, 0, maxU, maxV, lightmap, normal); - } - - protected void renderBoxEdges(PoseStack ms, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, float lineWidth, Vector4f color, int lightmap, boolean disableNormals) { - Vector3f origin = originTemp; - - PoseStack.Pose pose = ms.last(); - - float lineLengthX = maxPos.x() - minPos.x(); - float lineLengthY = maxPos.y() - minPos.y(); - float lineLengthZ = maxPos.z() - minPos.z(); - - origin.load(minPos); - bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); - bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); - bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); - - origin.set(maxPos.x(), minPos.y(), minPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); - bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); - - origin.set(minPos.x(), maxPos.y(), minPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); - bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); - - origin.set(minPos.x(), minPos.y(), maxPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); - bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); - - origin.set(minPos.x(), maxPos.y(), maxPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); - - origin.set(maxPos.x(), minPos.y(), maxPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); - - origin.set(maxPos.x(), maxPos.y(), minPos.z()); - bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java index b0f646ec2..0f005a5bb 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java @@ -8,156 +8,94 @@ import java.util.Set; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.phys.Vec3; public class BlockClusterOutline extends Outline { - private final Cluster cluster; + private Cluster cluster; - protected final Vector3f pos0Temp = new Vector3f(); - protected final Vector3f pos1Temp = new Vector3f(); - protected final Vector3f pos2Temp = new Vector3f(); - protected final Vector3f pos3Temp = new Vector3f(); - protected final Vector3f normalTemp = new Vector3f(); - protected final Vector3f originTemp = new Vector3f(); - - public BlockClusterOutline(Iterable positions) { + public BlockClusterOutline(Iterable selection) { cluster = new Cluster(); - positions.forEach(cluster::include); + selection.forEach(cluster::include); } @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - params.loadColor(colorTemp); - Vector4f color = colorTemp; - int lightmap = params.lightmap; - boolean disableLineNormals = params.disableLineNormals; + cluster.visibleEdges.forEach(edge -> { + Vec3 start = Vec3.atLowerCornerOf(edge.pos); + Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); + renderAACuboidLine(ms, buffer, start, Vec3.atLowerCornerOf(edge.pos.relative(direction))); + }); - renderFaces(ms, buffer, pt, color, lightmap); - renderEdges(ms, buffer, pt, color, lightmap, disableLineNormals); - } - - protected void renderFaces(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap) { - Optional optionalFaceTexture = params.faceTexture; - if (!optionalFaceTexture.isPresent()) + Optional faceTexture = params.faceTexture; + if (!faceTexture.isPresent()) return; - AllSpecialTextures faceTexture = optionalFaceTexture.get(); - PoseStack.Pose pose = ms.last(); - RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), true); - VertexConsumer consumer = buffer.getLateBuffer(renderType); + RenderType translucentType = RenderTypes.getOutlineTranslucent(faceTexture.get() + .getLocation(), true); + VertexConsumer builder = buffer.getLateBuffer(translucentType); cluster.visibleFaces.forEach((face, axisDirection) -> { Direction direction = Direction.get(axisDirection, face.axis); BlockPos pos = face.pos; if (axisDirection == AxisDirection.POSITIVE) pos = pos.relative(direction.getOpposite()); - bufferBlockFace(pose, consumer, pos, direction, color, lightmap); + renderBlockFace(ms, builder, pos, direction); }); } - protected void renderEdges(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap, boolean disableNormals) { - float lineWidth = params.getLineWidth(); - if (lineWidth == 0) - return; + static Vec3 xyz = new Vec3(-.5, -.5, -.5); + static Vec3 Xyz = new Vec3(.5, -.5, -.5); + static Vec3 xYz = new Vec3(-.5, .5, -.5); + static Vec3 XYz = new Vec3(.5, .5, -.5); + static Vec3 xyZ = new Vec3(-.5, -.5, .5); + static Vec3 XyZ = new Vec3(.5, -.5, .5); + static Vec3 xYZ = new Vec3(-.5, .5, .5); + static Vec3 XYZ = new Vec3(.5, .5, .5); + + protected void renderBlockFace(PoseStack ms, VertexConsumer builder, BlockPos pos, Direction face) { + Vec3 center = VecHelper.getCenterOf(pos); + Vec3 offset = Vec3.atLowerCornerOf(face.getNormal()); + offset = offset.scale(1 / 128d); + center = center.add(offset); - PoseStack.Pose pose = ms.last(); - VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + ms.pushPose(); + ms.translate(center.x, center.y, center.z); - cluster.visibleEdges.forEach(edge -> { - BlockPos pos = edge.pos; - Vector3f origin = originTemp; - origin.set(pos.getX(), pos.getY(), pos.getZ()); - Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); - bufferCuboidLine(pose, consumer, origin, direction, 1, lineWidth, color, lightmap, disableNormals); - }); - } - - public static void loadFaceData(Direction face, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector3f normal) { switch (face) { - case DOWN -> { - // 0 1 2 3 - pos0.set(0, 0, 1); - pos1.set(0, 0, 0); - pos2.set(1, 0, 0); - pos3.set(1, 0, 1); - normal.set(0, -1, 0); + case DOWN: + putQuad(ms, builder, xyz, Xyz, XyZ, xyZ, face); + break; + case EAST: + putQuad(ms, builder, XYz, XYZ, XyZ, Xyz, face); + break; + case NORTH: + putQuad(ms, builder, xYz, XYz, Xyz, xyz, face); + break; + case SOUTH: + putQuad(ms, builder, XYZ, xYZ, xyZ, XyZ, face); + break; + case UP: + putQuad(ms, builder, xYZ, XYZ, XYz, xYz, face); + break; + case WEST: + putQuad(ms, builder, xYZ, xYz, xyz, xyZ, face); + default: + break; } - case UP -> { - // 4 5 6 7 - pos0.set(0, 1, 0); - pos1.set(0, 1, 1); - pos2.set(1, 1, 1); - pos3.set(1, 1, 0); - normal.set(0, 1, 0); - } - case NORTH -> { - // 7 2 1 4 - pos0.set(1, 1, 0); - pos1.set(1, 0, 0); - pos2.set(0, 0, 0); - pos3.set(0, 1, 0); - normal.set(0, 0, -1); - } - case SOUTH -> { - // 5 0 3 6 - pos0.set(0, 1, 1); - pos1.set(0, 0, 1); - pos2.set(1, 0, 1); - pos3.set(1, 1, 1); - normal.set(0, 0, 1); - } - case WEST -> { - // 4 1 0 5 - pos0.set(0, 1, 0); - pos1.set(0, 0, 0); - pos2.set(0, 0, 1); - pos3.set(0, 1, 1); - normal.set(-1, 0, 0); - } - case EAST -> { - // 6 3 2 7 - pos0.set(1, 1, 1); - pos1.set(1, 0, 1); - pos2.set(1, 0, 0); - pos3.set(1, 1, 0); - normal.set(1, 0, 0); - } - } - } - public static void addPos(float x, float y, float z, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3) { - pos0.add(x, y, z); - pos1.add(x, y, z); - pos2.add(x, y, z); - pos3.add(x, y, z); - } - - protected void bufferBlockFace(PoseStack.Pose pose, VertexConsumer consumer, BlockPos pos, Direction face, Vector4f color, int lightmap) { - Vector3f pos0 = pos0Temp; - Vector3f pos1 = pos1Temp; - Vector3f pos2 = pos2Temp; - Vector3f pos3 = pos3Temp; - Vector3f normal = normalTemp; - - loadFaceData(face, pos0, pos1, pos2, pos3, normal); - addPos(pos.getX() + face.getStepX() * 1 / 128f, - pos.getY() + face.getStepY() * 1 / 128f, - pos.getZ() + face.getStepZ() * 1 / 128f, - pos0, pos1, pos2, pos3); - - bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, lightmap, normal); + ms.popPose(); } private static class Cluster { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java index 6ca4b1550..4c0b22ba4 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java @@ -1,7 +1,6 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Vector4f; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.Mth; @@ -30,12 +29,7 @@ public class ChasingAABBOutline extends AABBOutline { @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - params.loadColor(colorTemp); - Vector4f color = colorTemp; - int lightmap = params.lightmap; - boolean disableLineNormals = params.disableLineNormals; - - renderBox(ms, buffer, interpolateBBs(prevBB, bb, pt), color, lightmap, disableLineNormals); + renderBB(ms, buffer, interpolateBBs(prevBB, bb, pt)); } private static AABB interpolateBBs(AABB current, AABB target, float pt) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/ItemOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/ItemOutline.java new file mode 100644 index 000000000..3d7776c4e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/ItemOutline.java @@ -0,0 +1,51 @@ +package com.simibubi.create.foundation.utility.outliner; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +import java.util.*; + +public class ItemOutline extends Outline { + + protected Vec3 pos; + protected ItemStack stack; + + public ItemOutline(Vec3 pos, ItemStack stack) { + this.pos = pos; + this.stack = stack; + } + + @Override + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { + Minecraft mc = Minecraft.getInstance(); + ms.pushPose(); + + TransformStack.cast(ms) + .translate(pos) + .scale(params.alpha); + + mc.getItemRenderer().render(stack, ItemTransforms.TransformType.FIXED, false, ms, + buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, + mc.getItemRenderer().getModel(stack, null, null, 0)); + + ms.popPose(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java index d59aa203b..7803dbe84 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java @@ -1,10 +1,6 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; -import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.Mth; @@ -12,50 +8,33 @@ import net.minecraft.world.phys.Vec3; public class LineOutline extends Outline { - protected final Vector3f start = new Vector3f(); - protected final Vector3f end = new Vector3f(); - - public LineOutline set(Vector3f start, Vector3f end) { - this.start.load(start); - this.start.load(end); - return this; - } + protected Vec3 start = Vec3.ZERO; + protected Vec3 end = Vec3.ZERO; public LineOutline set(Vec3 start, Vec3 end) { - this.start.set((float) start.x, (float) start.y, (float) start.z); - this.end.set((float) end.x, (float) end.y, (float) end.z); + this.start = start; + this.end = end; return this; } @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - float width = params.getLineWidth(); - if (width == 0) - return; - - VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); - params.loadColor(colorTemp); - Vector4f color = colorTemp; - int lightmap = params.lightmap; - boolean disableLineNormals = params.disableLineNormals; - renderInner(ms, consumer, pt, width, color, lightmap, disableLineNormals); - } - - protected void renderInner(PoseStack ms, VertexConsumer consumer, float pt, float width, Vector4f color, int lightmap, boolean disableNormals) { - bufferCuboidLine(ms, consumer, start, end, width, color, lightmap, disableNormals); + renderCuboidLine(ms, buffer, start, end); } public static class EndChasingLineOutline extends LineOutline { - private float progress = 0; - private float prevProgress = 0; - private boolean lockStart; - private final Vector3f startTemp = new Vector3f(); + float prevProgress = 0; + float progress = 0; + private boolean lockStart; public EndChasingLineOutline(boolean lockStart) { this.lockStart = lockStart; } + @Override + public void tick() {} + public EndChasingLineOutline setProgress(float progress) { prevProgress = this.progress; this.progress = progress; @@ -63,24 +42,25 @@ public class LineOutline extends Outline { } @Override - protected void renderInner(PoseStack ms, VertexConsumer consumer, float pt, float width, Vector4f color, int lightmap, boolean disableNormals) { - float distanceToTarget = Mth.lerp(pt, prevProgress, progress); - Vector3f end; - if (lockStart) { - end = this.start; - } else { - end = this.end; - distanceToTarget = 1 - distanceToTarget; - } - - Vector3f start = this.startTemp; - start.load(this.start); - start.sub(end); - start.mul(distanceToTarget); - start.add(end); - - bufferCuboidLine(ms, consumer, start, end, width, color, lightmap, disableNormals); + public LineOutline set(Vec3 start, Vec3 end) { + if (!end.equals(this.end)) + super.set(start, end); + return this; } + + @Override + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { + float distanceToTarget = Mth.lerp(pt, prevProgress, progress); + if (!lockStart) + distanceToTarget = 1 - distanceToTarget; + Vec3 start = lockStart ? this.end : this.start; + Vec3 end = lockStart ? this.start : this.end; + + start = end.add(this.start.subtract(end) + .scale(distanceToTarget)); + renderCuboidLine(ms, buffer, start, end); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java index 071274aab..8f0b7d62e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java @@ -8,497 +8,156 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Matrix3f; -import com.mojang.math.Matrix4f; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; public abstract class Outline { - protected final OutlineParams params; - - protected final Vector4f colorTemp = new Vector4f(); - protected final Vector3f diffPosTemp = new Vector3f(); - protected final Vector3f minPosTemp = new Vector3f(); - protected final Vector3f maxPosTemp = new Vector3f(); - protected final Vector4f posTransformTemp = new Vector4f(); - protected final Vector3f normalTransformTemp = new Vector3f(); + protected OutlineParams params; + protected Matrix3f transformNormals; // TODO: not used? public Outline() { params = new OutlineParams(); } - public OutlineParams getParams() { - return params; - } - public abstract void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt); public void tick() {} - public void bufferCuboidLine(PoseStack poseStack, VertexConsumer consumer, Vector3f start, Vector3f end, float width, Vector4f color, int lightmap, boolean disableNormals) { - Vector3f diff = this.diffPosTemp; - diff.load(end); - diff.sub(start); - - float length = Mth.sqrt(diff.x() * diff.x() + diff.y() * diff.y() + diff.z() * diff.z()); - float hAngle = AngleHelper.deg(Mth.atan2(diff.x(), diff.z())); - float hDistance = Mth.sqrt(diff.x() * diff.x() + diff.z() * diff.z()); - float vAngle = AngleHelper.deg(Mth.atan2(hDistance, diff.y())) - 90; - - poseStack.pushPose(); - TransformStack.cast(poseStack) - .rotateY(hAngle) - .rotateX(vAngle); - bufferCuboidLine(poseStack.last(), consumer, start, Direction.NORTH, length, width, color, lightmap, disableNormals); - poseStack.popPose(); + public OutlineParams getParams() { + return params; } - public void bufferCuboidLine(PoseStack.Pose pose, VertexConsumer consumer, Vector3f origin, Direction direction, float length, float width, Vector4f color, int lightmap, boolean disableNormals) { - Vector3f minPos = minPosTemp; - Vector3f maxPos = maxPosTemp; - - float halfWidth = width / 2; - minPos.set(origin.x() - halfWidth, origin.y() - halfWidth, origin.z() - halfWidth); - maxPos.set(origin.x() + halfWidth, origin.y() + halfWidth, origin.z() + halfWidth); - - switch (direction) { - case DOWN -> { - minPos.add(0, -length, 0); - } - case UP -> { - maxPos.add(0, length, 0); - } - case NORTH -> { - minPos.add(0, 0, -length); - } - case SOUTH -> { - maxPos.add(0, 0, length); - } - case WEST -> { - minPos.add(-length, 0, 0); - } - case EAST -> { - maxPos.add(length, 0, 0); - } - } - - bufferCuboid(pose, consumer, minPos, maxPos, color, lightmap, disableNormals); + public void renderCuboidLine(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 start, Vec3 end) { + Vec3 diff = end.subtract(start); + float hAngle = AngleHelper.deg(Mth.atan2(diff.x, diff.z)); + float hDistance = (float) diff.multiply(1, 0, 1) + .length(); + float vAngle = AngleHelper.deg(Mth.atan2(hDistance, diff.y)) - 90; + ms.pushPose(); + TransformStack.cast(ms) + .translate(start) + .rotateY(hAngle).rotateX(vAngle); + renderAACuboidLine(ms, buffer, Vec3.ZERO, new Vec3(0, 0, diff.length())); + ms.popPose(); } - public void bufferCuboid(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap, boolean disableNormals) { - Vector4f posTransformTemp = this.posTransformTemp; - Vector3f normalTransformTemp = this.normalTransformTemp; + public void renderAACuboidLine(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 start, Vec3 end) { + float lineWidth = params.getLineWidth(); + if (lineWidth == 0) + return; - float minX = minPos.x(); - float minY = minPos.y(); - float minZ = minPos.z(); - float maxX = maxPos.x(); - float maxY = maxPos.y(); - float maxZ = maxPos.z(); + VertexConsumer builder = buffer.getBuffer(RenderTypes.getOutlineSolid()); - Matrix4f posMatrix = pose.pose(); - - posTransformTemp.set(minX, minY, maxZ, 1); - posTransformTemp.transform(posMatrix); - double x0 = posTransformTemp.x(); - double y0 = posTransformTemp.y(); - double z0 = posTransformTemp.z(); - - posTransformTemp.set(minX, minY, minZ, 1); - posTransformTemp.transform(posMatrix); - double x1 = posTransformTemp.x(); - double y1 = posTransformTemp.y(); - double z1 = posTransformTemp.z(); - - posTransformTemp.set(maxX, minY, minZ, 1); - posTransformTemp.transform(posMatrix); - double x2 = posTransformTemp.x(); - double y2 = posTransformTemp.y(); - double z2 = posTransformTemp.z(); - - posTransformTemp.set(maxX, minY, maxZ, 1); - posTransformTemp.transform(posMatrix); - double x3 = posTransformTemp.x(); - double y3 = posTransformTemp.y(); - double z3 = posTransformTemp.z(); - - posTransformTemp.set(minX, maxY, minZ, 1); - posTransformTemp.transform(posMatrix); - double x4 = posTransformTemp.x(); - double y4 = posTransformTemp.y(); - double z4 = posTransformTemp.z(); - - posTransformTemp.set(minX, maxY, maxZ, 1); - posTransformTemp.transform(posMatrix); - double x5 = posTransformTemp.x(); - double y5 = posTransformTemp.y(); - double z5 = posTransformTemp.z(); - - posTransformTemp.set(maxX, maxY, maxZ, 1); - posTransformTemp.transform(posMatrix); - double x6 = posTransformTemp.x(); - double y6 = posTransformTemp.y(); - double z6 = posTransformTemp.z(); - - posTransformTemp.set(maxX, maxY, minZ, 1); - posTransformTemp.transform(posMatrix); - double x7 = posTransformTemp.x(); - double y7 = posTransformTemp.y(); - double z7 = posTransformTemp.z(); - - float r = color.x(); - float g = color.y(); - float b = color.z(); - float a = color.w(); - - Matrix3f normalMatrix = pose.normal(); - - // down - - if (disableNormals) { - normalTransformTemp.set(0, 1, 0); - } else { - normalTransformTemp.set(0, -1, 0); + Vec3 diff = end.subtract(start); + if (diff.x + diff.y + diff.z < 0) { + Vec3 temp = start; + start = end; + end = temp; + diff = diff.scale(-1); } - normalTransformTemp.transform(normalMatrix); - float nx0 = normalTransformTemp.x(); - float ny0 = normalTransformTemp.y(); - float nz0 = normalTransformTemp.z(); - consumer.vertex(x0, y0, z0) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx0, ny0, nz0) - .endVertex(); + Vec3 extension = diff.normalize() + .scale(lineWidth / 2); + Vec3 plane = VecHelper.axisAlingedPlaneOf(diff); + Direction face = Direction.getNearest(diff.x, diff.y, diff.z); + Axis axis = face.getAxis(); - consumer.vertex(x1, y1, z1) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx0, ny0, nz0) - .endVertex(); + start = start.subtract(extension); + end = end.add(extension); + plane = plane.scale(lineWidth / 2); - consumer.vertex(x2, y2, z2) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx0, ny0, nz0) - .endVertex(); + Vec3 a1 = plane.add(start); + Vec3 b1 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vec3 a2 = plane.add(start); + Vec3 b2 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vec3 a3 = plane.add(start); + Vec3 b3 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vec3 a4 = plane.add(start); + Vec3 b4 = plane.add(end); - consumer.vertex(x3, y3, z3) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx0, ny0, nz0) - .endVertex(); - - // up - - normalTransformTemp.set(0, 1, 0); - normalTransformTemp.transform(normalMatrix); - float nx1 = normalTransformTemp.x(); - float ny1 = normalTransformTemp.y(); - float nz1 = normalTransformTemp.z(); - - consumer.vertex(x4, y4, z4) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx1, ny1, nz1) - .endVertex(); - - consumer.vertex(x5, y5, z5) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx1, ny1, nz1) - .endVertex(); - - consumer.vertex(x6, y6, z6) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx1, ny1, nz1) - .endVertex(); - - consumer.vertex(x7, y7, z7) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx1, ny1, nz1) - .endVertex(); - - // north - - if (disableNormals) { - normalTransformTemp.set(0, 1, 0); - } else { - normalTransformTemp.set(0, 0, -1); + if (params.disableNormals) { + face = Direction.UP; + putQuad(ms, builder, b4, b3, b2, b1, face); + putQuad(ms, builder, a1, a2, a3, a4, face); + putQuad(ms, builder, a1, b1, b2, a2, face); + putQuad(ms, builder, a2, b2, b3, a3, face); + putQuad(ms, builder, a3, b3, b4, a4, face); + putQuad(ms, builder, a4, b4, b1, a1, face); + return; } - normalTransformTemp.transform(normalMatrix); - float nx2 = normalTransformTemp.x(); - float ny2 = normalTransformTemp.y(); - float nz2 = normalTransformTemp.z(); - consumer.vertex(x7, y7, z7) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx2, ny2, nz2) - .endVertex(); - - consumer.vertex(x2, y2, z2) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx2, ny2, nz2) - .endVertex(); - - consumer.vertex(x1, y1, z1) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx2, ny2, nz2) - .endVertex(); - - consumer.vertex(x4, y4, z4) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx2, ny2, nz2) - .endVertex(); - - // south - - if (disableNormals) { - normalTransformTemp.set(0, 1, 0); - } else { - normalTransformTemp.set(0, 0, 1); - } - normalTransformTemp.transform(normalMatrix); - float nx3 = normalTransformTemp.x(); - float ny3 = normalTransformTemp.y(); - float nz3 = normalTransformTemp.z(); - - consumer.vertex(x5, y5, z5) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx3, ny3, nz3) - .endVertex(); - - consumer.vertex(x0, y0, z0) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx3, ny3, nz3) - .endVertex(); - - consumer.vertex(x3, y3, z3) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx3, ny3, nz3) - .endVertex(); - - consumer.vertex(x6, y6, z6) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx3, ny3, nz3) - .endVertex(); - - // west - - if (disableNormals) { - normalTransformTemp.set(0, 1, 0); - } else { - normalTransformTemp.set(-1, 0, 0); - } - normalTransformTemp.transform(normalMatrix); - float nx4 = normalTransformTemp.x(); - float ny4 = normalTransformTemp.y(); - float nz4 = normalTransformTemp.z(); - - consumer.vertex(x4, y4, z4) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx4, ny4, nz4) - .endVertex(); - - consumer.vertex(x1, y1, z1) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx4, ny4, nz4) - .endVertex(); - - consumer.vertex(x0, y0, z0) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx4, ny4, nz4) - .endVertex(); - - consumer.vertex(x5, y5, z5) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx4, ny4, nz4) - .endVertex(); - - // east - - if (disableNormals) { - normalTransformTemp.set(0, 1, 0); - } else { - normalTransformTemp.set(1, 0, 0); - } - normalTransformTemp.transform(normalMatrix); - float nx5 = normalTransformTemp.x(); - float ny5 = normalTransformTemp.y(); - float nz5 = normalTransformTemp.z(); - - consumer.vertex(x6, y6, z6) - .color(r, g, b, a) - .uv(0, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx5, ny5, nz5) - .endVertex(); - - consumer.vertex(x3, y3, z3) - .color(r, g, b, a) - .uv(0, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx5, ny5, nz5) - .endVertex(); - - consumer.vertex(x2, y2, z2) - .color(r, g, b, a) - .uv(1, 1) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx5, ny5, nz5) - .endVertex(); - - consumer.vertex(x7, y7, z7) - .color(r, g, b, a) - .uv(1, 0) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx5, ny5, nz5) - .endVertex(); + putQuad(ms, builder, b4, b3, b2, b1, face); + putQuad(ms, builder, a1, a2, a3, a4, face.getOpposite()); + Vec3 vec = a1.subtract(a4); + face = Direction.getNearest(vec.x, vec.y, vec.z); + putQuad(ms, builder, a1, b1, b2, a2, face); + vec = VecHelper.rotate(vec, -90, axis); + face = Direction.getNearest(vec.x, vec.y, vec.z); + putQuad(ms, builder, a2, b2, b3, a3, face); + vec = VecHelper.rotate(vec, -90, axis); + face = Direction.getNearest(vec.x, vec.y, vec.z); + putQuad(ms, builder, a3, b3, b4, a4, face); + vec = VecHelper.rotate(vec, -90, axis); + face = Direction.getNearest(vec.x, vec.y, vec.z); + putQuad(ms, builder, a4, b4, b1, a1, face); } - public void bufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, int lightmap, Vector3f normal) { - bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, 0, 0, 1, 1, lightmap, normal); + public void putQuad(PoseStack ms, VertexConsumer builder, Vec3 v1, Vec3 v2, Vec3 v3, Vec3 v4, + Direction normal) { + putQuadUV(ms, builder, v1, v2, v3, v4, 0, 0, 1, 1, normal); } - public void bufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, float minU, float minV, float maxU, float maxV, int lightmap, Vector3f normal) { - Vector4f posTransformTemp = this.posTransformTemp; - Vector3f normalTransformTemp = this.normalTransformTemp; + public void putQuadUV(PoseStack ms, VertexConsumer builder, Vec3 v1, Vec3 v2, Vec3 v3, Vec3 v4, float minU, + float minV, float maxU, float maxV, Direction normal) { + putVertex(ms, builder, v1, minU, minV, normal); + putVertex(ms, builder, v2, maxU, minV, normal); + putVertex(ms, builder, v3, maxU, maxV, normal); + putVertex(ms, builder, v4, minU, maxV, normal); + } - Matrix4f posMatrix = pose.pose(); + protected void putVertex(PoseStack ms, VertexConsumer builder, Vec3 pos, float u, float v, Direction normal) { + putVertex(ms.last(), builder, (float) pos.x, (float) pos.y, (float) pos.z, u, v, normal); + } - posTransformTemp.set(pos0.x(), pos0.y(), pos0.z(), 1); - posTransformTemp.transform(posMatrix); - double x0 = posTransformTemp.x(); - double y0 = posTransformTemp.y(); - double z0 = posTransformTemp.z(); + protected void putVertex(PoseStack.Pose pose, VertexConsumer builder, float x, float y, float z, float u, float v, Direction normal) { + Color rgb = params.rgb; + if (transformNormals == null) + transformNormals = pose.normal(); - posTransformTemp.set(pos1.x(), pos1.y(), pos1.z(), 1); - posTransformTemp.transform(posMatrix); - double x1 = posTransformTemp.x(); - double y1 = posTransformTemp.y(); - double z1 = posTransformTemp.z(); + int xOffset = 0; + int yOffset = 0; + int zOffset = 0; - posTransformTemp.set(pos2.x(), pos2.y(), pos2.z(), 1); - posTransformTemp.transform(posMatrix); - double x2 = posTransformTemp.x(); - double y2 = posTransformTemp.y(); - double z2 = posTransformTemp.z(); + if (normal != null) { + xOffset = normal.getStepX(); + yOffset = normal.getStepY(); + zOffset = normal.getStepZ(); + } - posTransformTemp.set(pos3.x(), pos3.y(), pos3.z(), 1); - posTransformTemp.transform(posMatrix); - double x3 = posTransformTemp.x(); - double y3 = posTransformTemp.y(); - double z3 = posTransformTemp.z(); - - float r = color.x(); - float g = color.y(); - float b = color.z(); - float a = color.w(); - - normalTransformTemp.load(normal); - normalTransformTemp.transform(pose.normal()); - float nx = normalTransformTemp.x(); - float ny = normalTransformTemp.y(); - float nz = normalTransformTemp.z(); - - consumer.vertex(x0, y0, z0) - .color(r, g, b, a) - .uv(minU, minV) + builder.vertex(pose.pose(), x, y, z) + .color(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * params.alpha) + .uv(u, v) .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx, ny, nz) + .uv2(params.lightMap) + .normal(pose.normal(), xOffset, yOffset, zOffset) .endVertex(); - consumer.vertex(x1, y1, z1) - .color(r, g, b, a) - .uv(minU, maxV) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx, ny, nz) - .endVertex(); - - consumer.vertex(x2, y2, z2) - .color(r, g, b, a) - .uv(maxU, maxV) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx, ny, nz) - .endVertex(); - - consumer.vertex(x3, y3, z3) - .color(r, g, b, a) - .uv(maxU, minV) - .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(lightmap) - .normal(nx, ny, nz) - .endVertex(); + transformNormals = null; } public static class OutlineParams { @@ -507,9 +166,9 @@ public abstract class Outline { protected Direction highlightedFace; protected boolean fadeLineWidth; protected boolean disableCull; - protected boolean disableLineNormals; + protected boolean disableNormals; protected float alpha; - protected int lightmap; + protected int lightMap; protected Color rgb; private float lineWidth; @@ -519,7 +178,7 @@ public abstract class Outline { lineWidth = 1 / 32f; fadeLineWidth = true; rgb = Color.WHITE; - lightmap = LightTexture.FULL_BRIGHT; + lightMap = LightTexture.FULL_BRIGHT; } // builder @@ -534,8 +193,8 @@ public abstract class Outline { return this; } - public OutlineParams lightmap(int light) { - lightmap = light; + public OutlineParams lightMap(int light) { + lightMap = light; return this; } @@ -564,8 +223,8 @@ public abstract class Outline { return this; } - public OutlineParams disableLineNormals() { - disableLineNormals = true; + public OutlineParams disableNormals() { + disableNormals = true; return this; } @@ -584,9 +243,6 @@ public abstract class Outline { return highlightedFace; } - public void loadColor(Vector4f vec) { - vec.set(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * alpha); - } } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java index 0e4b472d0..9401de6ca 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java @@ -14,6 +14,7 @@ import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -32,7 +33,7 @@ public class Outliner { public OutlineParams showLine(Object slot, Vec3 start, Vec3 end) { if (!outlines.containsKey(slot)) { LineOutline outline = new LineOutline(); - addOutline(slot, outline); + outlines.put(slot, new OutlineEntry(outline)); } OutlineEntry entry = outlines.get(slot); entry.ticksTillRemoval = 1; @@ -43,7 +44,7 @@ public class Outliner { public OutlineParams endChasingLine(Object slot, Vec3 start, Vec3 end, float chasingProgress, boolean lockStart) { if (!outlines.containsKey(slot)) { EndChasingLineOutline outline = new EndChasingLineOutline(lockStart); - addOutline(slot, outline); + outlines.put(slot, new OutlineEntry(outline)); } OutlineEntry entry = outlines.get(slot); entry.ticksTillRemoval = 1; @@ -75,11 +76,18 @@ public class Outliner { public OutlineParams showCluster(Object slot, Iterable selection) { BlockClusterOutline outline = new BlockClusterOutline(selection); - addOutline(slot, outline); - return outline.getParams(); + OutlineEntry entry = new OutlineEntry(outline); + outlines.put(slot, entry); + return entry.getOutline() + .getParams(); } - // + public OutlineParams showItem(Object slot, Vec3 pos, ItemStack stack) { + ItemOutline outline = new ItemOutline(pos, stack); + OutlineEntry entry = new OutlineEntry(outline); + outlines.put(slot, entry); + return entry.getOutline().getParams(); + } public void keep(Object slot) { if (outlines.containsKey(slot)) @@ -105,19 +113,17 @@ public class Outliner { // Utility - private void addOutline(Object slot, Outline outline) { - outlines.put(slot, new OutlineEntry(outline)); - } - private void createAABBOutlineIfMissing(Object slot, AABB bb) { if (!outlines.containsKey(slot) || !(outlines.get(slot).outline instanceof AABBOutline)) { ChasingAABBOutline outline = new ChasingAABBOutline(bb); - addOutline(slot, outline); + outlines.put(slot, new OutlineEntry(outline)); } } private ChasingAABBOutline getAndRefreshAABB(Object slot) { - return getAndRefreshAABB(slot, 1); + OutlineEntry entry = outlines.get(slot); + entry.ticksTillRemoval = 1; + return (ChasingAABBOutline) entry.getOutline(); } private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) { @@ -146,7 +152,7 @@ public class Outliner { params.alpha = 1; if (entry.isFading()) { int prevTicks = entry.ticksTillRemoval + 1; - float fadeticks = OutlineEntry.FADE_TICKS; + float fadeticks = OutlineEntry.fadeTicks; float lastAlpha = prevTicks >= 0 ? 1 : 1 + (prevTicks / fadeticks); float currentAlpha = 1 + (entry.ticksTillRemoval / fadeticks); float alpha = Mth.lerp(pt, lastAlpha, currentAlpha); @@ -160,35 +166,33 @@ public class Outliner { } public static class OutlineEntry { - public static final int FADE_TICKS = 8; - private final Outline outline; - private int ticksTillRemoval = 1; + static final int fadeTicks = 8; + private Outline outline; + private int ticksTillRemoval; public OutlineEntry(Outline outline) { this.outline = outline; - } - - public Outline getOutline() { - return outline; - } - - public int getTicksTillRemoval() { - return ticksTillRemoval; - } - - public boolean isAlive() { - return ticksTillRemoval >= -FADE_TICKS; - } - - public boolean isFading() { - return ticksTillRemoval < 0; + ticksTillRemoval = 1; } public void tick() { ticksTillRemoval--; outline.tick(); } + + public boolean isAlive() { + return ticksTillRemoval >= -fadeTicks; + } + + public boolean isFading() { + return ticksTillRemoval < 0; + } + + public Outline getOutline() { + return outline; + } + } } diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 86e0d8237..20b959087 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -920,8 +920,14 @@ "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up", "create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world", - + "enchantment.create.capacity.desc": "Increases Backtank air capacity.", - "enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused." + "enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.", + + "create.bogey.style.updated_style": "Updated style", + "create.bogey.style.updated_style_and_size": "Updated style and size", + "create.bogey.style.no_other_sizes": "No other sizes", + "create.bogey.style.invalid": "Unnamed style", + "create.bogey.style.standard": "Standard" }