Added the Notification API

This commit is contained in:
Felix Cravic 2020-08-04 00:32:03 +02:00
parent 7007c507c1
commit 593f2002a9
8 changed files with 246 additions and 207 deletions

View File

@ -3,6 +3,7 @@ package fr.themode.demo;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.demo.generator.NoiseTestGenerator;
import net.minestom.server.MinecraftServer;
import net.minestom.server.advancements.FrameType;
import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.benchmark.ThreadResult;
import net.minestom.server.chat.ChatColor;
@ -11,10 +12,7 @@ import net.minestom.server.chat.ColoredText;
import net.minestom.server.chat.RichMessage;
import net.minestom.server.entity.*;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.fakeplayer.FakePlayer;
import net.minestom.server.entity.fakeplayer.FakePlayerController;
import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.entity.EntityDeathEvent;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.ItemUpdateStateEvent;
import net.minestom.server.event.item.PickupItemEvent;
@ -27,6 +25,7 @@ import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import net.minestom.server.ping.ResponseDataConsumer;
@ -46,7 +45,7 @@ public class PlayerInit {
private static volatile Inventory inventory;
static {
//StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("instance_data");
//StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("instance_data", new StorageOption().setCompression(true));
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
NoiseTestGenerator noiseTestGenerator = new NoiseTestGenerator();
//instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(storageFolder);
@ -160,7 +159,7 @@ public class PlayerInit {
zombie.setAttribute(Attribute.MOVEMENT_SPEED, 0.25f);
zombie.setInstance(player.getInstance());*/
FakePlayer.initPlayer(UUID.randomUUID(), "test", fakePlayer -> {
/*FakePlayer.initPlayer(UUID.randomUUID(), "test", fakePlayer -> {
//fakePlayer.setInstance(player.getInstance());
fakePlayer.teleport(player.getPosition());
fakePlayer.setSkin(PlayerSkin.fromUsername("TheMode911"));
@ -172,7 +171,7 @@ public class PlayerInit {
fakePlayer.setArrowCount(25);
FakePlayerController controller = fakePlayer.getController();
controller.sendChatMessage("I am a bot!");
});
});*/
//Hologram hologram = new Hologram(player.getInstance(), player.getPosition(), "Hey guy");
});
@ -245,7 +244,7 @@ public class PlayerInit {
displayData.title = ColoredText.of("Hello");
displayData.description = ColoredText.of("Hello");
displayData.icon = new ItemStack(Material.DIRT, (byte) 1);
displayData.frameType = AdvancementsPacket.FrameType.TASK;
displayData.frameType = FrameType.TASK;
displayData.flags = 0x1;
displayData.backgroundTexture = "minecraft:textures/block/red_wool.png";
@ -270,7 +269,7 @@ public class PlayerInit {
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.frameType = FrameType.GOAL;
displayData.flags = 0x2;
secondAdvancement.displayData = displayData;
@ -299,36 +298,14 @@ public class PlayerInit {
player.getInventory().setItemStack(i, new ItemStack(Material.STONE, (byte) 127));
}*/
/*ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
{
ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
MapMeta mapMeta = (MapMeta) map.getItemMeta();
mapMeta.setMapId(1);
player.getInventory().setItemStack(0, map);
//player.getInventory().setItemStack(0, map);
{
// Map test
MapDataPacket mapDataPacket = new MapDataPacket();
mapDataPacket.mapId = 1;
mapDataPacket.scale = 1;
mapDataPacket.trackingPosition = false;
mapDataPacket.locked = false;
mapDataPacket.icons = null;
mapDataPacket.columns = (byte) 127;
mapDataPacket.rows = (byte) 127;
mapDataPacket.x = 0;
mapDataPacket.z = 0;
final byte[] data = new byte[127 * 127];
for (int i = 0; i < data.length; i++) {
final byte color = (byte) (i % 2 == 0 ? 5 : 10);
data[i] = color;
}
mapDataPacket.data = data;
player.getPlayerConnection().sendPacket(mapDataPacket);
}*/
ItemStack item = new ItemStack(Material.STONE_SWORD, (byte) 1);
item.setDisplayName(ColoredText.of("Item name"));
@ -347,12 +324,19 @@ public class PlayerInit {
//player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100));
{
/*EntityItemFrame entityItemFrame = new EntityItemFrame(new Position(-5, 36, 9, 0, 180), EntityItemFrame.ItemFrameOrientation.DOWN);
entityItemFrame.setNoGravity(true);
entityItemFrame.setInstance(player.getInstance());
entityItemFrame.setItemStack(item);*/
}
Instance instance = player.getInstance();
WorldBorder worldBorder = instance.getWorldBorder();
worldBorder.setDiameter(30);
RichMessage richMessage = RichMessage.of(ColoredText.of(ChatColor.RED + "test item"));
richMessage.setHoverEvent(ChatHoverEvent.showItem(new ItemStack(Material.DIAMOND, (byte) 1)));
richMessage.setHoverEvent(ChatHoverEvent.showEntity(player));
richMessage.setInsertion("Test Insert");
System.out.println(richMessage.toString());
player.sendMessage(richMessage);
@ -386,6 +370,10 @@ public class PlayerInit {
event.setRespawnPosition(new Position(0f, 41f, 0f));
});
player.addEventCallback(PlayerCommandEvent.class, event -> {
System.out.println("COMMAND EVENT");
});
player.addEventCallback(PlayerUseItemEvent.class, useEvent -> {
player.sendMessage("Using item in air: " + useEvent.getItemStack().getMaterial());
});

View File

@ -1,18 +1,16 @@
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.advancements.FrameType;
import net.minestom.server.advancements.notifications.Notification;
import net.minestom.server.advancements.notifications.NotificationCenter;
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;
import java.util.Arrays;
public class SimpleCommand implements CommandProcessor {
@Override
@ -58,19 +56,19 @@ public class SimpleCommand implements CommandProcessor {
System.gc();
player.sendMessage("Garbage collector called");*/
Instance instance = player.getInstance();
/*Instance instance = player.getInstance();
ChickenCreature chickenCreature = new ChickenCreature(new Position(-10, 43, -10));
chickenCreature.setInstance(instance);
chickenCreature.setPathTo(player.getPosition());
chickenCreature.setPathTo(player.getPosition());*/
final Notification notification = new Notification(ColoredText.of(ChatColor.BRIGHT_GREEN + "Welcome to Minestom!"),
FrameType.TASK, Material.APPLE);
NotificationCenter.send(notification, Arrays.asList(player));
NotificationCenter.send(notification, Arrays.asList(player));
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,20 @@
package net.minestom.server.advancements;
/**
* Describes the frame around the Advancement.
* Also describes the type of advancement it is for "toast" notifications.
*/
public enum FrameType {
/**
* 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
}

View File

@ -1,36 +0,0 @@
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

@ -1,101 +0,0 @@
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,59 @@
package net.minestom.server.advancements.notifications;
import net.minestom.server.advancements.FrameType;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import org.jetbrains.annotations.NotNull;
/**
* Represent a message which can be send using the {@link NotificationCenter}
*/
public class Notification {
private final ColoredText title;
private final FrameType frameType;
private final ItemStack icon;
public Notification(@NotNull ColoredText title, @NotNull FrameType frameType, @NotNull ItemStack icon) {
this.title = title;
this.frameType = frameType;
this.icon = icon;
}
public Notification(@NotNull ColoredText title, @NotNull FrameType frameType, @NotNull Material icon) {
this.title = title;
this.frameType = frameType;
this.icon = new ItemStack(icon, (byte) 1);
}
/**
* Get the title of the notification
*
* @return the notification title
*/
@NotNull
public ColoredText getTitle() {
return title;
}
/**
* Get the frame type of the notification
*
* @return the notification frame type
*/
@NotNull
public FrameType getFrameType() {
return frameType;
}
/**
* Get the icon of the notification
*
* @return the notification icon
*/
@NotNull
protected ItemStack getIcon() {
return icon;
}
}

View File

@ -0,0 +1,129 @@
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 net.minestom.server.network.player.PlayerConnection;
import java.sql.Date;
import java.util.Collection;
/**
* Used to send one or multiples {@link Notification}
*/
public class NotificationCenter {
private static final String IDENTIFIER = "minestom:notification";
/**
* Can't create an instance
*/
private NotificationCenter() {
}
public static void send(Notification notification, Player player) {
final PlayerConnection playerConnection = player.getPlayerConnection();
playerConnection.sendPacket(getCreatePacket(notification));
playerConnection.sendPacket(getRemovePacket());
}
public static void send(Notification notification, Collection<Player> players) {
// Can't use PacketWriterUtils before we need the packets to come in the correct order
players.forEach(player -> {
send(notification, player);
});
}
/**
* Create the packet responsive for showing the Toast to players
*
* @param notification the notification
* @return the packet to show the Toast
*/
private static AdvancementsPacket getCreatePacket(Notification notification) {
// 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 = notification.getTitle();
// Description is required, but never shown/seen so, small Easter egg.
displayData.description = ColoredText.of("Articdive was here. #Minestom");
displayData.icon = notification.getIcon();
displayData.frameType = notification.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 = IDENTIFIER;
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 = IDENTIFIER;
progressMapping.value = advancementProgress;
}
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{progressMapping};
return advancementsPacket;
}
/**
* Create the packet responsive for removing the advancement identifier
*
* @return the packet to remove the identifier
*/
private static AdvancementsPacket getRemovePacket() {
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
advancementsPacket.identifiersToRemove = new String[]{IDENTIFIER};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{};
return advancementsPacket;
}
}

View File

@ -1,5 +1,6 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.advancements.FrameType;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.PacketWriter;
@ -34,25 +35,6 @@ 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 {
/**
* 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.
*/