Added Advancements and Advancement Toasties.

This commit is contained in:
Articdive 2020-08-03 17:17:32 +02:00
parent 485089078d
commit 30ff313cad
No known key found for this signature in database
GPG Key ID: B069585F0F7D90DE
7 changed files with 253 additions and 15 deletions

View File

@ -28,6 +28,7 @@ import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position;
@ -227,6 +228,63 @@ public class PlayerInit {
scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED");
scoreboard.setTitle("test");*/
// Testing advancements
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = true;
AdvancementsPacket.AdvancementMapping firstMapping = new AdvancementsPacket.AdvancementMapping();
{
AdvancementsPacket.Advancement firstAdvancement = new AdvancementsPacket.Advancement();
firstMapping.key = "minestom:advancement";
firstMapping.value = firstAdvancement;
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
displayData.x = 0.0F;
displayData.y = 0.0F;
displayData.title = ColoredText.of("Hello");
displayData.description = ColoredText.of("Hello");
displayData.icon = new ItemStack(Material.DIRT, (byte) 1);
displayData.frameType = AdvancementsPacket.FrameType.TASK;
displayData.flags = 0x1;
displayData.backgroundTexture = "minecraft:textures/block/red_wool.png";
firstAdvancement.displayData = displayData;
firstAdvancement.criterions = new String[]{};
firstAdvancement.requirements = new AdvancementsPacket.Requirement[]{};
}
// This advancement will be to the bottom right of the firstAdvancement
// The background of this advancement is apparentely ignored!
AdvancementsPacket.AdvancementMapping secondMapping = new AdvancementsPacket.AdvancementMapping();
{
AdvancementsPacket.Advancement secondAdvancement = new AdvancementsPacket.Advancement();
secondMapping.key = "minestom:advance";
secondMapping.value = secondAdvancement;
secondAdvancement.parentIdentifier = "minestom:advancement";
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
displayData.x = 2.0F;
displayData.y = 2.0F;
displayData.title = ColoredText.of("Hello World");
displayData.description = ColoredText.of("Hello World");
displayData.icon = new ItemStack(Material.DIAMOND, (byte) 1);
displayData.frameType = AdvancementsPacket.FrameType.GOAL;
displayData.flags = 0x2;
secondAdvancement.displayData = displayData;
secondAdvancement.criterions = new String[]{};
secondAdvancement.requirements = new AdvancementsPacket.Requirement[]{};
}
advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{firstMapping, secondMapping};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{};
player.getPlayerConnection().sendPacket(advancementsPacket);
});
player.addEventCallback(PlayerSpawnEvent.class, event -> {

View File

@ -1,10 +1,17 @@
package fr.themode.demo.commands;
import fr.themode.demo.entity.ChickenCreature;
import net.minestom.server.advancements.notifications.AdvancementNotification;
import net.minestom.server.advancements.notifications.AdvancementNotificationManager;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.command.CommandProcessor;
import net.minestom.server.command.CommandSender;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.Instance;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import net.minestom.server.utils.Position;
public class SimpleCommand implements CommandProcessor {
@ -58,6 +65,12 @@ public class SimpleCommand implements CommandProcessor {
chickenCreature.setPathTo(player.getPosition());
new AdvancementNotificationManager().sendAdvancementNotification(
new AdvancementNotification(
ColoredText.of(ChatColor.BRIGHT_GREEN + "Welcome to Minestom!"),
new ItemStack(Material.ACACIA_BOAT, (byte) 1), AdvancementsPacket.FrameType.GOAL)
, player
);
return true;
}

View File

@ -0,0 +1,36 @@
package net.minestom.server.advancements.notifications;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import org.jetbrains.annotations.NotNull;
/**
* @author Lukas Mansour (Articdive)
*/
public class AdvancementNotification {
private final ColoredText title;
private final ItemStack icon;
private final AdvancementsPacket.FrameType frameType;
public AdvancementNotification(@NotNull ColoredText title, @NotNull ItemStack icon, @NotNull AdvancementsPacket.FrameType frameType) {
this.title = title;
this.icon = icon;
this.frameType = frameType;
}
@NotNull
public ColoredText getTitle() {
return title;
}
@NotNull
public ItemStack getIcon() {
return icon;
}
@NotNull
public AdvancementsPacket.FrameType getFrameType() {
return frameType;
}
}

View File

@ -0,0 +1,101 @@
package net.minestom.server.advancements.notifications;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import java.sql.Date;
/**
* @author Lukas Mansour
*/
public class AdvancementNotificationManager {
public AdvancementNotificationManager() {
}
public void sendAdvancementNotification(AdvancementNotification advancementNotification, Player player) {
// Sending
{
// For An advancement to be shown, it must have all of it's criteria achieved (progress 100%)
// Create a Criteria that we can set to 100% achieved.
// Criteria
AdvancementsPacket.Criteria criteria = new AdvancementsPacket.Criteria();
{
AdvancementsPacket.CriterionProgress progress = new AdvancementsPacket.CriterionProgress();
progress.achieved = true;
progress.dateOfAchieving = new Date(System.currentTimeMillis()).getTime();
criteria.criterionProgress = progress;
criteria.criterionIdentifier = "minestom:some_criteria";
}
// Now create an AdvancementsPacket that we can send:
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
AdvancementsPacket.AdvancementMapping mapping = new AdvancementsPacket.AdvancementMapping();
{
// Get the advancement
AdvancementsPacket.Advancement advancement = new AdvancementsPacket.Advancement();
// Setup display data for the advancement
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
{
displayData.title = advancementNotification.getTitle();
// Description is required, but never shown/seen so, small Easter egg.
displayData.description = ColoredText.of("Articdive was here. #Minestom");
displayData.icon = advancementNotification.getIcon();
displayData.frameType = advancementNotification.getFrameType();
displayData.flags = 0x6;
// No background texture required as we are using 0x6
displayData.x = 0.0F;
displayData.y = 0.0F;
}
advancement.displayData = displayData;
// Add the criteria to the advancement
advancement.criterions = new String[]{criteria.criterionIdentifier};
// Add the requirement of the criteria to the advancement
AdvancementsPacket.Requirement requirement = new AdvancementsPacket.Requirement();
{
requirement.requirements = new String[]{criteria.criterionIdentifier};
}
advancement.requirements = new AdvancementsPacket.Requirement[]{requirement};
mapping.key = "minestom:advancement_login";
mapping.value = advancement;
}
// Add the mapping to the main packet
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping};
// We have no identifiers to remove.
advancementsPacket.identifiersToRemove = new String[]{};
// Now we need to set the player's progress for the criteria.
AdvancementsPacket.ProgressMapping progressMapping = new AdvancementsPacket.ProgressMapping();
{
AdvancementsPacket.AdvancementProgress advancementProgress = new AdvancementsPacket.AdvancementProgress();
advancementProgress.criteria = new AdvancementsPacket.Criteria[]{criteria};
progressMapping.key = "minestom:advancement_login";
progressMapping.value = advancementProgress;
}
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{progressMapping};
// Now let's send the the tasty toast.
player.getPlayerConnection().sendPacket(advancementsPacket);
}
// Now we should send a packet telling the player to remove that advancement
// Removing
{
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
advancementsPacket.identifiersToRemove = new String[]{"minestom:advancement_login"};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{};
player.getPlayerConnection().sendPacket(advancementsPacket);
}
}
}

View File

@ -0,0 +1,12 @@
package net.minestom.server.listener;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.play.ClientAdvancementTabPacket;
public class AdvancementTabListener {
public static void listener(ClientAdvancementTabPacket packet, Player player) {
// Currentely unused and don't see much usage for an API
// TODO: Create an Event?
}
}

View File

@ -45,6 +45,7 @@ public class PacketListenerManager {
setListener(ClientPlayerAbilitiesPacket.class, AbilitiesListener::listener);
setListener(ClientTeleportConfirmPacket.class, TeleportListener::listener);
setListener(ClientResourcePackStatusPacket.class, ResourcePackListener::listener);
setListener(ClientAdvancementTabPacket.class, AdvancementTabListener::listener);
}
public <T extends ClientPlayPacket> void process(T packet, Player player) {

View File

@ -1,5 +1,6 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.network.packet.server.ServerPacket;
@ -20,7 +21,6 @@ public class AdvancementsPacket implements ServerPacket {
for (AdvancementMapping advancementMapping : advancementMappings) {
advancementMapping.write(writer);
}
writer.writeStringArray(identifiersToRemove);
writer.writeVarInt(progressMappings.length);
@ -34,10 +34,28 @@ public class AdvancementsPacket implements ServerPacket {
return ServerPacketIdentifier.ADVANCEMENTS;
}
/**
* Describes the frame around the Advancement.
* Also describes the type of advancement it is for "toast" notifications.
*/
public enum FrameType {
TASK, CHALLENGE, GOAL
/**
* A simple rounded square as the frame.
*/
TASK,
/**
* A spike in all 8 directions as the frame.
*/
CHALLENGE,
/**
* A square with a outward rounded edge on the top and bottom as the frame.
*/
GOAL
}
/**
* AdvancementMapping maps the namespaced ID to the Advancement.
*/
public static class AdvancementMapping {
public String key;
@ -51,22 +69,21 @@ public class AdvancementsPacket implements ServerPacket {
}
public static class Advancement {
public boolean hasParent;
public String identifier;
public boolean hasDisplay;
public String parentIdentifier;
public DisplayData displayData;
public String[] criterions;
public Requirement[] requirements;
private void write(PacketWriter writer) {
writer.writeBoolean(hasParent);
if (identifier != null) {
writer.writeSizedString(identifier);
// hasParent
writer.writeBoolean(parentIdentifier != null);
if (parentIdentifier != null) {
writer.writeSizedString(parentIdentifier);
}
writer.writeBoolean(hasDisplay);
if (hasDisplay) {
// hasDisplay
writer.writeBoolean(displayData != null);
if (displayData != null) {
displayData.write(writer);
}
@ -81,8 +98,8 @@ public class AdvancementsPacket implements ServerPacket {
}
public static class DisplayData {
public String title;
public String description;
public ColoredText title;
public ColoredText description;
public ItemStack icon;
public FrameType frameType;
public int flags;
@ -91,8 +108,8 @@ public class AdvancementsPacket implements ServerPacket {
public float y;
private void write(PacketWriter writer) {
writer.writeSizedString(title);
writer.writeSizedString(description);
writer.writeSizedString(title.toString());
writer.writeSizedString(description.toString());
writer.writeItemStack(icon);
writer.writeVarInt(frameType.ordinal());
writer.writeInt(flags);