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();
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);
Advancement advancement = new Advancement(ColoredText.of("adv"), ColoredText.of("desc"),
Material.WOODEN_AXE, FrameType.CHALLENGE, 1, 0)
@ -244,7 +245,6 @@ public class PlayerInit {
.showToast(true).setHidden(false);
tab.createAdvancement("second2", advancement2, root);
//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.utils.PacketUtils;
import java.util.Date;
/**
* Represent an advancement situated in an {@link AdvancementTab}
*/
public class Advancement {
protected AdvancementTab tab;
private boolean achieved;
private ColoredText title;
private ColoredText description;
@ -28,6 +35,9 @@ public class Advancement {
private String identifier;
private Advancement parent;
// Packet
private AdvancementsPacket.Criteria criteria;
public Advancement(ColoredText title, ColoredText description,
ItemStack icon, FrameType frameType,
float x, float y) {
@ -45,6 +55,27 @@ public class Advancement {
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
*
@ -222,6 +253,18 @@ public class Advancement {
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() {
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
displayData.x = x;
@ -256,8 +299,14 @@ public class Advancement {
}
adv.displayData = toDisplayData();
adv.criterions = new String[]{};
adv.requirements = new AdvancementsPacket.Requirement[]{};
adv.criterions = new String[]{criteria.criterionIdentifier};
AdvancementsPacket.Requirement requirement = new AdvancementsPacket.Requirement();
{
requirement.requirements = new String[]{criteria.criterionIdentifier};
}
adv.requirements = new AdvancementsPacket.Requirement[]{requirement};
}
return mapping;
@ -276,7 +325,7 @@ public class Advancement {
advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{toProgressMapping()};
return advancementsPacket;
}
@ -285,6 +334,8 @@ public class Advancement {
* Send update to all tab viewers if one of the advancement value changes
*/
protected void update() {
updateCriteria();
if (tab != null) {
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() {
byte result = 0;

View File

@ -2,13 +2,25 @@ package net.minestom.server.advancements;
import net.minestom.server.utils.validate.Check;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Used to manages advancement tabs
*/
public class AdvancementManager {
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) {
Check.stateCondition(advancementTabMap.containsKey(rootIdentifier),
"A tab with the identifier '" + rootIdentifier + "' already exists");
@ -17,8 +29,23 @@ public class AdvancementManager {
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) {
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.*;
/**
* Represents a tab which can be shared between multiple players
*/
public class AdvancementTab implements Viewable {
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
*/
@ -102,14 +69,16 @@ public class AdvancementTab implements Viewable {
advancementsPacket.resetAdvancements = false;
List<AdvancementsPacket.AdvancementMapping> mappings = new ArrayList<>();
List<AdvancementsPacket.ProgressMapping> progressMappings = new ArrayList<>();
for (Advancement advancement : advancementMap.keySet()) {
mappings.add(advancement.toMapping());
progressMappings.add(advancement.toProgressMapping());
}
advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = mappings.toArray(new AdvancementsPacket.AdvancementMapping[0]);
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{};
advancementsPacket.progressMappings = progressMappings.toArray(new AdvancementsPacket.ProgressMapping[0]);
return advancementsPacket;
}
@ -127,6 +96,7 @@ public class AdvancementTab implements Viewable {
advancement.setTab(this);
advancement.setIdentifier(identifier);
advancement.setParent(parent);
advancement.updateCriteria();
this.advancementMap.put(advancement, parent);
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
*
* @param time
* @return
* @param time the current time in milliseconds
* @return true if the velocity update packet should be send
*/
protected boolean shouldSendVelocityUpdate(long time) {
return (time - lastVelocityUpdateTime) >= velocityUpdatePeriod;
@ -191,6 +191,13 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
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) {
Check.notNull(position, "Teleport position cannot be null");
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
*
* @param time update time in milliseconds
* @param time the update time in milliseconds
*/
public void tick(long time) {
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
*/
public boolean hasVelocity() {
@ -680,7 +689,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
/**
* Change the gravity of the entity
*
* @param gravityDragPerTick
* @param gravityDragPerTick the gravity drag per tick
*/
public void setGravity(float 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
* The index is wrote using {@link #fillMetadataIndex(PacketWriter, int)}
*
* @param index
* @param index the metadata index
*/
protected void sendMetadataIndex(int index) {
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();

View File

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