Advancement API

This commit is contained in:
Felix Cravic 2020-08-06 07:42:00 +02:00
parent 64719a732c
commit bf0dd4a750
6 changed files with 119 additions and 49 deletions

View File

@ -228,7 +228,8 @@ public class PlayerInit {
{ {
AdvancementManager advancementManager = MinecraftServer.getAdvancementManager(); AdvancementManager advancementManager = MinecraftServer.getAdvancementManager();
AdvancementRoot root = new AdvancementRoot(ColoredText.of("title"), ColoredText.of(ChatColor.BLUE + "description"), AdvancementRoot root = new AdvancementRoot(ColoredText.of("title"), ColoredText.of(ChatColor.BLUE + "description"),
Material.APPLE, FrameType.TASK, 0, 0, "minecraft:textures/block/red_wool.png"); Material.APPLE, FrameType.TASK, 0, 0,
"minecraft:textures/block/red_wool.png");
AdvancementTab tab = advancementManager.createTab("root", root); AdvancementTab tab = advancementManager.createTab("root", root);
Advancement advancement = new Advancement(ColoredText.of("adv"), ColoredText.of("desc"), Advancement advancement = new Advancement(ColoredText.of("adv"), ColoredText.of("desc"),
Material.WOODEN_AXE, FrameType.CHALLENGE, 1, 0) Material.WOODEN_AXE, FrameType.CHALLENGE, 1, 0)
@ -244,7 +245,6 @@ public class PlayerInit {
.showToast(true).setHidden(false); .showToast(true).setHidden(false);
tab.createAdvancement("second2", advancement2, root); tab.createAdvancement("second2", advancement2, root);
//player.getPlayerConnection().sendPacket(tab.removePacket()); //player.getPlayerConnection().sendPacket(tab.removePacket());
} }
}); });

View File

@ -8,10 +8,17 @@ import net.minestom.server.network.packet.server.play.AdvancementsPacket;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.PacketUtils;
import java.util.Date;
/**
* Represent an advancement situated in an {@link AdvancementTab}
*/
public class Advancement { public class Advancement {
protected AdvancementTab tab; protected AdvancementTab tab;
private boolean achieved;
private ColoredText title; private ColoredText title;
private ColoredText description; private ColoredText description;
@ -28,6 +35,9 @@ public class Advancement {
private String identifier; private String identifier;
private Advancement parent; private Advancement parent;
// Packet
private AdvancementsPacket.Criteria criteria;
public Advancement(ColoredText title, ColoredText description, public Advancement(ColoredText title, ColoredText description,
ItemStack icon, FrameType frameType, ItemStack icon, FrameType frameType,
float x, float y) { float x, float y) {
@ -45,6 +55,27 @@ public class Advancement {
this(title, description, new ItemStack(icon, (byte) 1), frameType, x, y); this(title, description, new ItemStack(icon, (byte) 1), frameType, x, y);
} }
/**
* Get if the advancement is achieved
*
* @return true if the advancement is achieved
*/
public boolean isAchieved() {
return achieved;
}
/**
* Make the advancement achieved
*
* @param achieved true to make it achieved
* @return this advancement
*/
public Advancement setAchieved(boolean achieved) {
this.achieved = achieved;
update();
return this;
}
/** /**
* Get the advancement tab linked to this advancement * Get the advancement tab linked to this advancement
* *
@ -222,6 +253,18 @@ public class Advancement {
this.parent = parent; this.parent = parent;
} }
protected AdvancementsPacket.ProgressMapping toProgressMapping() {
AdvancementsPacket.ProgressMapping progressMapping = new AdvancementsPacket.ProgressMapping();
{
AdvancementsPacket.AdvancementProgress advancementProgress = new AdvancementsPacket.AdvancementProgress();
advancementProgress.criteria = new AdvancementsPacket.Criteria[]{criteria};
progressMapping.key = identifier;
progressMapping.value = advancementProgress;
}
return progressMapping;
}
protected AdvancementsPacket.DisplayData toDisplayData() { protected AdvancementsPacket.DisplayData toDisplayData() {
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData(); AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
displayData.x = x; displayData.x = x;
@ -256,8 +299,14 @@ public class Advancement {
} }
adv.displayData = toDisplayData(); adv.displayData = toDisplayData();
adv.criterions = new String[]{}; adv.criterions = new String[]{criteria.criterionIdentifier};
adv.requirements = new AdvancementsPacket.Requirement[]{};
AdvancementsPacket.Requirement requirement = new AdvancementsPacket.Requirement();
{
requirement.requirements = new String[]{criteria.criterionIdentifier};
}
adv.requirements = new AdvancementsPacket.Requirement[]{requirement};
} }
return mapping; return mapping;
@ -276,7 +325,7 @@ public class Advancement {
advancementsPacket.identifiersToRemove = new String[]{}; advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping}; advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{}; advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{toProgressMapping()};
return advancementsPacket; return advancementsPacket;
} }
@ -285,6 +334,8 @@ public class Advancement {
* Send update to all tab viewers if one of the advancement value changes * Send update to all tab viewers if one of the advancement value changes
*/ */
protected void update() { protected void update() {
updateCriteria();
if (tab != null) { if (tab != null) {
tab.createBuffer = PacketUtils.writePacket(tab.createPacket()); tab.createBuffer = PacketUtils.writePacket(tab.createPacket());
@ -298,6 +349,19 @@ public class Advancement {
} }
} }
protected void updateCriteria() {
this.criteria = new AdvancementsPacket.Criteria();
{
AdvancementsPacket.CriterionProgress progress = new AdvancementsPacket.CriterionProgress();
progress.achieved = achieved;
if (achieved) {
progress.dateOfAchieving = new Date(System.currentTimeMillis()).getTime();
}
this.criteria.criterionProgress = progress;
this.criteria.criterionIdentifier = identifier;
}
}
private int getFlags() { private int getFlags() {
byte result = 0; byte result = 0;

View File

@ -2,13 +2,25 @@ package net.minestom.server.advancements;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/**
* Used to manages advancement tabs
*/
public class AdvancementManager { public class AdvancementManager {
private Map<String, AdvancementTab> advancementTabMap = new HashMap<>(); private Map<String, AdvancementTab> advancementTabMap = new HashMap<>();
/**
* Create a new tab with a single advancement
*
* @param rootIdentifier the root identifier
* @param root the root advancement
* @return the {@link AdvancementTab} created
* @throws IllegalStateException if a tab with the identifier {@code rootIdentifier} already exists
*/
public AdvancementTab createTab(String rootIdentifier, AdvancementRoot root) { public AdvancementTab createTab(String rootIdentifier, AdvancementRoot root) {
Check.stateCondition(advancementTabMap.containsKey(rootIdentifier), Check.stateCondition(advancementTabMap.containsKey(rootIdentifier),
"A tab with the identifier '" + rootIdentifier + "' already exists"); "A tab with the identifier '" + rootIdentifier + "' already exists");
@ -17,8 +29,23 @@ public class AdvancementManager {
return advancementTab; return advancementTab;
} }
/**
* Get an advancement tab by its root identifier
*
* @param rootIdentifier the root identifier of the tab
* @return the {@link AdvancementTab} associated with the identifer, null if not any
*/
public AdvancementTab getTab(String rootIdentifier) { public AdvancementTab getTab(String rootIdentifier) {
return advancementTabMap.get(rootIdentifier); return advancementTabMap.get(rootIdentifier);
} }
/**
* Get all the created tab
*
* @return the collection containing all created {@link AdvancementTab}
*/
public Collection<AdvancementTab> getTabs() {
return advancementTabMap.values();
}
} }

View File

@ -11,6 +11,9 @@ import net.minestom.server.utils.validate.Check;
import java.util.*; import java.util.*;
/**
* Represents a tab which can be shared between multiple players
*/
public class AdvancementTab implements Viewable { public class AdvancementTab implements Viewable {
private Set<Player> viewers = new HashSet<>(); private Set<Player> viewers = new HashSet<>();
@ -49,42 +52,6 @@ public class AdvancementTab implements Viewable {
} }
// FIXME
public void complete(String identifier) {
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";
}
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
// Add the mapping to the main packet
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[0];
// 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};
sendPacketToViewers(advancementsPacket);
}
/** /**
* Update the packet buffer * Update the packet buffer
*/ */
@ -102,14 +69,16 @@ public class AdvancementTab implements Viewable {
advancementsPacket.resetAdvancements = false; advancementsPacket.resetAdvancements = false;
List<AdvancementsPacket.AdvancementMapping> mappings = new ArrayList<>(); List<AdvancementsPacket.AdvancementMapping> mappings = new ArrayList<>();
List<AdvancementsPacket.ProgressMapping> progressMappings = new ArrayList<>();
for (Advancement advancement : advancementMap.keySet()) { for (Advancement advancement : advancementMap.keySet()) {
mappings.add(advancement.toMapping()); mappings.add(advancement.toMapping());
progressMappings.add(advancement.toProgressMapping());
} }
advancementsPacket.identifiersToRemove = new String[]{}; advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = mappings.toArray(new AdvancementsPacket.AdvancementMapping[0]); advancementsPacket.advancementMappings = mappings.toArray(new AdvancementsPacket.AdvancementMapping[0]);
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{}; advancementsPacket.progressMappings = progressMappings.toArray(new AdvancementsPacket.ProgressMapping[0]);
return advancementsPacket; return advancementsPacket;
} }
@ -127,6 +96,7 @@ public class AdvancementTab implements Viewable {
advancement.setTab(this); advancement.setTab(this);
advancement.setIdentifier(identifier); advancement.setIdentifier(identifier);
advancement.setParent(parent); advancement.setParent(parent);
advancement.updateCriteria();
this.advancementMap.put(advancement, parent); this.advancementMap.put(advancement, parent);
updatePacket(); updatePacket();

View File

@ -166,8 +166,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
/** /**
* Checks if now is a good time to send a velocity update packet * Checks if now is a good time to send a velocity update packet
* *
* @param time * @param time the current time in milliseconds
* @return * @return true if the velocity update packet should be send
*/ */
protected boolean shouldSendVelocityUpdate(long time) { protected boolean shouldSendVelocityUpdate(long time) {
return (time - lastVelocityUpdateTime) >= velocityUpdatePeriod; return (time - lastVelocityUpdateTime) >= velocityUpdatePeriod;
@ -191,6 +191,13 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
this.velocityUpdatePeriod = velocityUpdatePeriod; this.velocityUpdatePeriod = velocityUpdatePeriod;
} }
/**
* Teleport the entity only if the chunk at {@code position} is loaded or if
* {@link Instance#hasEnabledAutoChunkLoad()} returns true
*
* @param position the teleport position
* @param callback the callback executed, even if auto chunk is not enabled
*/
public void teleport(Position position, Runnable callback) { public void teleport(Position position, Runnable callback) {
Check.notNull(position, "Teleport position cannot be null"); Check.notNull(position, "Teleport position cannot be null");
Check.stateCondition(instance == null, "You need to use Entity#setInstance before teleporting an entity!"); Check.stateCondition(instance == null, "You need to use Entity#setInstance before teleporting an entity!");
@ -312,7 +319,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
/** /**
* Update the entity, called every tick * Update the entity, called every tick
* *
* @param time update time in milliseconds * @param time the update time in milliseconds
*/ */
public void tick(long time) { public void tick(long time) {
if (instance == null) if (instance == null)
@ -669,6 +676,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
} }
/** /**
* Get if the entity currently has a velocity applied
*
* @return true if velocity is not set to 0 * @return true if velocity is not set to 0
*/ */
public boolean hasVelocity() { public boolean hasVelocity() {
@ -680,7 +689,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
/** /**
* Change the gravity of the entity * Change the gravity of the entity
* *
* @param gravityDragPerTick * @param gravityDragPerTick the gravity drag per tick
*/ */
public void setGravity(float gravityDragPerTick) { public void setGravity(float gravityDragPerTick) {
this.gravityDragPerTick = gravityDragPerTick; this.gravityDragPerTick = gravityDragPerTick;
@ -1181,7 +1190,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
* Send a {@link EntityMetaDataPacket} containing only the specified index * Send a {@link EntityMetaDataPacket} containing only the specified index
* The index is wrote using {@link #fillMetadataIndex(PacketWriter, int)} * The index is wrote using {@link #fillMetadataIndex(PacketWriter, int)}
* *
* @param index * @param index the metadata index
*/ */
protected void sendMetadataIndex(int index) { protected void sendMetadataIndex(int index) {
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket(); EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();

View File

@ -110,7 +110,7 @@ public class PacketWriter extends OutputStream {
public void writeBufferAndFree(BufferWrapper buffer) { public void writeBufferAndFree(BufferWrapper buffer) {
ByteBuffer byteBuffer = buffer.getByteBuffer(); ByteBuffer byteBuffer = buffer.getByteBuffer();
int size = buffer.getSize(); final int size = buffer.getSize();
byte[] cache = new byte[size]; byte[] cache = new byte[size];
byteBuffer.position(0).get(cache, 0, size); byteBuffer.position(0).get(cache, 0, size);
writeBytes(cache); writeBytes(cache);
@ -145,7 +145,7 @@ public class PacketWriter extends OutputStream {
public byte[] toByteArray() { public byte[] toByteArray() {
byte[] bytes = new byte[buffer.readableBytes()]; byte[] bytes = new byte[buffer.readableBytes()];
int readerIndex = buffer.readerIndex(); final int readerIndex = buffer.readerIndex();
buffer.getBytes(readerIndex, bytes); buffer.getBytes(readerIndex, bytes);
return bytes; return bytes;
} }