Minestom/src/main/java/net/minestom/server/network/packet/server/play/AdvancementsPacket.java

256 lines
10 KiB
Java

package net.minestom.server.network.packet.server.play;
import net.kyori.adventure.text.Component;
import net.minestom.server.advancements.FrameType;
import net.minestom.server.adventure.ComponentHolder;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.ServerPacket.ComponentHolding;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.UnaryOperator;
import static net.minestom.server.network.NetworkBuffer.*;
public record AdvancementsPacket(boolean reset, @NotNull List<AdvancementMapping> advancementMappings,
@NotNull List<String> identifiersToRemove,
@NotNull List<ProgressMapping> progressMappings) implements ServerPacket.Play, ServerPacket.ComponentHolding {
public static final int MAX_ADVANCEMENTS = Short.MAX_VALUE;
public AdvancementsPacket {
advancementMappings = List.copyOf(advancementMappings);
identifiersToRemove = List.copyOf(identifiersToRemove);
progressMappings = List.copyOf(progressMappings);
}
public AdvancementsPacket(@NotNull NetworkBuffer reader) {
this(reader.read(BOOLEAN), reader.readCollection(AdvancementMapping::new, MAX_ADVANCEMENTS),
reader.readCollection(STRING, MAX_ADVANCEMENTS),
reader.readCollection(ProgressMapping::new, MAX_ADVANCEMENTS));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.write(BOOLEAN, reset);
writer.writeCollection(advancementMappings);
writer.writeCollection(STRING, identifiersToRemove);
writer.writeCollection(progressMappings);
}
@Override
public int playId() {
return ServerPacketIdentifier.ADVANCEMENTS;
}
// TODO is the display-item needed to be updated?
@Override
public @NotNull Collection<Component> components() {
final var displayData = this.advancementMappings.stream().map(AdvancementMapping::value).map(Advancement::displayData).filter(Objects::nonNull).toList();
final var titles = displayData.stream().map(DisplayData::title).toList();
final var descriptions = displayData.stream().map(DisplayData::description).toList();
final var list = new ArrayList<Component>();
list.addAll(titles);
list.addAll(descriptions);
return List.copyOf(list);
}
@Override
public @NotNull ServerPacket copyWithOperator(final @NotNull UnaryOperator<Component> operator) {
return new AdvancementsPacket(
this.reset,
this.advancementMappings.stream().map(mapping -> mapping.copyWithOperator(operator)).toList(),
this.identifiersToRemove,
this.progressMappings
);
}
/**
* AdvancementMapping maps the namespaced ID to the Advancement.
*/
public record AdvancementMapping(@NotNull String key,
@NotNull Advancement value) implements NetworkBuffer.Writer, ComponentHolder<AdvancementMapping> {
public AdvancementMapping(@NotNull NetworkBuffer reader) {
this(reader.read(STRING), new Advancement(reader));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.write(STRING, key);
writer.write(value);
}
@Override
public @NotNull Collection<Component> components() {
return this.value.components();
}
@Override
public @NotNull AdvancementMapping copyWithOperator(@NotNull UnaryOperator<Component> operator) {
return this.value.displayData == null ? this : new AdvancementMapping(this.key, this.value.copyWithOperator(operator));
}
}
public record Advancement(@Nullable String parentIdentifier, @Nullable DisplayData displayData,
@NotNull List<Requirement> requirements,
boolean sendTelemetryData) implements NetworkBuffer.Writer, ComponentHolder<Advancement> {
public Advancement {
requirements = List.copyOf(requirements);
}
public Advancement(@NotNull NetworkBuffer reader) {
this(reader.readOptional(STRING), reader.readOptional(DisplayData::new),
reader.readCollection(Requirement::new, MAX_ADVANCEMENTS), reader.read(BOOLEAN));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.writeOptional(STRING, parentIdentifier);
writer.writeOptional(displayData);
writer.writeCollection(requirements);
writer.write(BOOLEAN, sendTelemetryData);
}
@Override
public @NotNull Collection<Component> components() {
return this.displayData != null ? this.displayData.components() : List.of();
}
@Override
public @NotNull Advancement copyWithOperator(@NotNull UnaryOperator<Component> operator) {
return this.displayData == null ? this : new Advancement(this.parentIdentifier, this.displayData.copyWithOperator(operator), this.requirements, this.sendTelemetryData);
}
}
public record Requirement(@NotNull List<String> requirements) implements NetworkBuffer.Writer {
public Requirement {
requirements = List.copyOf(requirements);
}
public Requirement(@NotNull NetworkBuffer reader) {
this(reader.readCollection(STRING, MAX_ADVANCEMENTS));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.writeCollection(STRING, requirements);
}
}
public record DisplayData(@NotNull Component title, @NotNull Component description,
@NotNull ItemStack icon, @NotNull FrameType frameType,
int flags, @Nullable String backgroundTexture,
float x, float y) implements NetworkBuffer.Writer, ComponentHolder<DisplayData> {
public DisplayData(@NotNull NetworkBuffer reader) {
this(read(reader));
}
private DisplayData(DisplayData displayData) {
this(displayData.title, displayData.description,
displayData.icon, displayData.frameType,
displayData.flags, displayData.backgroundTexture,
displayData.x, displayData.y);
}
private static DisplayData read(@NotNull NetworkBuffer reader) {
var title = reader.read(COMPONENT);
var description = reader.read(COMPONENT);
var icon = reader.read(ITEM);
var frameType = FrameType.values()[reader.read(VAR_INT)];
var flags = reader.read(INT);
var backgroundTexture = (flags & 0x1) != 0 ? reader.read(STRING) : null;
var x = reader.read(FLOAT);
var y = reader.read(FLOAT);
return new DisplayData(title, description,
icon, frameType,
flags, backgroundTexture,
x, y);
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.write(COMPONENT, title);
writer.write(COMPONENT, description);
writer.write(ITEM, icon);
writer.writeEnum(FrameType.class, frameType);
writer.write(INT, flags);
if ((flags & 0x1) != 0) {
assert backgroundTexture != null;
writer.write(STRING, backgroundTexture);
}
writer.write(FLOAT, x);
writer.write(FLOAT, y);
}
@Override
public @NotNull Collection<Component> components() {
return List.of(this.title, this.description);
}
@Override
public @NotNull DisplayData copyWithOperator(@NotNull UnaryOperator<Component> operator) {
return new DisplayData(operator.apply(this.title), operator.apply(this.description), this.icon, this.frameType, this.flags, this.backgroundTexture, this.x, this.y);
}
}
public record ProgressMapping(@NotNull String key,
@NotNull AdvancementProgress progress) implements NetworkBuffer.Writer {
public ProgressMapping(@NotNull NetworkBuffer reader) {
this(reader.read(STRING), new AdvancementProgress(reader));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.write(STRING, key);
writer.write(progress);
}
}
public record AdvancementProgress(@NotNull List<Criteria> criteria) implements NetworkBuffer.Writer {
public AdvancementProgress {
criteria = List.copyOf(criteria);
}
public AdvancementProgress(@NotNull NetworkBuffer reader) {
this(reader.readCollection(Criteria::new, MAX_ADVANCEMENTS));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.writeCollection(criteria);
}
}
public record Criteria(@NotNull String criterionIdentifier,
@NotNull CriterionProgress criterionProgress) implements NetworkBuffer.Writer {
public Criteria(@NotNull NetworkBuffer reader) {
this(reader.read(STRING), new CriterionProgress(reader));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.write(STRING, criterionIdentifier);
writer.write(criterionProgress);
}
}
public record CriterionProgress(@Nullable Long dateOfAchieving) implements NetworkBuffer.Writer {
public CriterionProgress(@NotNull NetworkBuffer reader) {
this(reader.readOptional(LONG));
}
@Override
public void write(@NotNull NetworkBuffer writer) {
writer.writeOptional(LONG, dateOfAchieving);
}
}
}