mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-01 05:58:00 +01:00
Added a lot of comments
This commit is contained in:
parent
ee90f82969
commit
b97b75f13c
@ -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());
|
||||
});
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user