Speed limit
- Added a means to control the throttle/max speed of a controlled train - Train Controls now show an xp bar overlay
This commit is contained in:
parent
70b8d2e998
commit
091812b42d
14 changed files with 297 additions and 165 deletions
|
@ -2,6 +2,7 @@ package com.simibubi.create;
|
|||
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueSelectionHandler;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.SBBContraptionManager;
|
||||
import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer;
|
||||
|
@ -102,6 +103,7 @@ public class CreateClient {
|
|||
private static void registerOverlays() {
|
||||
// Register overlays in reverse order
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.AIR_LEVEL_ELEMENT, "Create's Remaining Air", CopperBacktankArmorLayer.REMAINING_AIR_OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.EXPERIENCE_BAR_ELEMENT, "Create's Train Driver HUD", TrainHUD.OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Toolboxes", ToolboxHandlerClient.OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Goggle Information", GoggleOverlayRenderer.OVERLAY);
|
||||
OverlayRegistry.registerOverlayAbove(ForgeIngameGui.HOTBAR_ELEMENT, "Create's Blueprints", BlueprintOverlayRenderer.OVERLAY);
|
||||
|
|
|
@ -106,11 +106,11 @@ public class ControlsHandler {
|
|||
|
||||
// Keepalive Pressed Keys
|
||||
if (packetCooldown == 0) {
|
||||
if (!pressedKeys.isEmpty()) {
|
||||
// if (!pressedKeys.isEmpty()) {
|
||||
AllPackets.channel
|
||||
.sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos, false));
|
||||
packetCooldown = PACKET_RATE;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
currentlyPressed = pressedKeys;
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import net.minecraftforge.client.gui.ForgeIngameGui;
|
||||
import net.minecraftforge.client.gui.IIngameOverlay;
|
||||
|
||||
public class TrainHUD {
|
||||
|
||||
public static final IIngameOverlay OVERLAY = TrainHUD::renderOverlay;
|
||||
|
||||
static LerpedFloat displayedSpeed = LerpedFloat.linear();
|
||||
static LerpedFloat displayedThrottle = LerpedFloat.linear();
|
||||
|
||||
static Double editedThrottle = null;
|
||||
static int hudPacketCooldown = 5;
|
||||
|
||||
public static void tick() {
|
||||
Carriage carriage = getCarriage();
|
||||
if (carriage == null)
|
||||
return;
|
||||
|
||||
Train train = carriage.train;
|
||||
double value =
|
||||
Math.abs(train.speed) / (train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF());
|
||||
value = Mth.clamp(value + 0.05f, 0, 1);
|
||||
displayedSpeed.chase((int) (value * 18) / 18f, .5f, Chaser.EXP);
|
||||
displayedSpeed.tickChaser();
|
||||
displayedThrottle.chase(editedThrottle != null ? editedThrottle : train.throttle, .75f, Chaser.EXP);
|
||||
displayedThrottle.tickChaser();
|
||||
|
||||
if (editedThrottle == null)
|
||||
return;
|
||||
if (Mth.equal(editedThrottle, train.throttle)) {
|
||||
editedThrottle = null;
|
||||
hudPacketCooldown = 5;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hudPacketCooldown-- > 0)
|
||||
return;
|
||||
AllPackets.channel.sendToServer(new TrainHUDUpdatePacket.Serverbound(train, editedThrottle));
|
||||
hudPacketCooldown = 5;
|
||||
}
|
||||
|
||||
private static Carriage getCarriage() {
|
||||
if (!(ControlsHandler.entityRef.get() instanceof CarriageContraptionEntity cce))
|
||||
return null;
|
||||
return cce.getCarriage();
|
||||
}
|
||||
|
||||
public static void renderOverlay(ForgeIngameGui gui, PoseStack poseStack, float partialTicks, int width,
|
||||
int height) {
|
||||
if (!(ControlsHandler.entityRef.get() instanceof CarriageContraptionEntity cce))
|
||||
return;
|
||||
Carriage carriage = cce.getCarriage();
|
||||
if (carriage == null)
|
||||
return;
|
||||
Entity cameraEntity = Minecraft.getInstance()
|
||||
.getCameraEntity();
|
||||
if (cameraEntity == null)
|
||||
return;
|
||||
BlockPos localPos = ControlsHandler.controlsPos;
|
||||
if (localPos == null)
|
||||
return;
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(width / 2 - 91, height - 29, 0);
|
||||
|
||||
// Speed, Throttle
|
||||
|
||||
AllGuiTextures.TRAIN_HUD_FRAME.render(poseStack, -2, 1);
|
||||
AllGuiTextures.TRAIN_HUD_SPEED_BG.render(poseStack, 0, 0);
|
||||
|
||||
int w = (int) (AllGuiTextures.TRAIN_HUD_SPEED.width * displayedSpeed.getValue(partialTicks));
|
||||
int h = AllGuiTextures.TRAIN_HUD_SPEED.height;
|
||||
|
||||
AllGuiTextures.TRAIN_HUD_SPEED.bind();
|
||||
GuiComponent.blit(poseStack, 0, 0, 0, AllGuiTextures.TRAIN_HUD_SPEED.startX,
|
||||
AllGuiTextures.TRAIN_HUD_SPEED.startY, w, h, 256, 256);
|
||||
|
||||
AllGuiTextures.TRAIN_HUD_DIRECTION.render(poseStack, 77, -20);
|
||||
|
||||
w = (int) (AllGuiTextures.TRAIN_HUD_THROTTLE.width * (1 - displayedThrottle.getValue(partialTicks)));
|
||||
AllGuiTextures.TRAIN_HUD_THROTTLE.bind();
|
||||
int invW = AllGuiTextures.TRAIN_HUD_THROTTLE.width - w;
|
||||
GuiComponent.blit(poseStack, invW, 0, 0, AllGuiTextures.TRAIN_HUD_THROTTLE.startX + invW,
|
||||
AllGuiTextures.TRAIN_HUD_THROTTLE.startY, w, h, 256, 256);
|
||||
AllGuiTextures.TRAIN_HUD_THROTTLE_POINTER.render(poseStack,
|
||||
Math.max(1, AllGuiTextures.TRAIN_HUD_THROTTLE.width - w) - 3, -2);
|
||||
|
||||
// Direction
|
||||
|
||||
StructureBlockInfo info = cce.getContraption()
|
||||
.getBlocks()
|
||||
.get(localPos);
|
||||
Direction initialOrientation = cce.getInitialOrientation()
|
||||
.getCounterClockWise();
|
||||
boolean inverted = false;
|
||||
if (info != null && info.state.hasProperty(ControlsBlock.FACING))
|
||||
inverted = !info.state.getValue(ControlsBlock.FACING)
|
||||
.equals(initialOrientation);
|
||||
|
||||
boolean reversing = ControlsHandler.currentlyPressed.contains(1);
|
||||
inverted ^= reversing;
|
||||
int angleOffset = (ControlsHandler.currentlyPressed.contains(2) ? -45 : 0)
|
||||
+ (ControlsHandler.currentlyPressed.contains(3) ? 45 : 0);
|
||||
if (reversing)
|
||||
angleOffset *= -1;
|
||||
|
||||
float snapSize = 22.5f;
|
||||
float diff = AngleHelper.getShortestAngleDiff(cameraEntity.getYRot(), cce.yaw) + (inverted ? -90 : 90);
|
||||
if (Math.abs(diff) < 60)
|
||||
diff = 0;
|
||||
|
||||
float angle = diff + angleOffset;
|
||||
float snappedAngle = (snapSize * Math.round(angle / snapSize)) % 360f;
|
||||
|
||||
poseStack.translate(91, -9, 0);
|
||||
poseStack.scale(0.925f, 0.925f, 1);
|
||||
PlacementHelpers.textured(poseStack, 0, 0, 1, snappedAngle);
|
||||
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
public static boolean onScroll(double delta) {
|
||||
Carriage carriage = getCarriage();
|
||||
if (carriage == null)
|
||||
return false;
|
||||
|
||||
double prevThrottle = editedThrottle == null ? carriage.train.throttle : editedThrottle;
|
||||
editedThrottle = Mth.clamp(prevThrottle + (delta > 0 ? 1 : -1) / 18f, 1 / 18f, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
|
||||
public class TrainHUDUpdatePacket extends SimplePacketBase {
|
||||
|
||||
UUID trainId;
|
||||
|
||||
Double throttle;
|
||||
double speed;
|
||||
int fuelTicks;
|
||||
|
||||
public TrainHUDUpdatePacket() {}
|
||||
|
||||
public TrainHUDUpdatePacket(Train train) {
|
||||
trainId = train.id;
|
||||
throttle = train.throttle;
|
||||
speed = train.speedBeforeStall == null ? train.speed : train.speedBeforeStall;
|
||||
fuelTicks = train.fuelTicks;
|
||||
}
|
||||
|
||||
public TrainHUDUpdatePacket(FriendlyByteBuf buffer) {
|
||||
trainId = buffer.readUUID();
|
||||
if (buffer.readBoolean())
|
||||
throttle = buffer.readDouble();
|
||||
speed = buffer.readDouble();
|
||||
fuelTicks = buffer.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeUUID(trainId);
|
||||
buffer.writeBoolean(throttle != null);
|
||||
if (throttle != null)
|
||||
buffer.writeDouble(throttle);
|
||||
buffer.writeDouble(speed);
|
||||
buffer.writeInt(fuelTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Supplier<Context> context) {
|
||||
Context c = context.get();
|
||||
c.enqueueWork(() -> {
|
||||
ServerPlayer sender = c.getSender();
|
||||
boolean clientSide = sender == null;
|
||||
Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId);
|
||||
if (train == null)
|
||||
return;
|
||||
|
||||
if (throttle != null)
|
||||
train.throttle = throttle;
|
||||
if (clientSide) {
|
||||
train.speed = speed;
|
||||
train.fuelTicks = fuelTicks;
|
||||
}
|
||||
|
||||
});
|
||||
c.setPacketHandled(true);
|
||||
}
|
||||
|
||||
public static class Serverbound extends TrainHUDUpdatePacket {
|
||||
|
||||
public Serverbound(FriendlyByteBuf buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
public Serverbound(Train train, Double sendThrottle) {
|
||||
trainId = train.id;
|
||||
throttle = sendThrottle;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,6 @@ import java.util.UUID;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.jozufozu.flywheel.repack.joml.Math;
|
||||
import com.simibubi.create.AllEntityDataSerializers;
|
||||
import com.simibubi.create.AllEntityTypes;
|
||||
import com.simibubi.create.Create;
|
||||
|
@ -21,6 +20,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUDUpdatePacket;
|
||||
import com.simibubi.create.content.contraptions.particle.CubeParticleData;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity;
|
||||
|
@ -45,6 +45,7 @@ import net.minecraft.network.chat.TextComponent;
|
|||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
|
@ -279,7 +280,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
if (sounds == null)
|
||||
sounds = new CarriageSounds(this);
|
||||
sounds.tick(dce);
|
||||
|
||||
|
||||
if (particles == null)
|
||||
particles = new CarriageParticles(this);
|
||||
particles.tick(dce);
|
||||
|
@ -503,6 +504,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
}
|
||||
|
||||
double navDistanceTotal = 0;
|
||||
int hudPacketCooldown = 0;
|
||||
|
||||
@Override
|
||||
public boolean control(BlockPos controlsLocalPos, Collection<Integer> heldControls, Player player) {
|
||||
|
@ -527,6 +529,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
inverted = !info.state.getValue(ControlsBlock.FACING)
|
||||
.equals(initialOrientation);
|
||||
|
||||
if (hudPacketCooldown-- <= 0 && player instanceof ServerPlayer sp) {
|
||||
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), new TrainHUDUpdatePacket(carriage.train));
|
||||
hudPacketCooldown = 5;
|
||||
}
|
||||
|
||||
int targetSpeed = 0;
|
||||
if (heldControls.contains(0))
|
||||
targetSpeed++;
|
||||
|
@ -584,6 +591,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
int targetColor = arrived ? 0x00_91EA44 : 0x00_ffffff;
|
||||
player.displayClientMessage(greenComponent.withStyle(st -> st.withColor(mixedColor))
|
||||
.append(whiteComponent.withStyle(st -> st.withColor(targetColor))), true);
|
||||
carriage.train.manualTick = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -609,14 +617,15 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
targetSteer < 0 ? SteerDirection.RIGHT : targetSteer > 0 ? SteerDirection.LEFT : SteerDirection.NONE;
|
||||
|
||||
double topSpeed = carriage.train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF();
|
||||
double cappedTopSpeed = topSpeed * carriage.train.throttle;
|
||||
|
||||
if (carriage.getLeadingPoint().edge != null && carriage.getLeadingPoint().edge.isTurn()
|
||||
|| carriage.getTrailingPoint().edge != null && carriage.getTrailingPoint().edge.isTurn())
|
||||
topSpeed = carriage.train.maxTurnSpeed();
|
||||
|
||||
carriage.train.targetSpeed = topSpeed * targetSpeed;
|
||||
if (slow)
|
||||
carriage.train.targetSpeed /= 6;
|
||||
topSpeed /= 4;
|
||||
carriage.train.targetSpeed = Math.min(topSpeed, cappedTopSpeed) * targetSpeed;
|
||||
|
||||
boolean counteringAcceleration = Math.abs(Math.signum(targetSpeed) - Math.signum(carriage.train.speed)) > 1.5f;
|
||||
carriage.train.manualTick = true;
|
||||
|
|
|
@ -17,7 +17,6 @@ import javax.annotation.Nullable;
|
|||
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.jozufozu.flywheel.repack.joml.Math;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.logistics.trains.DimensionPalette;
|
||||
import com.simibubi.create.content.logistics.trains.TrackEdge;
|
||||
|
@ -158,8 +157,8 @@ public class Navigation {
|
|||
|
||||
boolean primary = entering.equals(signal.groups.getFirst());
|
||||
boolean crossSignal = signal.types.get(primary) == SignalType.CROSS_SIGNAL;
|
||||
boolean occupied =
|
||||
signal.isForcedRed(nodes.getSecond()) || signalEdgeGroup.isOccupiedUnless(train);
|
||||
boolean occupied = !train.manualTick
|
||||
&& (signal.isForcedRed(nodes.getSecond()) || signalEdgeGroup.isOccupiedUnless(train));
|
||||
|
||||
if (!crossSignalTracked) {
|
||||
if (crossSignal) { // Now entering cross signal path
|
||||
|
@ -244,7 +243,6 @@ public class Navigation {
|
|||
train.burnFuel();
|
||||
|
||||
double topSpeed = train.maxSpeed();
|
||||
double turnTopSpeed = train.maxTurnSpeed();
|
||||
|
||||
if (targetDistance < 10) {
|
||||
double target = topSpeed * ((targetDistance) / 10);
|
||||
|
@ -253,6 +251,9 @@ public class Navigation {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
topSpeed *= train.throttle;
|
||||
double turnTopSpeed = Math.min(topSpeed, train.maxTurnSpeed());
|
||||
|
||||
double targetSpeed = targetDistance > brakingDistance ? topSpeed * speedMod : 0;
|
||||
|
||||
|
@ -279,6 +280,8 @@ public class Navigation {
|
|||
}
|
||||
|
||||
private boolean currentSignalResolved() {
|
||||
if (train.manualTick)
|
||||
return true;
|
||||
if (distanceToDestination < .5f)
|
||||
return true;
|
||||
SignalBoundary signal = train.graph.getPoint(EdgePointType.SIGNAL, waitingForSignal.getFirst());
|
||||
|
|
|
@ -77,6 +77,9 @@ public class Train {
|
|||
public double speed = 0;
|
||||
public double targetSpeed = 0;
|
||||
public Double speedBeforeStall = null;
|
||||
|
||||
public double throttle = 1;
|
||||
public boolean honk = false;
|
||||
|
||||
public UUID id;
|
||||
public UUID owner;
|
||||
|
@ -886,15 +889,16 @@ public class Train {
|
|||
}
|
||||
|
||||
public void approachTargetSpeed(float accelerationMod) {
|
||||
if (Mth.equal(targetSpeed, speed))
|
||||
double actualTarget = targetSpeed;
|
||||
if (Mth.equal(actualTarget, speed))
|
||||
return;
|
||||
if (manualTick)
|
||||
leaveStation();
|
||||
double acceleration = acceleration();
|
||||
if (speed < targetSpeed)
|
||||
speed = Math.min(speed + acceleration * accelerationMod, targetSpeed);
|
||||
else if (speed > targetSpeed)
|
||||
speed = Math.max(speed - acceleration * accelerationMod, targetSpeed);
|
||||
if (speed < actualTarget)
|
||||
speed = Math.min(speed + acceleration * accelerationMod, actualTarget);
|
||||
else if (speed > actualTarget)
|
||||
speed = Math.max(speed - acceleration * accelerationMod, actualTarget);
|
||||
}
|
||||
|
||||
public void collectInitiallyOccupiedSignalBlocks() {
|
||||
|
@ -1060,6 +1064,7 @@ public class Train {
|
|||
tag.putIntArray("CarriageSpacing", carriageSpacing);
|
||||
tag.putBoolean("DoubleEnded", doubleEnded);
|
||||
tag.putDouble("Speed", speed);
|
||||
tag.putDouble("Throttle", throttle);
|
||||
if (speedBeforeStall != null)
|
||||
tag.putDouble("SpeedBeforeStall", speedBeforeStall);
|
||||
tag.putInt("Fuel", fuelTicks);
|
||||
|
@ -1113,6 +1118,7 @@ public class Train {
|
|||
Train train = new Train(id, owner, graph, carriages, carriageSpacing, doubleEnded);
|
||||
|
||||
train.speed = tag.getDouble("Speed");
|
||||
train.throttle = tag.getDouble("Throttle");
|
||||
if (tag.contains("SpeedBeforeStall"))
|
||||
train.speedBeforeStall = tag.getDouble("SpeedBeforeStall");
|
||||
train.targetSpeed = tag.getDouble("TargetSpeed");
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
package com.simibubi.create.content.logistics.trains.track;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainRelocator;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.HitResult.Type;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class TrackRemoval {
|
||||
|
||||
static BlockPos startPos;
|
||||
static BlockPos hoveringPos;
|
||||
static Set<BlockPos> toRemove;
|
||||
|
||||
// TODO localisation
|
||||
|
||||
public static void sneakWrenched(BlockPos pos) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (startPos != null) {
|
||||
startPos = null;
|
||||
player.displayClientMessage(new TextComponent("Track removal aborted").withStyle(ChatFormatting.RED), true);
|
||||
return;
|
||||
}
|
||||
startPos = pos;
|
||||
}
|
||||
|
||||
public static void wrenched(BlockPos pos) {
|
||||
if (startPos == null || hoveringPos == null || toRemove == null)
|
||||
return;
|
||||
if (TrainRelocator.isRelocating())
|
||||
return;
|
||||
AllPackets.channel.sendToServer(new TrackRemovalPacket(toRemove));
|
||||
startPos = null;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public static void clientTick() {
|
||||
if (startPos == null)
|
||||
return;
|
||||
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
ItemStack stack = player.getMainHandItem();
|
||||
HitResult hitResult = Minecraft.getInstance().hitResult;
|
||||
|
||||
if (hitResult == null)
|
||||
return;
|
||||
if (hitResult.getType() != Type.BLOCK)
|
||||
return;
|
||||
|
||||
if (!AllItems.WRENCH.isIn(stack)) {
|
||||
hoveringPos = null;
|
||||
startPos = null;
|
||||
player.displayClientMessage(new TextComponent("Track removal aborted").withStyle(ChatFormatting.RED), true);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockHitResult result = (BlockHitResult) hitResult;
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
Level level = player.level;
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (!(blockState.getBlock()instanceof ITrackBlock track)) {
|
||||
player.displayClientMessage(new TextComponent("Select a second track piece, Unequip Wrench to abort"),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockPos.equals(hoveringPos)) {
|
||||
if (hoveringPos.equals(startPos)) {
|
||||
player.displayClientMessage(
|
||||
new TextComponent("Starting point selected. Right-Click a second Track piece"), true);
|
||||
} else if (toRemove == null) {
|
||||
player.displayClientMessage(new TextComponent("Starting point not reachable, Sneak-Click to abort")
|
||||
.withStyle(ChatFormatting.RED), true);
|
||||
} else
|
||||
player.displayClientMessage(new TextComponent("Right-Click to confirm").withStyle(ChatFormatting.GREEN),
|
||||
true);
|
||||
|
||||
//
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hoveringPos = blockPos;
|
||||
toRemove = new HashSet<>();
|
||||
|
||||
List<BlockPos> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
|
||||
if (search(level, hoveringPos, frontier, visited, 0)) {
|
||||
toRemove.add(hoveringPos);
|
||||
toRemove.add(startPos);
|
||||
return;
|
||||
}
|
||||
|
||||
toRemove = null;
|
||||
}
|
||||
|
||||
private static boolean search(Level level, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
|
||||
int depth) {
|
||||
if (pos.equals(startPos))
|
||||
return true;
|
||||
if (depth > 32)
|
||||
return false;
|
||||
if (!visited.add(pos))
|
||||
return false;
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
if (!(blockState.getBlock()instanceof ITrackBlock track))
|
||||
return false;
|
||||
for (DiscoveredLocation discoveredLocation : track.getConnected(level, pos, blockState, false, null)) {
|
||||
for (BlockPos blockPos : discoveredLocation.allAdjacent()) {
|
||||
if (!search(level, blockPos, frontier, visited, depth + 1))
|
||||
continue;
|
||||
toRemove.add(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,7 @@ import com.simibubi.create.content.contraptions.components.steam.SteamEngineBloc
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsHandler;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics;
|
||||
|
@ -44,7 +45,6 @@ import com.simibubi.create.content.logistics.trains.management.schedule.TrainHat
|
|||
import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackPlacement;
|
||||
import com.simibubi.create.content.logistics.trains.track.TrackRemoval;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
|
||||
import com.simibubi.create.foundation.fluid.FluidHelper;
|
||||
|
@ -164,11 +164,11 @@ public class ClientEvents {
|
|||
ToolboxHandlerClient.clientTick();
|
||||
TrackTargetingClient.clientTick();
|
||||
TrackPlacement.clientTick();
|
||||
TrackRemoval.clientTick();
|
||||
TrainRelocator.clientTick();
|
||||
DisplayLinkBlockItem.clientTick();
|
||||
CurvedTrackInteraction.clientTick();
|
||||
CameraDistanceModifier.tick();
|
||||
TrainHUD.tick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.simibubi.create.events;
|
||||
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD;
|
||||
import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient;
|
||||
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
|
||||
import com.simibubi.create.content.logistics.trains.entity.TrainRelocator;
|
||||
|
@ -42,7 +43,7 @@ public class InputEvents {
|
|||
// CollisionDebugger.onScroll(delta);
|
||||
boolean cancelled = CreateClient.SCHEMATIC_HANDLER.mouseScrolled(delta)
|
||||
|| CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta)
|
||||
|| ScrollValueHandler.onScroll(delta);
|
||||
|| ScrollValueHandler.onScroll(delta) || TrainHUD.onScroll(delta);
|
||||
event.setCanceled(cancelled);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,13 @@ public enum AllGuiTextures implements ScreenElement {
|
|||
|
||||
SPEECH_TOOLTIP_BACKGROUND("widgets", 0, 24, 8, 8),
|
||||
SPEECH_TOOLTIP_COLOR("widgets", 8, 24, 8, 8),
|
||||
|
||||
TRAIN_HUD_SPEED_BG("widgets", 0, 190, 182, 5),
|
||||
TRAIN_HUD_SPEED("widgets", 0, 185, 182, 5),
|
||||
TRAIN_HUD_THROTTLE("widgets", 0, 195, 182, 5),
|
||||
TRAIN_HUD_THROTTLE_POINTER("widgets", 0, 209, 6, 9),
|
||||
TRAIN_HUD_FRAME("widgets", 0, 200, 186, 7),
|
||||
TRAIN_HUD_DIRECTION("widgets", 77, 165, 28, 20),
|
||||
|
||||
// PlacementIndicator
|
||||
PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256);
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.glu
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueSelectionPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInputPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUDUpdatePacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
|
||||
|
@ -94,7 +95,7 @@ public enum AllPackets {
|
|||
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new,
|
||||
PLAY_TO_SERVER),
|
||||
PLAY_TO_SERVER),
|
||||
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER),
|
||||
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER),
|
||||
CLEAR_CONTAINER(ClearContainerPacket.class, ClearContainerPacket::new, PLAY_TO_SERVER),
|
||||
|
@ -114,10 +115,12 @@ public enum AllPackets {
|
|||
EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER),
|
||||
LINKED_CONTROLLER_INPUT(LinkedControllerInputPacket.class, LinkedControllerInputPacket::new, PLAY_TO_SERVER),
|
||||
LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER),
|
||||
LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::new, PLAY_TO_SERVER),
|
||||
LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::new,
|
||||
PLAY_TO_SERVER),
|
||||
C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER),
|
||||
SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER),
|
||||
BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, PLAY_TO_SERVER),
|
||||
BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new,
|
||||
PLAY_TO_SERVER),
|
||||
CONFIGURE_SYMMETRY_WAND(ConfigureSymmetryWandPacket.class, ConfigureSymmetryWandPacket::new, PLAY_TO_SERVER),
|
||||
CONFIGURE_WORLDSHAPER(ConfigureWorldshaperPacket.class, ConfigureWorldshaperPacket::new, PLAY_TO_SERVER),
|
||||
TOOLBOX_EQUIP(ToolboxEquipPacket.class, ToolboxEquipPacket::new, PLAY_TO_SERVER),
|
||||
|
@ -135,6 +138,7 @@ public enum AllPackets {
|
|||
GLUE_IN_AREA(SuperGlueSelectionPacket.class, SuperGlueSelectionPacket::new, PLAY_TO_SERVER),
|
||||
GLUE_REMOVED(SuperGlueRemovalPacket.class, SuperGlueRemovalPacket::new, PLAY_TO_SERVER),
|
||||
TRAIN_COLLISION(TrainCollisionPacket.class, TrainCollisionPacket::new, PLAY_TO_SERVER),
|
||||
C_TRAIN_HUD(TrainHUDUpdatePacket.Serverbound.class, TrainHUDUpdatePacket.Serverbound::new, PLAY_TO_SERVER),
|
||||
|
||||
// Server to Client
|
||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
|
||||
|
@ -156,14 +160,17 @@ public enum AllPackets {
|
|||
FUNNEL_FLAP(FunnelFlapPacket.class, FunnelFlapPacket::new, PLAY_TO_CLIENT),
|
||||
POTATO_CANNON(PotatoCannonPacket.class, PotatoCannonPacket::new, PLAY_TO_CLIENT),
|
||||
SOUL_PULSE(SoulPulseEffectPacket.class, SoulPulseEffectPacket::new, PLAY_TO_CLIENT),
|
||||
PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new, PLAY_TO_CLIENT),
|
||||
SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT),
|
||||
PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new,
|
||||
PLAY_TO_CLIENT),
|
||||
SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class,
|
||||
PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT),
|
||||
SYNC_RAIL_GRAPH(TrackGraphSyncPacket.class, TrackGraphSyncPacket::new, PLAY_TO_CLIENT),
|
||||
SYNC_EDGE_GROUP(SignalEdgeGroupPacket.class, SignalEdgeGroupPacket::new, PLAY_TO_CLIENT),
|
||||
SYNC_TRAIN(TrainPacket.class, TrainPacket::new, PLAY_TO_CLIENT),
|
||||
REMOVE_TE(RemoveTileEntityPacket.class, RemoveTileEntityPacket::new, PLAY_TO_CLIENT),
|
||||
S_CONFIGURE_TRAIN(TrainEditReturnPacket.class, TrainEditReturnPacket::new, PLAY_TO_CLIENT),
|
||||
CONTROLS_ABORT(ControlsStopControllingPacket.class, ControlsStopControllingPacket::new, PLAY_TO_CLIENT),
|
||||
S_TRAIN_HUD(TrainHUDUpdatePacket.class, TrainHUDUpdatePacket::new, PLAY_TO_CLIENT),
|
||||
|
||||
;
|
||||
|
||||
|
@ -190,8 +197,9 @@ public enum AllPackets {
|
|||
}
|
||||
|
||||
public static void sendToNear(Level world, BlockPos pos, int range, Object message) {
|
||||
channel.send(PacketDistributor.NEAR
|
||||
.with(TargetPoint.p(pos.getX(), pos.getY(), pos.getZ(), range, world.dimension())), message);
|
||||
channel.send(
|
||||
PacketDistributor.NEAR.with(TargetPoint.p(pos.getX(), pos.getY(), pos.getZ(), range, world.dimension())),
|
||||
message);
|
||||
}
|
||||
|
||||
private static class LoadedPacket<T extends SimplePacketBase> {
|
||||
|
|
|
@ -245,7 +245,7 @@ public class PlacementHelpers {
|
|||
ms.popPose();
|
||||
}
|
||||
|
||||
private static void textured(PoseStack ms, float centerX, float centerY, float alpha, float snappedAngle) {
|
||||
public static void textured(PoseStack ms, float centerX, float centerY, float alpha, float snappedAngle) {
|
||||
RenderSystem.enableTexture();
|
||||
AllGuiTextures.PLACEMENT_INDICATOR_SHEET.bind();
|
||||
RenderSystem.enableDepthTest();
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 9.5 KiB |
Loading…
Reference in a new issue