mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-05-19 20:13:53 +02:00
e5c6ca157c
commit 053dd09df6c426ab5e570f42a1edb5df3d0fbd01 Merge: 6d1e1c71decc645eba
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 commitecc645eba7
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 commit205e47352e
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 21:02:19 2023 -0700 Fix up ItemOutline commit6cf204f6af
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 commitfe049bc771
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:26:16 2023 -0700 Revert "Revert "Rewrite outline buffering"" This reverts commit726bfaf0
commit435b4c1c16
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 commit662da6bab1
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 commit122fe77afa
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 8 20:15:46 2023 -0700 Fix up upside down rendering commitd83285e8a4
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 commitcdb0ad210b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 10:15:47 2023 +0100 Fixed merge artifact commit457d5f33ed
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 commit00e953a585
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 commita7a25896c1
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 commit4e4e227a35
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 10:10:30 2023 +0100 Cleanup to cycle groups commitaa94fc97d1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun May 7 09:50:50 2023 +0100 Removed unused import of Railways commit7622128bec
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 commit1e4d5504ee
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 18:03:39 2023 -0700 Don't revert non-buggy changes commitb306cf2124
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 18:00:59 2023 -0700 Take materials into consideration when trains pathfind commitfca02ae4bf
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat May 6 10:25:51 2023 -0700 Add materials to track graph commit726bfaf0b5
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 21:16:49 2023 -0700 Revert "Rewrite outline buffering" This reverts commitd4106d545b
. commit171897bed2
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 20:55:25 2023 -0700 Fix up style cycling commitcbd0cf20da
Author: techno-sam <linux.techno.sam@gmail.com> Date: Fri May 5 07:32:06 2023 -0700 clean up nether portal carriage handling commitd556f08876
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 commitda26c0ccbf
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 commit81eeadb853
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 16:15:28 2023 +0100 Small cleanup commitc7e9df973c
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 16:13:51 2023 +0100 Fixed issue raised in #1 commit2f285b6eb7
Author: techno-sam <linux.techno.sam@gmail.com> Date: Mon May 1 08:13:27 2023 -0700 add data gen commit206de01311
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 commit6564f4fa73
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 commite5d7595822
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon May 1 10:09:03 2023 +0100 Connected Custom Bogey Particle Types To CarriageParticles commite91753a33c
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 30 19:51:26 2023 -0700 Fix up some problems commit9815f1490f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:12:43 2023 +0100 Implemented default data when shifting styles commitda30e78815
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:12:14 2023 +0100 Added Particles To Bogey Style (And Respective Builder) commit08c000b8ba
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:01:19 2023 +0100 Added Backup Rendering If A Size Is Not Present commit2b76e8d7b3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 21:00:40 2023 +0100 Added Common Renderer To Remove Function commit411ec36f57
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:59:50 2023 +0100 Added Display Name To Standard Bogey Style commit112306d5d4
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:59:30 2023 +0100 Displayed new style name when changing betweeen them commit5634670b27
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:06:00 2023 +0100 General Cleanup commit0f7a8b7b24
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:05:50 2023 +0100 Implemented Changes To Remaining Classes commit8aedc00f96
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:02:06 2023 +0100 Removed Bogey Style Handling From Registrate commitedf8079abf
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:40 2023 +0100 Removed Unused Registry Handling commit6a185c4e72
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:16 2023 +0100 Refactored Bogey Sizes commite10d07ddc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 30 20:01:00 2023 +0100 Overhauled Bogey Style commit74d98a2ad5
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 commite629d02f50
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 9 07:18:22 2023 -0700 Track API Clean up code a bit commitd9ce6ce995
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sun Apr 9 07:14:46 2023 -0700 Track API? Fix placement commit7fbf08ba54
Author: techno-sam <linux.techno.sam@gmail.com> Date: Sat Apr 8 11:11:24 2023 -0700 Track API? Fix up some placement issues commit35644f1434
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 commitf7c56b867a
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 commit2a59fd7e8a
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 commit5ba30d6a85
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 commitd52065808c
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 commit53240bd42f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 21:42:29 2023 +0100 Corrected Bogey InteractionResult To Pass commit69326e361a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 21:30:28 2023 +0100 Fixed Default Values When Used Styles Are Removed commit4f176979de
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 19:33:17 2023 +0100 Fixed Carriage Sounds (Again) commit1e80af3303
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 19:27:58 2023 +0100 Refactored Bogey Sizes To Seperate Class commit129be61fee
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 17:20:17 2023 +0100 Fixed Bogey Sound Loading commit2543185a55
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Mon Apr 3 09:45:23 2023 +0100 Added Bogey Sound Customisation commit1ad5ae9514
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 commit96566b1614
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 commiteedd984738
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:53:55 2023 +0100 Fixed Large Bogey Size commit68ca0974c6
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:47:58 2023 +0100 Implemented Style Cycling & Default Values commita55ba4267a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:46:15 2023 +0100 Implemented renderer instance creator commit43523302c2
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sun Apr 2 16:45:33 2023 +0100 Removed Unused Standard Bogey Instance commit773e084422
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 commit0c0b5a1ed6
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Apr 1 18:39:58 2023 +0100 Linked Style Registry To Bogey Blocks commit71f839ee51
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Apr 1 18:39:03 2023 +0100 Replaced size boolean with direct use of size enum commit50ff081704
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:47:13 2023 +0100 Added Resource Location To NBT helper methods commitd1e1f7ec5a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:47:13 2023 +0100 Re-worked BogeyStyles commitda593fccb1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 30 18:46:02 2023 +0100 Refactored IBogeyBlock to AbstractBogeyBlock and extracted relevant StandardBogeyBlock implementations commit17432c9113
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Sat Mar 25 10:20:50 2023 +0000 Fixed Incorrect Registry Loading commitc7d899369a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:44:03 2023 +0000 Registered Registers commit6d862290d7
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:43:23 2023 +0000 Added BogeyStyleBuilder To Registrate commit3dfb9e3b3b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:43:08 2023 +0000 Implemented AllBogeyStyles commitc9e71b462d
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:42:56 2023 +0000 Created BogeyStyleBuilder commita90977d642
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:42:25 2023 +0000 Created AllRegistries and BogeyStyle Registry commit154d455f3f
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Fri Mar 24 23:41:56 2023 +0000 Added BogeyStyle Wrapper commitdfb7640bfc
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:50:41 2023 +0000 Removed left over logging statement commit9920536cc3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:50:18 2023 +0000 Implemented Secondary Shaft To Large Renderer commit6cd40cc6f9
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 commit06fb901144
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:39:11 2023 +0000 Implemented Common Rendering For StandardBogeyRenderer commit435b0f8266
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:38:40 2023 +0000 Added Common Renderer commit96a0623dab
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 18:38:29 2023 +0000 Implemented BlockState Models For Rendering commit469d9d592b
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:42:28 2023 +0000 Added Standard Bogey Instance (Might be redundant) commit2661d260d8
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:42:06 2023 +0000 Refactored Changes To Existing Methods commit9ded16fbab
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:41:15 2023 +0000 Integrated BogeyRenderer To BogeyInstance (Also Corrected Rendering In Contraption) commit4a82fcbca1
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:40:13 2023 +0000 Implemented Changes To StandardBogeyBlock commit7238fb93f3
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Thu Mar 23 17:39:51 2023 +0000 Added Renderer To IBogeyBlock commitded4c1f613
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 commit91727cc84a
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Wed Mar 22 17:03:28 2023 +0000 Implemented Model Data Initializer to StandardBogeyRenderer commit6d98a1f469
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Wed Mar 22 17:03:00 2023 +0000 Added Contraption Model Instance Initializer commit3c02fe6ecc
Author: Rabbitminers <79579164+Rabbitminers@users.noreply.github.com> Date: Tue Mar 21 22:45:34 2023 +0000 Added missing render type check commit6672c49649
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Tue Mar 21 22:37:36 2023 +0000 Re-created standard bogey with test api commita8a9491fa0
Author: Rabbitminers <Rabbitminers2.0@gmail.com> Date: Tue Mar 21 22:34:54 2023 +0000 Implemented Proof Of Concept Generic Bogey Renderer commite4e5ac1c40
Author: SpottyTheTurtle <69260662+SpottyTheTurtle@users.noreply.github.com> Date: Sat Mar 11 21:34:59 2023 +0000 init
900 lines
30 KiB
Java
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;
|
|
}
|
|
}
|
|
|
|
}
|