use of ebf.tim.models.ParticleFX in project Trains-In-Motion-1.7.10 by EternalBlueFlame.
the class GenericRailTransport method onUpdate.
/**
* <h2> on entity update </h2>
*
* defines what should be done every tick
* used for:
* managing the list of bogies and seats, respawning them if they disappear.
* managing speed, acceleration. and direction.
* managing rotationYaw and rotationPitch.
* updating rider entity positions if there is no one riding the core seat.
* calling on link management.
* @see #manageLinks()
* syncing the owner entity ID with client.
* being sure the transport is listed in the main class (for lighting management).
* @see ClientProxy#onTick(TickEvent.ClientTickEvent)
* and updating the lighting block.
*/
@Override
public void onUpdate() {
//if the cart has fallen out of the map, destroy it.
if (posY < -64.0D & isDead) {
worldObj.removeEntity(this);
}
if (this.chunkTicket == null) {
this.requestTicket();
}
//always be sure the bogies exist on client and server.
if (!worldObj.isRemote && (frontBogie == null || backBogie == null)) {
//spawn frontLinkedTransport bogie
vectorCache[1][0] = getLengthFromCenter();
vectorCache[0] = RailUtility.rotatePoint(vectorCache[1], rotationPitch, rotationYaw, 0);
frontBogie = new EntityBogie(worldObj, posX + vectorCache[0][0], posY + vectorCache[0][1], posZ + vectorCache[0][2], getEntityId(), true);
frontBogie.setVelocity(frontVelocityX, 0, frontVelocityZ);
//spawn backLinkedTransport bogie
vectorCache[1][0] = -getLengthFromCenter();
vectorCache[0] = RailUtility.rotatePoint(vectorCache[1], rotationPitch, rotationYaw, 0);
backBogie = new EntityBogie(worldObj, posX + vectorCache[0][0], posY + vectorCache[0][1], posZ + vectorCache[0][2], getEntityId(), false);
backBogie.setVelocity(backVelocityX, 0, backVelocityZ);
worldObj.spawnEntityInWorld(frontBogie);
worldObj.spawnEntityInWorld(backBogie);
if (getRiderOffsets() != null && getRiderOffsets().length > 1 && seats.size() < getRiderOffsets().length) {
for (int i = 0; i < getRiderOffsets().length - 1; i++) {
EntitySeat seat = new EntitySeat(worldObj, posX, posY, posZ, getEntityId(), i);
worldObj.spawnEntityInWorld(seat);
seats.add(seat);
}
}
}
/*
* run the hitbox check whether or not the bogies exist so we can ensure interaction even during severe client-sided error.
*check if the bogies exist, because they may not yet, and if they do, check if they are actually moving or colliding.
* no point in processing movement if they aren't moving or if the train hit something.
* if it is clear however, then we need to add velocity to the bogies based on the current state of the train's speed and fuel, and reposition the train.
* but either way we have to position the bogies around the train, just to be sure they don't accidentally fly off at some point.
*
*/
if (frontBogie != null && backBogie != null) {
//handle movement.
if (!hitboxHandler.getCollision(this)) {
frontBogie.minecartMove(rotationPitch, rotationYaw, getBoolean(boolValues.BRAKE), getBoolean(boolValues.RUNNING), getType().isTrain());
backBogie.minecartMove(rotationPitch, rotationYaw, getBoolean(boolValues.BRAKE), getBoolean(boolValues.RUNNING), getType().isTrain());
} else {
frontBogie.addVelocity(-frontBogie.motionX, -frontBogie.motionY, -frontBogie.motionZ);
backBogie.addVelocity(-backBogie.motionX, -backBogie.motionY, -backBogie.motionZ);
frontBogie.minecartMove(rotationPitch, rotationYaw, getBoolean(boolValues.BRAKE), getBoolean(boolValues.RUNNING), getType().isTrain());
backBogie.minecartMove(rotationPitch, rotationYaw, getBoolean(boolValues.BRAKE), getBoolean(boolValues.RUNNING), getType().isTrain());
}
frontVelocityX = frontBogie.motionX;
frontVelocityZ = frontBogie.motionZ;
backVelocityX = backBogie.motionX;
backVelocityZ = backBogie.motionZ;
//position this
setPosition(((frontBogie.posX + backBogie.posX) * 0.5D), ((frontBogie.posY + backBogie.posY) * 0.5D), ((frontBogie.posZ + backBogie.posZ) * 0.5D));
setRotation((float) Math.toDegrees(Math.atan2(frontBogie.posZ - backBogie.posZ, frontBogie.posX - backBogie.posX)), MathHelper.floor_double(Math.acos(frontBogie.posY / backBogie.posY) * RailUtility.degreesD));
if (ticksExisted % 2 == 0) {
//align bogies
vectorCache[1][0] = getLengthFromCenter();
vectorCache[0] = rotatePoint(vectorCache[1], rotationPitch, rotationYaw, 0.0f);
frontBogie.setPosition(vectorCache[0][0] + posX, frontBogie.posY, vectorCache[0][2] + posZ);
vectorCache[1][0] = -getLengthFromCenter();
vectorCache[0] = rotatePoint(vectorCache[1], rotationPitch, rotationYaw, 0.0f);
backBogie.setPosition(vectorCache[0][0] + posX, backBogie.posY, vectorCache[0][2] + posZ);
}
manageLinks();
}
//rider updating isn't called if there's no driver/conductor, so just in case of that, we reposition the seats here too.
if (riddenByEntity == null && getRiderOffsets() != null) {
for (int i = 0; i < seats.size(); i++) {
vectorCache[0] = rotatePoint(getRiderOffsets()[i], rotationPitch, rotationYaw, 0);
vectorCache[0][0] += posX;
vectorCache[0][1] += posY;
vectorCache[0][2] += posZ;
seats.get(i).setPosition(vectorCache[0][0], vectorCache[0][1], vectorCache[0][2]);
}
}
//be sure the owner entityID is currently loaded, this variable is dynamic so we don't save it to NBT.
if (!worldObj.isRemote && ticksExisted % 5 == 0) {
manageFuel();
@Nullable Entity player = CommonProxy.getEntityFromUuid(owner);
if (player != null) {
ownerID = player.getEntityId();
}
//sync the linked transports with client, and on server, easier to use an ID than a UUID.
Entity linkedTransport = CommonProxy.getEntityFromUuid(frontLinkedTransport);
frontLinkedID = linkedTransport instanceof GenericRailTransport ? linkedTransport.getEntityId() : 0;
linkedTransport = CommonProxy.getEntityFromUuid(backLinkedTransport);
backLinkedID = linkedTransport instanceof GenericRailTransport ? linkedTransport.getEntityId() : 0;
if (updateWatchers) {
if (fluidTank != null) {
dataWatcher.updateObject(20, fluidTank.amount);
}
this.dataWatcher.updateObject(19, ownerID);
this.dataWatcher.updateObject(17, bools.toInt());
this.dataWatcher.updateObject(21, linkedTransport instanceof GenericRailTransport ? linkedTransport.getEntityId() : 0);
this.dataWatcher.updateObject(22, linkedTransport instanceof GenericRailTransport ? linkedTransport.getEntityId() : 0);
}
}
/*
* be sure the client proxy has a reference to this so the lamps can be updated, and then every other tick, attempt to update the lamp position if it's necessary.
*/
if (backBogie != null && !isDead && worldObj.isRemote) {
if (ClientProxy.EnableLights && !ClientProxy.carts.contains(this)) {
ClientProxy.carts.add(this);
}
if (lamp.Y > 1 && ticksExisted % 2 == 1) {
vectorCache[0][0] = this.posX + getLampOffset().xCoord;
vectorCache[0][1] = this.posY + getLampOffset().yCoord;
vectorCache[0][2] = this.posZ + getLampOffset().zCoord;
lamp.ShouldUpdate(worldObj, RailUtility.rotatePoint(vectorCache[0], rotationPitch, rotationYaw, 0));
}
//update the particles here rather than on render tick, it's not as smooth, but close enough and far less CPU use.
if (ClientProxy.EnableSmokeAndSteam) {
int itteration = 0;
int maxSpawnThisTick = 0;
for (float[] smoke : getSmokeOffset()) {
for (int i = 0; i < smoke[4]; i++) {
//define the position
vectorCache[7][0] = smoke[0];
vectorCache[7][1] = smoke[1];
vectorCache[7][2] = smoke[2];
vectorCache[8] = RailUtility.rotatePoint(vectorCache[7], rotationPitch, rotationYaw, 0);
//this helps make them spawn more evenly rather than all at once. It also helps prevent a lot of lag.
if (getBoolean(boolValues.RUNNING) && particles.size() <= itteration && maxSpawnThisTick < 5) {
particles.add(new ParticleFX(posZ, posY, posX, smoke[3], vectorCache[8], backBogie.motionX + (rand.nextInt(40) - 20) * 0.001f, smoke[1] * 0.05, backBogie.motionZ + (rand.nextInt(40) - 20) * 0.001f));
maxSpawnThisTick++;
} else if (maxSpawnThisTick == 0) {
//if the particles have finished spawning in, move them.
particles.get(itteration).onUpdate(this, posX, posY, posZ, getBoolean(boolValues.RUNNING));
}
itteration++;
}
}
}
}
}
Aggregations