Create/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java
simibubi e5c6ca157c Squashed commit of the following:
commit 053dd09df6c426ab5e570f42a1edb5df3d0fbd01
Merge: 6d1e1c71d ecc645eba
Author: simibubi <31564874+simibubi@users.noreply.github.com>
Date:   Tue May 9 18:22:42 2023 +0200

    Merge branch '1.18/api' of https://github.com/Layers-of-Railways/Create into pr/4692

commit ecc645eba7
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Tue May 9 11:24:11 2023 +0100

    Implemented support for creating and removing individual blockstate models

commit 6d1e1c71de7ce20f6fd9fc8ed4ed9bdd1072829a
Author: simibubi <31564874+simibubi@users.noreply.github.com>
Date:   Tue May 9 12:16:54 2023 +0200

    Less error logging when migrating old worlds

commit 205e47352e
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 21:02:19 2023 -0700

    Fix up ItemOutline

commit 6cf204f6af
Merge: fe049bc77 2e3c906ce
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:28:56 2023 -0700

    Merge remote-tracking branch 'upstream/mc1.18/dev' into 1.18/api

    # Conflicts:
    #	src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java

commit fe049bc771
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:26:16 2023 -0700

    Revert "Revert "Rewrite outline buffering""

    This reverts commit 726bfaf0

commit 435b4c1c16
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:20:23 2023 -0700

    Clean up last bits of upside down rendering

commit 662da6bab1
Merge: 122fe77af d83285e8a
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:16:32 2023 -0700

    Merge remote-tracking branch 'origin/1.18/api' into 1.18/api

    # Conflicts:
    #	src/main/java/com/simibubi/create/content/logistics/trains/StandardBogeyRenderer.java

commit 122fe77afa
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 8 20:15:46 2023 -0700

    Fix up upside down rendering

commit d83285e8a4
Merge: 00e953a58 cdb0ad210
Author: techno-sam <77073745+techno-sam@users.noreply.github.com>
Date:   Sun May 7 07:02:18 2023 -0700

    Merge pull request #3 from Layers-of-Railways/1.18/bogey-api

    Cleanup cycle groups and unused imports

commit cdb0ad210b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 10:15:47 2023 +0100

    Fixed merge artifact

commit 457d5f33ed
Merge: 4e4e227a3 00e953a58
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 10:14:07 2023 +0100

    Merge remote-tracking branch 'origin/1.18/api' into 1.18/api

commit 00e953a585
Merge: 1e4d5504e a7a25896c
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Sun May 7 10:13:49 2023 +0100

    Merge pull request #2 from Rabbitminers/mc1.18/dev

    Added Return Values and Small Cleanup

commit a7a25896c1
Merge: 7622128be 1e4d5504e
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Sun May 7 10:13:40 2023 +0100

    Merge branch '1.18/api' into mc1.18/dev

commit 4e4e227a35
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 10:10:30 2023 +0100

    Cleanup to cycle groups

commit aa94fc97d1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun May 7 09:50:50 2023 +0100

    Removed unused import of Railways

commit 7622128bec
Merge: 81eeadb85 d52065808
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Sun May 7 09:11:59 2023 +0100

    Merge branch 'Layers-of-Railways:mc1.18/dev' into mc1.18/dev

commit 1e4d5504ee
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 18:03:39 2023 -0700

    Don't revert non-buggy changes

commit b306cf2124
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 18:00:59 2023 -0700

    Take materials into consideration when trains pathfind

commit fca02ae4bf
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat May 6 10:25:51 2023 -0700

    Add materials to track graph

commit 726bfaf0b5
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 21:16:49 2023 -0700

    Revert "Rewrite outline buffering"

    This reverts commit d4106d545b.

commit 171897bed2
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 20:55:25 2023 -0700

    Fix up style cycling

commit cbd0cf20da
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 07:32:06 2023 -0700

    clean up nether portal carriage handling

commit d556f08876
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Fri May 5 07:06:02 2023 -0700

    upside down bogeys work in nether portals
    fixed coupling anchor offsets

commit da26c0ccbf
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Thu May 4 09:32:53 2023 -0700

    working on upside down bogeys in nether portals

commit 81eeadb853
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 16:15:28 2023 +0100

    Small cleanup

commit c7e9df973c
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 16:13:51 2023 +0100

    Fixed issue raised in #1

commit 2f285b6eb7
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Mon May 1 08:13:27 2023 -0700

    add data gen

commit 206de01311
Merge: e91753a33 6564f4fa7
Author: techno-sam <77073745+techno-sam@users.noreply.github.com>
Date:   Mon May 1 06:49:21 2023 -0700

    Merge pull request #1 from Rabbitminers/mc1.18/dev

    Bogey API

commit 6564f4fa73
Merge: e5d759582 e91753a33
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Mon May 1 10:40:32 2023 +0100

    Merge branch '1.18/api' into mc1.18/dev

commit e5d7595822
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon May 1 10:09:03 2023 +0100

    Connected Custom Bogey Particle Types To CarriageParticles

commit e91753a33c
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 30 19:51:26 2023 -0700

    Fix up some problems

commit 9815f1490f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:12:43 2023 +0100

    Implemented default data when shifting styles

commit da30e78815
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:12:14 2023 +0100

    Added Particles To Bogey Style (And Respective Builder)

commit 08c000b8ba
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:01:19 2023 +0100

    Added Backup Rendering If A Size Is Not Present

commit 2b76e8d7b3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 21:00:40 2023 +0100

    Added Common Renderer To Remove Function

commit 411ec36f57
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:59:50 2023 +0100

    Added Display Name To Standard Bogey Style

commit 112306d5d4
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:59:30 2023 +0100

    Displayed new style name when changing betweeen them

commit 5634670b27
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:06:00 2023 +0100

    General Cleanup

commit 0f7a8b7b24
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:05:50 2023 +0100

    Implemented Changes To Remaining Classes

commit 8aedc00f96
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:02:06 2023 +0100

    Removed Bogey Style Handling From Registrate

commit edf8079abf
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:40 2023 +0100

    Removed Unused Registry Handling

commit 6a185c4e72
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:16 2023 +0100

    Refactored Bogey Sizes

commit e10d07ddc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 30 20:01:00 2023 +0100

    Overhauled Bogey Style

commit 74d98a2ad5
Merge: e629d02f5 4ebcf8201
Author: techno-sam <77073745+techno-sam@users.noreply.github.com>
Date:   Sun Apr 23 07:16:33 2023 -0700

    Merge branch 'Creators-of-Create:mc1.18/dev' into 1.18/api

commit e629d02f50
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 9 07:18:22 2023 -0700

    Track API

    Clean up code a bit

commit d9ce6ce995
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sun Apr 9 07:14:46 2023 -0700

    Track API?

    Fix placement

commit 7fbf08ba54
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat Apr 8 11:11:24 2023 -0700

    Track API?

    Fix up some placement issues

commit 35644f1434
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Sat Apr 8 08:11:13 2023 -0700

    Track API maybe?

    Datagen
    Seems to be working

commit f7c56b867a
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Thu Apr 6 21:24:31 2023 -0700

    Track API maybe?

    Fix build - broken generic
    Not yet tested, but it is progress

commit 2a59fd7e8a
Author: techno-sam <linux.techno.sam@gmail.com>
Date:   Thu Apr 6 21:13:54 2023 -0700

    Track API maybe?

    Not yet tested, but it is progress

commit 5ba30d6a85
Merge: e4e5ac1c4 c2977bbff
Author: techno-sam <77073745+techno-sam@users.noreply.github.com>
Date:   Thu Apr 6 17:10:39 2023 -0700

    Merge branch 'Creators-of-Create:mc1.18/dev' into 1.18/api

commit d52065808c
Merge: e4e5ac1c4 c2977bbff
Author: techno-sam <77073745+techno-sam@users.noreply.github.com>
Date:   Thu Apr 6 17:10:26 2023 -0700

    Merge branch 'Creators-of-Create:mc1.18/dev' into mc1.18/dev

commit 53240bd42f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 21:42:29 2023 +0100

    Corrected Bogey InteractionResult To Pass

commit 69326e361a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 21:30:28 2023 +0100

    Fixed Default Values When Used Styles Are Removed

commit 4f176979de
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 19:33:17 2023 +0100

    Fixed Carriage Sounds (Again)

commit 1e80af3303
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 19:27:58 2023 +0100

    Refactored Bogey Sizes To Seperate Class

commit 129be61fee
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 17:20:17 2023 +0100

    Fixed Bogey Sound Loading

commit 2543185a55
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 09:45:23 2023 +0100

    Added Bogey Sound Customisation

commit 1ad5ae9514
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Mon Apr 3 00:44:53 2023 +0100

    Added Size Transforms If Size Is Not Available For New Style

commit 96566b1614
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 23:02:02 2023 +0100

    Moved Bogey Style Inside Of Bogey Data And Implemented Bogey Data Communication

commit eedd984738
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:53:55 2023 +0100

    Fixed Large Bogey Size

commit 68ca0974c6
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:47:58 2023 +0100

    Implemented Style Cycling & Default Values

commit a55ba4267a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:46:15 2023 +0100

    Implemented renderer instance creator

commit 43523302c2
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sun Apr 2 16:45:33 2023 +0100

    Removed Unused Standard Bogey Instance

commit 773e084422
Merge: 0c0b5a1ed d1e1f7ec5
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Apr 1 18:50:15 2023 +0100

    Merge remote-tracking branch 'origin/mc1.18/dev' into mc1.18/dev

    # Conflicts:
    #	src/main/java/com/simibubi/create/AllBogeyStyles.java
    #	src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java
    #	src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyStyle.java
    #	src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java
    #	src/main/java/com/simibubi/create/content/logistics/trains/entity/StandardBogeyInstance.java
    #	src/main/java/com/simibubi/create/foundation/data/BogeyStyleBuilder.java

commit 0c0b5a1ed6
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Apr 1 18:39:58 2023 +0100

    Linked Style Registry To Bogey Blocks

commit 71f839ee51
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Apr 1 18:39:03 2023 +0100

    Replaced size boolean with direct use of size enum

commit 50ff081704
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:47:13 2023 +0100

    Added Resource Location To NBT helper methods

commit d1e1f7ec5a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:47:13 2023 +0100

    Re-worked BogeyStyles

commit da593fccb1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 30 18:46:02 2023 +0100

    Refactored IBogeyBlock to AbstractBogeyBlock and extracted relevant StandardBogeyBlock implementations

commit 17432c9113
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Sat Mar 25 10:20:50 2023 +0000

    Fixed Incorrect Registry Loading

commit c7d899369a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:44:03 2023 +0000

    Registered Registers

commit 6d862290d7
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:43:23 2023 +0000

    Added BogeyStyleBuilder To Registrate

commit 3dfb9e3b3b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:43:08 2023 +0000

    Implemented AllBogeyStyles

commit c9e71b462d
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:42:56 2023 +0000

    Created BogeyStyleBuilder

commit a90977d642
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:42:25 2023 +0000

    Created AllRegistries and BogeyStyle Registry

commit 154d455f3f
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Fri Mar 24 23:41:56 2023 +0000

    Added BogeyStyle Wrapper

commit dfb7640bfc
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:50:41 2023 +0000

    Removed left over logging statement

commit 9920536cc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:50:18 2023 +0000

    Implemented Secondary Shaft To Large Renderer

commit 6cd40cc6f9
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:49:56 2023 +0000

    Prevented Overwrite When Using Two BlockStates Of The Same Type With Different Properties

commit 06fb901144
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:39:11 2023 +0000

    Implemented Common Rendering For StandardBogeyRenderer

commit 435b0f8266
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:38:40 2023 +0000

    Added Common Renderer

commit 96a0623dab
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 18:38:29 2023 +0000

    Implemented BlockState Models For Rendering

commit 469d9d592b
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:42:28 2023 +0000

    Added Standard Bogey Instance (Might be redundant)

commit 2661d260d8
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:42:06 2023 +0000

    Refactored Changes To Existing Methods

commit 9ded16fbab
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:41:15 2023 +0000

    Integrated BogeyRenderer To BogeyInstance (Also Corrected Rendering In Contraption)

commit 4a82fcbca1
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:40:13 2023 +0000

    Implemented Changes To StandardBogeyBlock

commit 7238fb93f3
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Thu Mar 23 17:39:51 2023 +0000

    Added Renderer To IBogeyBlock

commit ded4c1f613
Merge: 91727cc84 3c02fe6ec
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Wed Mar 22 17:03:37 2023 +0000

    Merge remote-tracking branch 'origin/mc1.18/dev' into mc1.18/dev

commit 91727cc84a
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Wed Mar 22 17:03:28 2023 +0000

    Implemented Model Data Initializer to StandardBogeyRenderer

commit 6d98a1f469
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Wed Mar 22 17:03:00 2023 +0000

    Added Contraption Model Instance Initializer

commit 3c02fe6ecc
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com>
Date:   Tue Mar 21 22:45:34 2023 +0000

    Added missing render type check

commit 6672c49649
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Tue Mar 21 22:37:36 2023 +0000

    Re-created standard bogey with test api

commit a8a9491fa0
Author: Rabbitminers <Rabbitminers2.0@gmail.com>
Date:   Tue Mar 21 22:34:54 2023 +0000

    Implemented Proof Of Concept Generic Bogey Renderer

commit e4e5ac1c40
Author: SpottyTheTurtle <69260662+SpottyTheTurtle@users.noreply.github.com>
Date:   Sat Mar 11 21:34:59 2023 +0000

    init
2023-05-09 18:23:47 +02:00

900 lines
30 KiB
Java

package com.simibubi.create.content.logistics.trains.entity;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
import com.simibubi.create.content.logistics.trains.DimensionPalette;
import com.simibubi.create.content.logistics.trains.TrackGraph;
import com.simibubi.create.content.logistics.trains.TrackNodeLocation;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.IEdgePointListener;
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
public class Carriage {
public static final AtomicInteger netIdGenerator = new AtomicInteger();
public Train train;
public int id;
public boolean blocked;
public boolean stalled;
public Couple<Boolean> presentConductors;
public int bogeySpacing;
public Couple<CarriageBogey> bogeys;
public TrainCargoManager storage;
CompoundTag serialisedEntity;
Map<Integer, CompoundTag> serialisedPassengers;
private Map<ResourceKey<Level>, DimensionalCarriageEntity> entities;
static final int FIRST = 0, MIDDLE = 1, LAST = 2, BOTH = 3;
public Carriage(CarriageBogey bogey1, @Nullable CarriageBogey bogey2, int bogeySpacing) {
this.bogeySpacing = bogeySpacing;
this.bogeys = Couple.create(bogey1, bogey2);
this.id = netIdGenerator.incrementAndGet();
this.serialisedEntity = new CompoundTag();
this.presentConductors = Couple.create(false, false);
this.serialisedPassengers = new HashMap<>();
this.entities = new HashMap<>();
this.storage = new TrainCargoManager();
bogey1.setLeading();
bogey1.carriage = this;
if (bogey2 != null)
bogey2.carriage = this;
}
public boolean isOnIncompatibleTrack() {
return leadingBogey().type.isOnIncompatibleTrack(this, true)
|| trailingBogey().type.isOnIncompatibleTrack(this, false);
}
public void setTrain(Train train) {
this.train = train;
}
public boolean presentInMultipleDimensions() {
return entities.size() > 1;
}
public void setContraption(Level level, CarriageContraption contraption) {
this.storage = null;
CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption);
entity.setCarriage(this);
contraption.startMoving(level);
contraption.onEntityInitialize(level, entity);
updateContraptionAnchors();
DimensionalCarriageEntity dimensional = getDimensional(level);
dimensional.alignEntity(entity);
dimensional.removeAndSaveEntity(entity, false);
}
public DimensionalCarriageEntity getDimensional(Level level) {
return getDimensional(level.dimension());
}
public DimensionalCarriageEntity getDimensional(ResourceKey<Level> dimension) {
return entities.computeIfAbsent(dimension, $ -> new DimensionalCarriageEntity());
}
@Nullable
public DimensionalCarriageEntity getDimensionalIfPresent(ResourceKey<Level> dimension) {
return entities.get(dimension);
}
public double travel(Level level, TrackGraph graph, double distance, TravellingPoint toFollowForward,
TravellingPoint toFollowBackward, int type) {
Function<TravellingPoint, ITrackSelector> forwardControl =
toFollowForward == null ? train.navigation::control : mp -> mp.follow(toFollowForward);
Function<TravellingPoint, ITrackSelector> backwardControl =
toFollowBackward == null ? train.navigation::control : mp -> mp.follow(toFollowBackward);
boolean onTwoBogeys = isOnTwoBogeys();
double stress = train.derailed ? 0 : onTwoBogeys ? bogeySpacing - getAnchorDiff() : 0;
blocked = false;
MutableDouble distanceMoved = new MutableDouble(distance);
boolean iterateFromBack = distance < 0;
for (boolean firstBogey : Iterate.trueAndFalse) {
if (!firstBogey && !onTwoBogeys)
continue;
boolean actuallyFirstBogey = !onTwoBogeys || (firstBogey ^ iterateFromBack);
CarriageBogey bogey = bogeys.get(actuallyFirstBogey);
double bogeyCorrection = stress * (actuallyFirstBogey ? 0.5d : -0.5d);
double bogeyStress = bogey.getStress();
for (boolean firstWheel : Iterate.trueAndFalse) {
boolean actuallyFirstWheel = firstWheel ^ iterateFromBack;
TravellingPoint point = bogey.points.get(actuallyFirstWheel);
TravellingPoint prevPoint = !actuallyFirstWheel ? bogey.points.getFirst()
: !actuallyFirstBogey && onTwoBogeys ? bogeys.getFirst().points.getSecond() : null;
TravellingPoint nextPoint = actuallyFirstWheel ? bogey.points.getSecond()
: actuallyFirstBogey && onTwoBogeys ? bogeys.getSecond().points.getFirst() : null;
double correction = bogeyStress * (actuallyFirstWheel ? 0.5d : -0.5d);
double toMove = distanceMoved.getValue();
ITrackSelector frontTrackSelector =
prevPoint == null ? forwardControl.apply(point) : point.follow(prevPoint);
ITrackSelector backTrackSelector =
nextPoint == null ? backwardControl.apply(point) : point.follow(nextPoint);
boolean atFront = (type == FIRST || type == BOTH) && actuallyFirstWheel && actuallyFirstBogey;
boolean atBack =
(type == LAST || type == BOTH) && !actuallyFirstWheel && (!actuallyFirstBogey || !onTwoBogeys);
IEdgePointListener frontListener = train.frontSignalListener();
IEdgePointListener backListener = train.backSignalListener();
IEdgePointListener passiveListener = point.ignoreEdgePoints();
toMove += correction + bogeyCorrection;
ITrackSelector trackSelector = toMove > 0 ? frontTrackSelector : backTrackSelector;
IEdgePointListener signalListener =
toMove > 0 ? atFront ? frontListener : atBack ? backListener : passiveListener
: atFront ? backListener : atBack ? frontListener : passiveListener;
double moved = point.travel(graph, toMove, trackSelector, signalListener, point.ignoreTurns(), c -> {
for (DimensionalCarriageEntity dce : entities.values())
if (c.either(tnl -> tnl.equalsIgnoreDim(dce.pivot)))
return false;
if (entities.size() > 1) {
train.status.doublePortal();
return true;
}
return false;
});
blocked |= point.blocked;
distanceMoved.setValue(moved);
}
}
updateContraptionAnchors();
manageEntities(level);
return distanceMoved.getValue();
}
public double getAnchorDiff() {
double diff = 0;
int entries = 0;
TravellingPoint leadingPoint = getLeadingPoint();
TravellingPoint trailingPoint = getTrailingPoint();
if (leadingPoint.node1 != null && trailingPoint.node1 != null)
if (!leadingPoint.node1.getLocation().dimension.equals(trailingPoint.node1.getLocation().dimension))
return bogeySpacing;
for (DimensionalCarriageEntity dce : entities.values())
if (dce.leadingAnchor() != null && dce.trailingAnchor() != null) {
entries++;
diff += dce.leadingAnchor()
.distanceTo(dce.trailingAnchor());
}
if (entries == 0)
return bogeySpacing;
return diff / entries;
}
public void updateConductors() {
if (anyAvailableEntity() == null || entities.size() > 1 || serialisedPassengers.size() > 0)
return;
presentConductors.replace($ -> false);
for (DimensionalCarriageEntity dimensionalCarriageEntity : entities.values()) {
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity != null && entity.isAlive())
presentConductors.replaceWithParams((current, checked) -> current || checked, entity.checkConductors());
}
}
private Set<ResourceKey<Level>> currentlyTraversedDimensions = new HashSet<>();
public void manageEntities(Level level) {
currentlyTraversedDimensions.clear();
bogeys.forEach(cb -> {
if (cb == null)
return;
cb.points.forEach(tp -> {
if (tp.node1 == null)
return;
currentlyTraversedDimensions.add(tp.node1.getLocation().dimension);
});
});
for (Iterator<Entry<ResourceKey<Level>, DimensionalCarriageEntity>> iterator = entities.entrySet()
.iterator(); iterator.hasNext();) {
Entry<ResourceKey<Level>, DimensionalCarriageEntity> entry = iterator.next();
boolean discard =
!currentlyTraversedDimensions.isEmpty() && !currentlyTraversedDimensions.contains(entry.getKey());
MinecraftServer server = level.getServer();
if (server == null)
continue;
ServerLevel currentLevel = server.getLevel(entry.getKey());
if (currentLevel == null)
continue;
DimensionalCarriageEntity dimensionalCarriageEntity = entry.getValue();
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity == null) {
if (discard)
iterator.remove();
else if (dimensionalCarriageEntity.positionAnchor != null && CarriageEntityHandler
.isActiveChunk(currentLevel, new BlockPos(dimensionalCarriageEntity.positionAnchor)))
dimensionalCarriageEntity.createEntity(currentLevel, anyAvailableEntity() == null);
} else {
if (discard) {
discard = dimensionalCarriageEntity.discardTicks > 3;
dimensionalCarriageEntity.discardTicks++;
} else
dimensionalCarriageEntity.discardTicks = 0;
CarriageEntityHandler.validateCarriageEntity(entity);
if (!entity.isAlive() || entity.leftTickingChunks || discard) {
dimensionalCarriageEntity.removeAndSaveEntity(entity, discard);
if (discard)
iterator.remove();
continue;
}
}
entity = dimensionalCarriageEntity.entity.get();
if (entity != null && dimensionalCarriageEntity.positionAnchor != null) {
dimensionalCarriageEntity.alignEntity(entity);
entity.syncCarriage();
}
}
}
public void updateContraptionAnchors() {
CarriageBogey leadingBogey = leadingBogey();
if (leadingBogey.points.either(t -> t.edge == null))
return;
CarriageBogey trailingBogey = trailingBogey();
if (trailingBogey.points.either(t -> t.edge == null))
return;
ResourceKey<Level> leadingBogeyDim = leadingBogey.getDimension();
ResourceKey<Level> trailingBogeyDim = trailingBogey.getDimension();
double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing();
double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing();
boolean leadingUpsideDown = leadingBogey.isUpsideDown();
boolean trailingUpsideDown = trailingBogey.isUpsideDown();
for (boolean leading : Iterate.trueAndFalse) {
TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint();
TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint();
ResourceKey<Level> dimension = point.node1.getLocation().dimension;
ResourceKey<Level> otherDimension = otherPoint.node1.getLocation().dimension;
if (dimension.equals(otherDimension) && leading) {
getDimensional(dimension).discardPivot();
continue;
}
DimensionalCarriageEntity dce = getDimensional(dimension);
dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
: pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
leadingUpsideDown, trailingUpsideDown);
boolean backAnchorFlip = trailingBogey.isUpsideDown() ^ leadingBogey.isUpsideDown();
if (isOnTwoBogeys()) {
dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
: pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
leadingUpsideDown, trailingUpsideDown));
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition(backAnchorFlip)
: pivoted(dce, dimension, point,
leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2,
leadingUpsideDown, trailingUpsideDown));
} else {
if (dimension.equals(otherDimension)) {
dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition);
} else {
dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition()
: pivoted(dce, dimension, point, leadingWheelSpacing,
leadingUpsideDown, trailingUpsideDown));
dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition()
: pivoted(dce, dimension, point, leadingWheelSpacing,
leadingUpsideDown, trailingUpsideDown));
}
}
int prevmin = dce.minAllowedLocalCoord();
int prevmax = dce.maxAllowedLocalCoord();
dce.updateCutoff(leading);
if (prevmin != dce.minAllowedLocalCoord() || prevmax != dce.maxAllowedLocalCoord()) {
dce.updateRenderedCutoff();
dce.updatePassengerLoadout();
}
}
}
private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey<Level> dimension, TravellingPoint start,
double offset, boolean leadingUpsideDown, boolean trailingUpsideDown) {
if (train.graph == null)
return dce.pivot == null ? null : dce.pivot.getLocation();
TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint());
if (pivot == null)
return null;
boolean flipped = start != getLeadingPoint() && (leadingUpsideDown != trailingUpsideDown);
Vec3 startVec = start.getPosition(flipped);
Vec3 portalVec = pivot.getLocation()
.add(0, leadingUpsideDown ? -1.0 : 1.0, 0);
return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec);
}
public void alignEntity(Level level) {
DimensionalCarriageEntity dimensionalCarriageEntity = entities.get(level.dimension());
if (dimensionalCarriageEntity != null) {
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity != null)
dimensionalCarriageEntity.alignEntity(entity);
}
}
public TravellingPoint getLeadingPoint() {
return leadingBogey().leading();
}
public TravellingPoint getTrailingPoint() {
return trailingBogey().trailing();
}
public CarriageBogey leadingBogey() {
return bogeys.getFirst();
}
public CarriageBogey trailingBogey() {
return isOnTwoBogeys() ? bogeys.getSecond() : leadingBogey();
}
public boolean isOnTwoBogeys() {
return bogeys.getSecond() != null;
}
public CarriageContraptionEntity anyAvailableEntity() {
for (DimensionalCarriageEntity dimensionalCarriageEntity : entities.values()) {
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity != null)
return entity;
}
return null;
}
public void forEachPresentEntity(Consumer<CarriageContraptionEntity> callback) {
for (DimensionalCarriageEntity dimensionalCarriageEntity : entities.values()) {
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity != null)
callback.accept(entity);
}
}
public CompoundTag write(DimensionPalette dimensions) {
CompoundTag tag = new CompoundTag();
tag.put("FirstBogey", bogeys.getFirst()
.write(dimensions));
if (isOnTwoBogeys())
tag.put("SecondBogey", bogeys.getSecond()
.write(dimensions));
tag.putInt("Spacing", bogeySpacing);
tag.putBoolean("FrontConductor", presentConductors.getFirst());
tag.putBoolean("BackConductor", presentConductors.getSecond());
tag.putBoolean("Stalled", stalled);
Map<Integer, CompoundTag> passengerMap = new HashMap<>();
for (DimensionalCarriageEntity dimensionalCarriageEntity : entities.values()) {
CarriageContraptionEntity entity = dimensionalCarriageEntity.entity.get();
if (entity == null)
continue;
serialize(entity);
Contraption contraption = entity.getContraption();
if (contraption == null)
continue;
Map<UUID, Integer> mapping = contraption.getSeatMapping();
for (Entity passenger : entity.getPassengers())
if (mapping.containsKey(passenger.getUUID()))
passengerMap.put(mapping.get(passenger.getUUID()), passenger.serializeNBT());
}
tag.put("Entity", serialisedEntity.copy());
CompoundTag passengerTag = new CompoundTag();
passengerMap.putAll(serialisedPassengers);
passengerMap.forEach((seat, nbt) -> passengerTag.put("Seat" + seat, nbt.copy()));
tag.put("Passengers", passengerTag);
tag.put("EntityPositioning", NBTHelper.writeCompoundList(entities.entrySet(), e -> {
CompoundTag c = e.getValue()
.write();
c.putInt("Dim", dimensions.encode(e.getKey()));
return c;
}));
return tag;
}
private void serialize(Entity entity) {
serialisedEntity = entity.serializeNBT();
serialisedEntity.remove("Passengers");
serialisedEntity.getCompound("Contraption")
.remove("Passengers");
}
public static Carriage read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
CarriageBogey bogey1 = CarriageBogey.read(tag.getCompound("FirstBogey"), graph, dimensions);
CarriageBogey bogey2 =
tag.contains("SecondBogey") ? CarriageBogey.read(tag.getCompound("SecondBogey"), graph, dimensions) : null;
Carriage carriage = new Carriage(bogey1, bogey2, tag.getInt("Spacing"));
carriage.stalled = tag.getBoolean("Stalled");
carriage.presentConductors = Couple.create(tag.getBoolean("FrontConductor"), tag.getBoolean("BackConductor"));
carriage.serialisedEntity = tag.getCompound("Entity")
.copy();
NBTHelper.iterateCompoundList(tag.getList("EntityPositioning", Tag.TAG_COMPOUND),
c -> carriage.getDimensional(dimensions.decode(c.getInt("Dim")))
.read(c));
CompoundTag passengersTag = tag.getCompound("Passengers");
passengersTag.getAllKeys()
.forEach(key -> carriage.serialisedPassengers.put(Integer.valueOf(key.substring(4)),
passengersTag.getCompound(key)));
return carriage;
}
private TravellingPoint portalScout = new TravellingPoint();
public class DimensionalCarriageEntity {
public Vec3 positionAnchor;
public Couple<Vec3> rotationAnchors;
public WeakReference<CarriageContraptionEntity> entity;
public TrackNodeLocation pivot;
int discardTicks;
// 0 == whole, 0..1 = fading out, -1..0 = fading in
public float cutoff;
// client
public boolean pointsInitialised;
public DimensionalCarriageEntity() {
this.entity = new WeakReference<>(null);
this.rotationAnchors = Couple.create(null, null);
this.pointsInitialised = false;
}
public void discardPivot() {
int prevmin = minAllowedLocalCoord();
int prevmax = maxAllowedLocalCoord();
cutoff = 0;
pivot = null;
if ((!serialisedPassengers.isEmpty() && entity.get() != null) || prevmin != minAllowedLocalCoord()
|| prevmax != maxAllowedLocalCoord()) {
updatePassengerLoadout();
updateRenderedCutoff();
}
}
public void updateCutoff(boolean leadingIsCurrent) {
Vec3 leadingAnchor = rotationAnchors.getFirst();
Vec3 trailingAnchor = rotationAnchors.getSecond();
if (leadingAnchor == null || trailingAnchor == null)
return;
if (pivot == null) {
cutoff = 0;
return;
}
Vec3 pivotLoc = pivot.getLocation()
.add(0, 1, 0);
double leadingSpacing = leadingBogey().type.getWheelPointSpacing() / 2;
double trailingSpacing = trailingBogey().type.getWheelPointSpacing() / 2;
double anchorSpacing = leadingSpacing + bogeySpacing + trailingSpacing;
if (isOnTwoBogeys()) {
Vec3 diff = trailingAnchor.subtract(leadingAnchor)
.normalize();
trailingAnchor = trailingAnchor.add(diff.scale(trailingSpacing));
leadingAnchor = leadingAnchor.add(diff.scale(-leadingSpacing));
}
double leadingDiff = leadingAnchor.distanceTo(pivotLoc);
double trailingDiff = trailingAnchor.distanceTo(pivotLoc);
leadingDiff /= anchorSpacing;
trailingDiff /= anchorSpacing;
if (leadingIsCurrent && leadingDiff > trailingDiff && leadingDiff > 1)
cutoff = 0;
else if (leadingIsCurrent && leadingDiff < trailingDiff && trailingDiff > 1)
cutoff = 1;
else if (!leadingIsCurrent && leadingDiff > trailingDiff && leadingDiff > 1)
cutoff = -1;
else if (!leadingIsCurrent && leadingDiff < trailingDiff && trailingDiff > 1)
cutoff = 0;
else
cutoff = (float) Mth.clamp(1 - (leadingIsCurrent ? leadingDiff : trailingDiff), 0, 1)
* (leadingIsCurrent ? 1 : -1);
}
public TrackNodeLocation findPivot(ResourceKey<Level> dimension, boolean leading) {
if (pivot != null)
return pivot;
TravellingPoint start = leading ? getLeadingPoint() : getTrailingPoint();
TravellingPoint end = !leading ? getLeadingPoint() : getTrailingPoint();
portalScout.node1 = start.node1;
portalScout.node2 = start.node2;
portalScout.edge = start.edge;
portalScout.position = start.position;
ITrackSelector trackSelector = portalScout.follow(end);
int distance = bogeySpacing + 10;
int direction = leading ? -1 : 1;
portalScout.travel(train.graph, direction * distance, trackSelector, portalScout.ignoreEdgePoints(),
portalScout.ignoreTurns(), nodes -> {
for (boolean b : Iterate.trueAndFalse)
if (nodes.get(b).dimension.equals(dimension))
pivot = nodes.get(b);
return true;
});
return pivot;
}
public CompoundTag write() {
CompoundTag tag = new CompoundTag();
tag.putFloat("Cutoff", cutoff);
tag.putInt("DiscardTicks", discardTicks);
storage.write(tag, false);
if (pivot != null)
tag.put("Pivot", pivot.write(null));
if (positionAnchor != null)
tag.put("PositionAnchor", VecHelper.writeNBT(positionAnchor));
if (rotationAnchors.both(Objects::nonNull))
tag.put("RotationAnchors", rotationAnchors.serializeEach(VecHelper::writeNBTCompound));
return tag;
}
public void read(CompoundTag tag) {
cutoff = tag.getFloat("Cutoff");
discardTicks = tag.getInt("DiscardTicks");
storage.read(tag, null, false);
if (tag.contains("Pivot"))
pivot = TrackNodeLocation.read(tag.getCompound("Pivot"), null);
if (positionAnchor != null)
return;
if (tag.contains("PositionAnchor"))
positionAnchor = VecHelper.readNBT(tag.getList("PositionAnchor", Tag.TAG_DOUBLE));
if (tag.contains("RotationAnchors"))
rotationAnchors = Couple.deserializeEach(tag.getList("RotationAnchors", Tag.TAG_COMPOUND),
VecHelper::readNBTCompound);
}
public Vec3 leadingAnchor() {
return isOnTwoBogeys() ? rotationAnchors.getFirst() : positionAnchor;
}
public Vec3 trailingAnchor() {
return isOnTwoBogeys() ? rotationAnchors.getSecond() : positionAnchor;
}
public int minAllowedLocalCoord() {
if (cutoff <= 0)
return Integer.MIN_VALUE;
if (cutoff >= 1)
return Integer.MAX_VALUE;
return Mth.floor(-bogeySpacing + -1 + (2 + bogeySpacing) * cutoff);
}
public int maxAllowedLocalCoord() {
if (cutoff >= 0)
return Integer.MAX_VALUE;
if (cutoff <= -1)
return Integer.MIN_VALUE;
return Mth.ceil(-bogeySpacing + -1 + (2 + bogeySpacing) * (cutoff + 1));
}
public void updatePassengerLoadout() {
Entity entity = this.entity.get();
if (!(entity instanceof CarriageContraptionEntity cce))
return;
if (!(entity.level instanceof ServerLevel sLevel))
return;
Set<Integer> loadedPassengers = new HashSet<>();
int min = minAllowedLocalCoord();
int max = maxAllowedLocalCoord();
for (Entry<Integer, CompoundTag> entry : serialisedPassengers.entrySet()) {
Integer seatId = entry.getKey();
List<BlockPos> seats = cce.getContraption()
.getSeats();
if (seatId >= seats.size())
continue;
BlockPos localPos = seats.get(seatId);
if (!cce.isLocalCoordWithin(localPos, min, max))
continue;
CompoundTag tag = entry.getValue();
Entity passenger = null;
if (tag.contains("PlayerPassenger")) {
passenger = sLevel.getServer()
.getPlayerList()
.getPlayer(tag.getUUID("PlayerPassenger"));
} else {
passenger = EntityType.loadEntityRecursive(tag, entity.level, e -> {
e.moveTo(positionAnchor);
return e;
});
if (passenger != null)
sLevel.tryAddFreshEntityWithPassengers(passenger);
}
if (passenger != null) {
ResourceKey<Level> passengerDimension = passenger.level.dimension();
if (!passengerDimension.equals(sLevel.dimension()) && passenger instanceof ServerPlayer sp)
continue;
cce.addSittingPassenger(passenger, seatId);
}
loadedPassengers.add(seatId);
}
loadedPassengers.forEach(serialisedPassengers::remove);
Map<UUID, Integer> mapping = cce.getContraption()
.getSeatMapping();
for (Entity passenger : entity.getPassengers()) {
BlockPos localPos = cce.getContraption()
.getSeatOf(passenger.getUUID());
if (cce.isLocalCoordWithin(localPos, min, max))
continue;
if (!mapping.containsKey(passenger.getUUID()))
continue;
Integer seat = mapping.get(passenger.getUUID());
if ((passenger instanceof ServerPlayer sp)) {
dismountPlayer(sLevel, sp, seat, true);
continue;
}
serialisedPassengers.put(seat, passenger.serializeNBT());
passenger.discard();
}
}
private void dismountPlayer(ServerLevel sLevel, ServerPlayer sp, Integer seat, boolean portal) {
if (!portal) {
sp.stopRiding();
return;
}
CompoundTag tag = new CompoundTag();
tag.putUUID("PlayerPassenger", sp.getUUID());
serialisedPassengers.put(seat, tag);
sp.stopRiding();
sp.getPersistentData()
.remove("ContraptionDismountLocation");
for (Entry<ResourceKey<Level>, DimensionalCarriageEntity> other : entities.entrySet()) {
DimensionalCarriageEntity otherDce = other.getValue();
if (otherDce == this)
continue;
if (sp.level.dimension()
.equals(other.getKey()))
continue;
Vec3 loc = otherDce.pivot == null ? otherDce.positionAnchor : otherDce.pivot.getLocation();
if (loc == null)
continue;
ServerLevel level = sLevel.getServer()
.getLevel(other.getKey());
sp.teleportTo(level, loc.x, loc.y, loc.z, sp.getYRot(), sp.getXRot());
sp.setPortalCooldown();
AllAdvancements.TRAIN_PORTAL.awardTo(sp);
}
}
public void updateRenderedCutoff() {
Entity entity = this.entity.get();
if (!(entity instanceof CarriageContraptionEntity cce))
return;
Contraption contraption = cce.getContraption();
if (!(contraption instanceof CarriageContraption cc))
return;
cc.portalCutoffMin = minAllowedLocalCoord();
cc.portalCutoffMax = maxAllowedLocalCoord();
if (!entity.level.isClientSide())
return;
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(cce));
}
@OnlyIn(Dist.CLIENT)
private void invalidate(CarriageContraptionEntity entity) {
entity.getContraption().deferInvalidate = true;
entity.updateRenderedPortalCutoff();
}
private void createEntity(Level level, boolean loadPassengers) {
Entity entity = EntityType.create(serialisedEntity, level)
.orElse(null);
if (!(entity instanceof CarriageContraptionEntity cce)) {
train.invalid = true;
return;
}
entity.moveTo(positionAnchor);
this.entity = new WeakReference<>(cce);
cce.setCarriage(Carriage.this);
cce.syncCarriage();
if (level instanceof ServerLevel sl)
sl.addFreshEntity(entity);
updatePassengerLoadout();
}
private void removeAndSaveEntity(CarriageContraptionEntity entity, boolean portal) {
Contraption contraption = entity.getContraption();
if (contraption != null) {
Map<UUID, Integer> mapping = contraption.getSeatMapping();
for (Entity passenger : entity.getPassengers()) {
if (!mapping.containsKey(passenger.getUUID()))
continue;
Integer seat = mapping.get(passenger.getUUID());
if (passenger instanceof ServerPlayer sp) {
dismountPlayer(sp.getLevel(), sp, seat, portal);
continue;
}
serialisedPassengers.put(seat, passenger.serializeNBT());
}
}
for (Entity passenger : entity.getPassengers())
if (!(passenger instanceof Player))
passenger.discard();
serialize(entity);
entity.discard();
this.entity.clear();
}
public void alignEntity(CarriageContraptionEntity entity) {
if (rotationAnchors.either(Objects::isNull))
return;
Vec3 positionVec = rotationAnchors.getFirst();
Vec3 coupledVec = rotationAnchors.getSecond();
double diffX = positionVec.x - coupledVec.x;
double diffY = positionVec.y - coupledVec.y;
double diffZ = positionVec.z - coupledVec.z;
entity.prevYaw = entity.yaw;
entity.prevPitch = entity.pitch;
if (!entity.level.isClientSide()) {
Vec3 lookahead = positionAnchor.add(positionAnchor.subtract(entity.position())
.normalize()
.scale(16));
for (Entity e : entity.getPassengers()) {
if (!(e instanceof Player))
continue;
if (e.distanceToSqr(entity) > 32 * 32)
continue;
if (CarriageEntityHandler.isActiveChunk(entity.level, new BlockPos(lookahead)))
break;
train.carriageWaitingForChunks = id;
return;
}
if (entity.getPassengers()
.stream()
.anyMatch(p -> p instanceof Player)
) {
}
if (train.carriageWaitingForChunks == id)
train.carriageWaitingForChunks = -1;
entity.setServerSidePrevPosition();
}
entity.setPos(positionAnchor);
entity.yaw = (float) (Mth.atan2(diffZ, diffX) * 180 / Math.PI) + 180;
entity.pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI) * -1;
if (!entity.firstPositionUpdate)
return;
entity.xo = entity.getX();
entity.yo = entity.getY();
entity.zo = entity.getZ();
entity.prevYaw = entity.yaw;
entity.prevPitch = entity.pitch;
}
}
}