Look ma, both threads!

- Movement of client-side trains is now controlled via network packets (Manual controls and Relocation not yet adjusted for sidedness)
- Modified train settings now get broadcasted to other players
- Cleaned up redundant delegation between classes involved in controlling the carriages
This commit is contained in:
simibubi 2022-03-08 03:51:03 +01:00
parent 3c64ada850
commit 9629cb84eb
87 changed files with 1145 additions and 437 deletions

View file

@ -174,9 +174,9 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour;
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
import com.simibubi.create.content.logistics.trains.management.StationBlock;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBlock;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock;
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
import com.simibubi.create.content.logistics.trains.track.TrackBlockItem;

View file

@ -10,8 +10,8 @@ import com.simibubi.create.content.logistics.item.filter.AttributeFilterContaine
import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen;
import com.simibubi.create.content.logistics.item.filter.FilterContainer;
import com.simibubi.create.content.logistics.item.filter.FilterScreen;
import com.simibubi.create.content.logistics.trains.management.ScheduleContainer;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleContainer;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.content.schematics.block.SchematicTableContainer;
import com.simibubi.create.content.schematics.block.SchematicTableScreen;
import com.simibubi.create.content.schematics.block.SchematicannonContainer;

View file

@ -0,0 +1,18 @@
package com.simibubi.create;
import com.simibubi.create.content.logistics.trains.entity.CarriageSyncDataSerializer;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.registries.DataSerializerEntry;
import net.minecraftforge.registries.IForgeRegistry;
public class AllEntityDataSerializers {
public static final CarriageSyncDataSerializer CARRIAGE_DATA = new CarriageSyncDataSerializer();
public static void register(RegistryEvent.Register<DataSerializerEntry> event) {
IForgeRegistry<DataSerializerEntry> registry = event.getRegistry();
registry.register(new DataSerializerEntry(CARRIAGE_DATA).setRegistryName(Create.asResource("carriage_data")));
}
}

View file

@ -41,7 +41,7 @@ import com.simibubi.create.content.curiosities.weapons.PotatoCannonItem;
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem;
import com.simibubi.create.content.logistics.item.LinkedControllerItem;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.management.ScheduleItem;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem;
import com.simibubi.create.content.schematics.item.SchematicAndQuillItem;
import com.simibubi.create.content.schematics.item.SchematicItem;
import com.simibubi.create.foundation.data.AssetLookup;

View file

@ -171,10 +171,10 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
import com.simibubi.create.content.logistics.item.LecternControllerTileEntity;
import com.simibubi.create.content.logistics.trains.IBogeyTileEntityRenderer;
import com.simibubi.create.content.logistics.trains.management.StationRenderer;
import com.simibubi.create.content.logistics.trains.management.StationTileEntity;
import com.simibubi.create.content.logistics.trains.management.signal.SignalRenderer;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalRenderer;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
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.StandardBogeyTileEntity;
import com.simibubi.create.content.logistics.trains.track.TrackInstance;
import com.simibubi.create.content.logistics.trains.track.TrackRenderer;

View file

@ -52,6 +52,7 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
import net.minecraftforge.registries.DataSerializerEntry;
@Mod(Create.ID)
public class Create {
@ -116,6 +117,7 @@ public class Create {
modEventBus.addGenericListener(RecipeSerializer.class, AllRecipeTypes::register);
modEventBus.addGenericListener(ParticleType.class, AllParticleTypes::register);
modEventBus.addGenericListener(SoundEvent.class, AllSoundEvents::register);
modEventBus.addGenericListener(DataSerializerEntry.class, AllEntityDataSerializers::register);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
}

View file

@ -34,7 +34,7 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
import com.simibubi.create.content.logistics.block.vault.ItemVaultConnectivityHandler;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.management.StationBlock;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
import com.simibubi.create.foundation.config.ContraptionMovementSetting;
import net.minecraft.core.BlockPos;

View file

@ -41,10 +41,7 @@ public class ControlsMovementBehaviour extends MovementBehaviour {
Collection<Integer> pressed = ControlsHandler.currentlyPressed;
equipAnimation.chase(1, .2f, Chaser.EXP);
steering.chase((pressed.contains(3) ? 1 : 0) + (pressed.contains(2) ? -1 : 0), 0.2f, Chaser.EXP);
if (context.contraption.entity instanceof CarriageContraptionEntity car) {
Carriage carriage = car.getCarriage();
speed.chase(Math.abs(carriage.train.speed), 0.2f, Chaser.EXP);
}
speed.chase(0, 0.2f, Chaser.EXP); // TODO
} else
equipAnimation.chase(0, .2f, Chaser.EXP);
float pt = AnimationTickHolder.getPartialTicks(context.world);

View file

@ -9,8 +9,8 @@ import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlo
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.ScheduleItem;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -30,9 +30,9 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour
ItemStack itemInHand = player.getItemInHand(activeHand);
if (!AllItems.SCHEDULE.isIn(itemInHand))
return false;
if (!(contraptionEntity instanceof CarriageContraptionEntity carriage))
if (!(contraptionEntity instanceof CarriageContraptionEntity carriageEntity))
return false;
Contraption contraption = carriage.getContraption();
Contraption contraption = carriageEntity.getContraption();
if (!(contraption instanceof CarriageContraption carriageContraption))
return false;
@ -49,7 +49,7 @@ public class BlazeBurnerInteractionBehaviour extends MovingInteractionBehaviour
Schedule schedule = ScheduleItem.getSchedule(itemInHand);
if (schedule == null)
return false;
Train train = carriage.getCarriage().train;
Train train = carriageEntity.getCarriage().train;
if (train == null)
return false;
if (train.heldForAssembly) {

View file

@ -9,8 +9,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.SignalState;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Couple;

View file

@ -10,12 +10,15 @@ import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.lwjgl.glfw.GLFW;
import com.simibubi.create.AllKeys;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.entity.TrainPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
import com.simibubi.create.foundation.networking.AllPackets;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
@ -24,18 +27,19 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.PacketDistributor;
public class GlobalRailwayManager {
public Map<UUID, TrackGraph> trackNetworks;
public Map<UUID, SignalEdgeGroup> signalEdgeGroups;
public Map<UUID, Train> trains;
public Map<Integer, Carriage> carriageById;
private TrackSavedData trackData;
public TrackGraphSync sync;
//
private RailwaySavedData savedData;
public GlobalRailwayManager() {
cleanUp();
@ -47,6 +51,9 @@ public class GlobalRailwayManager {
trackNetworks.values()
.forEach(g -> sync.sendFullGraphTo(g, serverPlayer));
sync.sendEdgeGroups(signalEdgeGroups.keySet(), serverPlayer);
for (Train train : trains.values())
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> serverPlayer),
new TrainPacket(train, false));
}
}
@ -55,16 +62,16 @@ public class GlobalRailwayManager {
if (server == null || server.overworld() != level)
return;
cleanUp();
trackData = null;
savedData = null;
loadTrackData(server);
}
private void loadTrackData(MinecraftServer server) {
if (trackData != null)
if (savedData != null)
return;
trackData = TrackSavedData.load(server);
trackNetworks = trackData.getTrackNetworks();
signalEdgeGroups = trackData.getSignalBlocks();
savedData = RailwaySavedData.load(server);
trackNetworks = savedData.getTrackNetworks();
signalEdgeGroups = savedData.getSignalBlocks();
}
public void levelUnloaded(LevelAccessor level) {
@ -78,13 +85,12 @@ public class GlobalRailwayManager {
trackNetworks = new HashMap<>();
signalEdgeGroups = new HashMap<>();
trains = new HashMap<>();
carriageById = new HashMap<>();
sync = new TrackGraphSync();
}
public void markTracksDirty() {
if (trackData != null)
trackData.setDirty();
if (savedData != null)
savedData.setDirty();
}
//
@ -168,4 +174,17 @@ public class GlobalRailwayManager {
.forEach(TrackGraph::debugViewNodes);
}
public GlobalRailwayManager sided(LevelAccessor level) {
if (level != null && !level.isClientSide())
return this;
MutableObject<GlobalRailwayManager> m = new MutableObject<>();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> clientManager(m));
return m.getValue();
}
@OnlyIn(Dist.CLIENT)
private void clientManager(MutableObject<GlobalRailwayManager> m) {
m.setValue(CreateClient.RAILWAYS);
}
}

View file

@ -0,0 +1,11 @@
package com.simibubi.create.content.logistics.trains;
import com.simibubi.create.foundation.utility.Couple;
public class GraphLocation {
public TrackGraph graph;
public Couple<TrackNodeLocation> edge;
public double position;
}

View file

@ -11,7 +11,7 @@ import javax.annotation.Nullable;
import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
import com.simibubi.create.content.logistics.trains.track.TrackShape;
import com.simibubi.create.foundation.utility.Iterate;

View file

@ -5,7 +5,7 @@ import java.util.Map;
import java.util.UUID;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;
@ -13,7 +13,7 @@ import net.minecraft.nbt.Tag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.saveddata.SavedData;
public class TrackSavedData extends SavedData {
public class RailwaySavedData extends SavedData {
private Map<UUID, TrackGraph> trackNetworks = new HashMap<>();
private Map<UUID, SignalEdgeGroup> signalEdgeGroups = new HashMap<>();
@ -26,8 +26,8 @@ public class TrackSavedData extends SavedData {
return nbt;
}
private static TrackSavedData load(CompoundTag nbt) {
TrackSavedData sd = new TrackSavedData();//TODO load trains before everything else
private static RailwaySavedData load(CompoundTag nbt) {
RailwaySavedData sd = new RailwaySavedData();//TODO load trains before everything else
sd.trackNetworks = new HashMap<>();
sd.signalEdgeGroups = new HashMap<>();
NBTHelper.iterateCompoundList(nbt.getList("RailGraphs", Tag.TAG_COMPOUND), c -> {
@ -49,12 +49,12 @@ public class TrackSavedData extends SavedData {
return signalEdgeGroups;
}
private TrackSavedData() {}
private RailwaySavedData() {}
public static TrackSavedData load(MinecraftServer server) {
public static RailwaySavedData load(MinecraftServer server) {
return server.overworld()
.getDataStorage()
.computeIfAbsent(TrackSavedData::load, TrackSavedData::new, "create_tracks");
.computeIfAbsent(RailwaySavedData::load, RailwaySavedData::new, "create_tracks");
}
}

View file

@ -1,6 +1,6 @@
package com.simibubi.create.content.logistics.trains;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;

View file

@ -23,14 +23,14 @@ import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointManager;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointStorage;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.utility.Color;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;
@ -217,6 +217,7 @@ public class TrackGraph {
if (train.graph != this)
continue;
train.graph = toOther;
train.syncTrackGraphChanges();
}
}

View file

@ -6,7 +6,6 @@ import java.util.Map.Entry;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.BlockPos;

View file

@ -11,8 +11,8 @@ import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroupPacket;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroupPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -8,9 +8,9 @@ import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;

View file

@ -9,7 +9,7 @@ import java.util.Set;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.management.signal.SignalPropagator;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalPropagator;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.lang.ref.WeakReference;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
@ -8,20 +9,17 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ISignalBoundaryListener;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction.Axis;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
@ -31,17 +29,19 @@ public class Carriage {
public static final AtomicInteger netIdGenerator = new AtomicInteger();
public Train train;
public CarriageContraption contraption;
public int bogeySpacing;
public int id;
public boolean blocked;
public Couple<Boolean> presentConductors;
public boolean hasForwardConductor;
public boolean hasBackwardConductor;
WeakReference<CarriageContraptionEntity> entity;
public int bogeySpacing;
Couple<CarriageBogey> bogeys;
CompoundTag serialisedEntity;
WeakReference<CarriageContraptionEntity> entity;
// client
public boolean pointsInitialised;
static final int FIRST = 0, MIDDLE = 1, LAST = 2, BOTH = 3;
public Carriage(CarriageBogey bogey1, @Nullable CarriageBogey bogey2, int bogeySpacing) {
@ -49,6 +49,8 @@ public class Carriage {
this.bogeys = Couple.create(bogey1, bogey2);
this.entity = new WeakReference<>(null);
this.id = netIdGenerator.incrementAndGet();
this.serialisedEntity = new CompoundTag();
this.pointsInitialised = false;
bogey1.carriage = this;
if (bogey2 != null)
@ -59,9 +61,13 @@ public class Carriage {
this.train = train;
}
public void setContraption(CarriageContraption contraption) {
this.contraption = contraption;
contraption.setCarriage(this);
public void setContraption(Level level, CarriageContraption contraption) {
CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption);
entity.setInitialOrientation(contraption.getAssemblyDirection()
.getClockWise());
entity.setCarriage(this);
contraption.startMoving(level);
serialisedEntity = entity.serializeNBT();
}
public double travel(Level level, TrackGraph graph, double distance,
@ -121,35 +127,36 @@ public class Carriage {
bogey.updateAnchorPosition();
}
tickEntity(level);
return distanceMoved.getValue();
double actualMovement = distanceMoved.getValue();
manageEntity(level, actualMovement);
return actualMovement;
}
public void updateConductors() {
CarriageContraptionEntity entity = this.entity.get();
if (entity == null || !entity.isAlive())
return;
Couple<Boolean> sides = entity.checkConductors();
hasForwardConductor = sides.getFirst();
hasBackwardConductor = sides.getSecond();
if (entity != null && entity.isAlive())
presentConductors = entity.checkConductors();
}
public void createEntity(Level level) {
contraption.startMoving(level);
CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption);
Optional<Entity> entityFromData = EntityType.create(serialisedEntity, level);
Entity entity = entityFromData.orElse(null);
if (!(entity instanceof CarriageContraptionEntity cce))
return;
Vec3 pos = leadingBogey().anchorPosition;
entity.setPos(pos);
entity.setInitialOrientation(contraption.getAssemblyDirection()
.getClockWise());
level.addFreshEntity(entity);
this.entity = new WeakReference<>(entity);
cce.setPos(pos);
cce.setCarriage(this);
cce.setGraph(train.graph == null ? null : train.graph.id);
cce.syncCarriage();
level.addFreshEntity(cce);
this.entity = new WeakReference<>(cce);
}
public ChunkPos getChunk() {
return new ChunkPos(new BlockPos(leadingBogey().anchorPosition));
}
protected void tickEntity(Level level) {
protected void manageEntity(Level level, double actualMovement) {
CarriageContraptionEntity entity = this.entity.get();
if (entity == null) {
if (CarriageEntityHandler.isActiveChunk(level, getChunk()))
@ -157,6 +164,7 @@ public class Carriage {
} else {
CarriageEntityHandler.validateCarriageEntity(entity);
if (!entity.isAlive()) {
serialisedEntity = entity.serializeNBT();
this.entity.clear();
return;
}
@ -165,11 +173,12 @@ public class Carriage {
entity = this.entity.get();
if (entity == null)
return;
if (!entity.level.isClientSide)
moveEntity(entity);
alignEntity(entity);
entity.syncCarriage();
}
public void moveEntity(CarriageContraptionEntity entity) {
public void alignEntity(CarriageContraptionEntity entity) {
Vec3 positionVec = isOnTwoBogeys() ? leadingBogey().anchorPosition
: leadingBogey().leading()
.getPosition();
@ -215,93 +224,4 @@ public class Carriage {
return bogeys.getSecond() != null;
}
public static class CarriageBogey {
Carriage carriage;
IBogeyBlock type;
Couple<TravellingPoint> points;
Vec3 anchorPosition;
LerpedFloat wheelAngle;
LerpedFloat yaw;
LerpedFloat pitch;
public Vec3 leadingCouplingAnchor;
public Vec3 trailingCouplingAnchor;
int derailAngle;
public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) {
this.type = type;
points = Couple.create(point, point2);
wheelAngle = LerpedFloat.angular();
yaw = LerpedFloat.angular();
pitch = LerpedFloat.angular();
updateAnchorPosition();
derailAngle = Create.RANDOM.nextInt(90) - 45;
}
public void updateAngles(double distanceMoved) {
double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius());
Vec3 positionVec = leading().getPosition();
Vec3 coupledVec = trailing().getPosition();
double diffX = positionVec.x - coupledVec.x;
double diffY = positionVec.y - coupledVec.y;
double diffZ = positionVec.z - coupledVec.z;
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
if (carriage.train.derailed)
yRot += derailAngle;
wheelAngle.setValue((wheelAngle.getValue() - angleDiff * Math.signum(carriage.train.speed)) % 360);
pitch.setValue(xRot);
yaw.setValue(-yRot);
}
public TravellingPoint leading() {
return points.getFirst();
}
public TravellingPoint trailing() {
return points.getSecond();
}
public double getStress() {
return type.getWheelPointSpacing() - leading().getPosition()
.distanceTo(trailing().getPosition());
}
public void updateAnchorPosition() {
anchorPosition = points.getFirst()
.getPosition()
.add(points.getSecond()
.getPosition())
.scale(.5);
}
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
float partialTicks, boolean leading) {
Vec3 thisOffset = type.getConnectorAnchorOffset();
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, entityXRot, Axis.X);
thisOffset = VecHelper.rotate(thisOffset, -180, Axis.Y);
thisOffset = thisOffset.add(0, 0, leading ? 0 : -bogeySpacing);
thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X);
thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y);
if (leading)
leadingCouplingAnchor = entityPos.add(thisOffset);
else {
trailingCouplingAnchor = entityPos.add(thisOffset);
}
}
}
}

View file

@ -0,0 +1,103 @@
package com.simibubi.create.content.logistics.trains.entity;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.core.Direction.Axis;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class CarriageBogey {
public Carriage carriage;
IBogeyBlock type;
Couple<TravellingPoint> points;
Vec3 anchorPosition;
LerpedFloat wheelAngle;
LerpedFloat yaw;
LerpedFloat pitch;
public Vec3 leadingCouplingAnchor;
public Vec3 trailingCouplingAnchor;
int derailAngle;
public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) {
this.type = type;
points = Couple.create(point, point2);
wheelAngle = LerpedFloat.angular();
yaw = LerpedFloat.angular();
pitch = LerpedFloat.angular();
updateAnchorPosition();
derailAngle = Create.RANDOM.nextInt(90) - 45;
}
public void updateAngles(double distanceMoved) {
double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius());
Vec3 positionVec = leading().getPosition();
Vec3 coupledVec = trailing().getPosition();
double diffX = positionVec.x - coupledVec.x;
double diffY = positionVec.y - coupledVec.y;
double diffZ = positionVec.z - coupledVec.z;
float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90;
float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)));
if (carriage.train.derailed)
yRot += derailAngle;
wheelAngle.setValue((wheelAngle.getValue() - angleDiff * Math.signum(carriage.train.speed)) % 360);
pitch.setValue(xRot);
yaw.setValue(-yRot);
}
public TravellingPoint leading() {
return points.getFirst();
}
public TravellingPoint trailing() {
return points.getSecond();
}
public double getStress() {
return type.getWheelPointSpacing() - leading().getPosition()
.distanceTo(trailing().getPosition());
}
public void updateAnchorPosition() {
if (points.getFirst().node1 == null)
return;
anchorPosition = points.getFirst()
.getPosition()
.add(points.getSecond()
.getPosition())
.scale(.5);
}
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
float partialTicks, boolean leading) {
Vec3 thisOffset = type.getConnectorAnchorOffset();
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, entityXRot, Axis.X);
thisOffset = VecHelper.rotate(thisOffset, -180, Axis.Y);
thisOffset = thisOffset.add(0, 0, leading ? 0 : -bogeySpacing);
thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y);
thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X);
thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y);
if (leading)
leadingCouplingAnchor = entityPos.add(thisOffset);
else
trailingCouplingAnchor = entityPos.add(thisOffset);
}
}

View file

@ -40,11 +40,7 @@ public class CarriageContraption extends Contraption {
public Couple<Boolean> blazeBurnerConductors;
public Map<BlockPos, Couple<Boolean>> conductorSeats;
// runtime
private Carriage carriage;
public int temporaryCarriageIdHolder = -1;
// for assembly only
// during assembly only
private int bogeys;
private boolean sidewaysControls;
private BlockPos secondBogeyPos;
@ -138,8 +134,6 @@ public class CarriageContraption extends Contraption {
public CompoundTag writeNBT(boolean spawnPacket) {
CompoundTag tag = super.writeNBT(spawnPacket);
NBTHelper.writeEnum(tag, "AssemblyDirection", getAssemblyDirection());
if (spawnPacket)
tag.putInt("CarriageId", carriage.id);
tag.putBoolean("FrontControls", forwardControls);
tag.putBoolean("BackControls", backwardControls);
tag.putBoolean("FrontBlazeConductor", blazeBurnerConductors.getFirst());
@ -159,8 +153,6 @@ public class CarriageContraption extends Contraption {
@Override
public void readNBT(Level world, CompoundTag nbt, boolean spawnData) {
assemblyDirection = NBTHelper.readEnum(nbt, "AssemblyDirection", Direction.class);
if (spawnData)
temporaryCarriageIdHolder = nbt.getInt("CarriageId");
forwardControls = nbt.getBoolean("FrontControls");
backwardControls = nbt.getBoolean("BackControls");
blazeBurnerConductors =
@ -191,15 +183,6 @@ public class CarriageContraption extends Contraption {
return assemblyDirection;
}
public void setCarriage(Carriage carriage) {
this.carriage = carriage;
temporaryCarriageIdHolder = carriage.id;
}
public Carriage getCarriage() {
return carriage;
}
public boolean hasForwardControls() {
return forwardControls;
}

View file

@ -1,17 +1,24 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.base.Strings;
import com.simibubi.create.AllEntityDataSerializers;
import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
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.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.Color;
import com.simibubi.create.foundation.utility.Couple;
@ -23,8 +30,12 @@ import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
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.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@ -38,8 +49,20 @@ import net.minecraftforge.fml.DistExecutor;
public class CarriageContraptionEntity extends OrientedContraptionEntity {
private static final EntityDataAccessor<CarriageSyncData> CARRIAGE_DATA =
SynchedEntityData.defineId(CarriageContraptionEntity.class, AllEntityDataSerializers.CARRIAGE_DATA);
private static final EntityDataAccessor<Optional<UUID>> TRACK_GRAPH =
SynchedEntityData.defineId(CarriageContraptionEntity.class, EntityDataSerializers.OPTIONAL_UUID);
public UUID trainId;
public int carriageIndex;
private Carriage carriage;
public boolean validForRender;
public CarriageContraptionEntity(EntityType<?> type, Level world) {
super(type, world);
validForRender = false;
}
@Override
@ -47,6 +70,46 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
return true;
}
@Override
protected void defineSynchedData() {
super.defineSynchedData();
entityData.define(CARRIAGE_DATA, new CarriageSyncData());
entityData.define(TRACK_GRAPH, Optional.empty());
}
public void syncCarriage() {
CarriageSyncData carriageData = getCarriageData();
if (carriageData == null)
return;
if (carriage == null)
return;
carriageData.update(this, carriage);
}
@Override
public void onSyncedDataUpdated(EntityDataAccessor<?> key) {
super.onSyncedDataUpdated(key);
if (!level.isClientSide)
return;
if (key == TRACK_GRAPH)
updateTrackGraph();
if (key == CARRIAGE_DATA) {
CarriageSyncData carriageData = getCarriageData();
if (carriageData == null)
return;
if (carriage == null)
return;
carriageData.apply(this, carriage);
}
}
private CarriageSyncData getCarriageData() {
return entityData.get(CARRIAGE_DATA);
}
public static CarriageContraptionEntity create(Level world, CarriageContraption contraption) {
CarriageContraptionEntity entity =
new CarriageContraptionEntity(AllEntityTypes.CARRIAGE_CONTRAPTION.get(), world);
@ -56,9 +119,97 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
return entity;
}
@Override
protected void tickContraption() {
if (!(contraption instanceof CarriageContraption))
return;
if (carriage == null) {
if (level.isClientSide) {
Train train = Create.RAILWAYS.sided(level).trains.get(trainId);
if (train == null || train.carriages.size() <= carriageIndex)
return;
carriage = train.carriages.get(carriageIndex);
updateTrackGraph();
} else
discard();
return;
}
tickActors();
contraption.stalled = false;
for (MutablePair<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
MovementContext context = pair.right;
context.stall = false;
}
CarriageSyncData carriageData = getCarriageData();
if (!level.isClientSide) {
if (tickCount % getType().updateInterval() == 0 && carriageData.isDirty()) {
entityData.set(CARRIAGE_DATA, null);
entityData.set(CARRIAGE_DATA, carriageData);
carriageData.setDirty(false);
}
return;
}
if (!carriage.pointsInitialised)
return;
carriageData.approach(this, carriage, 1f / getType().updateInterval());
carriage.bogeys.getFirst()
.updateAnchorPosition();
if (carriage.isOnTwoBogeys())
carriage.bogeys.getSecond()
.updateAnchorPosition();
xo = getX();
yo = getY();
zo = getZ();
carriage.alignEntity(this);
double distanceTo = position().distanceTo(new Vec3(xo, yo, zo));
carriage.bogeys.getFirst()
.updateAngles(distanceTo);
if (carriage.isOnTwoBogeys())
carriage.bogeys.getSecond()
.updateAngles(distanceTo);
if (carriage.train.derailed)
spawnDerailParticles(carriage);
validForRender = true;
}
Vec3 derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, 1.5f)
.multiply(1, .25f, 1);
private void spawnDerailParticles(Carriage carriage) {
if (random.nextFloat() < 1 / 20f) {
Vec3 v = position().add(derailParticleOffset);
level.addParticle(ParticleTypes.CAMPFIRE_COSY_SMOKE, v.x, v.y, v.z, 0, .04, 0);
}
}
@Override
protected void writeAdditional(CompoundTag compound, boolean spawnPacket) {
super.writeAdditional(compound, spawnPacket);
compound.putUUID("TrainId", trainId);
compound.putInt("CarriageIndex", carriageIndex);
}
@Override
protected void readAdditional(CompoundTag compound, boolean spawnPacket) {
super.readAdditional(compound, spawnPacket);
trainId = compound.getUUID("TrainId");
carriageIndex = compound.getInt("CarriageIndex");
}
@Override
public Component getContraptionName() {
Carriage carriage = getCarriage();
if (carriage != null)
return carriage.train.name;
Component contraptionName = super.getContraptionName();
@ -89,12 +240,11 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
@Override
public boolean startControlling(BlockPos controlsLocalPos, Player player) {
Carriage carriage = getCarriage();
if (carriage == null)
return false;
if (carriage.train.derailed)
return false;
if (carriage.train.heldForAssembly) {
if (!level.isClientSide && carriage.train.heldForAssembly) {
player.displayClientMessage(Lang.translate("schedule.train_still_assembling"), true);
return false;
}
@ -111,7 +261,6 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
@Override
public boolean control(BlockPos controlsLocalPos, Collection<Integer> heldControls, Player player) {
Carriage carriage = getCarriage();
if (carriage == null)
return false;
if (carriage.train.derailed)
@ -227,58 +376,21 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
stationMessage = false;
}
@Override
protected void tickContraption() {
if (!(contraption instanceof CarriageContraption))
private void updateTrackGraph() {
if (carriage == null)
return;
Carriage carriage = getCarriage();
if (carriage == null) {
discard();
Optional<UUID> optional = entityData.get(TRACK_GRAPH);
if (optional.isEmpty()) {
carriage.train.graph = null;
carriage.train.derailed = true;
return;
}
tickActors();
contraption.stalled = false;
for (MutablePair<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
MovementContext context = pair.right;
context.stall = false;
}
if (!level.isClientSide)
TrackGraph graph = CreateClient.RAILWAYS.sided(level).trackNetworks.get(optional.get());
if (graph == null)
return;
xo = getX();
yo = getY();
zo = getZ();
carriage.moveEntity(this);
double distanceTo = position().distanceTo(new Vec3(xo, yo, zo));
carriage.bogeys.getFirst()
.updateAngles(distanceTo);
if (carriage.isOnTwoBogeys())
carriage.bogeys.getSecond()
.updateAngles(distanceTo);
if (carriage.train.derailed)
spawnDerailParticles(carriage);
}
public Carriage getCarriage() {
int id = ((CarriageContraption) contraption).temporaryCarriageIdHolder;
Carriage carriage = Create.RAILWAYS.carriageById.get(id); // TODO: thread breach
return carriage;
}
Vec3 derailParticleOffset = VecHelper.offsetRandomly(Vec3.ZERO, Create.RANDOM, 1.5f)
.multiply(1, .25f, 1);
private void spawnDerailParticles(Carriage carriage) {
if (random.nextFloat() < 1 / 20f) {
Vec3 v = position().add(derailParticleOffset);
level.addParticle(ParticleTypes.CAMPFIRE_COSY_SMOKE, v.x, v.y, v.z, 0, .04, 0);
}
carriage.train.graph = graph;
carriage.train.derailed = false;
}
@Override
@ -286,4 +398,18 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
return false;
}
public Carriage getCarriage() {
return carriage;
}
public void setCarriage(Carriage carriage) {
this.carriage = carriage;
this.trainId = carriage.train.id;
this.carriageIndex = carriage.train.carriages.indexOf(carriage);
}
public void setGraph(@Nullable UUID graphId) {
entityData.set(TRACK_GRAPH, Optional.ofNullable(graphId));
}
}

View file

@ -20,7 +20,7 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
double cameraY, double cameraZ) {
if (!super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ))
return false;
return ((CarriageContraption) entity.getContraption()).temporaryCarriageIdHolder != -1;
return entity.validForRender;
}
@Override

View file

@ -7,7 +7,6 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;

View file

@ -0,0 +1,281 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.Vector;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class CarriageSyncData {
public Vector<Pair<Couple<Integer>, Float>> wheelLocations;
public float distanceToDestination;
// For Client interpolation
private TravellingPoint[] pointsToApproach;
private float[] pointDistanceSnapshot;
private float destinationDistanceSnapshot;
public CarriageSyncData() {
wheelLocations = new Vector<>(4);
pointDistanceSnapshot = new float[4];
pointsToApproach = new TravellingPoint[4];
destinationDistanceSnapshot = 0;
for (int i = 0; i < 4; i++) {
wheelLocations.add(null);
pointsToApproach[i] = new TravellingPoint();
}
}
public CarriageSyncData copy() {
CarriageSyncData data = new CarriageSyncData();
for (int i = 0; i < 4; i++)
data.wheelLocations.set(i, wheelLocations.get(i));
data.distanceToDestination = distanceToDestination;
return data;
}
public void write(FriendlyByteBuf buffer) {
for (Pair<Couple<Integer>, Float> pair : wheelLocations) {
buffer.writeBoolean(pair == null);
if (pair == null)
break;
pair.getFirst()
.forEach(buffer::writeInt);
buffer.writeFloat(pair.getSecond());
}
buffer.writeFloat(distanceToDestination);
}
public void read(FriendlyByteBuf buffer) {
for (int i = 0; i < 4; i++) {
if (buffer.readBoolean())
break;
wheelLocations.set(i, Pair.of(Couple.create(buffer::readInt), buffer.readFloat()));
}
distanceToDestination = buffer.readFloat();
}
public void update(CarriageContraptionEntity entity, Carriage carriage) {
TrackGraph graph = carriage.train.graph;
if (graph == null)
return;
for (boolean first : Iterate.trueAndFalse) {
if (!first && !carriage.isOnTwoBogeys())
break;
CarriageBogey bogey = carriage.bogeys.get(first);
for (boolean firstPoint : Iterate.trueAndFalse) {
TravellingPoint point = bogey.points.get(firstPoint);
int index = (first ? 0 : 2) + (firstPoint ? 0 : 1);
Pair<Couple<Integer>, Float> pair =
Pair.of(Couple.create(point.node1.getNetId(), point.node2.getNetId()), (float) point.position);
wheelLocations.set(index, pair);
}
}
distanceToDestination = (float) carriage.train.navigation.distanceToDestination;
setDirty(true);
}
public void apply(CarriageContraptionEntity entity, Carriage carriage) {
TrackGraph graph = carriage.train.graph;
if (graph == null)
return;
for (int i = 0; i < wheelLocations.size(); i++) {
Pair<Couple<Integer>, Float> pair = wheelLocations.get(i);
if (pair == null)
break;
CarriageBogey bogey = carriage.bogeys.get(i / 2 == 0);
TravellingPoint bogeyPoint = bogey.points.get(i % 2 == 0);
TravellingPoint point = carriage.pointsInitialised ? pointsToApproach[i] : bogeyPoint;
Couple<TrackNode> nodes = pair.getFirst()
.map(graph::getNode);
if (nodes.either(Objects::isNull))
continue;
TrackEdge edge = graph.getConnectionsFrom(nodes.getFirst())
.get(nodes.getSecond());
if (edge == null)
continue;
point.node1 = nodes.getFirst();
point.node2 = nodes.getSecond();
point.edge = edge;
point.position = pair.getSecond();
if (carriage.pointsInitialised) {
float foundDistance = -1;
boolean direction = false;
for (boolean forward : Iterate.trueAndFalse) {
float distanceTo = getDistanceTo(graph, bogeyPoint, point, foundDistance, forward);
if (distanceTo > 0 && (foundDistance == -1 || distanceTo < foundDistance)) {
foundDistance = distanceTo;
direction = forward;
}
}
if (foundDistance != -1) {
pointDistanceSnapshot[i] = (direction ? 1 : -1) * foundDistance;
} else {
// could not pathfind to server location
bogeyPoint.node1 = point.node1;
bogeyPoint.node2 = point.node2;
bogeyPoint.edge = point.edge;
bogeyPoint.position = point.position;
pointDistanceSnapshot[i] = 0;
}
}
}
if (!carriage.pointsInitialised) {
carriage.train.navigation.distanceToDestination = distanceToDestination;
carriage.pointsInitialised = true;
return;
}
destinationDistanceSnapshot = (float) (distanceToDestination - carriage.train.navigation.distanceToDestination);
}
public void approach(CarriageContraptionEntity entity, Carriage carriage, float partial) {
TrackGraph graph = carriage.train.graph;
if (graph == null)
return;
carriage.train.navigation.distanceToDestination += partial * destinationDistanceSnapshot;
for (boolean first : Iterate.trueAndFalse) {
if (!first && !carriage.isOnTwoBogeys())
break;
CarriageBogey bogey = carriage.bogeys.get(first);
for (boolean firstPoint : Iterate.trueAndFalse) {
int index = (first ? 0 : 2) + (firstPoint ? 0 : 1);
float f = pointDistanceSnapshot[index];
if (Mth.equal(f, 0))
continue;
TravellingPoint point = bogey.points.get(firstPoint);
MutableBoolean success = new MutableBoolean(true);
TravellingPoint toApproach = pointsToApproach[index];
point.travel(graph, partial * f,
point.follow(toApproach, b -> success.setValue(success.booleanValue() && b)),
point.ignoreSignals());
// could not pathfind to server location
if (!success.booleanValue()) {
point.node1 = toApproach.node1;
point.node2 = toApproach.node2;
point.edge = toApproach.edge;
point.position = toApproach.position;
pointDistanceSnapshot[index] = 0;
}
}
}
}
public float getDistanceTo(TrackGraph graph, TravellingPoint current, TravellingPoint target, float maxDistance,
boolean forward) {
if (maxDistance == -1)
maxDistance = 32;
Set<TrackEdge> visited = new HashSet<>();
Map<TrackEdge, Pair<Boolean, TrackEdge>> reachedVia = new IdentityHashMap<>();
PriorityQueue<Pair<Double, Pair<Couple<TrackNode>, TrackEdge>>> frontier =
new PriorityQueue<>((p1, p2) -> Double.compare(p1.getFirst(), p2.getFirst()));
TrackNode initialNode1 = forward ? current.node1 : current.node2;
TrackNode initialNode2 = forward ? current.node2 : current.node1;
TrackEdge initialEdge = graph.getConnectionsFrom(initialNode1)
.get(initialNode2);
TrackNode targetNode1 = forward ? target.node1 : target.node2;
TrackNode targetNode2 = forward ? target.node2 : target.node1;
TrackEdge targetEdge = graph.getConnectionsFrom(targetNode1)
.get(targetNode2);
double distanceToNode2 =
forward ? initialEdge.getLength(initialNode1, initialNode2) - current.position : current.position;
frontier.add(Pair.of(distanceToNode2, Pair.of(Couple.create(initialNode1, initialNode2), initialEdge)));
while (!frontier.isEmpty()) {
Pair<Double, Pair<Couple<TrackNode>, TrackEdge>> poll = frontier.poll();
double distance = poll.getFirst();
Pair<Couple<TrackNode>, TrackEdge> currentEntry = poll.getSecond();
TrackNode node1 = currentEntry.getFirst()
.getFirst();
TrackNode node2 = currentEntry.getFirst()
.getSecond();
TrackEdge edge = currentEntry.getSecond();
if (edge == targetEdge)
return (float) (distance
- (forward ? edge.getLength(node1, node2) - target.position : target.position));
if (distance > maxDistance)
continue;
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2);
for (Entry<TrackNode, TrackEdge> entry : connectionsFrom.entrySet()) {
TrackNode newNode = entry.getKey();
TrackEdge newEdge = entry.getValue();
Vec3 currentDirection = edge.getDirection(node1, node2, false);
Vec3 newDirection = newEdge.getDirection(node2, newNode, true);
if (currentDirection.dot(newDirection) < 3 / 4f)
continue;
if (!visited.add(entry.getValue()))
continue;
validTargets.add(entry);
}
if (validTargets.isEmpty())
continue;
for (Entry<TrackNode, TrackEdge> entry : validTargets) {
TrackNode newNode = entry.getKey();
TrackEdge newEdge = entry.getValue();
reachedVia.put(newEdge, Pair.of(validTargets.size() > 1, edge));
frontier.add(Pair.of(newEdge.getLength(node2, newNode) + distance,
Pair.of(Couple.create(node2, newNode), newEdge)));
}
}
return -1;
}
//
private boolean isDirty;
public void setDirty(boolean dirty) {
isDirty = dirty;
}
public boolean isDirty() {
return isDirty;
}
}

View file

@ -0,0 +1,25 @@
package com.simibubi.create.content.logistics.trains.entity;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.syncher.EntityDataSerializer;
public class CarriageSyncDataSerializer implements EntityDataSerializer<CarriageSyncData> {
@Override
public void write(FriendlyByteBuf buffer, CarriageSyncData data) {
data.write(buffer);
}
@Override
public CarriageSyncData read(FriendlyByteBuf buffer) {
CarriageSyncData data = new CarriageSyncData();
data.read(buffer);
return data;
}
@Override
public CarriageSyncData copy(CarriageSyncData data) {
return data.copy();
}
}

View file

@ -17,12 +17,12 @@ import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;

View file

@ -19,23 +19,22 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ISignalBoundaryListener;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
@ -49,6 +48,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Explosion.BlockInteraction;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.PacketDistributor;
public class Train {
@ -84,7 +84,9 @@ public class Train {
double[] stress;
public Train(UUID id, UUID owner, TrackGraph graph, List<Carriage> carriages, List<Integer> carriageSpacing) {
public Train(UUID id, UUID owner, TrackGraph graph, List<Carriage> carriages, List<Integer> carriageSpacing,
boolean doubleEnded) {
this.id = id;
this.owner = owner;
this.graph = graph;
@ -94,14 +96,10 @@ public class Train {
this.stress = new double[carriageSpacing.size()];
this.name = Lang.translate("train.unnamed");
this.status = new TrainStatus(this);
this.doubleEnded = doubleEnded;
carriages.forEach(c -> {
c.setTrain(this);
Create.RAILWAYS.carriageById.put(c.id, c);
});
carriages.forEach(c -> c.setTrain(this));
doubleEnded = carriages.stream()
.anyMatch(c -> c.contraption.hasBackwardControls());
navigation = new Navigation(this);
runtime = new ScheduleRuntime(this);
heldForAssembly = true;
@ -283,14 +281,14 @@ public class Train {
public boolean hasForwardConductor() {
for (Carriage carriage : carriages)
if (carriage.hasForwardConductor)
if (carriage.presentConductors.getFirst())
return true;
return false;
}
public boolean hasBackwardConductor() {
for (Carriage carriage : carriages)
if (carriage.hasBackwardConductor)
if (carriage.presentConductors.getSecond())
return true;
return false;
}
@ -370,6 +368,8 @@ public class Train {
return;
speed = -Mth.clamp(speed, -.5, .5);
derailed = true;
graph = null;
syncTrackGraphChanges();
status.crash();
}
@ -396,8 +396,6 @@ public class Train {
entity.setPos(Vec3
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset)));
entity.disassemble();
Create.RAILWAYS.carriageById.remove(carriage.id);
CreateClient.RAILWAYS.carriageById.remove(carriage.id);
offset += carriage.bogeySpacing;
@ -410,7 +408,7 @@ public class Train {
currentStation.cancelReservation(this);
Create.RAILWAYS.trains.remove(id);
CreateClient.RAILWAYS.trains.remove(id); // TODO Thread breach
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(this, false));
return true;
}
@ -428,7 +426,7 @@ public class Train {
navigation.cancelNavigation();
forEachTravellingPoint(tp -> migratingPoints.add(new TrainMigration(tp)));
graph = null;
syncTrackGraphChanges();
}
public void forEachTravellingPoint(Consumer<TravellingPoint> callback) {
@ -497,6 +495,7 @@ public class Train {
migrationCooldown = 40;
status.failedMigration();
derailed = true;
syncTrackGraphChanges();
return;
}
@ -516,10 +515,19 @@ public class Train {
if (currentStation != null)
currentStation.reserveFor(this);
updateSignalBlocks = true;
syncTrackGraphChanges();
return;
}
}
public void syncTrackGraphChanges() {
for (Carriage carriage : carriages) {
CarriageContraptionEntity entity = carriage.entity.get();
if (entity != null)
entity.setGraph(graph == null ? null : graph.id);
}
}
public int getTotalLength() {
int length = 0;
for (int i = 0; i < carriages.size(); i++) {

View file

@ -2,11 +2,11 @@ package com.simibubi.create.content.logistics.trains.entity;
import java.util.Map.Entry;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.VecHelper;

View file

@ -0,0 +1,109 @@
package com.simibubi.create.content.logistics.trains.entity;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.network.NetworkEvent.Context;
import net.minecraftforge.registries.ForgeRegistries;
public class TrainPacket extends SimplePacketBase {
UUID trainId;
Train train;
boolean add;
public TrainPacket(Train train, boolean add) {
this.train = train;
this.add = add;
}
public TrainPacket(FriendlyByteBuf buffer) {
add = buffer.readBoolean();
trainId = buffer.readUUID();
if (!add)
return;
UUID owner = buffer.readUUID();
List<Carriage> carriages = new ArrayList<>();
List<Integer> carriageSpacing = new ArrayList<>();
int size = buffer.readVarInt();
for (int i = 0; i < size; i++) {
Couple<CarriageBogey> bogies = Couple.create(null, null);
for (boolean first : Iterate.trueAndFalse) {
if (!first && !buffer.readBoolean())
continue;
IBogeyBlock type = (IBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation());
bogies.set(first, new CarriageBogey(type, new TravellingPoint(), new TravellingPoint()));
}
int spacing = buffer.readVarInt();
carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing));
}
size = buffer.readVarInt();
for (int i = 0; i < size; i++)
carriageSpacing.add(buffer.readVarInt());
boolean doubleEnded = buffer.readBoolean();
train = new Train(trainId, owner, null, carriages, carriageSpacing, doubleEnded);
}
@Override
public void write(FriendlyByteBuf buffer) {
buffer.writeBoolean(add);
buffer.writeUUID(train.id);
if (!add)
return;
buffer.writeUUID(train.owner);
buffer.writeVarInt(train.carriages.size());
for (Carriage carriage : train.carriages) {
for (boolean first : Iterate.trueAndFalse) {
if (!first) {
boolean onTwoBogeys = carriage.isOnTwoBogeys();
buffer.writeBoolean(onTwoBogeys);
if (!onTwoBogeys)
continue;
}
CarriageBogey bogey = carriage.bogeys.get(first);
buffer.writeResourceLocation(((Block) bogey.type).getRegistryName());
}
buffer.writeVarInt(carriage.bogeySpacing);
}
buffer.writeVarInt(train.carriageSpacing.size());
train.carriageSpacing.forEach(buffer::writeVarInt);
buffer.writeBoolean(train.doubleEnded);
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Map<UUID, Train> trains = CreateClient.RAILWAYS.trains;
if (add)
trains.put(train.id, train);
else
trains.remove(trainId);
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -13,6 +13,7 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandlerClient;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
@ -21,7 +22,6 @@ import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ISignalBoundaryListener;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang;
@ -35,6 +35,7 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
@ -72,7 +73,7 @@ public class TrainRelocator {
return;
if (mc.level == null)
return;
Train relocating = getRelocating();
Train relocating = getRelocating(mc.level);
if (relocating != null) {
Boolean relocate = relocateClient(relocating, false); // TODO send packet
if (relocate != null && relocate.booleanValue()) {
@ -190,7 +191,7 @@ public class TrainRelocator {
return;
if (relocatingTrain != null) {
Train relocating = getRelocating();
Train relocating = getRelocating(mc.level);
if (relocating == null) {
relocatingTrain = null;
return;
@ -270,10 +271,8 @@ public class TrainRelocator {
return false;
}
private static Train getRelocating() {
if (relocatingTrain == null)
return null;
return Create.RAILWAYS.trains.get(relocatingTrain); // TODO: thread breach
private static Train getRelocating(LevelAccessor level) {
return relocatingTrain == null ? null : Create.RAILWAYS.sided(level).trains.get(relocatingTrain);
}
private static Train getTrainFromEntity(CarriageContraptionEntity carriageContraptionEntity) {

View file

@ -9,15 +9,18 @@ import java.util.UUID;
import java.util.Vector;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.management.GraphLocation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Pair;
@ -68,6 +71,10 @@ public class TravellingPoint {
}
public ITrackSelector follow(TravellingPoint other) {
return follow(other, null);
}
public ITrackSelector follow(TravellingPoint other, @Nullable Consumer<Boolean> success) {
return (graph, pair) -> {
List<Entry<TrackNode, TrackEdge>> validTargets = pair.getSecond();
boolean forward = pair.getFirst();
@ -75,8 +82,11 @@ public class TravellingPoint {
TrackNode secondary = forward ? other.node2 : other.node1;
for (Entry<TrackNode, TrackEdge> entry : validTargets)
if (entry.getKey() == target || entry.getKey() == secondary)
if (entry.getKey() == target || entry.getKey() == secondary) {
if (success != null)
success.accept(true);
return entry;
}
Vector<List<Entry<TrackNode, TrackEdge>>> frontiers = new Vector<>(validTargets.size());
Vector<Set<TrackEdge>> visiteds = new Vector<>(validTargets.size());
@ -107,15 +117,19 @@ public class TravellingPoint {
continue;
TrackNode nextNode = nextEntry.getKey();
if (nextNode == target)
if (nextNode == target) {
if (success != null)
success.accept(true);
return entry;
}
frontier.add(nextEntry);
}
}
}
Create.LOGGER.warn("Couldn't find follow target, choosing first");
if (success != null)
success.accept(false);
return validTargets.get(0);
};
}

View file

@ -1,13 +0,0 @@
package com.simibubi.create.content.logistics.trains.management;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.foundation.utility.Couple;
public class GraphLocation {
public TrackGraph graph;
public Couple<TrackNodeLocation> edge;
public double position;
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import java.util.ArrayList;
import java.util.List;
@ -9,7 +9,7 @@ import javax.annotation.Nullable;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;

View file

@ -5,7 +5,7 @@ import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;

View file

@ -8,7 +8,7 @@ import java.util.UUID;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;

View file

@ -5,9 +5,9 @@ import java.util.Map;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import java.util.UUID;
@ -6,15 +6,14 @@ import javax.annotation.Nullable;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackGraphHelper;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.EdgeData;
import com.simibubi.create.content.logistics.trains.management.signal.SingleTileEdgePoint;
import com.simibubi.create.content.logistics.trains.management.signal.TrackEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -98,9 +97,10 @@ public class TrackTargetingBehaviour<T extends TrackEdgePoint> extends TileEntit
@SuppressWarnings("unchecked")
public T createEdgePoint() {
boolean isClientSide = getWorld().isClientSide;
Level level = getWorld();
boolean isClientSide = level.isClientSide;
if (migrationData == null || isClientSide)
for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) { // TODO thread breach
for (TrackGraph trackGraph : Create.RAILWAYS.sided(level).trackNetworks.values()) {
T point = trackGraph.getPoint(edgePointType, id);
if (point == null)
continue;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.logistics.trains.ITrackBlock;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.Random;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.HashSet;
import java.util.Map;
@ -9,8 +9,8 @@ import com.google.common.base.Objects;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.OverlayState;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.SignalState;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.OverlayState;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.HashSet;
import java.util.Set;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.ArrayList;
import java.util.Collection;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.ArrayList;
import java.util.HashSet;
@ -17,6 +17,7 @@ import com.simibubi.create.content.logistics.trains.TrackGraphSync;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
@ -157,6 +158,8 @@ public class SignalPropagator {
// other/own boundary found
SignalBoundary nextBoundary =
signalData.next(EdgePointType.SIGNAL, currentNode, nextNode, currentEdge, 0);
if (nextBoundary == null)
continue;
if (boundaryCallback.test(Pair.of(currentNode, nextBoundary))) {
notifyTrains(graph, edge, oppositeEdge);
Create.RAILWAYS.sync.edgeDataChanged(graph, currentNode, nextNode, edge, oppositeEdge);

View file

@ -1,12 +1,12 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.OverlayState;
import com.simibubi.create.content.logistics.trains.management.signal.SignalTileEntity.SignalState;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.OverlayState;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;

View file

@ -1,11 +1,11 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.List;
import javax.annotation.Nullable;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.NBTHelper;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.signal;
package com.simibubi.create.content.logistics.trains.management.edgePoint.signal;
import java.util.UUID;
@ -7,8 +7,8 @@ import com.simibubi.create.content.logistics.trains.TrackEdge;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Couple;

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.lang.ref.WeakReference;
import java.util.List;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
@ -87,4 +88,12 @@ public abstract class AbstractStationScreen extends AbstractSimiScreen {
ms.popPose();
}
protected Train getImminent() {
return te.imminentTrain == null ? null : CreateClient.RAILWAYS.trains.get(te.imminentTrain);
}
protected boolean trainPresent() {
return te.trainPresent;
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.lang.ref.WeakReference;
import java.util.List;
@ -105,7 +105,7 @@ public class AssemblyScreen extends AbstractStationScreen {
private void tickTrainDisplay() {
Train train = displayedTrain.get();
Train imminentTrain = station.getPresentTrain();
Train imminentTrain = getImminent();
if (train == null) {
if (imminentTrain != null) {

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.lang.ref.WeakReference;
@ -6,7 +6,7 @@ import javax.annotation.Nullable;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.signal.SingleTileEdgePoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.util.List;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes;
@ -62,10 +62,8 @@ public class StationBlock extends HorizontalDirectionalBlock implements ITE<Stat
ItemStack itemInHand = pPlayer.getItemInHand(pHand);
if (AllItems.WRENCH.isIn(itemInHand))
return InteractionResult.PASS;
if (itemInHand.getItem() == Items.SPONGE) {
if (itemInHand.getItem() == Items.SPONGE)
Create.RAILWAYS.trains.clear();
Create.RAILWAYS.carriageById.clear();
}
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> withTileEntityDo(pLevel, pPos, te -> this.displayScreen(te, pPlayer)));
return InteractionResult.SUCCESS;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.GraphLocation;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket;

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.jozufozu.flywheel.core.PartialModel;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.lang.ref.WeakReference;
import java.util.List;
@ -125,7 +125,7 @@ public class StationScreen extends AbstractStationScreen {
leavingAnimation = 0;
newTrainButton.active = true;
newTrainButton.visible = true;
Train imminentTrain = station.getImminentTrain();
Train imminentTrain = getImminent();
if (imminentTrain != null) {
displayedTrain = new WeakReference<>(imminentTrain);
@ -144,7 +144,7 @@ public class StationScreen extends AbstractStationScreen {
int trainIconWidth = getTrainIconWidth(imminentTrain);
int targetPos = background.width / 2 - trainIconWidth / 2;
float f = (float) (imminentTrain.navigation.distanceToDestination / 15f);
if (imminentTrain.currentStation.equals(station.getId()))
if (trainPresent())
f = 0;
trainPosition.startWithValue(targetPos - (targetPos + 5) * f);
}
@ -169,14 +169,14 @@ public class StationScreen extends AbstractStationScreen {
return;
}
boolean trainAtStation = train.currentStation != null && train.currentStation.equals(station.getId());
if (train.navigation.destination != station && !trainAtStation) {
if (getImminent() != train) {
leavingAnimation = 80;
return;
}
boolean trainAtStation = trainPresent();
disassembleTrainButton.active = trainAtStation; // TODO te.canAssemble
openScheduleButton.active = train.runtime.schedule != null;
openScheduleButton.active = train.runtime.getSchedule() != null;
float f = trainAtStation ? 0 : (float) (train.navigation.distanceToDestination / 30f);
trainPosition.setValue(targetPos - (targetPos + trainIconWidth) * f);

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.util.ArrayList;
import java.util.Arrays;
@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Nullable;
@ -20,11 +21,14 @@ import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNode;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.entity.Carriage;
import com.simibubi.create.content.logistics.trains.entity.Carriage.CarriageBogey;
import com.simibubi.create.content.logistics.trains.entity.CarriageBogey;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TrainPacket;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Iterate;
@ -46,6 +50,7 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.PacketDistributor;
public class StationTileEntity extends SmartTileEntity {
@ -54,6 +59,10 @@ public class StationTileEntity extends SmartTileEntity {
protected int failedCarriageIndex;
protected AssemblyException lastException;
// for display
UUID imminentTrain;
boolean trainPresent;
public StationTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
setLazyTickRate(20);
@ -73,6 +82,17 @@ public class StationTileEntity extends SmartTileEntity {
failedCarriageIndex = tag.getInt("FailedCarriageIndex");
super.read(tag, clientPacket);
invalidateRenderBoundingBox();
if (!clientPacket)
return;
if (!tag.contains("ImminentTrain")) {
imminentTrain = null;
trainPresent = false;
return;
}
imminentTrain = tag.getUUID("ImminentTrain");
trainPresent = tag.getBoolean("TrainPresent");
}
@Override
@ -80,6 +100,18 @@ public class StationTileEntity extends SmartTileEntity {
AssemblyException.write(tag, lastException);
tag.putInt("FailedCarriageIndex", failedCarriageIndex);
super.write(tag, clientPacket);
if (!clientPacket)
return;
GlobalStation station = getStation();
if (station == null)
return;
Train imminentTrain = station.getImminentTrain();
if (imminentTrain == null)
return;
tag.putUUID("ImminentTrain", imminentTrain.id);
tag.putBoolean("TrainPresent", imminentTrain.getCurrentStation() == station);
}
@Nullable
@ -109,6 +141,23 @@ public class StationTileEntity extends SmartTileEntity {
if (isAssembling() && level.isClientSide)
refreshAssemblyInfo();
super.tick();
if (level.isClientSide)
return;
GlobalStation station = getStation();
if (station == null)
return;
Train imminentTrain = station.getImminentTrain();
boolean trainPresent = imminentTrain != null && imminentTrain.getCurrentStation() == station;
UUID imminentID = imminentTrain != null ? imminentTrain.id : null;
if (this.trainPresent != trainPresent || !Objects.equals(imminentID, this.imminentTrain)) {
this.imminentTrain = imminentID;
this.trainPresent = trainPresent;
sendData();
}
}
public void trackClicked(Player player, ITrackBlock track, BlockState state, BlockPos pos) {
@ -192,7 +241,7 @@ public class StationTileEntity extends SmartTileEntity {
}
BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos));
if (potentialBogeyState.getBlock() instanceof IBogeyBlock bogey && bogeyIndex < bogeyLocations.length) {
if (potentialBogeyState.getBlock()instanceof IBogeyBlock bogey && bogeyIndex < bogeyLocations.length) {
bogeyTypes[bogeyIndex] = bogey;
bogeyLocations[bogeyIndex] = i;
bogeyIndex++;
@ -412,9 +461,7 @@ public class StationTileEntity extends SmartTileEntity {
}
contraptions.add(contraption);
Carriage carriage = new Carriage(firstBogey, secondBogey, bogeySpacing);
carriage.setContraption(contraption);
carriages.add(carriage);
carriages.add(new Carriage(firstBogey, secondBogey, bogeySpacing));
}
if (!atLeastOneForwardControls) {
@ -427,7 +474,13 @@ public class StationTileEntity extends SmartTileEntity {
contraption.expandBoundsAroundAxis(Axis.Y);
}
Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing);
Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing, contraptions.stream()
.anyMatch(CarriageContraption::hasBackwardControls));
for (int i = 0; i < contraptions.size(); i++)
carriages.get(i)
.setContraption(level, contraptions.get(i));
GlobalStation station = getStation();
if (station != null) {
train.setCurrentStation(station);
@ -436,6 +489,7 @@ public class StationTileEntity extends SmartTileEntity {
train.collectInitiallyOccupiedSignalBlocks();
Create.RAILWAYS.trains.put(train.id, train);
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, true));
clearException();
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import java.util.UUID;
import java.util.function.Supplier;
@ -6,12 +6,16 @@ import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.entity.TrainIconType;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraftforge.network.NetworkEvent.Context;
import net.minecraftforge.network.PacketDistributor;
public class TrainEditPacket extends SimplePacketBase {
@ -44,18 +48,34 @@ public class TrainEditPacket extends SimplePacketBase {
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Train train = Create.RAILWAYS.trains.get(id);
if (train == null)
return;
if (!name.isBlank())
train.name = new TextComponent(name);
train.icon = TrainIconType.byId(iconType);
train.heldForAssembly = heldForAssembly;
});
context.get()
.setPacketHandled(true);
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayer sender = ctx.getSender();
Level level = sender == null ? null : sender.level;
Train train = Create.RAILWAYS.sided(level).trains.get(id);
if (train == null)
return;
if (!name.isBlank())
train.name = new TextComponent(name);
train.icon = TrainIconType.byId(iconType);
train.heldForAssembly = heldForAssembly;
if (sender != null)
AllPackets.channel.send(PacketDistributor.ALL.noArg(),
new TrainEditReturnPacket(id, name, heldForAssembly, iconType));
});
ctx.setPacketHandled(true);
}
public static class TrainEditReturnPacket extends TrainEditPacket {
public TrainEditReturnPacket(FriendlyByteBuf buffer) {
super(buffer);
}
public TrainEditReturnPacket(UUID id, String name, boolean heldForAssembly, ResourceLocation iconType) {
super(id, name, heldForAssembly, iconType);
}
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.edgePoint.station;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.gui.AllGuiTextures;

View file

@ -7,7 +7,6 @@ import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.client.gui.components.events.GuiEventListener;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.schedule;
public class RunningScheduleScreen {

View file

@ -5,6 +5,18 @@ import java.util.List;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.FluidThresholdCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.IdleCargoCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ItemThresholdCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationPoweredCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationUnloadedCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimeOfDayCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.FilteredDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.NearestDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.RedstoneDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.schedule;
import com.simibubi.create.foundation.gui.container.GhostItemContainer;

View file

@ -3,6 +3,8 @@ package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.schedule;
import com.simibubi.create.AllContainerTypes;
import com.simibubi.create.AllSoundEvents;
@ -6,7 +6,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Lang;
@ -79,7 +78,7 @@ public class ScheduleItem extends Item implements MenuProvider {
Contraption contraption = entity.getContraption();
if (contraption instanceof CarriageContraption cc) {
Train train = cc.getCarriage().train;
Train train = entity.getCarriage().train;
if (train == null)
return InteractionResult.SUCCESS;
if (train.heldForAssembly) {

View file

@ -1,15 +1,14 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEntry;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.FilteredDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management;
package com.simibubi.create.content.logistics.trains.management.schedule;
import java.util.ArrayList;
import java.util.Collections;
@ -16,15 +16,11 @@ import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.simibubi.create.content.logistics.trains.management.schedule.FilteredDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEditPacket;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEntry;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.TimedWaitCondition.TimeUnit;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay;
import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimedWaitCondition.TimeUnit;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.FilteredDestination;
import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleDestination;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.UIRenderHelper;

View file

@ -1,11 +1,12 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import java.util.function.BiConsumer;
@ -7,7 +7,8 @@ import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.processing.EmptyingByBasin;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.Lang;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import java.util.function.BiConsumer;
@ -6,7 +6,8 @@ import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;

View file

@ -1,9 +1,11 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;

View file

@ -1,8 +1,8 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -1,8 +1,8 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import java.util.function.BiConsumer;
@ -8,7 +8,8 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.utility.Lang;

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.condition;
import java.util.List;
import java.util.function.BiConsumer;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.gui.widget.Label;
import com.simibubi.create.foundation.gui.widget.ScrollInput;
import com.simibubi.create.foundation.gui.widget.SelectionScrollInput;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import java.util.List;
import java.util.function.BiConsumer;
@ -8,7 +8,8 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.ScheduleScreen;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;

View file

@ -1,8 +1,10 @@
package com.simibubi.create.content.logistics.trains.management.schedule;
package com.simibubi.create.content.logistics.trains.management.schedule.destination;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.trains.management.schedule.IScheduleInput;
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.nbt.CompoundTag;

View file

@ -23,8 +23,8 @@ import com.simibubi.create.content.logistics.trains.ITrackBlock;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
import com.simibubi.create.content.logistics.trains.TrackPropagator;
import com.simibubi.create.content.logistics.trains.management.StationTileEntity;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;

View file

@ -35,7 +35,7 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionP
import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler;
import com.simibubi.create.content.logistics.trains.entity.CarriageCouplingRenderer;
import com.simibubi.create.content.logistics.trains.entity.TrainRelocator;
import com.simibubi.create.content.logistics.trains.management.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
import com.simibubi.create.content.logistics.trains.track.TrackPlacement;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;

View file

@ -10,11 +10,11 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.content.logistics.trains.GlobalRailwayManager;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.entity.Train;
import com.simibubi.create.content.logistics.trains.management.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime;
import com.simibubi.create.content.logistics.trains.management.ScheduleRuntime.State;
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
import com.simibubi.create.content.logistics.trains.management.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;

View file

@ -44,10 +44,12 @@ import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.logistics.packet.FunnelFlapPacket;
import com.simibubi.create.content.logistics.packet.TunnelFlapPacket;
import com.simibubi.create.content.logistics.trains.TrackGraphSyncPacket;
import com.simibubi.create.content.logistics.trains.management.StationEditPacket;
import com.simibubi.create.content.logistics.trains.management.TrainEditPacket;
import com.simibubi.create.content.logistics.trains.entity.TrainPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroupPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationEditPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.TrainEditPacket;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.TrainEditPacket.TrainEditReturnPacket;
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleEditPacket;
import com.simibubi.create.content.logistics.trains.management.signal.SignalEdgeGroupPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket;
import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
@ -110,7 +112,7 @@ public enum AllPackets {
TOOLBOX_DISPOSE_ALL(ToolboxDisposeAllPacket.class, ToolboxDisposeAllPacket::new, PLAY_TO_SERVER),
CONFIGURE_SCHEDULE(ScheduleEditPacket.class, ScheduleEditPacket::new, PLAY_TO_SERVER),
CONFIGURE_STATION(StationEditPacket.class, StationEditPacket::new, PLAY_TO_SERVER),
CONFIGURE_TRAIN(TrainEditPacket.class, TrainEditPacket::new, PLAY_TO_SERVER),
C_CONFIGURE_TRAIN(TrainEditPacket.class, TrainEditPacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
@ -135,7 +137,9 @@ public enum AllPackets {
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),
;