Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,17 @@
import cam72cam.immersiverailroading.Config;
import cam72cam.immersiverailroading.ImmersiveRailroading;
import cam72cam.immersiverailroading.entity.EntityCoupleableRollingStock.CouplerType;
import cam72cam.immersiverailroading.floor.NavMesh;
import cam72cam.immersiverailroading.library.Permissions;
import cam72cam.immersiverailroading.model.part.Door;
import cam72cam.immersiverailroading.model.part.Seat;
import cam72cam.immersiverailroading.render.ExpireableMap;
import cam72cam.immersiverailroading.util.MathUtil;
import cam72cam.immersiverailroading.util.VecUtil;
import cam72cam.mod.entity.Entity;
import cam72cam.mod.entity.Player;
import cam72cam.mod.entity.boundingbox.IBoundingBox;
import cam72cam.mod.entity.custom.IRidable;
import cam72cam.mod.entity.sync.TagSync;
import cam72cam.mod.item.ClickResult;
import cam72cam.mod.item.ItemStack;
import cam72cam.mod.math.Vec3d;
import cam72cam.mod.model.obj.OBJFace;
import cam72cam.mod.serialization.SerializationException;
import cam72cam.mod.serialization.TagCompound;
import cam72cam.mod.serialization.TagField;
Expand Down Expand Up @@ -63,7 +58,7 @@ public ClickResult onClick(Player player, Player.Hand hand) {
}
}

protected Vec3d getSeatPosition(UUID passenger) {
private Vec3d getSeatPosition(UUID passenger) {
String seat = seatedPassengers.entrySet().stream()
.filter(x -> x.getValue().equals(passenger))
.map(Map.Entry::getKey).findFirst().orElse(null);
Expand All @@ -75,45 +70,31 @@ protected Vec3d getSeatPosition(UUID passenger) {

@Override
public Vec3d getMountOffset(Entity passenger, Vec3d off) {
NavMesh navMesh = getDefinition().navMesh;
if (passenger.isVillager() && !payingPassengerPositions.containsKey(passenger.getUUID())) {
payingPassengerPositions.put(passenger.getUUID(), passenger.getPosition());
}

if (passenger.isVillager() && !seatedPassengers.containsValue(passenger.getUUID())) {
for (Seat<?> seat : getDefinition().getModel().getSeats()) {
if (!seatedPassengers.containsKey(seat.part.key)) {
seatedPassengers.put(seat.part.key, passenger.getUUID());
break;
}
}
}

off = off.scale(gauge.scale());
Vec3d seat = getSeatPosition(passenger.getUUID());
if (seat != null) {
return seat;
}

Vec3d realOffset = off.rotateYaw(-90);
IBoundingBox queryBox = IBoundingBox.from(
realOffset.subtract(4f, 4f, 4f),
realOffset.add(4f, 4f, 4f)
);

List<OBJFace> nearby = new ArrayList<>();
navMesh.queryBVH(navMesh.root, queryBox, nearby, this.gauge.scale());

Vec3d closestPoint = null;
double closestDistanceSq = Double.MAX_VALUE;

for (OBJFace tri : nearby) {
Vec3d p0 = tri.vertex0.pos;
Vec3d p1 = tri.vertex1.pos;
Vec3d p2 = tri.vertex2.pos;

Vec3d pointOnTri = MathUtil.closestPointOnTriangle(realOffset, p0, p1, p2);
double distSq = realOffset.subtract(pointOnTri).lengthSquared();

if (distSq < closestDistanceSq) {
closestDistanceSq = distSq;
closestPoint = pointOnTri;
}
if (passenger.isVillager()) {
int wiggle = 10;
off = off.add((Math.random()-0.5) * wiggle, 0, (Math.random()-0.5) * wiggle);
}
off = this.getDefinition().correctPassengerBounds(gauge, off, shouldRiderSit(passenger));

if (closestPoint != null) {
return closestPoint.rotateYaw(90);
} else {
return new Vec3d(0, 0, 0);
}
return off;
}

@Override
Expand All @@ -132,53 +113,22 @@ public boolean shouldRiderSit(Entity passenger) {

@Override
public Vec3d onPassengerUpdate(Entity passenger, Vec3d offset) {
Vec3d movement = new Vec3d(0, 0, 0);
if (passenger.isPlayer()) {
movement = playerMovement(passenger.asPlayer(), offset);
}
Vec3d targetXZ = VecUtil.rotatePitch(movement, -this.getRotationPitch());

Vec3d rayStart = targetXZ.rotateYaw(-90).add(0, 1, 0);
Vec3d rayDir = new Vec3d(0, -1, 0);

Vec3d localTarget = targetXZ.rotateYaw(-90);

IBoundingBox rayBox = IBoundingBox.from(
localTarget.subtract(0.5f, 0.5f, 0.5f),
localTarget.add(0.5f, 0.5f, 0.5f)
);
List<OBJFace> nearby = new ArrayList<>();
NavMesh navMesh = getDefinition().navMesh;
navMesh.queryBVH(navMesh.root, rayBox, nearby, this.gauge.scale());

double closestY = Float.NEGATIVE_INFINITY;
boolean hit = false;

for(OBJFace tri : nearby) {
Double t = MathUtil.intersectRayTriangle(rayStart, rayDir, tri);
if (t != null && t >= 0) {
Vec3d hitPoint = rayStart.add(rayDir.scale(t));
if (!hit || hitPoint.y > closestY) {
closestY = hitPoint.y;
hit = true;
}
}

}

if (hit) {
offset = VecUtil.rotatePitch(new Vec3d(targetXZ.x, closestY, targetXZ.z), this.getRotationPitch());
offset = playerMovement(passenger.asPlayer(), offset);
}

Vec3d seat = getSeatPosition(passenger.getUUID());
if (seat != null) {
offset = seat;
} else {
offset = this.getDefinition().correctPassengerBounds(gauge, offset, shouldRiderSit(passenger));
}
offset = offset.add(0, Math.sin(Math.toRadians(this.getRotationPitch())) * offset.z, 0);

return offset;
}

protected boolean isNearestDoorOpen(Player source) {
private boolean isNearestDoorOpen(Player source) {
// Find any doors that are close enough that are closed (and then negate)
return !this.getDefinition().getModel().getDoors().stream()
.filter(d -> d.type == Door.Types.CONNECTING)
Expand All @@ -188,138 +138,63 @@ protected boolean isNearestDoorOpen(Player source) {
.isPresent();
}

protected Vec3d playerMovement(Player source, Vec3d offset) {
private Vec3d playerMovement(Player source, Vec3d offset) {
Vec3d movement = source.getMovementInput();
if (movement.length() <= 0.1) {
return offset;
/*
if (sprinting) {
movement = movement.scale(3);
}
*/
if (movement.length() < 0.1) {
return offset;
}

movement = new Vec3d(movement.x, 0, movement.z).rotateYaw(this.getRotationYaw() - source.getRotationYawHead());

if (!getDefinition().hitsNavCollisionMesh(this.gauge, offset, movement)) {
offset = offset.add(movement);
}

movement = new Vec3d(movement.x, 0, movement.z).rotateYaw(this.getRotationYaw() - source.getRotationYawHead());
Vec3d localOffset = offset.rotateYaw(-90).add(movement.rotateYaw(-90));

IBoundingBox rayBox = IBoundingBox.from(
localOffset.subtract(0.2f, 0.2f, 0.2f),
localOffset.add(0.2f, 0.2f, 0.2f)
);
List<OBJFace> nearby = new ArrayList<>();
NavMesh navMesh = getDefinition().navMesh;
navMesh.queryBVH(navMesh.collisionRoot, rayBox, nearby, this.gauge.scale());
if (this instanceof EntityCoupleableRollingStock) {
EntityCoupleableRollingStock couplable = (EntityCoupleableRollingStock) this;

Vec3d rayStart = localOffset.add(0, 1, 0);
Vec3d rayDir = movement.rotateYaw(-90).normalize();

for (OBJFace tri : nearby) {
Double t = MathUtil.intersectRayTriangle(rayStart, rayDir, tri);
if (t != null && t >= 0) {
return offset;
}
}

if (isDoorOpen(offset, movement)) {
return offset;
}

offset = offset.add(movement);

if (getWorld().isServer) {
for (Door<?> door : getDefinition().getModel().getDoors()) {
if (door.isAtOpenDoor(source, this, Door.Types.EXTERNAL)) {
Vec3d doorCenter = door.center(this);
Vec3d toDoor = doorCenter.subtract(offset).normalize();
double dot = toDoor.dotProduct(movement.normalize());
if (dot > 0.5) {
this.removePassenger(source);
break;
}
}
}
}

if (this instanceof EntityCoupleableRollingStock) {
EntityCoupleableRollingStock coupleable = (EntityCoupleableRollingStock) this;

boolean isAtFront = isAtCoupler(offset, movement, EntityCoupleableRollingStock.CouplerType.FRONT);
boolean isAtBack = isAtCoupler(offset, movement, EntityCoupleableRollingStock.CouplerType.BACK);
boolean atFront = this.getDefinition().isAtFront(gauge, offset);
boolean atBack = this.getDefinition().isAtRear(gauge, offset);
// TODO config for strict doors
boolean atDoor = isNearestDoorOpen(source);

isAtFront &= atDoor;
isAtBack &= atDoor;
atFront &= atDoor;
atBack &= atDoor;

for (EntityCoupleableRollingStock.CouplerType coupler : EntityCoupleableRollingStock.CouplerType.values()) {
boolean atCoupler = coupler == EntityCoupleableRollingStock.CouplerType.FRONT ? isAtFront : isAtBack;
if (atCoupler && coupleable.isCoupled(coupler)) {
for (CouplerType coupler : CouplerType.values()) {
boolean atCoupler = coupler == CouplerType.FRONT ? atFront : atBack;
if (atCoupler && couplable.isCoupled(coupler)) {
EntityCoupleableRollingStock coupled = ((EntityCoupleableRollingStock) this).getCoupled(coupler);
if (coupled != null) {
if (coupled.isNearestDoorOpen(source)) {
if (((EntityRidableRollingStock)coupled).isNearestDoorOpen(source)) {
coupled.addPassenger(source);
}
} else if (this.getTickCount() > 20) {
ImmersiveRailroading.info(
"Tried to move between cars (%s, %s), but %s was not found",
this.getUUID(),
coupleable.getCoupledUUID(coupler),
coupleable.getCoupledUUID(coupler)
couplable.getCoupledUUID(coupler),
couplable.getCoupledUUID(coupler)
);
}
return offset;
}
}
}

return offset;
}
}

private boolean isDoorOpen(Vec3d start, Vec3d end) {
start = VecUtil.rotatePitch(start, -this.getRotationPitch());
end = VecUtil.rotatePitch(end, -this.getRotationPitch());

start = start.rotateYaw(-90);
end = start.add(end.rotateYaw(-90));

List<Door<?>> doors = getDefinition().getModel().getDoors().stream()
.filter(d -> d.type == Door.Types.INTERNAL || d.type == Door.Types.CONNECTING)
.filter(d -> !d.isOpen(this)).collect(Collectors.toList());
boolean intersects = false;
for (Door<?> door : doors) {
IBoundingBox box = IBoundingBox.from(
door.part.min,
door.part.max
);
intersects = box.intersectsSegment(start, end);
if (intersects) {
break;
}
if (getDefinition().getModel().getDoors().stream().anyMatch(x -> x.isAtOpenDoor(source, this, Door.Types.EXTERNAL)) &&
getWorld().isServer &&
!this.getDefinition().correctPassengerBounds(gauge, offset, shouldRiderSit(source)).equals(offset)
) {
this.removePassenger(source);
}
return intersects;
}

private boolean isAtCoupler(Vec3d offset, Vec3d movement, EntityCoupleableRollingStock.CouplerType type) {
offset = offset.rotateYaw(-90);
double coupler = getDefinition().getCouplerPosition(type, this.gauge);
Vec3d couplerPos = new Vec3d(type == EntityCoupleableRollingStock.CouplerType.FRONT ? -coupler : coupler, offset.y, offset.z);

IBoundingBox queryBox = IBoundingBox.from(
couplerPos.subtract(0.2, 0.2, 0.2),
couplerPos.add(0.2, 0.2, 0.2)
);

List<OBJFace> nearby = new ArrayList<>();
NavMesh navMesh = getDefinition().navMesh;
navMesh.queryBVH(navMesh.root, queryBox, nearby, this.gauge.scale());

for (OBJFace tri : nearby) {
Vec3d p0 = tri.vertex0.pos;
Vec3d p1 = tri.vertex1.pos;
Vec3d p2 = tri.vertex2.pos;

Vec3d closestPoint = MathUtil.closestPointOnTriangle(offset, p0, p1, p2);
double distance = offset.subtract(closestPoint).length();
if (distance < 0.5) {
Vec3d toCoupler = couplerPos.subtract(offset).normalize();
double dot = toCoupler.dotProduct(movement.rotateYaw(-90).normalize());
if (dot > 0.5) return true;
}
}
return false;
return offset;
}

@Override
Expand Down
Loading