Extract common functionality to DataBranch
This commit is contained in:
parent
9554bf3fe2
commit
621ee57cc2
@ -1,14 +1,133 @@
|
|||||||
package info.openrocket.core.simulation;
|
package info.openrocket.core.simulation;
|
||||||
|
|
||||||
|
import info.openrocket.core.util.ArrayList;
|
||||||
|
import info.openrocket.core.util.ModID;
|
||||||
import info.openrocket.core.util.Monitorable;
|
import info.openrocket.core.util.Monitorable;
|
||||||
|
import info.openrocket.core.util.Mutable;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A branch of data / collection of data points for a specific type of data.
|
* A branch of data / collection of data points for a specific type of data.
|
||||||
* @param <T> the type of data in this branch
|
* @param <T> the type of data in this branch
|
||||||
*/
|
*/
|
||||||
public interface DataBranch<T extends DataType> extends Monitorable {
|
public abstract class DataBranch<T extends DataType> implements Monitorable {
|
||||||
|
protected final String name;
|
||||||
|
protected final Map<T, ArrayList<Double>> values = new LinkedHashMap<>();
|
||||||
|
protected final Map<T, Double> maxValues = new HashMap<>();
|
||||||
|
protected final Map<T, Double> minValues = new HashMap<>();
|
||||||
|
|
||||||
|
protected final Mutable mutable = new Mutable();
|
||||||
|
protected ModID modID = ModID.INVALID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sole constructor. Defines the name of the DataBranch and at least one variable type.
|
||||||
|
*
|
||||||
|
* @param name the name of this DataBranch.
|
||||||
|
* @param types data types to include (must include at least one type).
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
public DataBranch(String name, T... types) {
|
||||||
|
if (types.length == 0) {
|
||||||
|
throw new IllegalArgumentException("Must specify at least one data type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
for (T t : types) {
|
||||||
|
addType(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataBranch(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addType(T type) {
|
||||||
|
if (values.containsKey(type)) {
|
||||||
|
throw new IllegalArgumentException("Value type " + type + " already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
values.put(type, new ArrayList<>());
|
||||||
|
minValues.put(type, Double.NaN);
|
||||||
|
maxValues.put(type, Double.NaN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new point into the data branch. The value for all types is set to NaN by default.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if this object has been made immutable.
|
||||||
|
*/
|
||||||
|
public void addPoint() {
|
||||||
|
mutable.check();
|
||||||
|
|
||||||
|
for (Map.Entry<T, ArrayList<Double>> entry : values.entrySet()) {
|
||||||
|
sanityCheckValues(entry.getKey(), Double.NaN);
|
||||||
|
entry.getValue().add(Double.NaN);
|
||||||
|
}
|
||||||
|
modID = new ModID();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sanityCheckValues(T type, Double value) {
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
|
||||||
|
if (list == null) {
|
||||||
|
list = new info.openrocket.core.util.ArrayList<>();
|
||||||
|
int n = getLength();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
list.add(Double.NaN);
|
||||||
|
}
|
||||||
|
values.put(type, list);
|
||||||
|
minValues.put(type, value);
|
||||||
|
maxValues.put(type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value for a specific data type at the latest point. New variable types can be
|
||||||
|
* added to the FlightDataBranch transparently.
|
||||||
|
*
|
||||||
|
* @param type the variable to set.
|
||||||
|
* @param value the value to set.
|
||||||
|
* @throws IllegalStateException if this object has been made immutable.
|
||||||
|
*/
|
||||||
|
public void setValue(T type, double value) {
|
||||||
|
mutable.check();
|
||||||
|
|
||||||
|
ArrayList<Double> list = values.computeIfAbsent(type, k -> {
|
||||||
|
ArrayList<Double> newList = new ArrayList<>();
|
||||||
|
int n = getLength();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
newList.add(Double.NaN);
|
||||||
|
}
|
||||||
|
minValues.put(k, Double.NaN);
|
||||||
|
maxValues.put(k, Double.NaN);
|
||||||
|
return newList;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (list.size() > 0) {
|
||||||
|
list.set(list.size() - 1, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double min = minValues.get(type);
|
||||||
|
double max = maxValues.get(type);
|
||||||
|
|
||||||
|
if (Double.isNaN(min) || (value < min)) {
|
||||||
|
minValues.put(type, value);
|
||||||
|
}
|
||||||
|
if (Double.isNaN(max) || (value > max)) {
|
||||||
|
maxValues.put(type, value);
|
||||||
|
}
|
||||||
|
modID = new ModID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of values for the specified variable type.
|
* Return an array of values for the specified variable type.
|
||||||
*
|
*
|
||||||
@ -16,7 +135,12 @@ public interface DataBranch<T extends DataType> extends Monitorable {
|
|||||||
* @return a list of the variable values, or <code>null</code> if
|
* @return a list of the variable values, or <code>null</code> if
|
||||||
* the variable type hasn't been added to this branch.
|
* the variable type hasn't been added to this branch.
|
||||||
*/
|
*/
|
||||||
List<Double> get(T type);
|
public List<Double> get(T type) {
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
if (list == null)
|
||||||
|
return null;
|
||||||
|
return list.clone();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value of the specified type at the specified index.
|
* Return the value of the specified type at the specified index.
|
||||||
@ -24,7 +148,16 @@ public interface DataBranch<T extends DataType> extends Monitorable {
|
|||||||
* @param index the data index of the value
|
* @param index the data index of the value
|
||||||
* @return the value at the specified index
|
* @return the value at the specified index
|
||||||
*/
|
*/
|
||||||
Double getByIndex(T type, int index);
|
public Double getByIndex(T type, int index) {
|
||||||
|
if (index < 0 || index >= getLength()) {
|
||||||
|
throw new IllegalArgumentException("Index out of bounds");
|
||||||
|
}
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
if (list == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the last value of the specified type in the branch, or NaN if the type is
|
* Return the last value of the specified type in the branch, or NaN if the type is
|
||||||
@ -33,7 +166,12 @@ public interface DataBranch<T extends DataType> extends Monitorable {
|
|||||||
* @param type the parameter type.
|
* @param type the parameter type.
|
||||||
* @return the last value in this branch, or NaN.
|
* @return the last value in this branch, or NaN.
|
||||||
*/
|
*/
|
||||||
double getLast(T type);
|
public double getLast(T type) {
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
if (list == null || list.isEmpty())
|
||||||
|
return Double.NaN;
|
||||||
|
return list.get(list.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the minimum value of the specified type in the branch, or NaN if the type
|
* Return the minimum value of the specified type in the branch, or NaN if the type
|
||||||
@ -42,7 +180,12 @@ public interface DataBranch<T extends DataType> extends Monitorable {
|
|||||||
* @param type the parameter type.
|
* @param type the parameter type.
|
||||||
* @return the minimum value in this branch, or NaN.
|
* @return the minimum value in this branch, or NaN.
|
||||||
*/
|
*/
|
||||||
double getMinimum(T type);
|
public double getMinimum(T type) {
|
||||||
|
Double v = minValues.get(type);
|
||||||
|
if (v == null)
|
||||||
|
return Double.NaN;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the maximum value of the specified type in the branch, or NaN if the type
|
* Return the maximum value of the specified type in the branch, or NaN if the type
|
||||||
@ -51,21 +194,59 @@ public interface DataBranch<T extends DataType> extends Monitorable {
|
|||||||
* @param type the parameter type.
|
* @param type the parameter type.
|
||||||
* @return the maximum value in this branch, or NaN.
|
* @return the maximum value in this branch, or NaN.
|
||||||
*/
|
*/
|
||||||
double getMaximum(T type);
|
public double getMaximum(T type) {
|
||||||
|
Double v = maxValues.get(type);
|
||||||
|
if (v == null)
|
||||||
|
return Double.NaN;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the number of data points in this branch.
|
* Return the number of data points in this branch.
|
||||||
*/
|
*/
|
||||||
int getLength();
|
public int getLength() {
|
||||||
|
for (ArrayList<Double> doubles : values.values()) {
|
||||||
|
return doubles.size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the variable types included in this branch. The types are sorted in their
|
* Return the variable types included in this branch. The types are sorted in their
|
||||||
* natural order.
|
* natural order.
|
||||||
*/
|
*/
|
||||||
T[] getTypes();
|
@SuppressWarnings("unchecked")
|
||||||
|
public T[] getTypes() {
|
||||||
|
Set<T> keySet = values.keySet();
|
||||||
|
T[] array = (T[]) Array.newInstance(keySet.iterator().next().getClass(), keySet.size());
|
||||||
|
keySet.toArray(array);
|
||||||
|
Arrays.sort(array);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the branch name.
|
* Return the branch name.
|
||||||
*/
|
*/
|
||||||
String getName();
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make this FlightDataBranch immutable. Any calls to the set methods that would
|
||||||
|
* modify this object will after this call throw an <code>IllegalStateException</code>.
|
||||||
|
*/
|
||||||
|
public void immute() {
|
||||||
|
mutable.immute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this branch is still mutable.
|
||||||
|
*/
|
||||||
|
public boolean isMutable() {
|
||||||
|
return mutable.isMutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModID getModID() {
|
||||||
|
return modID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package info.openrocket.core.simulation;
|
package info.openrocket.core.simulation;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -11,8 +8,6 @@ import info.openrocket.core.rocketcomponent.Rocket;
|
|||||||
import info.openrocket.core.rocketcomponent.RocketComponent;
|
import info.openrocket.core.rocketcomponent.RocketComponent;
|
||||||
import info.openrocket.core.util.ArrayList;
|
import info.openrocket.core.util.ArrayList;
|
||||||
import info.openrocket.core.util.ModID;
|
import info.openrocket.core.util.ModID;
|
||||||
import info.openrocket.core.util.Monitorable;
|
|
||||||
import info.openrocket.core.util.Mutable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single branch of flight data. The data is ordered based on some variable, typically time.
|
* A single branch of flight data. The data is ordered based on some variable, typically time.
|
||||||
@ -29,31 +24,11 @@ import info.openrocket.core.util.Mutable;
|
|||||||
*
|
*
|
||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
public class FlightDataBranch implements DataBranch<FlightDataType> {
|
public class FlightDataBranch extends DataBranch<FlightDataType> {
|
||||||
|
|
||||||
/** The name of this flight data branch. */
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final Map<FlightDataType, ArrayList<Double>> values = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
private final Map<FlightDataType, Double> maxValues = new HashMap<>();
|
|
||||||
private final Map<FlightDataType, Double> minValues = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* time for the rocket to reach apogee if the flight had been no recovery deployment
|
|
||||||
*/
|
|
||||||
private double timeToOptimumAltitude = Double.NaN;
|
private double timeToOptimumAltitude = Double.NaN;
|
||||||
/**
|
|
||||||
* Altitude the rocket would reach if there had been no recovery deployment.
|
|
||||||
*/
|
|
||||||
private double optimumAltitude = Double.NaN;
|
private double optimumAltitude = Double.NaN;
|
||||||
|
|
||||||
private final ArrayList<FlightEvent> events = new ArrayList<>();
|
private final ArrayList<FlightEvent> events = new ArrayList<>();
|
||||||
|
|
||||||
private final Mutable mutable = new Mutable();
|
|
||||||
|
|
||||||
private ModID modID = ModID.INVALID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sole constructor. Defines the name of the FlightDataBranch and at least one variable type.
|
* Sole constructor. Defines the name of the FlightDataBranch and at least one variable type.
|
||||||
*
|
*
|
||||||
@ -61,22 +36,7 @@ public class FlightDataBranch implements DataBranch<FlightDataType> {
|
|||||||
* @param types data types to include (must include at least one type).
|
* @param types data types to include (must include at least one type).
|
||||||
*/
|
*/
|
||||||
public FlightDataBranch(String name, FlightDataType... types) {
|
public FlightDataBranch(String name, FlightDataType... types) {
|
||||||
if (types.length == 0) {
|
super(name, types);
|
||||||
throw new IllegalArgumentException("Must specify at least one data type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.name = name;
|
|
||||||
|
|
||||||
for (FlightDataType t : types) {
|
|
||||||
if (values.containsKey(t)) {
|
|
||||||
throw new IllegalArgumentException("Value type " + t + " specified multiple " +
|
|
||||||
"times in constructor.");
|
|
||||||
}
|
|
||||||
|
|
||||||
values.put(t, new ArrayList<>());
|
|
||||||
minValues.put(t, Double.NaN);
|
|
||||||
maxValues.put(t, Double.NaN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +49,7 @@ public class FlightDataBranch implements DataBranch<FlightDataType> {
|
|||||||
* @param parent the parent branch to copy data from.
|
* @param parent the parent branch to copy data from.
|
||||||
*/
|
*/
|
||||||
public FlightDataBranch(String name, RocketComponent srcComponent, FlightDataBranch parent) {
|
public FlightDataBranch(String name, RocketComponent srcComponent, FlightDataBranch parent) {
|
||||||
this.name = name;
|
super(name);
|
||||||
|
|
||||||
// Copy all the values from the parent
|
// Copy all the values from the parent
|
||||||
copyValuesFromBranch(parent, srcComponent);
|
copyValuesFromBranch(parent, srcComponent);
|
||||||
@ -99,72 +59,13 @@ public class FlightDataBranch implements DataBranch<FlightDataType> {
|
|||||||
* Makes an 'empty' flight data branch which has no data but all built in data types are defined.
|
* Makes an 'empty' flight data branch which has no data but all built in data types are defined.
|
||||||
*/
|
*/
|
||||||
public FlightDataBranch() {
|
public FlightDataBranch() {
|
||||||
name = "Empty branch";
|
super("Empty branch");
|
||||||
for (FlightDataType type : FlightDataType.ALL_TYPES) {
|
for (FlightDataType type : FlightDataType.ALL_TYPES) {
|
||||||
this.setValue(type, Double.NaN);
|
this.setValue(type, Double.NaN);
|
||||||
}
|
}
|
||||||
this.immute();
|
this.immute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new point into the data branch. The value for all types is set to NaN by default.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException if this object has been made immutable.
|
|
||||||
*/
|
|
||||||
public void addPoint() {
|
|
||||||
mutable.check();
|
|
||||||
|
|
||||||
for (Map.Entry<FlightDataType, ArrayList<Double>> entry : values.entrySet()) {
|
|
||||||
sanityCheckValues(entry.getKey(), Double.NaN);
|
|
||||||
entry.getValue().add(Double.NaN);
|
|
||||||
}
|
|
||||||
modID = new ModID();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sanityCheckValues(FlightDataType type, Double value) {
|
|
||||||
ArrayList<Double> list = values.get(type);
|
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<>();
|
|
||||||
int n = getLength();
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
list.add(Double.NaN);
|
|
||||||
}
|
|
||||||
values.put(type, list);
|
|
||||||
minValues.put(type, value);
|
|
||||||
maxValues.put(type, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value for a specific data type at the latest point. New variable types can be
|
|
||||||
* added to the FlightDataBranch transparently.
|
|
||||||
*
|
|
||||||
* @param type the variable to set.
|
|
||||||
* @param value the value to set.
|
|
||||||
* @throws IllegalStateException if this object has been made immutable.
|
|
||||||
*/
|
|
||||||
public void setValue(FlightDataType type, double value) {
|
|
||||||
mutable.check();
|
|
||||||
|
|
||||||
sanityCheckValues(type, value);
|
|
||||||
ArrayList<Double> list = values.get(type);
|
|
||||||
|
|
||||||
if (list.size() > 0) {
|
|
||||||
list.set(list.size() - 1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
double min = minValues.get(type);
|
|
||||||
double max = maxValues.get(type);
|
|
||||||
|
|
||||||
if (Double.isNaN(min) || (value < min)) {
|
|
||||||
minValues.put(type, value);
|
|
||||||
}
|
|
||||||
if (Double.isNaN(max) || (value > max)) {
|
|
||||||
maxValues.put(type, value);
|
|
||||||
}
|
|
||||||
modID = new ModID();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all the current values in the branch and copies the values from the given branch.
|
* Clears all the current values in the branch and copies the values from the given branch.
|
||||||
@ -228,70 +129,6 @@ public class FlightDataBranch implements DataBranch<FlightDataType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FlightDataType[] getTypes() {
|
|
||||||
FlightDataType[] array = values.keySet().toArray(new FlightDataType[0]);
|
|
||||||
Arrays.sort(array);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLength() {
|
|
||||||
for (ArrayList<Double> doubles : values.values()) {
|
|
||||||
return doubles.size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Double> get(FlightDataType type) {
|
|
||||||
ArrayList<Double> list = values.get(type);
|
|
||||||
if (list == null)
|
|
||||||
return null;
|
|
||||||
return list.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double getByIndex(FlightDataType type, int index) {
|
|
||||||
if (index < 0 || index >= getLength()) {
|
|
||||||
throw new IllegalArgumentException("Index out of bounds");
|
|
||||||
}
|
|
||||||
ArrayList<Double> list = values.get(type);
|
|
||||||
if (list == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return list.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getLast(FlightDataType type) {
|
|
||||||
ArrayList<Double> list = values.get(type);
|
|
||||||
if (list == null || list.isEmpty())
|
|
||||||
return Double.NaN;
|
|
||||||
return list.get(list.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getMinimum(FlightDataType type) {
|
|
||||||
Double v = minValues.get(type);
|
|
||||||
if (v == null)
|
|
||||||
return Double.NaN;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getMaximum(FlightDataType type) {
|
|
||||||
Double v = maxValues.get(type);
|
|
||||||
if (v == null)
|
|
||||||
return Double.NaN;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the timeToOptimumAltitude
|
* @return the timeToOptimumAltitude
|
||||||
@ -388,28 +225,6 @@ public class FlightDataBranch implements DataBranch<FlightDataType> {
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make this FlightDataBranch immutable. Any calls to the set methods that would
|
|
||||||
* modify this object will after this call throw an <code>IllegalStateException</code>.
|
|
||||||
*/
|
|
||||||
public void immute() {
|
|
||||||
mutable.immute();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether this branch is still mutable.
|
|
||||||
*/
|
|
||||||
public boolean isMutable() {
|
|
||||||
return mutable.isMutable();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModID getModID() {
|
|
||||||
return modID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlightDataBranch clone() {
|
public FlightDataBranch clone() {
|
||||||
FlightDataType[] types = getTypes();
|
FlightDataType[] types = getTypes();
|
||||||
FlightDataBranch clone = new FlightDataBranch(name, types);
|
FlightDataBranch clone = new FlightDataBranch(name, types);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user