getCoverUUIDsFromItemStack(final ItemStack stack) {
if (stack.hasTagCompound() && stack.getTagCompound()
.hasKey(GT_Values.NBT.COVERS, TAG_COMPOUND)) {
final NBTTagList tagList = stack.getTagCompound()
.getTagList(GT_Values.NBT.COVERS, TAG_COMPOUND);
return IntStream.range(0, tagList.tagCount())
.mapToObj(tagList::getCompoundTagAt)
.map(nbt -> new CoverInfo(null, nbt).getCoverData())
.filter(
serializableObject -> serializableObject instanceof GT_Cover_Metrics_Transmitter.MetricsTransmitterData)
.map(data -> ((GT_Cover_Metrics_Transmitter.MetricsTransmitterData) data).getFrequency());
}
return Stream.empty();
}
/**
* Data transmitted by a Metrics Transmitter cover.
*
* Since only negative states ({@link State#HOST_DECONSTRUCTED HOST_DECONSTRUCTED} and
* {@link State#SELF_DESTRUCTED SELF DESTRUCTED}) are persisted, additional fields can be added to this data with
* little consequence. Ensure that any new fields are nullable, and make any getter for these fields return an
* {@link Optional}.
*/
public static class Data {
@NotNull
private final State state;
@Nullable
private final List payload;
@Nullable
private final Coordinates coordinates;
public Data(@NotNull State state) {
this.state = state;
this.payload = null;
this.coordinates = null;
}
public Data(@NotNull State state, @Nullable List payload) {
this.state = state;
this.payload = payload;
this.coordinates = null;
}
public Data(@NotNull State state, @Nullable List payload, @Nullable Coordinates coordinates) {
this.state = state;
this.payload = payload;
this.coordinates = coordinates;
}
/**
* Retrieves the payload for this data. Only present if the frequency is in an
* {@link State#OPERATIONAL operational} state. Will be cleared if the frequency goes into a
* {@link State#HOST_DECONSTRUCTED host-deconstructed} or {@link State#SELF_DESTRUCTED self-destructed} state.
*
* @return The data if present, or an empty Optional otherwise.
*/
@NotNull
public Optional> getPayload() {
return Optional.ofNullable(payload);
}
/**
* Gets the state of the frequency.
*
* @return The state
*/
@NotNull
public State getState() {
return state;
}
/**
* Gets the last known coordinates for the machine broadcasting metrics. Will only be present in an
* {@link State#OPERATIONAL operational} state.
*
* @return The coordinates
*/
@NotNull
public Optional getCoordinates() {
return Optional.ofNullable(coordinates);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Data data = (Data) o;
return state == data.state && Objects.equals(payload, data.payload)
&& Objects.equals(coordinates, data.coordinates);
}
@Override
public int hashCode() {
return Objects.hash(state, payload, coordinates);
}
}
@SuppressWarnings("ClassCanBeRecord")
public static class Coordinates {
private final String dimension;
private final int x;
private final int y;
private final int z;
public Coordinates(final String dimension, final int x, final int y, final int z) {
this.dimension = dimension;
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
public String getDimension() {
return dimension;
}
public String getLocalizedCoordinates() {
return StatCollector.translateToLocalFormatted(
"gt.db.metrics_cover.coords",
GT_Utility.formatNumbers(x),
GT_Utility.formatNumbers(y),
GT_Utility.formatNumbers(z));
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final Coordinates that = (Coordinates) o;
return x == that.x && y == that.y && z == that.z && Objects.equals(dimension, that.dimension);
}
@Override
public int hashCode() {
return Objects.hash(dimension, x, y, z);
}
}
public enum State {
// NOTE: type cannot be 0, as NuclearControl returns a 0 when querying for an integer from an item stack's NBT
// data when it really means null.
/** The machine is online and broadcasting metrics. */
OPERATIONAL(1),
/**
* The machine was picked up, but the cover is still attached. Will transition to operational state if the
* machine is placed back down and started up again.
*/
HOST_DECONSTRUCTED(2),
/**
* Cover was removed from its host machine, or machine was destroyed (in the limited number of ways we can
* detect.) Any frequency in this state will no longer get updates nor leave this state.
*/
SELF_DESTRUCTED(3);
private static final Map VALID_TYPE_INTEGERS = Arrays.stream(State.values())
.collect(Collectors.toMap(State::getType, Function.identity()));
private final int type;
State(final int type) {
if (type <= 0) {
throw new IllegalArgumentException("A state must have a positive, nonzero type parameter.");
}
this.type = type;
}
@NotNull
public static Optional find(int candidate) {
return Optional.ofNullable(VALID_TYPE_INTEGERS.get(candidate));
}
public int getType() {
return type;
}
}
}