[BugFix] Fixed Continuity Test
- Reimplemented the continuity test in BarrowmanCalculator - Added corresponding unit tests, too
This commit is contained in:
parent
0ab8dde5fb
commit
3f9be1387d
@ -2,12 +2,8 @@ package net.sf.openrocket.aerodynamics;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.BugException;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
|
|
||||||
@ -19,7 +15,6 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class AbstractAerodynamicCalculator implements AerodynamicCalculator {
|
public abstract class AbstractAerodynamicCalculator implements AerodynamicCalculator {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AbstractAerodynamicCalculator.class);
|
|
||||||
|
|
||||||
/** Number of divisions used when calculating worst CP. */
|
/** Number of divisions used when calculating worst CP. */
|
||||||
public static final int DIVISIONS = 360;
|
public static final int DIVISIONS = 360;
|
||||||
|
@ -3,6 +3,7 @@ package net.sf.openrocket.aerodynamics;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.Monitorable;
|
import net.sf.openrocket.util.Monitorable;
|
||||||
@ -66,5 +67,6 @@ public interface AerodynamicCalculator extends Monitorable {
|
|||||||
* @return a new, independent instance of this aerodynamic calculator type
|
* @return a new, independent instance of this aerodynamic calculator type
|
||||||
*/
|
*/
|
||||||
public AerodynamicCalculator newInstance();
|
public AerodynamicCalculator newInstance();
|
||||||
|
|
||||||
|
public boolean isContinuous( final Rocket rkt);
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,19 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
import net.sf.openrocket.aerodynamics.barrowman.FinSetCalc;
|
import net.sf.openrocket.aerodynamics.barrowman.FinSetCalc;
|
||||||
import net.sf.openrocket.aerodynamics.barrowman.RocketComponentCalc;
|
import net.sf.openrocket.aerodynamics.barrowman.RocketComponentCalc;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
||||||
import net.sf.openrocket.rocketcomponent.ExternalComponent;
|
import net.sf.openrocket.rocketcomponent.ExternalComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
||||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.RingInstanceable;
|
import net.sf.openrocket.rocketcomponent.RingInstanceable;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
|
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
@ -151,11 +155,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform the actual CP calculation.
|
|
||||||
*/
|
|
||||||
private AerodynamicForces calculateNonAxialForces(FlightConfiguration configuration, FlightConditions conditions,
|
private AerodynamicForces calculateNonAxialForces(FlightConfiguration configuration, FlightConditions conditions,
|
||||||
Map<RocketComponent, AerodynamicForces> map, WarningSet warnings) {
|
Map<RocketComponent, AerodynamicForces> map, WarningSet warnings) {
|
||||||
|
|
||||||
@ -164,8 +164,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
AerodynamicForces total = new AerodynamicForces();
|
AerodynamicForces total = new AerodynamicForces();
|
||||||
total.zero();
|
total.zero();
|
||||||
|
|
||||||
double radius = 0; // aft radius of previous component
|
|
||||||
double componentX = 0; // aft coordinate of previous component
|
|
||||||
AerodynamicForces forces = new AerodynamicForces();
|
AerodynamicForces forces = new AerodynamicForces();
|
||||||
|
|
||||||
if (warnings == null)
|
if (warnings == null)
|
||||||
@ -178,6 +176,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
if (calcMap == null)
|
if (calcMap == null)
|
||||||
buildCalcMap(configuration);
|
buildCalcMap(configuration);
|
||||||
|
|
||||||
|
|
||||||
|
if( ! isContinuous( configuration.getRocket() ) ){
|
||||||
|
warnings.add( Warning.DIAMETER_DISCONTINUITY);
|
||||||
|
}
|
||||||
|
|
||||||
for (RocketComponent component : configuration.getActiveComponents()) {
|
for (RocketComponent component : configuration.getActiveComponents()) {
|
||||||
|
|
||||||
// Skip non-aerodynamic components
|
// Skip non-aerodynamic components
|
||||||
@ -185,35 +188,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
// TODO: refactor this code block to a separate method, where it will operate on each stage separately.
|
|
||||||
//
|
|
||||||
// Developer's Note:
|
|
||||||
// !! this code assumes all SymmetricComponents are along the centerline
|
|
||||||
// With the implementation of ParallelStages and Pods, this is no longer true. -Daniel Williams
|
|
||||||
//
|
|
||||||
// // Check for discontinuities
|
|
||||||
if (component instanceof SymmetricComponent) {
|
|
||||||
SymmetricComponent sym = (SymmetricComponent) component;
|
|
||||||
// TODO:LOW: Ignores other cluster components (not clusterable)
|
|
||||||
double x = component.toAbsolute(Coordinate.NUL)[0].x;
|
|
||||||
|
|
||||||
// Check for lengthwise discontinuity
|
|
||||||
if (x > componentX + 0.0001) {
|
|
||||||
if (!MathUtil.equals(radius, 0)) {
|
|
||||||
warnings.add(Warning.DISCONTINUITY);
|
|
||||||
radius = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x;
|
|
||||||
|
|
||||||
// Check for radius discontinuity
|
|
||||||
if (!MathUtil.equals(sym.getForeRadius(), radius)) {
|
|
||||||
warnings.add(Warning.DISCONTINUITY);
|
|
||||||
// TODO: MEDIUM: Apply correction to values to cp and to map
|
|
||||||
}
|
|
||||||
radius = sym.getAftRadius();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call calculation method
|
// Call calculation method
|
||||||
forces.zero();
|
forces.zero();
|
||||||
RocketComponentCalc calcObj = calcMap.get(component);
|
RocketComponentCalc calcObj = calcMap.get(component);
|
||||||
@ -273,6 +247,51 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContinuous( final Rocket rkt){
|
||||||
|
return testIsContinuous( rkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean testIsContinuous( final RocketComponent treeRoot ){
|
||||||
|
Queue<RocketComponent> queue = new LinkedList<RocketComponent>();
|
||||||
|
queue.addAll(treeRoot.getChildren());
|
||||||
|
|
||||||
|
boolean isContinuous = true;
|
||||||
|
SymmetricComponent prevComp = null;
|
||||||
|
while((isContinuous)&&( null != queue.peek())){
|
||||||
|
RocketComponent comp = queue.poll();
|
||||||
|
if( comp instanceof SymmetricComponent ){
|
||||||
|
queue.addAll( comp.getChildren());
|
||||||
|
|
||||||
|
SymmetricComponent sym = (SymmetricComponent) comp;
|
||||||
|
if( null == prevComp){
|
||||||
|
prevComp = sym;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for radius discontinuity
|
||||||
|
if ( !MathUtil.equals(sym.getForeRadius(), prevComp.getAftRadius())) {
|
||||||
|
isContinuous = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// double x = component.toAbsolute(Coordinate.NUL)[0].x;
|
||||||
|
// // Check for lengthwise discontinuity
|
||||||
|
// if (x > componentX + 0.0001) {
|
||||||
|
// if (!MathUtil.equals(radius, 0)) {
|
||||||
|
// warnings.add(Warning.DISCONTINUITY);
|
||||||
|
// radius = 0;
|
||||||
|
//}
|
||||||
|
//componentX = component.toAbsolute(new Coordinate(component.getLength()))[0].x;
|
||||||
|
|
||||||
|
prevComp = sym;
|
||||||
|
}else if( comp instanceof ComponentAssembly ){
|
||||||
|
isContinuous &= testIsContinuous( comp );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return isContinuous;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////// DRAG CALCULATIONS ////////////////
|
//////////////// DRAG CALCULATIONS ////////////////
|
||||||
|
@ -321,7 +321,7 @@ public abstract class Warning {
|
|||||||
|
|
||||||
/** A <code>Warning</code> that the body diameter is discontinuous. */
|
/** A <code>Warning</code> that the body diameter is discontinuous. */
|
||||||
////Discontinuity in rocket body diameter.
|
////Discontinuity in rocket body diameter.
|
||||||
public static final Warning DISCONTINUITY =
|
public static final Warning DIAMETER_DISCONTINUITY =
|
||||||
new Other(trans.get("Warning.DISCONTINUITY"));
|
new Other(trans.get("Warning.DISCONTINUITY"));
|
||||||
|
|
||||||
/** A <code>Warning</code> that the fins are thick compared to the rocket body. */
|
/** A <code>Warning</code> that the fins are thick compared to the rocket body. */
|
||||||
|
@ -115,7 +115,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
public boolean isAfter(){
|
public boolean isAfter(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLaunchStage(){
|
public boolean isLaunchStage(){
|
||||||
return ( getRocket().getBottomCoreStage().equals(this));
|
return ( getRocket().getBottomCoreStage().equals(this));
|
||||||
}
|
}
|
||||||
|
@ -1938,8 +1938,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
return (MathUtil.pow2(innerRadius) + MathUtil.pow2(outerRadius)) / 2;
|
return (MathUtil.pow2(innerRadius) + MathUtil.pow2(outerRadius)) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////// OTHER
|
//////////// OTHER
|
||||||
|
|
||||||
|
|
||||||
|
@ -833,52 +833,53 @@ public class TestRockets {
|
|||||||
coreFins.setHeight(0.12);
|
coreFins.setHeight(0.12);
|
||||||
coreFins.setSweep(0.18);
|
coreFins.setSweep(0.18);
|
||||||
coreBody.addChild(coreFins);
|
coreBody.addChild(coreFins);
|
||||||
}
|
|
||||||
|
|
||||||
// ====== Booster Stage Set ======
|
|
||||||
// ====== ====== ====== ======
|
|
||||||
ParallelStage boosterStage = new ParallelStage();
|
|
||||||
boosterStage.setName("Booster Stage");
|
|
||||||
coreStage.addChild( boosterStage);
|
|
||||||
boosterStage.setRelativePositionMethod(Position.BOTTOM);
|
|
||||||
boosterStage.setAxialOffset(0.0);
|
|
||||||
boosterStage.setInstanceCount(2);
|
|
||||||
boosterStage.setRadialOffset(0.075);
|
|
||||||
|
|
||||||
{
|
|
||||||
NoseCone boosterCone = new NoseCone(Transition.Shape.POWER, 0.08, 0.0385);
|
|
||||||
boosterCone.setShapeParameter(0.5);
|
|
||||||
boosterCone.setName("Booster Nose");
|
|
||||||
boosterCone.setThickness(0.002);
|
|
||||||
//payloadFairingNoseCone.setLength(0.118);
|
|
||||||
//payloadFairingNoseCone.setAftRadius(0.052);
|
|
||||||
boosterCone.setAftShoulderRadius( 0.051 );
|
|
||||||
boosterCone.setAftShoulderLength( 0.02 );
|
|
||||||
boosterCone.setAftShoulderThickness( 0.001 );
|
|
||||||
boosterCone.setAftShoulderCapped( false );
|
|
||||||
boosterStage.addChild( boosterCone);
|
|
||||||
|
|
||||||
BodyTube boosterBody = new BodyTube(0.8, 0.0385, 0.001);
|
// ====== Booster Stage Set ======
|
||||||
boosterBody.setName("Booster Body");
|
// ====== ====== ====== ======
|
||||||
boosterBody.setOuterRadiusAutomatic(true);
|
ParallelStage boosterStage = new ParallelStage();
|
||||||
boosterStage.addChild( boosterBody);
|
boosterStage.setName("Booster Stage");
|
||||||
|
coreStage.addChild( boosterStage);
|
||||||
|
boosterStage.setRelativePositionMethod(Position.BOTTOM);
|
||||||
|
boosterStage.setAxialOffset(0.0);
|
||||||
|
boosterStage.setInstanceCount(2);
|
||||||
|
boosterStage.setRadialOffset(0.075);
|
||||||
|
|
||||||
{
|
{
|
||||||
InnerTube boosterMotorTubes = new InnerTube();
|
NoseCone boosterCone = new NoseCone(Transition.Shape.POWER, 0.08, 0.0385);
|
||||||
boosterMotorTubes.setName("Booster Motor Tubes");
|
boosterCone.setShapeParameter(0.5);
|
||||||
boosterMotorTubes.setLength(0.15);
|
boosterCone.setName("Booster Nose");
|
||||||
boosterMotorTubes.setOuterRadius(0.015); // => 29mm motors
|
boosterCone.setThickness(0.002);
|
||||||
boosterMotorTubes.setThickness(0.0005);
|
//payloadFairingNoseCone.setLength(0.118);
|
||||||
boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[5]); // 4-ring
|
//payloadFairingNoseCone.setAftRadius(0.052);
|
||||||
//boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[13]); // 9-star
|
boosterCone.setAftShoulderRadius( 0.051 );
|
||||||
boosterMotorTubes.setClusterScale(1.0);
|
boosterCone.setAftShoulderLength( 0.02 );
|
||||||
boosterBody.addChild( boosterMotorTubes);
|
boosterCone.setAftShoulderThickness( 0.001 );
|
||||||
|
boosterCone.setAftShoulderCapped( false );
|
||||||
|
boosterStage.addChild( boosterCone);
|
||||||
|
|
||||||
FlightConfigurationId motorConfigId = config.getFlightConfigurationID();
|
BodyTube boosterBody = new BodyTube(0.8, 0.0385, 0.001);
|
||||||
MotorConfiguration motorInstance = TestRockets.generateMotorInstance_G77_29mm();
|
boosterBody.setName("Booster Body");
|
||||||
motorInstance.setID( new MotorInstanceId( boosterMotorTubes.getName(), 1) );
|
boosterBody.setOuterRadiusAutomatic(true);
|
||||||
boosterMotorTubes.setMotorInstance( motorConfigId, motorInstance);
|
boosterStage.addChild( boosterBody);
|
||||||
boosterMotorTubes.setMotorOverhang(0.01234);
|
|
||||||
|
{
|
||||||
|
InnerTube boosterMotorTubes = new InnerTube();
|
||||||
|
boosterMotorTubes.setName("Booster Motor Tubes");
|
||||||
|
boosterMotorTubes.setLength(0.15);
|
||||||
|
boosterMotorTubes.setOuterRadius(0.015); // => 29mm motors
|
||||||
|
boosterMotorTubes.setThickness(0.0005);
|
||||||
|
boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[5]); // 4-ring
|
||||||
|
//boosterMotorTubes.setClusterConfiguration( ClusterConfiguration.CONFIGURATIONS[13]); // 9-star
|
||||||
|
boosterMotorTubes.setClusterScale(1.0);
|
||||||
|
boosterBody.addChild( boosterMotorTubes);
|
||||||
|
|
||||||
|
FlightConfigurationId motorConfigId = config.getFlightConfigurationID();
|
||||||
|
MotorConfiguration motorInstance = TestRockets.generateMotorInstance_G77_29mm();
|
||||||
|
motorInstance.setID( new MotorInstanceId( boosterMotorTubes.getName(), 1) );
|
||||||
|
boosterMotorTubes.setMotorInstance( motorConfigId, motorInstance);
|
||||||
|
boosterMotorTubes.setMotorOverhang(0.01234);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package net.sf.openrocket.aerodynamics;
|
package net.sf.openrocket.aerodynamics;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@ -12,7 +14,10 @@ import com.google.inject.Module;
|
|||||||
|
|
||||||
import net.sf.openrocket.ServicesForTesting;
|
import net.sf.openrocket.ServicesForTesting;
|
||||||
import net.sf.openrocket.plugin.PluginModule;
|
import net.sf.openrocket.plugin.PluginModule;
|
||||||
|
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.NoseCone;
|
||||||
|
import net.sf.openrocket.rocketcomponent.ParallelStage;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
@ -102,4 +107,51 @@ public class BarrowmanCalculatorTest {
|
|||||||
fail("Not yet implemented");
|
fail("Not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testContinuousRocket() {
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
AerodynamicCalculator calc = new BarrowmanCalculator();
|
||||||
|
|
||||||
|
assertTrue("Estes Alpha III should be continous: ", calc.isContinuous( rocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testContinuousRocketWithStrapOns() {
|
||||||
|
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
AerodynamicCalculator calc = new BarrowmanCalculator();
|
||||||
|
|
||||||
|
assertTrue("F9H should be continuous: ", calc.isContinuous( rocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRadialDiscontinuousRocket() {
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
AerodynamicCalculator calc = new BarrowmanCalculator();
|
||||||
|
|
||||||
|
NoseCone nose = (NoseCone)rocket.getChild(0).getChild(0);
|
||||||
|
BodyTube body = (BodyTube)rocket.getChild(0).getChild(1);
|
||||||
|
|
||||||
|
nose.setAftRadius(0.015);
|
||||||
|
body.setOuterRadius( 0.012 );
|
||||||
|
body.setName( body.getName()+" << discontinuous");
|
||||||
|
|
||||||
|
assertFalse(" Estes Alpha III has an undetected discontinuity:", calc.isContinuous( rocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRadialDiscontinuityWithStrapOns() {
|
||||||
|
Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
AerodynamicCalculator calc = new BarrowmanCalculator();
|
||||||
|
|
||||||
|
ParallelStage booster = (ParallelStage)rocket.getChild(1).getChild(1);
|
||||||
|
NoseCone nose = (NoseCone)booster.getChild(0);
|
||||||
|
BodyTube body = (BodyTube)booster.getChild(1);
|
||||||
|
|
||||||
|
nose.setAftRadius(0.015);
|
||||||
|
body.setOuterRadius( 0.012 );
|
||||||
|
body.setName( body.getName()+" << discontinuous");
|
||||||
|
|
||||||
|
assertFalse(" Missed discontinuity in Falcon 9 Heavy:", calc.isContinuous( rocket));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user