mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-05 03:02:37 +01:00
Merge branch '1.18/api' into mc1.18/dev
This commit is contained in:
commit
a7a25896c1
61 changed files with 1074 additions and 1189 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -42,4 +42,5 @@ local.properties
|
|||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
/libs/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 [------------------------<-",
|
||||
|
||||
|
|
|
@ -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<ResourceLocation, BogeyStyle> BOGEY_STYLES = new HashMap<>();
|
||||
public static final Map<ResourceLocation, Map<ResourceLocation, BogeyStyle>> STYLE_GROUPS = new HashMap<>(); // each set of styles that should be cycled through
|
||||
private static final Map<ResourceLocation, BogeyStyle> EMPTY_GROUP = ImmutableMap.of();
|
||||
|
||||
public static BogeyStyle STANDARD = create("standard")
|
||||
public static Map<ResourceLocation, BogeyStyle> 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<BogeySizes.BogeySize, BogeyStyle.SizeData> 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<Supplier<? extends CommonRenderer>> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -33,7 +33,7 @@ public class WorldshaperRenderHandler {
|
|||
|
||||
CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get())
|
||||
.colored(0xbfbfbf)
|
||||
.disableLineNormals()
|
||||
.disableNormals()
|
||||
.lineWidth(1 / 32f)
|
||||
.withFaceTexture(AllSpecialTextures.CHECKERED);
|
||||
}
|
||||
|
|
|
@ -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<StandardBogeyTileEntity>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
|
||||
public abstract class AbstractBogeyBlock<T extends AbstractBogeyTileEntity> extends Block implements ITE<T>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
|
||||
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS;
|
||||
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
||||
public BogeySizes.BogeySize size;
|
||||
|
@ -67,7 +73,23 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
|
|||
this.size = size;
|
||||
}
|
||||
|
||||
public static void register(ResourceLocation block) {
|
||||
public boolean isOnIncompatibleTrack(Carriage carriage, boolean leading) {
|
||||
TravellingPoint point = leading ? carriage.getLeadingPoint() : carriage.getTrailingPoint();
|
||||
CarriageBogey bogey = leading ? carriage.leadingBogey() : carriage.trailingBogey();
|
||||
return point.edge.getTrackMaterial().trackType != getTrackType(bogey.getStyle());
|
||||
}
|
||||
|
||||
public Set<TrackMaterial.TrackType> 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<StandardBo
|
|||
|
||||
public abstract double getWheelRadius();
|
||||
|
||||
public abstract Vec3 getConnectorAnchorOffset();
|
||||
public Vec3 getConnectorAnchorOffset(boolean upsideDown) {
|
||||
return getConnectorAnchorOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be implemented, but not called directly
|
||||
*/
|
||||
protected abstract Vec3 getConnectorAnchorOffset();
|
||||
|
||||
public boolean allowsSingleBogeyCarriage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract BogeyStyle getDefaultStyle();
|
||||
|
||||
/**
|
||||
* Legacy system doesn't capture bogey tile entities when constructing a train
|
||||
*/
|
||||
public boolean captureTileEntityForTrain() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks,
|
||||
MultiBufferSource buffers, int light, int overlay, StandardBogeyTileEntity sbte) {
|
||||
BogeyStyle style = sbte.getStyle();
|
||||
public void render(@Nullable BlockState state, boolean upsideDown, float wheelAngle, PoseStack ms, float partialTicks,
|
||||
MultiBufferSource buffers, int light, int overlay, BogeyStyle style, CompoundTag bogeyData) {
|
||||
if (style == null)
|
||||
style = getDefaultStyle();
|
||||
|
||||
final Optional<BogeyRenderer.CommonRenderer> commonRenderer
|
||||
= style.getInWorldCommonRenderInstance();
|
||||
final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize());
|
||||
|
@ -120,14 +160,17 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
|
|||
}
|
||||
ms.translate(0, -1.5 - 1 / 128f, 0);
|
||||
VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped());
|
||||
renderer.render(sbte.getBogeyData(), wheelAngle, ms, light, vb);
|
||||
if (bogeyData == null)
|
||||
bogeyData = new CompoundTag();
|
||||
renderer.render(upsideDown, bogeyData, wheelAngle, ms, light, vb, state == null);
|
||||
CompoundTag finalBogeyData = bogeyData;
|
||||
commonRenderer.ifPresent(common ->
|
||||
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<StandardBo
|
|||
|
||||
if (!player.isShiftKeyDown() && stack.is(AllItems.WRENCH.get()) && !player.getCooldowns().isOnCooldown(stack.getItem())
|
||||
&& AllBogeyStyles.BOGEY_STYLES.size() > 1) {
|
||||
Collection<BogeyStyle> 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<BogeySizes.BogeySize> validSizes = style.validSizes();
|
||||
|
||||
for (int i = 0; i < BogeySizes.count(); i++) {
|
||||
|
@ -181,17 +224,17 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
|
|||
sbte.setBogeyData(sbte.getBogeyData().merge(defaultData));
|
||||
|
||||
if (size == getSize()) {
|
||||
player.displayClientMessage(Lang.translateDirect("create.bogey.style.updated_style")
|
||||
.append(": " + style.displayName), true);
|
||||
player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style")
|
||||
.append(": ").append(style.displayName), true);
|
||||
} else {
|
||||
CompoundTag oldData = sbte.getBogeyData();
|
||||
level.setBlock(pos, this.getStateOfSize(sbte, size), 3);
|
||||
BlockEntity newBlockEntity = level.getBlockEntity(pos);
|
||||
if (!(newBlockEntity instanceof StandardBogeyTileEntity newTileEntity))
|
||||
if (!(newBlockEntity instanceof AbstractBogeyTileEntity newTileEntity))
|
||||
return InteractionResult.FAIL;
|
||||
newTileEntity.setBogeyData(oldData);
|
||||
player.displayClientMessage(Lang.translateDirect("create.bogey.style.updated_style_and_size")
|
||||
.append(": " + style.displayName), true);
|
||||
player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style_and_size")
|
||||
.append(": ").append(style.displayName), true);
|
||||
}
|
||||
|
||||
return InteractionResult.CONSUME;
|
||||
|
@ -200,28 +243,34 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
|
|||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* If, instead of using the style-based cycling system you prefer to use separate blocks, return them from this method
|
||||
*/
|
||||
protected List<ResourceLocation> getBogeyBlockCycle() {
|
||||
return BOGEYS;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) {
|
||||
Block block = state.getBlock();
|
||||
int indexOf = BOGEYS.indexOf(RegisteredObjects.getKeyOrThrow(block));
|
||||
List<ResourceLocation> 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<StandardBo
|
|||
|
||||
public BlockState getNextSize(Level level, BlockPos pos) {
|
||||
BlockEntity te = level.getBlockEntity(pos);
|
||||
if (te instanceof StandardBogeyTileEntity sbte)
|
||||
if (te instanceof AbstractBogeyTileEntity sbte)
|
||||
return this.getNextSize(sbte);
|
||||
return level.getBlockState(pos);
|
||||
}
|
||||
|
||||
public BlockState getNextSize(StandardBogeyTileEntity sbte) {
|
||||
/**
|
||||
* List of BlockState Properties to copy between sizes
|
||||
*/
|
||||
public List<Property<?>> propertiesToCopy() {
|
||||
return ImmutableList.of(WATERLOGGED, AXIS);
|
||||
}
|
||||
|
||||
// generic method needed to satisfy Property and BlockState's generic requirements
|
||||
private <V extends Comparable<V>> BlockState copyProperty(BlockState source, BlockState target, Property<V> 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<BogeyStyle> allStyles = AllBogeyStyles.BOGEY_STYLES.values();
|
||||
Collection<BogeyStyle> allStyles = style.getCycleGroup().values();
|
||||
if (allStyles.size() <= 1)
|
||||
return style;
|
||||
List<BogeyStyle> list = new ArrayList<>(allStyles);
|
||||
|
@ -279,4 +346,16 @@ public abstract class AbstractBogeyBlock extends Block implements ITE<StandardBo
|
|||
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
|
||||
return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack());
|
||||
}
|
||||
|
||||
public boolean canBeUpsideDown() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUpsideDown(BlockState state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BlockState getVersion(BlockState base, boolean upsideDown) {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ public abstract class BogeyRenderer {
|
|||
*
|
||||
* @param model The key for the model data to instantiate or retrieve
|
||||
* @param ms The posestack used for contraption model data
|
||||
* @param inContraption The type of model needed
|
||||
* @param inInstancedContraption The type of model needed
|
||||
* @param size The amount of models needed
|
||||
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||
*/
|
||||
public Transform<?>[] 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T extends BlockEntity> 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<DiscoveredLocation> list,
|
||||
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
||||
Function<Boolean, ResourceKey<Level>> dimensionFactory, Vec3 axis, BezierConnection viaTurn) {
|
||||
Function<Boolean, ResourceKey<Level>> dimensionFactory, Vec3 axis, BezierConnection viaTurn, BiFunction<Boolean, Vec3, TrackMaterial> 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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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<Integer> ids = pair.getFirst();
|
||||
Couple<Integer> 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<Integer> 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);
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import net.minecraft.world.phys.Vec3;
|
|||
public class TrackGraphSyncPacket extends TrackGraphPacket {
|
||||
|
||||
Map<Integer, Pair<TrackNodeLocation, Vec3>> addedNodes;
|
||||
List<Pair<Couple<Integer>, BezierConnection>> addedEdges;
|
||||
List<Pair<Pair<Couple<Integer>, TrackMaterial>, BezierConnection>> addedEdges;
|
||||
List<Integer> removedNodes;
|
||||
List<TrackEdgePoint> addedEdgePoints;
|
||||
List<UUID> 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<Couple<Integer>, BezierConnection> pair : addedEdges) {
|
||||
Couple<TrackNode> nodes = pair.getFirst()
|
||||
for (Pair<Pair<Couple<Integer>, TrackMaterial>, BezierConnection> pair : addedEdges) {
|
||||
Couple<TrackNode> 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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<Supplier<? extends CommonRenderer>> commonRendererFactory;
|
||||
|
||||
public final ResourceLocation name;
|
||||
public final ResourceLocation cycleGroup;
|
||||
private final Optional<CommonRenderer> commonRenderer;
|
||||
private final Map<BogeySizes.BogeySize, SizeData> 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<BogeySizes.BogeySize, SizeData> sizes, Optional<Supplier<? extends CommonRenderer>> commonRenderer) {
|
||||
public BogeyStyle(ResourceLocation name, ResourceLocation cycleGroup, Component displayName, ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle,
|
||||
CompoundTag defaultData, Map<BogeySizes.BogeySize, SizeData> sizes, Optional<CommonRenderer> 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<ResourceLocation, BogeyStyle> getCycleGroup() {
|
||||
return AllBogeyStyles.getCycleGroup(cycleGroup);
|
||||
}
|
||||
|
||||
public Block getNextBlock(BogeySizes.BogeySize currentSize) {
|
||||
return Stream.iterate(currentSize.increment(), BogeySizes.BogeySize::increment)
|
||||
|
|
|
@ -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<Level> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<TravellingPoint> 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<TravellingPoint> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -88,7 +88,13 @@ public class CarriageSounds {
|
|||
double distance2 = toBogey2.length();
|
||||
|
||||
Couple<CarriageBogey> bogeys = entity.getCarriage().bogeys;
|
||||
closestBogeySound = bogeys.get(distance1 > distance2).getStyle().getSoundType();
|
||||
CarriageBogey relevantBogey = bogeys.get(distance1 > distance2);
|
||||
if (relevantBogey == null) {
|
||||
relevantBogey = bogeys.getFirst();
|
||||
}
|
||||
if (relevantBogey != null) {
|
||||
closestBogeySound = relevantBogey.getStyle().getSoundType();
|
||||
}
|
||||
|
||||
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
|
||||
double distance = Math.min(distance1, distance2);
|
||||
|
|
|
@ -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<TrackMaterial.TrackType> 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<TrackEdge, Integer> 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<TrackNode, TrackEdge> target : validTargets) {
|
||||
if (!validTypes.contains(target.getValue().getTrackMaterial().trackType))
|
||||
continue;
|
||||
TrackNode newNode = target.getKey();
|
||||
TrackEdge newEdge = target.getValue();
|
||||
double newDistance = newEdge.getLength() + distance;
|
||||
|
|
|
@ -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<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
|
||||
MutableObject<UUID> prevGroup = new MutableObject<>(null);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Pair<Couple<TrackNode>, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<GraphLocation> 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<TrackNode> 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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<StandardBogeyTileEntity>, ProperWaterloggedBlock, ISpecialBlockItemRequirement {
|
||||
public class StandardBogeyBlock extends AbstractBogeyBlock<StandardBogeyTileEntity> implements ITE<StandardBogeyTileEntity>, 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<Standa
|
|||
return new Vec3(0, 7 / 32f, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BogeyStyle getDefaultStyle() {
|
||||
return AllBogeyStyles.STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
|
||||
Player player) {
|
||||
|
|
|
@ -1,112 +1,19 @@
|
|||
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 class StandardBogeyTileEntity extends CachedRenderBBTileEntity {
|
||||
public static String BOGEY_STYLE_KEY = "BogeyStyle";
|
||||
public static String BOGEY_DATA_KEY = "BogeyData";
|
||||
|
||||
private CompoundTag bogeyData;
|
||||
|
||||
public class StandardBogeyTileEntity extends AbstractBogeyTileEntity {
|
||||
public StandardBogeyTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BlockPos, BezierConnection> 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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -32,7 +32,7 @@ public class RotateTool extends PlacementToolBase {
|
|||
|
||||
line.getParams()
|
||||
.disableCull()
|
||||
.disableLineNormals()
|
||||
.disableNormals()
|
||||
.colored(0xdddddd)
|
||||
.lineWidth(1 / 16f);
|
||||
line.set(start, end)
|
||||
|
|
|
@ -60,6 +60,7 @@ public class AllCommands {
|
|||
.then(CameraDistanceCommand.register())
|
||||
.then(CameraAngleCommand.register())
|
||||
.then(FlySpeedCommand.register())
|
||||
//.then(DebugValueCommand.register())
|
||||
//.then(KillTPSCommand.register())
|
||||
.build();
|
||||
|
||||
|
|
|
@ -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<CommandSourceStack, ?> register() {
|
||||
return Commands.literal("debugValue")
|
||||
.requires(cs -> cs.hasPermission(4))
|
||||
.then(Commands.argument("value", FloatArgumentType.floatArg())
|
||||
.executes((ctx) -> {
|
||||
value = FloatArgumentType.getFloat(ctx, "value");
|
||||
ctx.getSource().sendSuccess(Components.literal("Set value to: "+value), true);
|
||||
return 1;
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ public class BuilderTransformers {
|
|||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static <B extends StandardBogeyBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> 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 <B extends TrapDoorBlock, P> NonNullUnaryOperator<BlockBuilder<B, P>> trapdoor(boolean orientable) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<AllSpecialTextures> optionalFaceTexture = highlighted ? params.hightlightedFaceTexture : params.faceTexture;
|
||||
Optional<AllSpecialTextures> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<BlockPos> positions) {
|
||||
public BlockClusterOutline(Iterable<BlockPos> 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<AllSpecialTextures> optionalFaceTexture = params.faceTexture;
|
||||
if (!optionalFaceTexture.isPresent())
|
||||
Optional<AllSpecialTextures> 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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<BlockPos> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue