Added a lot of comments

This commit is contained in:
Felix Cravic 2020-05-15 18:03:28 +02:00
parent ee90f82969
commit b97b75f13c
11 changed files with 178 additions and 38 deletions

View File

@ -177,6 +177,13 @@ public class PlayerInit {
player.sendMessage("CLICK PLAYER INVENTORY");
System.out.println("slot player: " + slot);
});
/*Sidebar scoreboard = new Sidebar("Scoreboard Title");
for (int i = 0; i < 15; i++) {
scoreboard.createLine(new Sidebar.ScoreboardLine("id" + i, "Hey guys " + i, i));
}
scoreboard.addViewer(player);
scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED");*/
});
player.addEventCallback(PlayerSpawnEvent.class, event -> {
@ -212,19 +219,16 @@ public class PlayerInit {
setAttribute(Attribute.MAX_HEALTH, 10);
heal();
Sidebar scoreboard = new Sidebar("Scoreboard Title");
for (int i = 0; i < 15; i++) {
scoreboard.createLine(new Sidebar.ScoreboardLine("id" + i, "Hey guys " + i, i));
}
scoreboard.addViewer(this);
scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED");
BelowNameScoreboard belowNameScoreboard = new BelowNameScoreboard();
setBelowNameScoreboard(belowNameScoreboard);
belowNameScoreboard.updateScore(this, 50);*/
});
player.addEventCallback(PlayerRespawnEvent.class, event -> {
event.setRespawnPosition(new Position(0f, 70f, 0f));
});
player.addEventCallback(PlayerUseItemEvent.class, useEvent -> {
player.sendMessage("Using item in air: " + useEvent.getItemStack().getMaterial());
});

View File

@ -8,6 +8,7 @@ import net.minestom.server.data.Data;
import net.minestom.server.data.DataContainer;
import net.minestom.server.event.Event;
import net.minestom.server.event.EventCallback;
import net.minestom.server.event.entity.EntityDeathEvent;
import net.minestom.server.event.entity.EntitySpawnEvent;
import net.minestom.server.event.entity.EntityTickEvent;
import net.minestom.server.event.entity.EntityVelocityEvent;
@ -20,6 +21,7 @@ import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.*;
import net.minestom.server.utils.time.TimeUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@ -114,18 +116,26 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
this(entityType, new Position());
}
/**
* @param id the entity unique id ({@link #getEntityId()})
* @return the entity having the specified id, null if not found
*/
public static Entity getEntity(int id) {
return entityById.get(id);
return entityById.getOrDefault(id, null);
}
private static int generateId() {
return lastEntityId.incrementAndGet();
}
/**
* Called each tick
*/
public abstract void update();
// Called when a new instance is set
/**
* Called when a new instance is set
*/
public abstract void spawn();
public boolean isOnGround() {
@ -375,6 +385,12 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
return eventCallbacks.getOrDefault(eventClass, new CopyOnWriteArrayList<>());
}
/**
* Each entity has an unique id which will change after a restart
* All entities can be retrieved by calling {@link Entity#getEntity(int)}
*
* @return the unique entity id
*/
public int getEntityId() {
return id;
}
@ -619,10 +635,17 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
sendMetadataIndex(0);
}
/**
* @return the current position of the entity
*/
public Position getPosition() {
return position;
}
/**
* @param position the checked position chunk
* @return true if the entity is in the same chunk as {@code position}
*/
public boolean sameChunk(Position position) {
Position pos = getPosition();
int chunkX1 = ChunkUtils.getChunkCoordinate((int) Math.floor(pos.getX()));
@ -638,6 +661,10 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
return sameChunk(entity.getPosition());
}
/**
* Remove the entity from the server immediately
* WARNING: this do not trigger the {@link EntityDeathEvent} event
*/
public void remove() {
this.shouldRemove = true;
entityById.remove(id);
@ -645,7 +672,15 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
instance.removeEntity(this);
}
public void scheduleRemove(long delay) {
/**
* Trigger {@link #remove()} after the specified time
*
* @param delay
* @param timeUnit to determine the delay unit
*/
public void scheduleRemove(long delay, TimeUnit timeUnit) {
delay = timeUnit.toMilliseconds(delay);
if (delay == 0) { // Cancel the scheduled remove
this.scheduledRemoveTime = 0;
return;
@ -653,6 +688,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
this.scheduledRemoveTime = System.currentTimeMillis() + delay;
}
/**
* @return true if {@link #scheduleRemove(long, TimeUnit)} has been called, false otherwise
*/
public boolean isRemoveScheduled() {
return scheduledRemoveTime != 0;
}
@ -667,6 +705,11 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
return velocityPacket;
}
/**
* Used to sync entities together, and sent when adding viewers
*
* @return The {@link EntityMetaDataPacket} related to this entity
*/
public EntityMetaDataPacket getMetadataPacket() {
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();
metaDataPacket.entityId = getEntityId();
@ -674,6 +717,11 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
return metaDataPacket;
}
/**
* Should be override when wanting to add a new metadata index
*
* @return The consumer used to write {@link EntityMetaDataPacket} in {@link #getMetadataPacket()}
*/
public Consumer<PacketWriter> getMetadataConsumer() {
return packet -> {
fillMetadataIndex(packet, 0);
@ -683,6 +731,12 @@ 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
*/
protected void sendMetadataIndex(int index) {
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();
metaDataPacket.entityId = getEntityId();
@ -693,6 +747,14 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
sendPacketToViewersAndSelf(metaDataPacket);
}
/**
* Used to fill/write a specific metadata index
* The proper use to add a new metadata index is to override this and add your case
* Then you can also override {@link #getMetadataConsumer()} and fill your newly added index
*
* @param packet the packet writer
* @param index the index to fill/write
*/
protected void fillMetadataIndex(PacketWriter packet, int index) {
switch (index) {
case 0:

View File

@ -11,6 +11,7 @@ import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.ChunkUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector;
import net.minestom.server.utils.time.TimeUnit;
import java.util.LinkedList;
import java.util.function.Consumer;
@ -119,7 +120,7 @@ public abstract class EntityCreature extends LivingEntity {
super.kill();
// Needed for proper death animation (wait for it to finish before destroying the entity)
scheduleRemove(1000);
scheduleRemove(1000, TimeUnit.MILLISECOND);
}
@Override

View File

@ -142,6 +142,9 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
syncEquipments();
}
/**
* Kill the entity, trigger the {@link EntityDeathEvent} event
*/
public void kill() {
refreshIsDead(true); // So the entity isn't killed over and over again
triggerStatus((byte) 3); // Start death animation status

View File

@ -31,10 +31,7 @@ import net.minestom.server.scoreboard.Team;
import net.minestom.server.sound.Sound;
import net.minestom.server.sound.SoundCategory;
import net.minestom.server.stat.PlayerStatistic;
import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.ChunkUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.*;
import net.minestom.server.world.Dimension;
import net.minestom.server.world.LevelType;
@ -71,6 +68,8 @@ public class Player extends LivingEntity {
private short heldSlot;
private Inventory openInventory;
private Position respawnPoint;
private int food;
private float foodSaturation;
private long startEatingTime;
@ -120,6 +119,8 @@ public class Player extends LivingEntity {
setBoundingBox(0.69f, 1.8f, 0.69f);
setRespawnPoint(new Position(0, 0, 0));
// Some client update
getPlayerConnection().sendPacket(getPropertiesPacket()); // Send default properties
refreshHealth();
@ -618,9 +619,23 @@ public class Player extends LivingEntity {
return !itemDropEvent.isCancelled();
}
/**
* Used to retrieve the default spawn point
* can be altered by the {@link PlayerRespawnEvent#setRespawnPosition(Position)}
*
* @return the default respawn point
*/
public Position getRespawnPoint() {
// TODO: Custom
return new Position(0f, 70f, 0f);
return respawnPoint;
}
/**
* Change the default spawn point
*
* @param respawnPoint
*/
public void setRespawnPoint(Position respawnPoint) {
this.respawnPoint = respawnPoint;
}
public void respawn() {
@ -671,7 +686,7 @@ public class Player extends LivingEntity {
}
public void setExp(float exp) {
if (exp < 0 || exp > 1)
if (!MathUtils.isBetween(exp, 0, 1))
throw new IllegalArgumentException("Exp should be between 0 and 1");
this.exp = exp;
sendExperienceUpdatePacket();
@ -884,7 +899,7 @@ public class Player extends LivingEntity {
}
/**
* Open the specified Inventory
* Open the specified Inventory, close the previous inventory if existing
*
* @param inventory the inventory to open
* @return true if the inventory has been opened/sent to the player, false otherwise (cancelled by event)
@ -916,6 +931,10 @@ public class Player extends LivingEntity {
return !inventoryOpenEvent.isCancelled();
}
/**
* Close the current inventory if there is any
* It closes the player inventory if {@link #getOpenInventory()} returns null
*/
public void closeInventory() {
Inventory openInventory = getOpenInventory();
CloseWindowPacket closeWindowPacket = new CloseWindowPacket();
@ -956,7 +975,7 @@ public class Player extends LivingEntity {
}
public void setPermissionLevel(int permissionLevel) {
if (permissionLevel < 0 || permissionLevel > 4)
if (!MathUtils.isBetween(permissionLevel, 0, 4))
throw new IllegalArgumentException("permissionLevel has to be between 0 and 4");
this.permissionLevel = permissionLevel;
@ -1032,6 +1051,12 @@ public class Player extends LivingEntity {
refreshAbilities();
}
/**
* This is the map used to send the statistic packet
* It is possible to add/remove/change statistic value directly into it
*
* @return the modifiable statistic map
*/
public Map<PlayerStatistic, Integer> getStatisticValueMap() {
return statisticValueMap;
}
@ -1052,6 +1077,13 @@ public class Player extends LivingEntity {
playerConnection.sendPacket(playerAbilitiesPacket);
}
/**
* All packets in the queue are executed in the {@link #update()} method
* It is used internally to add all received packet from the client
* Could be used to "simulate" a received packet, but to use at your own risk
*
* @param packet the packet to add in the queue
*/
public void addPacketToQueue(ClientPlayPacket packet) {
this.packets.add(packet);
}

View File

@ -8,10 +8,29 @@ import java.util.List;
public interface EventHandler {
/**
* Add a new event callback for the specified type {@code eventClass}
*
* @param eventClass the event class
* @param eventCallback the event callback
* @param <E> the event type
*/
<E extends Event> void addEventCallback(Class<E> eventClass, EventCallback<E> eventCallback);
/**
* @param eventClass
* @param <E>
* @return all event callbacks for the specified type {@code eventClass}
*/
<E extends Event> List<EventCallback> getEventCallbacks(Class<E> eventClass);
/**
* Call the specified event type using the Event object parameter
*
* @param eventClass the event class
* @param event the event object
* @param <E> the event type
*/
default <E extends Event> void callEvent(Class<E> eventClass, E event) {
List<EventCallback> eventCallbacks = getEventCallbacks(eventClass);
for (EventCallback<E> eventCallback : eventCallbacks) {
@ -19,6 +38,14 @@ public interface EventHandler {
}
}
/**
* Same as {@link #callEvent(Class, Event)} but add a Runnable which is called if the event is not cancelled
*
* @param eventClass the event class
* @param event the event object
* @param runnable the callback called when the event is not cancelled
* @param <E> the event type
*/
default <E extends CancellableEvent> void callCancellableEvent(Class<E> eventClass, E event, Runnable runnable) {
callEvent(eventClass, event);
if (!event.isCancelled()) {

View File

@ -259,13 +259,17 @@ public class InstanceContainer extends Instance {
public void loadOptionalChunk(int chunkX, int chunkZ, Consumer<Chunk> callback) {
Chunk chunk = getChunk(chunkX, chunkZ);
if (chunk != null) {
// Chunk already loaded
if (callback != null)
callback.accept(chunk);
} else {
if (hasEnabledAutoChunkLoad()) {
// Load chunk from StorageFolder or with ChunkGenerator
retrieveChunk(chunkX, chunkZ, callback);
} else {
callback.accept(null);
// Chunk not loaded, return null
if (callback != null)
callback.accept(null);
}
}
}

View File

@ -15,7 +15,6 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
// TODO update tick
public class Sidebar implements Viewable {
private static final AtomicInteger counter = new AtomicInteger();
@ -73,20 +72,18 @@ public class Sidebar implements Viewable {
}
public void updateLineContent(String id, String content) {
for (ScoreboardLine line : lines) {
if (line.id.equals(id)) {
line.refreshContent(content);
sendPacketToViewers(line.sidebarTeam.updatePrefix(content));
}
ScoreboardLine scoreboardLine = getLine(id);
if (scoreboardLine != null) {
scoreboardLine.refreshContent(content);
sendPacketToViewers(scoreboardLine.sidebarTeam.updatePrefix(content));
}
}
public void updateLineScore(String id, int score) {
for (ScoreboardLine line : lines) {
if (line.id.equals(id)) {
line.line = score;
sendPacketToViewers(line.getLineScoreUpdatePacket(objectiveName, score));
}
ScoreboardLine scoreboardLine = getLine(id);
if (scoreboardLine != null) {
scoreboardLine.line = score;
sendPacketToViewers(scoreboardLine.getLineScoreUpdatePacket(objectiveName, score));
}
}

View File

@ -8,7 +8,9 @@ public class ChunkUtils {
public static boolean isChunkUnloaded(Instance instance, float x, float z) {
int chunkX = getChunkCoordinate((int) x);
int chunkZ = getChunkCoordinate((int) z);
return instance.getChunk(chunkX, chunkZ) == null;
Chunk chunk = instance.getChunk(chunkX, chunkZ);
return chunk == null || !chunk.isLoaded();
}
public static int getChunkCoordinate(int xz) {

View File

@ -30,13 +30,21 @@ public class MathUtils {
public static Direction getHorizontalDirection(float yawInDegrees) {
// +45f gives a 90° angle for the direction (-1° and 1° are towards the same direction)
int directionIndex = (int) Math.floor(((yawInDegrees+45f) / 90f));
if(directionIndex < 0) {
int directionIndex = (int) Math.floor(((yawInDegrees + 45f) / 90f));
if (directionIndex < 0) {
directionIndex = (-directionIndex) % Direction.HORIZONTAL.length;
directionIndex = Direction.HORIZONTAL.length-directionIndex;
directionIndex = Direction.HORIZONTAL.length - directionIndex;
}
directionIndex %= Direction.HORIZONTAL.length;
return Direction.HORIZONTAL[directionIndex];
}
public static boolean isBetween(int number, int min, int max) {
return number >= min && number <= max;
}
public static boolean isBetween(float number, float min, float max) {
return number >= min && number <= max;
}
}

View File

@ -6,7 +6,7 @@ public enum TimeUnit {
TICK, MILLISECOND;
public long toMilliseconds(int value) {
public long toMilliseconds(long value) {
switch (this) {
case TICK:
return MinecraftServer.TICK_MS * value;