Hbm-s-Nuclear-Tech-GIT/src/main/java/com/hbm/entity/train/EntityRailCarRidable.java
2024-03-20 16:46:05 +01:00

296 lines
9.4 KiB
Java

package com.hbm.entity.train;
import java.util.ArrayList;
import java.util.List;
import com.hbm.main.MainRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
public abstract class EntityRailCarRidable extends EntityRailCarCargo {
public double engineSpeed;
public SeatDummyEntity[] passengerSeats;
public EntityRailCarRidable(World world) {
super(world);
this.passengerSeats = new SeatDummyEntity[this.getPassengerSeats().length];
}
/** Returns the linear speed added per tick when using powered movement */
public abstract double getPoweredAcceleration();
/** A mulitplier used on the speed either is there is no player in the train or if the parking brake is active */
public abstract double getPassivBrake();
/** The parking brake can be toggled, assuming a player is present, otherwise it is implicitly ON */
public abstract boolean shouldUseEngineBrake(EntityPlayer player);
/** The max speed the engine can provide in both directions */
public abstract double getMaxPoweredSpeed();
/** Whether the engine is turned on */
public abstract boolean canAccelerate();
/** Called every tick if acceleration is successful */
public void consumeFuel() { }
/** An additive to the engine's speed yielding the total speed, caused by uneven surfaces */
public double getGravitySpeed() {
return 0D;
}
@Override
public double getCurrentSpeed() { // in its current form, only call once per tick
if(this.riddenByEntity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) this.riddenByEntity;
if(this.canAccelerate()) {
if(player.moveForward > 0) {
engineSpeed += this.getPoweredAcceleration();
this.consumeFuel();
} else if(player.moveForward < 0) {
engineSpeed -= this.getPoweredAcceleration();
this.consumeFuel();
} else {
if(this.shouldUseEngineBrake(player)) {
engineSpeed *= this.getPassivBrake();
} else {
this.consumeFuel();
}
}
} else {
engineSpeed *= this.getPassivBrake();
}
} else {
engineSpeed *= this.getPassivBrake();
}
double maxSpeed = this.getMaxPoweredSpeed();
engineSpeed = MathHelper.clamp_double(engineSpeed, -maxSpeed, maxSpeed);
return engineSpeed + this.getGravitySpeed();
}
@Override
public boolean interactFirst(EntityPlayer player) {
if(super.interactFirst(player)) return true;
if(worldObj.isRemote) return true;
int nearestSeat = this.getNearestSeat(player);
if(nearestSeat == -1) {
player.mountEntity(this);
} else if(nearestSeat >= 0) {
SeatDummyEntity dummySeat = new SeatDummyEntity(worldObj, this, nearestSeat);
Vec3 passengerSeat = this.getPassengerSeats()[nearestSeat];
passengerSeat.rotateAroundY((float) (-this.rotationYaw * Math.PI / 180));
double x = renderX + passengerSeat.xCoord;
double y = renderY + passengerSeat.yCoord;
double z = renderZ + passengerSeat.zCoord;
dummySeat.setPosition(x, y - 1, z);
passengerSeats[nearestSeat] = dummySeat;
worldObj.spawnEntityInWorld(dummySeat);
player.mountEntity(dummySeat);
}
return true;
}
public int getNearestSeat(EntityPlayer player) {
double nearestDist = Double.POSITIVE_INFINITY;
int nearestSeat = -3;
Vec3[] seats = getPassengerSeats();
Vec3 look = player.getLook(2);
look.xCoord += player.posX;
look.yCoord += player.posY + player.eyeHeight - player.yOffset;
look.zCoord += player.posZ;
for(int i = 0; i < seats.length; i++) {
Vec3 seat = seats[i];
if(seat == null) continue;
if(passengerSeats[i] != null) continue;
seat.rotateAroundY((float) (-this.rotationYaw * Math.PI / 180));
double x = renderX + seat.xCoord;
double y = renderY + seat.yCoord;
double z = renderZ + seat.zCoord;
Vec3 delta = Vec3.createVectorHelper(look.xCoord - x, look.yCoord - y, look.zCoord - z);
double dist = delta.lengthVector();
if(dist < nearestDist) {
nearestDist = dist;
nearestSeat = i;
}
}
if(this.riddenByEntity == null) {
Vec3 seat = getRiderSeatPosition();
seat.rotateAroundY((float) (-this.rotationYaw * Math.PI / 180));
double x = renderX + seat.xCoord;
double y = renderY + seat.yCoord;
double z = renderZ + seat.zCoord;
Vec3 delta = Vec3.createVectorHelper(look.xCoord - x, look.yCoord - y, look.zCoord - z);
double dist = delta.lengthVector();
if(dist < nearestDist) {
nearestDist = dist;
nearestSeat = -1;
}
}
if(nearestDist > 180) return -2;
return nearestSeat;
}
@Override
public void onUpdate() {
super.onUpdate();
if(!worldObj.isRemote) {
Vec3[] seats = this.getPassengerSeats();
for(int i = 0; i < passengerSeats.length; i++) {
SeatDummyEntity seat = passengerSeats[i];
if(seat != null) {
if(seat.riddenByEntity == null) {
passengerSeats[i] = null;
seat.setDead();
} else {
Vec3 rot = seats[i];
rot.rotateAroundX((float) (this.rotationPitch * Math.PI / 180));
rot.rotateAroundY((float) (-this.rotationYaw * Math.PI / 180));
double x = renderX + rot.xCoord;
double y = renderY + rot.yCoord;
double z = renderZ + rot.zCoord;
seat.setPosition(x, y - 1, z);
}
}
}
}
}
@Override
public void updateRiderPosition() {
Vec3 offset = getRiderSeatPosition();
offset.rotateAroundX((float) (this.rotationPitch * Math.PI / 180));
offset.rotateAroundY((float) (-this.rotationYaw * Math.PI / 180));
if(this.riddenByEntity != null) {
this.riddenByEntity.setPosition(this.renderX + offset.xCoord, this.renderY + offset.yCoord, this.renderZ + offset.zCoord);
}
}
/** Returns a Vec3 showing the relative position from the driver to the core */
public abstract Vec3 getRiderSeatPosition();
public abstract Vec3[] getPassengerSeats();
/** Dynamic seats generated when a player clicks near a seat-spot, moves and rotates with the train as one would expect. */
public static class SeatDummyEntity extends Entity {
private int turnProgress;
private double trainX;
private double trainY;
private double trainZ;
public EntityRailCarRidable train;
public SeatDummyEntity(World world) { super(world); this.setSize(0.5F, 0.1F);}
public SeatDummyEntity(World world, EntityRailCarRidable train, int index) {
this(world);
this.train = train;
if(train != null) this.dataWatcher.updateObject(3, train.getEntityId());
this.dataWatcher.updateObject(4, index);
}
@Override protected void entityInit() { this.dataWatcher.addObject(3, new Integer(0)); this.dataWatcher.addObject(4, new Integer(0)); }
@Override protected void writeEntityToNBT(NBTTagCompound nbt) { }
@Override public boolean writeToNBTOptional(NBTTagCompound nbt) { return false; }
@Override public void readEntityFromNBT(NBTTagCompound nbt) { this.setDead(); }
@Override public void onUpdate() {
if(!worldObj.isRemote) {
if(this.train == null || this.train.isDead) {
this.setDead();
}
} else {
if(this.turnProgress > 0) {
this.prevRotationYaw = this.rotationYaw;
double x = this.posX + (this.trainX - this.posX) / (double) this.turnProgress;
double y = this.posY + (this.trainY - this.posY) / (double) this.turnProgress;
double z = this.posZ + (this.trainZ - this.posZ) / (double) this.turnProgress;
--this.turnProgress;
this.setPosition(x, y, z);
} else {
this.setPosition(this.posX, this.posY, this.posZ);
}
}
}
@Override @SideOnly(Side.CLIENT) public void setPositionAndRotation2(double posX, double posY, double posZ, float yaw, float pitch, int turnProg) {
this.trainX = posX;
this.trainY = posY;
this.trainZ = posZ;
this.turnProgress = turnProg + 2;
}
@Override
public void updateRiderPosition() {
if(this.riddenByEntity != null) {
if(train == null) {
int eid = this.dataWatcher.getWatchableObjectInt(3);
Entity entity = worldObj.getEntityByID(eid);
if(entity instanceof EntityRailCarRidable) {
train = (EntityRailCarRidable) entity;
}
}
//fallback for when train is null
if(train == null) {
this.riddenByEntity.setPosition(posX, posY + 1, posZ);
return;
}
//doing it like this instead of with the position directly removes any discrepancies caused by entity tick order
//mmhmhmhm silky smooth
int index = this.dataWatcher.getWatchableObjectInt(4);
Vec3 rot = this.train.getPassengerSeats()[index];
rot.rotateAroundX((float) (train.rotationPitch * Math.PI / 180));
rot.rotateAroundY((float) (-train.rotationYaw * Math.PI / 180));
double x = train.renderX + rot.xCoord;
double y = train.renderY + rot.yCoord;
double z = train.renderZ + rot.zCoord;
this.riddenByEntity.setPosition(x, y, z);
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void printHook(RenderGameOverlayEvent.Pre event, World world, int x, int y, int z) {
List<String> text = new ArrayList();
/*text.add("LTU: " + this.ltu);
text.add("Front: " + this.coupledFront);
text.add("Back: " + this.coupledBack);*/
text.add("Nearest seat: " + this.getNearestSeat(MainRegistry.proxy.me()));
//ILookOverlay.printGeneric(event, this.getClass().getSimpleName() + " " + this.hashCode(), 0xffff00, 0x404000, text);
}
}