diff --git a/src/main/java/train/client/gui/GuiLoco2.java b/src/main/java/train/client/gui/GuiLoco2.java index 50ac9fe27b..4a91954c87 100644 --- a/src/main/java/train/client/gui/GuiLoco2.java +++ b/src/main/java/train/client/gui/GuiLoco2.java @@ -440,15 +440,16 @@ protected void drawGuiContainerBackgroundLayer(float f, int t, int g) { fontRendererObj.drawStringWithShadow("Carts pulled: " + guiDetails. get("cartsPulled"), 1, 10, 0xFFFFFF); fontRendererObj.drawStringWithShadow("Mass pulled: " + guiDetails.get("massPulled") + " tons", 1, 20, 0xFFFFFF); fontRendererObj.drawStringWithShadow("Speed reduction: " + guiDetails.get("slowDown") + " km/h", 1, 30, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Accel reduction: " + (Math.round(guiDetails.get("accelSlowDown").getAsDouble() * 1000) / 1000), 1, 40, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Brake reduction: " + (Math.round(guiDetails.get("brakeSlowDown").getAsDouble() * 1000) / 1000), 1, 50, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Fuel consumption: " + ((loco.getFuelConsumption() * 0.2) + "").substring(0, Math.min(((loco.getFuelConsumption() * 0.2) + "").length(), 4)) + " mB/s", 1, - 60, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Fuel: " + loco.getFuel(), 1, 70, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Power: " + loco.transportMetricHorsePower() + " Mhp", 1, 80, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("State: " + loco.getState(), 1, 90, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Heat level: " + loco.getOverheatLevel(), 1, 100, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Maximum Speed: " + (loco.getCustomSpeedGUI()) + " km/h" + " (" + (loco.getCustomSpeedGUI() + guiDetails.get("slowDown").getAsFloat()) + "km/h)", 1, 110, 0xFFFFFF); - fontRendererObj.drawStringWithShadow("Destination: " + (loco.getDestinationGUI()), 1, 120, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Accel reduction: " + guiDetails.get("accelSlowDown"), 1, 40, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Brake reduction: " + guiDetails.get("brakeSlowDown"), 1, 50, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Fuel increase: " + guiDetails.get("fuelUseChange"), 1, 60, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Fuel base consumption: " + ((loco.getFuelConsumption() * 0.2) + "").substring(0, Math.min(((loco.getFuelConsumption() * 0.2) + "").length(), 4)) + " mB/s", 1, + 70, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Fuel: " + loco.getFuel(), 1, 80, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Power: " + loco.transportMetricHorsePower() + " Mhp", 1, 90, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("State: " + loco.getState(), 1, 100, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Heat level: " + loco.getOverheatLevel(), 1, 110, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Maximum Speed: " + (loco.getCustomSpeedGUI()) + " km/h" + " (" + (loco.getCustomSpeedGUI() + guiDetails.get("slowDown").getAsFloat()) + "km/h)", 1, 120, 0xFFFFFF); + fontRendererObj.drawStringWithShadow("Destination: " + (loco.getDestinationGUI()), 1, 130, 0xFFFFFF); } } \ No newline at end of file diff --git a/src/main/java/train/common/api/AbstractTrains.java b/src/main/java/train/common/api/AbstractTrains.java index c84ce47524..cf6407ab52 100644 --- a/src/main/java/train/common/api/AbstractTrains.java +++ b/src/main/java/train/common/api/AbstractTrains.java @@ -758,6 +758,60 @@ private AbstractTrains findFront(ArrayList transports) { return transports.get(0); } + /** + * Finds the direction from which a locomotive is pulling/pushing from. + * @return Returns 1 if from front, -1 if from back, or 0 if no pulling locomotive exists or this is the pulling locomotive. + */ + protected int pullingLocomotiveDirection() { + if (this instanceof Locomotive) { + if (!((Locomotive) this).canBePulled) { + return 0; + } + } + + ArrayList visited = new ArrayList<>(); // In case somebody makes a circular train + visited.add(this); + + boolean visitingFront = true; + + AbstractTrains previousTrain = this; + AbstractTrains train = frontLink; + while (!visited.contains(train)) { + if (train == null) { + // If we have reached the front end, reset and start from the back. If we reached that other end too, break. + if (visitingFront) { + visitingFront = false; + train = backLink; + previousTrain = this; + continue; + } + else { + break; + } + } + + visited.add(train); + + if (train instanceof Locomotive) { + if (!((Locomotive) train).canBePulled) { + return visitingFront ? 1 : -1; + } + } + + // Trains can link front to front and back to back, so keep traversing toward whatever side we didn't come from + if (train.frontLink != previousTrain) { + previousTrain = train; + train = train.frontLink; + } + else { + previousTrain = train; + train = train.backLink; + } + } + // Both front and back didn't find anything, so there's no pulling locomotive. + return 0; + } + /** * @return Returns String ArrayList of trusted players' usernames. */ diff --git a/src/main/java/train/common/api/EntityBogie.java b/src/main/java/train/common/api/EntityBogie.java index 592d7258c9..c74f4503dc 100644 --- a/src/main/java/train/common/api/EntityBogie.java +++ b/src/main/java/train/common/api/EntityBogie.java @@ -215,7 +215,6 @@ protected void func_145821_a(int x, int y, int z, double maxSpeed, double slopeA } private void moveOnTCRail(int i, int j, int k, Block l) { - limitSpeedOnTCRail(); if(l instanceof BlockTCRail) { if(!TCRailTypes.isCrossingTrack((TileTCRail) worldObj.getTileEntity(i, j, k)) && !TCRailTypes.isDiagonalCrossingTrack((TileTCRail) worldObj.getTileEntity(i,j,k))) { @@ -437,25 +436,19 @@ private void moveOnTC90TurnRail(int j,double radius, double startX, double start velocity[1] = Math.copySign(norm_cpx * motionSqrt, railPathZ2); } - private void limitSpeedOnTCRail() { - double maxSpeed = Math.min(3.0D, getMaxCartSpeedOnRail()); + private void limitSpeed(AbstractTrains host, double speedMagnitude) { - if (this.motionX < -maxSpeed) { - - this.motionX = -maxSpeed; - } - else if (this.motionX > maxSpeed) { - - this.motionX = maxSpeed; - } - - if (this.motionZ < -maxSpeed) { - - this.motionZ = -maxSpeed; + // Default speed for most carts + double maxSpeed = this.getMaxCartSpeedOnRail(); + // Current max speed for locos + if (host instanceof Locomotive) { + maxSpeed = Math.min(maxSpeed,SpeedHandler.convertSpeed((double)((Locomotive)host).getCurrentMaxSpeed())); } - else if (this.motionZ > maxSpeed) { - this.motionZ = maxSpeed; + if (speedMagnitude > maxSpeed) { + double overspeedFactor = speedMagnitude/maxSpeed; + velocity[0] /= overspeedFactor; + velocity[1] /= overspeedFactor; } } @@ -465,31 +458,32 @@ public GameProfile getOwner() { return this.entityMainTrain.getOwner(); } + /* + * Velocity needs to be added relative to each bogie's current rotation to prevent drifting between them, as the host's rotation doesn't match when entering curves. + * Always adding in the direction of existing movement prevents reverse, and is unpredictable with null starting velocity, so we compare the bogie's rotation to the host's. + */ public void addVelocity(AbstractTrains host, double speed) { - //cache rotation so it only has to be processed once per tick - Vec3f vec = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180 + host.rotationYaw,0); - velocity[0] += speed * vec.xCoord; - velocity[1] += speed * vec.zCoord; - } + Vec3f bogieRotation = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180+(float)Math.toDegrees(Math.atan2(velocity[1], velocity[0])),0); + Vec3f hostRotation = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180+host.rotationYaw,0); + int direction = bogieRotation.dotProduct(hostRotation) >= 0 ? 1 : -1; - public void multiplyVelocity(AbstractTrains host, double mult) { - Vec3f vec = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180 + host.rotationYaw,0); - velocity[0] *= (mult * vec.xCoord); - velocity[1] *= (mult * vec.zCoord); + velocity[0] += speed * bogieRotation.xCoord * direction; + velocity[1] += speed * bogieRotation.zCoord * direction; } - public void addLinking(AbstractTrains host, double speed){ - //cache rotation so it only has to be processed once per tick - Vec3f vec = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180+host.rotationYaw,0); - velocity[2]+=speed*vec.xCoord; - velocity[3]+=speed*vec.zCoord; + public void multiplyVelocity(double mult) { + velocity[0] *= mult; + velocity[1] *= mult; } - public void drag(AbstractTrains host, double drag){ - velocity[0]*=drag; - velocity[1]*=drag; - } + public void setVelocity(AbstractTrains host, double speed){ + Vec3f bogieRotation = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180+(float)Math.toDegrees(Math.atan2(velocity[1], velocity[0])),0); + Vec3f hostRotation = CommonUtil.rotatePoint(new Vec3f(1,0,0),0,180+host.rotationYaw,0); + int direction = bogieRotation.dotProduct(hostRotation) >= 0 ? 1 : -1; + velocity[0] = speed * bogieRotation.xCoord * direction; + velocity[1] = speed * bogieRotation.zCoord * direction; + } public World getWorld(){return worldObj;} @@ -539,12 +533,13 @@ public void minecartMove(AbstractTrains host) { oldBlockZ=zFloor; } - - //move on rails + isOnRail = true; + double speedMagnitude = Math.sqrt(Math.pow(velocity[0],2)+Math.pow(velocity[1],2))+Math.sqrt(Math.pow(velocity[2],2)+Math.pow(velocity[3],2)); + limitSpeed(host, speedMagnitude); if (l instanceof BlockRailBase) { this.yOffset=0.3425f; - loopVanilla(host, Math.abs(velocity[0])+Math.abs(velocity[1])+Math.abs(velocity[2])+Math.abs(velocity[3]), (BlockRailBase) l); + loopVanilla(host, speedMagnitude, (BlockRailBase) l); } else if (l instanceof BlockTCRail || l instanceof BlockTCRailGag){ this.yOffset=0.425f; moveOnTCRail(xFloor, yFloor, zFloor, l); @@ -553,6 +548,7 @@ public void minecartMove(AbstractTrains host) { yFloor++; posX+=(velocity[2]+velocity[0])*0.5; posZ+=(velocity[3]+velocity[1])*0.5; + isOnRail = false; } velocity[2]=0;velocity[3]=0; } @@ -626,6 +622,9 @@ private void moveBogieVanilla(double currentMotion){ railPathX = (martix[railMetadata][2][0]); railPathZ = (martix[railMetadata][2][1]); + railPathX = Math.copySign(Math.sqrt(Math.abs(railPathX)),railPathX); + railPathZ = Math.copySign(Math.sqrt(Math.abs(railPathZ)),railPathZ); + //cover moving reverse of track direction using the rotation from the closed loop rather than the full motion if((velocity[0]+velocity[2]) * railPathX + (velocity[1]+velocity[3]) * railPathZ <= 0.0D) { railPathX = -railPathX; @@ -634,15 +633,15 @@ private void moveBogieVanilla(double currentMotion){ setPositionRelative((currentMotion * railPathX), 0, (currentMotion * railPathZ)); - motionSqrt = Math.abs(velocity[0])+Math.abs(velocity[1]); + motionSqrt = Math.sqrt(Math.pow(velocity[0],2)+Math.pow(velocity[1],2)); velocity[0] = (float)(motionSqrt * railPathX); velocity[1] = (float)(motionSqrt * railPathZ); - motionSqrt = Math.abs(velocity[2])+Math.abs(velocity[3]); + motionSqrt = Math.sqrt(Math.pow(velocity[2],2)+Math.pow(velocity[3],2)); velocity[2] = (float)(motionSqrt * railPathX); velocity[3] = (float)(motionSqrt * railPathZ); - motionSqrt = Math.abs(velocity[0])+Math.abs(velocity[1])+Math.abs(velocity[2])+Math.abs(velocity[3]); + motionSqrt = Math.sqrt(Math.pow(velocity[0],2)+Math.pow(velocity[1],2))+Math.sqrt(Math.pow(velocity[2],2)+Math.pow(velocity[3],2)); //define the rail path again, to center the transport. railPathX2 = xFloor + 0.5D + martix[railMetadata][0][0]; diff --git a/src/main/java/train/common/api/EntityRollingStock.java b/src/main/java/train/common/api/EntityRollingStock.java index 0f27a57c5e..c6bbb4d6b3 100644 --- a/src/main/java/train/common/api/EntityRollingStock.java +++ b/src/main/java/train/common/api/EntityRollingStock.java @@ -13,6 +13,7 @@ import ebf.tim.entities.EntitySeat; import ebf.tim.utility.CommonUtil; import ebf.tim.utility.DebugUtil; +import fexcraft.tmt.slim.Vec3d; import fexcraft.tmt.slim.Vec3f; import io.netty.buffer.ByteBuf; import mods.railcraft.api.carts.CartTools; @@ -84,7 +85,6 @@ public class EntityRollingStock extends AbstractTrains implements ILinkableCart protected EntityPlayer playerEntity; - public float maxSpeed; public double speedLimiter = 1; public ItemStack item; @@ -644,7 +644,7 @@ public void setPositionAndRotation2(double par1, double par3, double par5, float this.rollingPitch=par8; } - List list = null; + Block l; @@ -809,7 +809,7 @@ else if (!seats.isEmpty() && worldObj.isRemote && Traincraft.proxy.getCurrentScr * backLink will be updated accordingly */ if (addedToChunk && ((this.frontLink == null && this.Link1 != 0) || (this.backLink == null && this.Link2 != 0))) { - list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.expand(15, 15, 15)); + List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.expand(15, 15, 15)); if (list != null && list.size() > 0) { for (Object entity : list) { @@ -993,47 +993,44 @@ public void appendMovement(double velocity){ bogieFront.addVelocity(this, velocity); } - public void addLinkingMove(double velocity){ - bogieBack.addLinking(this, velocity); - bogieFront.addLinking(this, velocity); + public void setVelocity(double velocity) { + bogieBack.setVelocity(this, velocity); + bogieFront.setVelocity(this, velocity); } - public void manageLink(EntityRollingStock other) { - if(isLocoTurnedOn || other.bogieBack ==null || other.bogieFront ==null || bogieBack ==null || bogieFront ==null) { - return; + + public double manageLink(EntityRollingStock other) { + if (isBraking || other.bogieBack == null || other.bogieFront == null || bogieBack == null || bogieFront == null) { + return 0d; + } + + // Locos that are not set to be pulled don't receive link movement + if (this instanceof Locomotive) { + if (!((Locomotive) this).canBePulled) { + return 0d; + } } double vecX = other.posX - posX; double vecZ = other.posZ - posZ; - - double springDist = MathHelper.sqrt_double(vecX * vecX + vecZ * vecZ) - -(getOptimalDistance(other)+other.getOptimalDistance(this)); - - if (springDist<0.1){ - springDist*=0.1; - } else if(springDist<0.5) { - springDist*=0.3; - } else { - springDist*=0.49; - } - if(backLink!=null && other.getEntityId() == backLink.getEntityId()) { - springDist *= -1; - } - - if(Math.abs(springDist)>0.01) { - addLinkingMove(springDist); - } + return MathHelper.sqrt_double(vecX * vecX + vecZ * vecZ) - (getOptimalDistance(other)+other.getOptimalDistance(this)); } /** * if X or Z is null, the bogie's existing motion velocity will be used */ - public void finalMove(EntityRollingStock stock){ - if(stock.frontLink instanceof EntityRollingStock &&stock.frontLink.hasMoved) { - stock.manageLink((EntityRollingStock) stock.frontLink); + public void finalMove(EntityRollingStock stock) { + double activeSpring = 0.5d; double passiveSpring = 0.25d; + double springDist = 0d; + int pullingDir = stock.pullingLocomotiveDirection(); + if (stock.frontLink instanceof EntityRollingStock && stock.frontLink.hasMoved) { + springDist += stock.manageLink((EntityRollingStock) stock.frontLink) * (pullingDir == 1 ? activeSpring : (pullingDir == -1 ? 0 : passiveSpring)); } - if(stock.backLink instanceof EntityRollingStock && stock.backLink.hasMoved){ - stock.manageLink((EntityRollingStock) stock.backLink); + if (stock.backLink instanceof EntityRollingStock && stock.backLink.hasMoved) { + springDist -= stock.manageLink((EntityRollingStock) stock.backLink) * (pullingDir == -1 ? activeSpring : (pullingDir == 1 ? 0 : passiveSpring)); + } + if (springDist != 0d) { + stock.setVelocity(springDist); } stock.applyDrag(); @@ -1061,21 +1058,15 @@ public void finalMove(EntityRollingStock stock){ } } - @Override public void applyDrag() { - float drag = 0.9998f, brakeBuff = 0; - //check if lope things can be done at all + float drag = 0.98f; float derailSlipFactor = 0.175f; + //If an active loco is linked, don't apply a constant drag for(AbstractTrains stock : consist) { - if(stock!=this && stock.isLocoTurnedOn){ - return; - } else if(stock ==this && isAccelerating()){ - return; + if(stock.isLocoTurnedOn){ + drag = 1f; + break; } } - if (isBraking) { - //realistically would be more like 2.4, but 5 makes gameplay more dramatic - brakeBuff += weightKg() * 3.0f; - } if(ConfigHandler.ENABLE_SLOPE_ACCELERATION) { if (Math.abs(rotationPitch) - 1 > 0) { //cap the pitch that we actually consider to be on a slope //vanilla uses 0.0078125 per tick for slope speed. @@ -1085,38 +1076,27 @@ public void applyDrag() { } } - //now do drag stuff - - //scale drag for derail, or air lateral friction. if you do both at the same time then it's way too much. - if(derail){ - drag*=CommonUtil.getBlockAt(getWorld(),posX,posY,posZ).slipperiness; - } else if (cachedVectors[2].yCoord > 0) { + //Derailed drag (sum up off-rail bogies and scale based on slipperiness of block below) + float bogiesOffRail = derail ? 1f : (bogieBack.isOnRail?0f:0.5f) + (bogieFront.isOnRail?0f:0.5f); + if(bogiesOffRail > 0) { + drag *= 1 - bogiesOffRail * derailSlipFactor * (1 - CommonUtil.getBlockAt(getWorld(),posX,posY,posZ).slipperiness); + } + //Lateral friction drag. If you do both at the same time then it's way too much. + else if (cachedVectors[2].yCoord > 0) { drag -= ((getFriction() * cachedVectors[2].yCoord * 4.448f)); //we don't know what 4.448 does } - //add in the drag from combined weight, plus brakes. - if(pullingWeight!=0) {//in theory this should never be 0, but we know forge is dumb - drag -= ((getAccelerator()==0?getFriction()*0.75:getFriction()*2.5) * (pullingWeight + brakeBuff)) / 1000; //was 4448, no idea. Just adjusted until something felt nice - } //cap the drag to prevent weird behavior. // if it goes to 1 or higher then we speed up, which is bad, if it's below 0 we reverse, which is also bad - if (drag > 0.9999f) { - drag = 0.9999f; - } else if (drag < 0f) { - drag = 0f; - } - - - if(!isAccelerating()) { - bogieFront.drag(this, drag); - bogieBack.drag(this, drag); - } + drag = Math.max(0, Math.min(0.9999f, drag)); + bogieFront.multiplyVelocity(drag); + bogieBack.multiplyVelocity(drag); } public float getFriction(){return 0.15f;} - public double getAccelerator(){return accelerate;} + //public double getAccelerator(){return accelerate;} public float getVelocity(){ @@ -1312,16 +1292,16 @@ public void multiplyVelocity(double vel) { if (train.backLink != null && last.backLink != null && last == train.backLink && train == last.backLink) { - train.bogieBack.multiplyVelocity(train, -vel); - train.bogieFront.multiplyVelocity(train, -vel); + train.bogieBack.multiplyVelocity(-vel); + train.bogieFront.multiplyVelocity(-vel); } else if (train.frontLink != null && last.frontLink != null && last == train.frontLink && train == last.frontLink) { - train.bogieBack.multiplyVelocity(train, -vel); - train.bogieFront.multiplyVelocity(train, -vel); + train.bogieBack.multiplyVelocity(-vel); + train.bogieFront.multiplyVelocity(-vel); } else { - train.bogieBack.multiplyVelocity(train, vel); - train.bogieFront.multiplyVelocity(train, vel); + train.bogieBack.multiplyVelocity(vel); + train.bogieFront.multiplyVelocity(vel); } } } @@ -1499,39 +1479,12 @@ public boolean shouldDoRailFunctions() { return true; } - protected void applyDragAndPushForces() { - motionX *= getDragAir(); - motionY *= 0.0D; - motionZ *= getDragAir(); - } - - /** - * Carts should return their drag factor here - * - * @return The drag rate. - */ - @Override - public double getDragAir() { - return isAccelerating()?1D:0.9998D; - } - @Override public void moveMinecartOnRail(int i, int j, int k, double d) {} - /** - * Returns the carts max speed. Carts going faster than 1.1 cause issues - * with chunk loading. This value is compared with the rails max speed to determine - * the carts current max speed. A normal rails max speed is 0.4. - * - * @return Carts max speed. - */ - @Override - public float getMaxCartSpeedOnRail() { - return maxSpeed; - } @Override public float getMaxSpeedAirLateral() { diff --git a/src/main/java/train/common/api/Locomotive.java b/src/main/java/train/common/api/Locomotive.java index 5530f4c78e..25f95dcc30 100644 --- a/src/main/java/train/common/api/Locomotive.java +++ b/src/main/java/train/common/api/Locomotive.java @@ -106,7 +106,6 @@ public abstract class Locomotive extends Freight implements WirelessTransmitter, /** * These variables are used to display changes in the GUI */ - public int currentNumCartsPulled = 0; public double currentMassPulled = 0; public double currentSpeedSlowDown = 0; public double currentAccelSlowDown = 0; @@ -128,7 +127,7 @@ public abstract class Locomotive extends Freight implements WirelessTransmitter, public Locomotive(World world) { super(world); if(world==null){return;} - setFuelConsumption(0); + setFuelConsumption(getSpecFuelConsumption()); dataWatcher.addObject(2, 0); this.setDefaultMass(0); this.setCustomSpeed(transportTopSpeed()); @@ -141,8 +140,8 @@ public Locomotive(World world) { dataWatcher.addObject(28, lightingDetailsJSONString()); //dataWatcher.addObject(32, lineWaypoints); - setAccel(0); - setBrake(0); + setAccel(getSpecAccel()); + setBrake(getSpecBrake()); this.entityCollisionReduction = 0.99F; if (this instanceof SteamTrain) isLocoTurnedOn = true; char[] chars = "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); @@ -293,10 +292,10 @@ public int setFuelConsumption(int c) { if (c != 0) { return fuelRate = c; } - return fuelRate = setFuelConsumption(); + return fuelRate = getSpecFuelConsumption(); } - public int setFuelConsumption() { + public int getSpecFuelConsumption() { return getSpec()==null?80:getSpec().getFuelConsumption(); } @@ -323,10 +322,10 @@ public double setAccel(double rate) { updateLinks(); } } - return accelerate = setAccel(); + return accelerate = getSpecAccel(); } } - public double setAccel() { + public double getSpecAccel() { return getSpec()==null?0.4:getSpec().getAccelerationRate(); } @@ -339,11 +338,11 @@ public double setBrake(double rate) { if (rate != 0) { return brake = rate; } else { - return brake = setBrake(); + return brake = getSpecBrake(); } } - public double setBrake() { + public double getSpecBrake() { return getSpec()==null?0.97:getSpec().getBrakeRate(); } @@ -572,19 +571,6 @@ public String getDestinationGUI() { public float transportTopSpeed(){return getSpec().getMaxSpeed();} - private double convertSpeed(double speed) { - if (ConfigHandler.REAL_TRAIN_SPEED) { - speed *= 2;// applying ratio - } else { - speed *= 6; - } - speed *= 36; - //speed *= 10;// convert in ms - //speed *= 6;// applying ratio - //speed *= 3.6;// convert in km/h - return speed; - } - public void soundHorn() { if(soundHorn==null){ soundHorn=getHorn(); @@ -901,7 +887,7 @@ else if (getState().equals("broken")) { super.onUpdate(); if (!worldObj.isRemote) { - dataWatcher.updateObject(25, (int)Math.round(convertSpeed(Math.sqrt(bogieBack.velocity[0] * bogieBack.velocity[0] + bogieBack.velocity[1] * bogieBack.velocity[1])))); + dataWatcher.updateObject(25, (int)Math.round(SpeedHandler.convertSpeedInv(Math.sqrt(bogieBack.velocity[0] * bogieBack.velocity[0] + bogieBack.velocity[1] * bogieBack.velocity[1])))); dataWatcher.updateObject(24, fuelTrain); dataWatcher.updateObject(20, overheatLevel); dataWatcher.updateObject(23, locoState); @@ -1065,12 +1051,12 @@ public boolean isLocoTurnedOn() { public String guiDetailsJSON() { JsonObject gui = new JsonObject(); - gui.addProperty("cartsPulled", currentNumCartsPulled); + gui.addProperty("cartsPulled", consist.size()-1); gui.addProperty("massPulled", currentMassPulled); gui.addProperty("slowDown", Math.round(currentSpeedSlowDown)); - gui.addProperty("accelSlowDown", currentAccelSlowDown); - gui.addProperty("brakeSlowDown", currentBrakeSlowDown); - gui.addProperty("fuelUseChange", currentFuelConsumptionChange); + gui.addProperty("accelSlowDown", (double)Math.round(currentAccelSlowDown*1000)/1000); + gui.addProperty("brakeSlowDown", (double)Math.round(currentBrakeSlowDown*1000)/1000); + gui.addProperty("fuelUseChange", (double)Math.round(currentFuelConsumptionChange*1000)/1000); return gui.toString(); } diff --git a/src/main/java/train/common/api/SpeedHandler.java b/src/main/java/train/common/api/SpeedHandler.java index 14dabbdfd9..32e8226993 100644 --- a/src/main/java/train/common/api/SpeedHandler.java +++ b/src/main/java/train/common/api/SpeedHandler.java @@ -8,56 +8,20 @@ import net.minecraft.world.World; import train.common.core.handlers.ConfigHandler; +/* + * Convert between internal TC velocity and minecart velocity + **/ public class SpeedHandler { - public static float handleSpeed(float railMaxSpeed, float maxSpeed, Entity entity) { - if(entity instanceof Locomotive) { - if (railMaxSpeed < 0.4f) { - return Math.min(convertSpeed(entity, maxSpeed), railMaxSpeed); - } else if (railMaxSpeed > 0.45f && railMaxSpeed < 1.1f ) { - return convertSpeed(entity, maxSpeed) + 0.2f; - } - - return convertSpeed(entity, maxSpeed); - }else { - return 15; - } - } - - /** - * - * @param world - * @param i - * @param j - * @param k - * @return - */ - public static boolean isSpeedRailAt(World world, int i, int j, int k) { - Block block = world.getBlock(i, j, k); - //Block block = Block.blocksList[id]; - if (block != null && block.getClass().getName().equals("IRailSpeed")) { - return true; - } - TileEntity tile = world.getTileEntity(i, j, k); - return tile != null && tile.getClass().getName().equals("IRailSpeed"); - } - - public double speedXFromPitch(EntityPlayer player, double var3) { - //System.out.println("X Y: " + player.rotationYaw + " |P: " + player.rotationPitch + " |Sin: " + (-MathHelper.sin(player.rotationYaw / 180.0F * (float) Math.PI)) + " |Cos: " + (MathHelper.cos(player.rotationPitch / 180.0F * (float) Math.PI))); - return -MathHelper.sin(player.rotationYaw / 180.0F * (float) Math.PI) * var3 * MathHelper.cos(player.rotationPitch / 180.0F * (float) Math.PI) * var3; - } - - public double speedZFromPitch(EntityPlayer player, double var3) { - //System.out.println("Z Y: " + player.rotationYaw + " |P: " + player.rotationPitch + " |Sin: " + (-MathHelper.sin(player.rotationYaw / 180.0F * (float) Math.PI)) + " |Cos: " + (MathHelper.cos(player.rotationPitch / 180.0F * (float) Math.PI))); - return MathHelper.cos(player.rotationYaw / 180.0F * (float) Math.PI) * var3 * MathHelper.cos(player.rotationPitch / 180.0F * (float) Math.PI) * var3; + public static double convertSpeed(double speed) { + speed /= ConfigHandler.REAL_TRAIN_SPEED?2f:6f; + speed /= 36f; // /10 for minecraft speed + return speed; } - /** - * - */ - private static float convertSpeed(Entity entity, float maxSpeed) { - float speed = ((Locomotive) entity).getMaxSpeed()*0.2775f;// speed is in m/s - speed /= ConfigHandler.REAL_TRAIN_SPEED?2f:6f;// applying ratio - return speed/10;// converted in minecraft speed + public static double convertSpeedInv(double speed) { + speed *= ConfigHandler.REAL_TRAIN_SPEED ? 2 : 6; + speed *= 36; // *10 for minecraft speed + return speed; } -} +} \ No newline at end of file diff --git a/src/main/java/train/common/core/HandleMaxAttachedCarts.java b/src/main/java/train/common/core/HandleMaxAttachedCarts.java index 0f9e9e7a49..a4430aae0d 100644 --- a/src/main/java/train/common/core/HandleMaxAttachedCarts.java +++ b/src/main/java/train/common/core/HandleMaxAttachedCarts.java @@ -3,166 +3,35 @@ import train.common.api.AbstractTrains; import train.common.api.Locomotive; -/** - * Power is not limited to 1000 anymore. Power is shared between locomotives in a train. - *

- * Speed: MaxSpeed-= (totalMass/(power/400)); - *

- * Then fuel rate: fuelRate -= (int) (scaledPower * totalMass*100) - *

- * Power is scaled again to fit the acceleration/brake values - * scaledPower = (totalMass/(power/200)); - * Then - * scaledPower = scalePower(scaledPower) - * scalePower() => (power/1000)*0.8 - *

- * Then acceleration: accelerate-=ScaledPower*Mass - *

- * Then brake: brake+=ScaledPower*Mass - */ public class HandleMaxAttachedCarts { - public HandleMaxAttachedCarts() { - - } + public HandleMaxAttachedCarts() {} /** - * handles the physic for the locomotive speed, acceleration, brake and fuel consumption depending of the carts attached to it + * Handles the debuffs from attached stocks to a Locomotive's speed, brake, accel and fuel rate */ - public static void PullPhysic(Locomotive cart1) { - double totalMass = 0; - if ((cart1).train != null && !(cart1).train.getTrains().isEmpty()) { + public static void PullPhysic(Locomotive Loco) { - for (int j1 = 0; j1 < (cart1).train.getTrains().size(); j1++) { - totalMass += ((cart1).train.getTrains().get(j1).weightKg()*0.1); - } - (cart1).currentNumCartsPulled = (cart1).train.getTrains().size() - 1; - (cart1).currentMassPulled = Math.round(totalMass * 10); - } else { - totalMass = 0; - (cart1).currentNumCartsPulled = 0; - (cart1).currentMassPulled = 0; - } - /** - * Speed is scaled by the mass of carts pulled and the power of the locomotive Power is converted before this calculation MaxSpeed-=exp((Power*Mass)/2) - */ - if (totalMass < 0) { - totalMass = 0; - } else { - totalMass *= 0.745; - } + Loco.currentMassPulled = Loco.pullingWeight * 0.07457; + double totalMhp = Loco.transportMetricHorsePower() > 0 ? Loco.transportMetricHorsePower() : 100; // Guarantee non-zero so we don't divide by zero - double power = 0; - if ((cart1).train != null && !(cart1).train.getTrains().isEmpty() && (cart1).train.getTrains().size() > 1) { - power =cart1.transportMetricHorsePower(); - for (int i = 0; i < (cart1).train.getTrains().size(); i++) { - AbstractTrains stock = (cart1).train.getTrains().get(i); - if (stock instanceof Locomotive && stock.uniqueID != (cart1).uniqueID) { - power += stock.transportMetricHorsePower(); - } + // Append passive locos Mhp + for (AbstractTrains stock : Loco.consist) { + if (stock instanceof Locomotive && stock.uniqueID != Loco.uniqueID) { + totalMhp += stock.transportMetricHorsePower(); } - //power = ((Locomotive) cart1).getPower();//((EntityRollingStock) cart1).train.getTrainPower(); - double maxSpeed = (cart1).getMaxSpeed();// reset speed and get default - - double maxSpeed1 = totalMass == 0 ? 0 : (totalMass / (power / 74.57)); - maxSpeed -= maxSpeed1; - if (maxSpeed > 0) {// if maxSpeed=0 then default is used: not good here! and we don't want negative speed - (cart1).setCustomSpeed(maxSpeed); - } else { - (cart1).setCustomSpeed(0.1); - } - (cart1).currentSpeedSlowDown = maxSpeed1; - //System.out.println("mass "+totalMass +" power "+power +" "+cart1 ); - - } else if ((cart1).train == null || (cart1).train.getTrains().size() < 2) { - double maxSpeed = (cart1).getMaxSpeed(); - (cart1).setCustomSpeed(maxSpeed); - (cart1).currentSpeedSlowDown = 0; - } - - /** - * acceleration is scaled by the mass of carts pulled and the power of the locomotive Power is converted and scaled before this calculation accelerate-=ScaledPower*Mass - */ - double scaledPower = totalMass == 0 ? 0 : (totalMass / (power / 745.7));//(power*totalMass)/(power*6);//scalePower(power); - scaledPower = scalePower(scaledPower); - double accelerate = (cart1).setAccel(0);// reset acceleration and get default - if ((power * totalMass) > 0) { - accelerate -= (scaledPower * totalMass * 1.13); - } - if (accelerate > 0) {// if accelerate=0 then default is used: not good here! and we don't want negative acceleration - (cart1).setAccel(accelerate); - } - if ((power * totalMass) > 0) { - (cart1).currentAccelSlowDown = (scaledPower * (totalMass * 1.13)); - } else { - (cart1).currentAccelSlowDown = 0; - } - - - /** - * brake is scaled by the mass of carts pulled and the power of the locomotive Power is converted and scaled before this calculation brake+=ScaledPower*Mass - */ - double brake = (cart1).setBrake(0);// reset brake and get default - brake += (scaledPower * totalMass); - if (brake > 1) - brake = 0.998; - if (brake > 0) {// if accelerate=0 then default is used: not good here! and we don't want negative brake or brake values higher than 1 (which mean acceleration) - if ((power * totalMass) > 0) (cart1).setBrake(brake); - } - if ((power * totalMass) > 0) { - (cart1).currentBrakeSlowDown = (scaledPower * (totalMass)); - } else { - (cart1).currentBrakeSlowDown = 0; - } - - - /** - * fuel consumption is scaled by the mass of carts pulled and the power of the locomotive Power is converted before this calculation fuelRate-=power*Mass - */ - - int fuelRate = (cart1).setFuelConsumption(0);// reset and get default - fuelRate -= (int) (scaledPower * totalMass * 100); - //if((power * totalMass)>0)System.out.println(cart1+"fuelRate "+fuelRate); - if (fuelRate > 0) {// if fuelRate=0 then default is used: not good here! and we don't want negative fuelRate - (cart1).setFuelConsumption(fuelRate); - } - if ((power * totalMass) > 0) { - (cart1).currentFuelConsumptionChange = (fuelRate); - } else { - (cart1).currentFuelConsumptionChange = 0; } + // Debuffs + Loco.currentSpeedSlowDown = Loco.currentMassPulled / totalMhp * 74.57; + Loco.currentBrakeSlowDown = Math.pow(Loco.currentMassPulled,2) / totalMhp * 0.7457 * 0.8; + Loco.currentAccelSlowDown = Loco.currentBrakeSlowDown * 1.13; + Loco.currentFuelConsumptionChange = Loco.currentBrakeSlowDown * 100; + // Get the defaults, then scale them + Loco.setCustomSpeed(Math.max( Loco.getMaxSpeed() - Loco.currentSpeedSlowDown,0)); // Avoid Speed < 0 + Loco.setBrake(Math.min( Loco.getSpecBrake() + Loco.currentBrakeSlowDown,0.998)); // Avoid Brake > 1 (acceleration) + Loco.setAccel(Math.max( Loco.getSpecAccel() - Loco.currentAccelSlowDown,0)); // Avoid Accel < 0 (braking) + Loco.setFuelConsumption( Loco.getSpecFuelConsumption() - (int)Loco.currentFuelConsumptionChange); } - - /** - * Possible values: from 0 to 1000 example: power=800 800/1000=0.8 1-0.8=0.2 return 0.2 - * - * @param power the power of the locomotive - * @return the converted power - */ - @Deprecated - private double convertPower(double power) { - power /= 1000; - power = 1 - power; - - return power; - - } - - /** - * Used to scale power for calculation like Brake and Acceleration rates - * - * @return - */ - private static double scalePower(double power) { - if (power == 0) { - return 0; - } - power /= 1000; - power *= 0.8; - return power; - - } - } \ No newline at end of file diff --git a/src/main/java/train/common/entity/rollingStockOld/special/EntityTracksBuilder.java b/src/main/java/train/common/entity/rollingStockOld/special/EntityTracksBuilder.java index 41bc333809..df6059e3cd 100644 --- a/src/main/java/train/common/entity/rollingStockOld/special/EntityTracksBuilder.java +++ b/src/main/java/train/common/entity/rollingStockOld/special/EntityTracksBuilder.java @@ -362,8 +362,9 @@ public void closeInventory() {} public int scaleMaxFuel(int i) { return (this.getFuel() * i) / maxFuel; } - - @Override + + // TODO: Convert to cleaner EntityRollingStock drag? + @Deprecated protected void applyDragAndPushForces() { double d26 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); if (d26 > 0.01D) { @@ -383,9 +384,9 @@ protected void applyDragAndPushForces() { motionY *= 0.0D; motionZ *= 0.69999997615814209D; } - motionX *= getDragAir(); + motionX *= 0.98d; motionY *= 0.0D; - motionZ *= getDragAir(); + motionZ *= 0.98d; } protected void updatePushForces() {