diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/Advancement.java b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/Advancement.java
new file mode 100644
index 000000000..22e9a92e5
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/Advancement.java
@@ -0,0 +1,46 @@
+/*
+ * Codename Minosoft
+ * Copyright (C) 2020 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.game.datatypes.player.advancements;
+
+import java.util.List;
+
+public class Advancement {
+ final String parentName;
+ final AdvancementDisplay display;
+ final List criteria;
+ final List requirements;
+
+ public Advancement(String parentName, AdvancementDisplay display, List criteria, List requirements) {
+ this.parentName = parentName;
+ this.display = display;
+ this.criteria = criteria;
+ this.requirements = requirements;
+ }
+
+ public String getParentName() {
+ return parentName;
+ }
+
+ public AdvancementDisplay getDisplay() {
+ return display;
+ }
+
+ public List getCriteria() {
+ return criteria;
+ }
+
+ public List getRequirements() {
+ return requirements;
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementDisplay.java b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementDisplay.java
new file mode 100644
index 000000000..e86dfc26e
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementDisplay.java
@@ -0,0 +1,116 @@
+/*
+ * Codename Minosoft
+ * Copyright (C) 2020 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.game.datatypes.player.advancements;
+
+import de.bixilon.minosoft.game.datatypes.TextComponent;
+import de.bixilon.minosoft.game.datatypes.inventory.Slot;
+import de.bixilon.minosoft.util.BitByte;
+
+public class AdvancementDisplay {
+ final TextComponent title;
+ final TextComponent description;
+ final Slot icon;
+ final AdvancementFrameTypes frameType;
+ final int flags;
+ final String backgroundTexture;
+ final float x;
+ final float y;
+
+ public AdvancementDisplay(TextComponent title, TextComponent description, Slot icon, AdvancementFrameTypes frameType, int flags, String backgroundTexture, float x, float y) {
+ this.title = title;
+ this.description = description;
+ this.icon = icon;
+ this.frameType = frameType;
+ this.flags = flags;
+ this.backgroundTexture = backgroundTexture;
+ this.x = x;
+ this.y = y;
+ }
+
+ public AdvancementDisplay(TextComponent title, TextComponent description, Slot icon, AdvancementFrameTypes frameType, int flags, float x, float y) {
+ this.title = title;
+ this.description = description;
+ this.icon = icon;
+ this.frameType = frameType;
+ this.flags = flags;
+ this.backgroundTexture = null;
+ this.x = x;
+ this.y = y;
+ }
+
+ public TextComponent getTitle() {
+ return title;
+ }
+
+ public TextComponent getDescription() {
+ return description;
+ }
+
+ public Slot getIcon() {
+ return icon;
+ }
+
+ public AdvancementFrameTypes getFrameType() {
+ return frameType;
+ }
+
+ public boolean hasBackgroundTexture() {
+ return BitByte.isBitMask(flags, 0x01);
+ }
+
+ public boolean showToast() {
+ return BitByte.isBitMask(flags, 0x02);
+ }
+
+ public boolean isHidden() {
+ return BitByte.isBitMask(flags, 0x04);
+ }
+
+ public String getBackgroundTexture() {
+ return backgroundTexture;
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public enum AdvancementFrameTypes {
+ TASK(0),
+ CHALLENGE(1),
+ GOAL(2);
+
+ final int id;
+
+ AdvancementFrameTypes(int id) {
+ this.id = id;
+ }
+
+ public static AdvancementFrameTypes byId(int id) {
+ for (AdvancementFrameTypes type : values()) {
+ if (type.getId() == id) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ public int getId() {
+ return id;
+ }
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementProgress.java b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementProgress.java
new file mode 100644
index 000000000..f30c99f6d
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/AdvancementProgress.java
@@ -0,0 +1,24 @@
+/*
+ * Codename Minosoft
+ * Copyright (C) 2020 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.game.datatypes.player.advancements;
+
+import java.util.HashMap;
+
+public class AdvancementProgress {
+ final HashMap progress;
+
+ public AdvancementProgress(HashMap progress) {
+ this.progress = progress;
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/CriterionProgress.java b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/CriterionProgress.java
new file mode 100644
index 000000000..002b078e2
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/game/datatypes/player/advancements/CriterionProgress.java
@@ -0,0 +1,32 @@
+/*
+ * Codename Minosoft
+ * Copyright (C) 2020 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.game.datatypes.player.advancements;
+
+public class CriterionProgress {
+ final boolean archived;
+ final Long archiveTime;
+
+ public CriterionProgress(boolean archived, Long archiveTime) {
+ this.archived = archived;
+ this.archiveTime = archiveTime;
+ }
+
+ public boolean isArchived() {
+ return archived;
+ }
+
+ public Long getArchiveTime() {
+ return archiveTime;
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketAdvancements.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketAdvancements.java
new file mode 100644
index 000000000..134ccca7b
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketAdvancements.java
@@ -0,0 +1,133 @@
+/*
+ * Codename Minosoft
+ * Copyright (C) 2020 Moritz Zwerger
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.protocol.packets.clientbound.play;
+
+import de.bixilon.minosoft.game.datatypes.TextComponent;
+import de.bixilon.minosoft.game.datatypes.inventory.Slot;
+import de.bixilon.minosoft.game.datatypes.player.advancements.Advancement;
+import de.bixilon.minosoft.game.datatypes.player.advancements.AdvancementDisplay;
+import de.bixilon.minosoft.game.datatypes.player.advancements.AdvancementProgress;
+import de.bixilon.minosoft.game.datatypes.player.advancements.CriterionProgress;
+import de.bixilon.minosoft.logging.Log;
+import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
+import de.bixilon.minosoft.protocol.protocol.InPacketBuffer;
+import de.bixilon.minosoft.protocol.protocol.PacketHandler;
+import de.bixilon.minosoft.util.BitByte;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class PacketAdvancements implements ClientboundPacket {
+ boolean reset;
+
+ HashMap advancements = new HashMap<>();
+ String[] toRemove;
+ HashMap progresses = new HashMap<>();
+
+
+ @Override
+ public boolean read(InPacketBuffer buffer) {
+ switch (buffer.getVersion()) {
+ case VERSION_1_12_2:
+ reset = buffer.readBoolean();
+ int length = buffer.readVarInt();
+ for (int i = 0; i < length; i++) {
+ String advancementKey = buffer.readString();
+
+ String parentName = null;
+ if (buffer.readBoolean()) {
+ parentName = buffer.readString();
+ }
+ AdvancementDisplay display = null;
+ if (buffer.readBoolean()) {
+ TextComponent title = buffer.readTextComponent();
+ TextComponent description = buffer.readTextComponent();
+ Slot icon = buffer.readSlot();
+ AdvancementDisplay.AdvancementFrameTypes frameType = AdvancementDisplay.AdvancementFrameTypes.byId(buffer.readVarInt());
+ int flags = buffer.readInt();
+ String backgroundTexture = null;
+ if (BitByte.isBitMask(flags, 0x01)) {
+ backgroundTexture = buffer.readString();
+ }
+ float x = buffer.readFloat();
+ float y = buffer.readFloat();
+ display = new AdvancementDisplay(title, description, icon, frameType, flags, backgroundTexture, x, y);
+ }
+ int criteriaCount = buffer.readVarInt();
+ List criteria = new ArrayList<>();
+ for (int ii = 0; ii < criteriaCount; ii++) {
+ criteria.add(buffer.readString());
+ }
+ int requirementsCount = buffer.readVarInt();
+ List requirements = new ArrayList<>();
+ for (int ii = 0; ii < requirementsCount; ii++) {
+ String[] requirement = new String[buffer.readVarInt()];
+ for (int iii = 0; iii < requirement.length; iii++) {
+ requirement[iii] = buffer.readString();
+ }
+ requirements.add(requirement);
+ }
+ advancements.put(advancementKey, new Advancement(parentName, display, criteria, requirements));
+ }
+ toRemove = new String[buffer.readVarInt()];
+ for (int i = 0; i < toRemove.length; i++) {
+ toRemove[i] = buffer.readString();
+ }
+ int progressesLength = buffer.readVarInt();
+ for (int i = 0; i < progressesLength; i++) {
+ HashMap progress = new HashMap<>();
+ String progressName = buffer.readString();
+ int criterionLength = buffer.readVarInt();
+ for (int ii = 0; ii < criterionLength; ii++) {
+ String criterionName = buffer.readString();
+ boolean archived = buffer.readBoolean();
+ Long archiveTime = null;
+ if (archived) {
+ archiveTime = buffer.readLong();
+ }
+ CriterionProgress criterionProgress = new CriterionProgress(archived, archiveTime);
+ progress.put(criterionName, criterionProgress);
+ }
+ progresses.put(progressName, new AdvancementProgress(progress));
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void log() {
+ Log.protocol(String.format("Receiving advancements (reset=%s, advancements=%s, progresses=%s)", reset, advancements.size(), progresses.size()));
+ }
+
+ @Override
+ public void handle(PacketHandler h) {
+ h.handle(this);
+ }
+
+ public boolean isReset() {
+ return reset;
+ }
+
+ public HashMap getAdvancements() {
+ return advancements;
+ }
+
+ public HashMap getProgresses() {
+ return progresses;
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java
index d34b21094..552b2bacb 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java
+++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java
@@ -571,4 +571,7 @@ public class PacketHandler {
public void handle(PacketSelectAdvancementTab pkg) {
}
+
+ public void handle(PacketAdvancements pkg) {
+ }
}
diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java
index 24348f23c..7586d994f 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java
+++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java
@@ -145,6 +145,7 @@ public abstract class Protocol implements ProtocolInterface {
packetClassMapping.put(Packets.Clientbound.PLAY_CRAFT_RECIPE_RESPONSE, PacketCraftRecipeResponse.class);
packetClassMapping.put(Packets.Clientbound.PLAY_UNLOCK_RECIPES, PacketUnlockRecipes.class);
packetClassMapping.put(Packets.Clientbound.PLAY_SELECT_ADVANCEMENT_TAB, PacketSelectAdvancementTab.class);
+ packetClassMapping.put(Packets.Clientbound.PLAY_ADVANCEMENTS, PacketAdvancements.class);
}
public static ProtocolVersion getLowestVersionSupported() {