mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-27 02:21:38 +01:00
Update
This commit is contained in:
parent
4263a3965b
commit
bdde4af581
19
src/main/java/fr/themode/minestom/Viewable.java
Normal file
19
src/main/java/fr/themode/minestom/Viewable.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package fr.themode.minestom;
|
||||||
|
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface Viewable {
|
||||||
|
|
||||||
|
void addViewer(Player player);
|
||||||
|
|
||||||
|
void removeViewer(Player player);
|
||||||
|
|
||||||
|
Set<Player> getViewers();
|
||||||
|
|
||||||
|
default boolean isViewer(Player player) {
|
||||||
|
return getViewers().contains(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/main/java/fr/themode/minestom/bossbar/BarColor.java
Normal file
13
src/main/java/fr/themode/minestom/bossbar/BarColor.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package fr.themode.minestom.bossbar;
|
||||||
|
|
||||||
|
public enum BarColor {
|
||||||
|
|
||||||
|
PINK,
|
||||||
|
BLUE,
|
||||||
|
RED,
|
||||||
|
GREEN,
|
||||||
|
YELLOW,
|
||||||
|
PURPLE,
|
||||||
|
WHITE;
|
||||||
|
|
||||||
|
}
|
11
src/main/java/fr/themode/minestom/bossbar/BarDivision.java
Normal file
11
src/main/java/fr/themode/minestom/bossbar/BarDivision.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package fr.themode.minestom.bossbar;
|
||||||
|
|
||||||
|
public enum BarDivision {
|
||||||
|
|
||||||
|
SOLID,
|
||||||
|
SEGMENT_6,
|
||||||
|
SEGMENT_10,
|
||||||
|
SEGMENT_12,
|
||||||
|
SEGMENT_20;
|
||||||
|
|
||||||
|
}
|
138
src/main/java/fr/themode/minestom/bossbar/BossBar.java
Normal file
138
src/main/java/fr/themode/minestom/bossbar/BossBar.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package fr.themode.minestom.bossbar;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Viewable;
|
||||||
|
import fr.themode.minestom.chat.Chat;
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.BossBarPacket;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
public class BossBar implements Viewable {
|
||||||
|
|
||||||
|
private UUID uuid = UUID.randomUUID();
|
||||||
|
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private float progress;
|
||||||
|
private BarColor color;
|
||||||
|
private BarDivision division;
|
||||||
|
private byte flags;
|
||||||
|
|
||||||
|
public BossBar(String title, BarColor color, BarDivision division) {
|
||||||
|
this.title = Chat.rawText(title);
|
||||||
|
this.color = color;
|
||||||
|
this.division = division;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewer(Player player) {
|
||||||
|
this.viewers.add(player);
|
||||||
|
player.refreshAddBossbar(this);
|
||||||
|
addToPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeViewer(Player player) {
|
||||||
|
this.viewers.remove(player);
|
||||||
|
player.refreshRemoveBossbar(this);
|
||||||
|
removeToPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Player> getViewers() {
|
||||||
|
return Collections.unmodifiableSet(viewers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = Chat.rawText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getProgress() {
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgress(float progress) {
|
||||||
|
this.progress = progress;
|
||||||
|
updateProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarColor getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(BarColor color) {
|
||||||
|
this.color = color;
|
||||||
|
updateStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarDivision getDivision() {
|
||||||
|
return division;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDivision(BarDivision division) {
|
||||||
|
this.division = division;
|
||||||
|
updateStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.REMOVE;
|
||||||
|
sendPacket(bossBarPacket);
|
||||||
|
// TODO remove bar from player class
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToPlayer(Player player) {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.ADD;
|
||||||
|
bossBarPacket.title = title;
|
||||||
|
bossBarPacket.health = progress;
|
||||||
|
bossBarPacket.color = color;
|
||||||
|
bossBarPacket.division = division;
|
||||||
|
bossBarPacket.flags = flags;
|
||||||
|
player.getPlayerConnection().sendPacket(bossBarPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeToPlayer(Player player) {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.REMOVE;
|
||||||
|
player.getPlayerConnection().sendPacket(bossBarPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTitle() {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.UPDATE_TITLE;
|
||||||
|
bossBarPacket.title = title;
|
||||||
|
sendPacket(bossBarPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress() {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.UPDATE_HEALTH;
|
||||||
|
bossBarPacket.health = progress;
|
||||||
|
sendPacket(bossBarPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStyle() {
|
||||||
|
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||||
|
bossBarPacket.uuid = uuid;
|
||||||
|
bossBarPacket.action = BossBarPacket.Action.UPDATE_STYLE;
|
||||||
|
bossBarPacket.color = color;
|
||||||
|
sendPacket(bossBarPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendPacket(BossBarPacket bossBarPacket) {
|
||||||
|
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(bossBarPacket));
|
||||||
|
}
|
||||||
|
}
|
8
src/main/java/fr/themode/minestom/chat/Chat.java
Normal file
8
src/main/java/fr/themode/minestom/chat/Chat.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package fr.themode.minestom.chat;
|
||||||
|
|
||||||
|
public class Chat {
|
||||||
|
|
||||||
|
public static String rawText(String text) {
|
||||||
|
return "{\"text\": \"" + text + "\"}";
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +1,81 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.themode.minestom.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
import fr.themode.minestom.instance.Instance;
|
import fr.themode.minestom.instance.Instance;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class Entity {
|
public abstract class Entity {
|
||||||
|
|
||||||
private static AtomicInteger lastEntityId = new AtomicInteger();
|
private static AtomicInteger lastEntityId = new AtomicInteger();
|
||||||
|
|
||||||
|
// Metadata
|
||||||
|
protected static final byte METADATA_BYTE = 0;
|
||||||
|
protected static final byte METADATA_VARINT = 1;
|
||||||
|
protected static final byte METADATA_FLOAT = 2;
|
||||||
|
protected static final byte METADATA_STRING = 3;
|
||||||
|
protected static final byte METADATA_CHAT = 4;
|
||||||
|
protected static final byte METADATA_OPTCHAT = 5;
|
||||||
|
protected static final byte METADATA_SLOT = 6;
|
||||||
|
protected static final byte METADATA_BOOLEAN = 7;
|
||||||
|
|
||||||
protected Instance instance;
|
protected Instance instance;
|
||||||
protected double lastX, lastY, lastZ;
|
protected double lastX, lastY, lastZ;
|
||||||
protected double x, y, z;
|
protected double x, y, z;
|
||||||
|
protected float yaw, pitch;
|
||||||
private int id;
|
private int id;
|
||||||
|
// Metadata
|
||||||
|
protected boolean onFire;
|
||||||
protected UUID uuid;
|
protected UUID uuid;
|
||||||
private boolean isActive; // False if entity has only been instanced without being added somewhere
|
private boolean isActive; // False if entity has only been instanced without being added somewhere
|
||||||
|
protected boolean crouched;
|
||||||
private boolean shouldRemove;
|
private boolean shouldRemove;
|
||||||
|
protected boolean UNUSED_METADATA;
|
||||||
|
protected boolean sprinting;
|
||||||
|
protected boolean swimming;
|
||||||
|
protected boolean invisible;
|
||||||
|
protected boolean glowing;
|
||||||
|
protected boolean usingElytra;
|
||||||
|
protected int air = 300;
|
||||||
|
protected String customName = "";
|
||||||
|
protected boolean customNameVisible;
|
||||||
|
protected boolean silent;
|
||||||
|
protected boolean noGravity;
|
||||||
|
protected Pose pose = Pose.STANDING;
|
||||||
|
private int entityType;
|
||||||
|
private long lastUpdate;
|
||||||
|
|
||||||
public Entity() {
|
public Entity(int entityType) {
|
||||||
this.id = generateId();
|
this.id = generateId();
|
||||||
|
this.entityType = entityType;
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int generateId() {
|
private static int generateId() {
|
||||||
return lastEntityId.incrementAndGet();
|
return lastEntityId.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void update();
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
if (shouldUpdate()) {
|
||||||
|
update();
|
||||||
|
this.lastUpdate = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getEntityType() {
|
||||||
|
return entityType;
|
||||||
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
@ -56,6 +101,10 @@ public class Entity {
|
|||||||
instance.addEntity(this);
|
instance.addEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getDistance(Entity entity) {
|
||||||
|
return (float) Math.sqrt(Math.pow(entity.getX() - getX(), 2) + Math.pow(entity.getY() - getY(), 2) + Math.pow(entity.getZ() - getZ(), 2));
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshPosition(double x, double y, double z) {
|
public void refreshPosition(double x, double y, double z) {
|
||||||
this.lastX = this.x;
|
this.lastX = this.x;
|
||||||
this.lastY = this.y;
|
this.lastY = this.y;
|
||||||
@ -91,10 +140,101 @@ public class Entity {
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getYaw() {
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPitch() {
|
||||||
|
return pitch;
|
||||||
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
this.shouldRemove = true;
|
this.shouldRemove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Buffer getMetadataBuffer() {
|
||||||
|
Buffer buffer = Buffer.create();
|
||||||
|
fillMetadataIndex(buffer, 0);
|
||||||
|
/*Utils.writeVarInt(buffer, 0);
|
||||||
|
Utils.writeString(buffer, customName);
|
||||||
|
buffer.putBoolean(silent);
|
||||||
|
buffer.putBoolean(noGravity);
|
||||||
|
Utils.writeVarInt(buffer, pose.ordinal());*/
|
||||||
|
|
||||||
|
// Chicken test
|
||||||
|
/*buffer.putByte((byte) 0); // Hand states
|
||||||
|
buffer.putFloat(10f); // Health
|
||||||
|
Utils.writeVarInt(buffer, 0); // Potion effect color
|
||||||
|
buffer.putBoolean(false); // Potion effect ambient
|
||||||
|
Utils.writeVarInt(buffer, 0); // Arrow count in entity
|
||||||
|
buffer.putByte((byte) 0); // (Insentient)
|
||||||
|
buffer.putBoolean(false); // baby (Ageable)*/
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillMetadataIndex(Buffer buffer, int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
fillStateMetadata(buffer);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
fillAirTickMetaData(buffer);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fillCustomNameMetaData(buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillStateMetadata(Buffer buffer) {
|
||||||
|
buffer.putByte((byte) 0);
|
||||||
|
buffer.putByte(METADATA_BYTE);
|
||||||
|
byte index0 = 0;
|
||||||
|
if (onFire)
|
||||||
|
index0 += 1;
|
||||||
|
if (crouched)
|
||||||
|
index0 += 2;
|
||||||
|
if (UNUSED_METADATA)
|
||||||
|
index0 += 4;
|
||||||
|
if (sprinting)
|
||||||
|
index0 += 8;
|
||||||
|
if (swimming)
|
||||||
|
index0 += 16;
|
||||||
|
if (invisible)
|
||||||
|
index0 += 32;
|
||||||
|
if (glowing)
|
||||||
|
index0 += 64;
|
||||||
|
if (usingElytra)
|
||||||
|
index0 += 128;
|
||||||
|
buffer.putByte(index0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillAirTickMetaData(Buffer buffer) {
|
||||||
|
buffer.putByte((byte) 1);
|
||||||
|
buffer.putByte(METADATA_VARINT);
|
||||||
|
Utils.writeVarInt(buffer, air);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillCustomNameMetaData(Buffer buffer) {
|
||||||
|
buffer.putByte((byte) 2);
|
||||||
|
buffer.putByte(METADATA_CHAT);
|
||||||
|
Utils.writeString(buffer, customName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldUpdate() {
|
||||||
|
return (float) (System.currentTimeMillis() - lastUpdate) >= 50f * 0.9f; // Margin of error
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Pose {
|
||||||
|
STANDING,
|
||||||
|
FALL_FLYING,
|
||||||
|
SLEEPING,
|
||||||
|
SWIMMING,
|
||||||
|
SPIN_ATTACK,
|
||||||
|
SNEAKING,
|
||||||
|
DYING;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean shouldRemove() {
|
protected boolean shouldRemove() {
|
||||||
return shouldRemove;
|
return shouldRemove;
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Viewable;
|
||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.EntityPacket;
|
import fr.themode.minestom.net.packet.server.play.*;
|
||||||
import fr.themode.minestom.net.packet.server.play.EntityRelativeMovePacket;
|
|
||||||
import fr.themode.minestom.net.packet.server.play.EntityTeleportPacket;
|
|
||||||
import fr.themode.minestom.net.packet.server.play.SpawnMobPacket;
|
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
public abstract class EntityCreature extends LivingEntity {
|
public abstract class EntityCreature extends LivingEntity implements Viewable {
|
||||||
|
|
||||||
private Set<Player> viewers = Collections.synchronizedSet(new HashSet<>());
|
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
private int entityType;
|
|
||||||
|
|
||||||
public EntityCreature(int entityType) {
|
public EntityCreature(int entityType) {
|
||||||
super();
|
super(entityType);
|
||||||
this.entityType = entityType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move(double x, double y, double z) {
|
public void move(double x, double y, double z) {
|
||||||
@ -56,6 +51,7 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
sendPacketToViewers(entityTeleportPacket);
|
sendPacketToViewers(entityTeleportPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addViewer(Player player) {
|
public void addViewer(Player player) {
|
||||||
this.viewers.add(player);
|
this.viewers.add(player);
|
||||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||||
@ -72,10 +68,15 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
spawnMobPacket.yaw = getYaw();
|
spawnMobPacket.yaw = getYaw();
|
||||||
spawnMobPacket.pitch = getPitch();
|
spawnMobPacket.pitch = getPitch();
|
||||||
spawnMobPacket.headPitch = 0;
|
spawnMobPacket.headPitch = 0;
|
||||||
|
EntityMetaDataPacket entityMetaDataPacket = new EntityMetaDataPacket();
|
||||||
|
entityMetaDataPacket.entityId = getEntityId();
|
||||||
|
entityMetaDataPacket.data = getMetadataBuffer();
|
||||||
playerConnection.sendPacket(entityPacket);
|
playerConnection.sendPacket(entityPacket);
|
||||||
playerConnection.sendPacket(spawnMobPacket);
|
playerConnection.sendPacket(spawnMobPacket);
|
||||||
|
playerConnection.sendPacket(entityMetaDataPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeViewer(Player player) {
|
public void removeViewer(Player player) {
|
||||||
synchronized (viewers) {
|
synchronized (viewers) {
|
||||||
if (!viewers.contains(player))
|
if (!viewers.contains(player))
|
||||||
@ -85,15 +86,12 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendPacketToViewers(ServerPacket packet) {
|
@Override
|
||||||
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Player> getViewers() {
|
public Set<Player> getViewers() {
|
||||||
return Collections.unmodifiableSet(viewers);
|
return Collections.unmodifiableSet(viewers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntityType() {
|
protected void sendPacketToViewers(ServerPacket packet) {
|
||||||
return entityType;
|
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(packet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
import fr.themode.minestom.Main;
|
import fr.themode.minestom.Main;
|
||||||
|
import fr.themode.minestom.instance.Chunk;
|
||||||
import fr.themode.minestom.instance.Instance;
|
import fr.themode.minestom.instance.Instance;
|
||||||
import fr.themode.minestom.instance.InstanceManager;
|
import fr.themode.minestom.instance.InstanceManager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@ -11,43 +13,98 @@ public class EntityManager {
|
|||||||
|
|
||||||
private static InstanceManager instanceManager = Main.getInstanceManager();
|
private static InstanceManager instanceManager = Main.getInstanceManager();
|
||||||
|
|
||||||
|
private ExecutorService objectsPool = Executors.newFixedThreadPool(2);
|
||||||
private ExecutorService creaturesPool = Executors.newFixedThreadPool(2);
|
private ExecutorService creaturesPool = Executors.newFixedThreadPool(2);
|
||||||
private ExecutorService playersPool = Executors.newFixedThreadPool(2);
|
private ExecutorService playersPool = Executors.newFixedThreadPool(2);
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
for (Instance instance : instanceManager.getInstances()) {
|
for (Instance instance : instanceManager.getInstances()) {
|
||||||
// TODO loop chunks and entities on it instead of individual (to have more non-blocking operation)
|
testTick2(instance);
|
||||||
|
|
||||||
// Creatures
|
|
||||||
for (EntityCreature creature : instance.getCreatures()) {
|
|
||||||
creaturesPool.submit(() -> {
|
|
||||||
boolean shouldRemove = creature.shouldRemove();
|
|
||||||
if (!shouldRemove) {
|
|
||||||
creature.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.shouldRemove()) {
|
|
||||||
instance.removeEntity(creature);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Players
|
|
||||||
for (Player player : instance.getPlayers()) {
|
|
||||||
playersPool.submit(() -> {
|
|
||||||
boolean shouldRemove = player.shouldRemove();
|
|
||||||
if (!shouldRemove) {
|
|
||||||
player.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.shouldRemove()) {
|
|
||||||
instance.removeEntity(player);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testTick2(Instance instance) {
|
||||||
|
for (Chunk chunk : instance.getChunks()) {
|
||||||
|
Set<ObjectEntity> objects = chunk.getObjectEntities();
|
||||||
|
Set<EntityCreature> creatures = chunk.getCreatures();
|
||||||
|
Set<Player> players = chunk.getPlayers();
|
||||||
|
|
||||||
|
if (!objects.isEmpty()) {
|
||||||
|
objectsPool.submit(() -> {
|
||||||
|
for (ObjectEntity objectEntity : objects) {
|
||||||
|
boolean shouldRemove = objectEntity.shouldRemove();
|
||||||
|
if (!shouldRemove) {
|
||||||
|
objectEntity.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectEntity.shouldRemove()) {
|
||||||
|
instance.removeEntity(objectEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!creatures.isEmpty()) {
|
||||||
|
creaturesPool.submit(() -> {
|
||||||
|
for (EntityCreature creature : creatures) {
|
||||||
|
boolean shouldRemove = creature.shouldRemove();
|
||||||
|
if (!shouldRemove) {
|
||||||
|
creature.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creature.shouldRemove()) {
|
||||||
|
instance.removeEntity(creature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!players.isEmpty()) {
|
||||||
|
playersPool.submit(() -> {
|
||||||
|
for (Player player : players) {
|
||||||
|
boolean shouldRemove = player.shouldRemove();
|
||||||
|
if (!shouldRemove) {
|
||||||
|
player.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.shouldRemove()) {
|
||||||
|
instance.removeEntity(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testTick(Instance instance) {
|
||||||
|
// Creatures
|
||||||
|
for (EntityCreature creature : instance.getCreatures()) {
|
||||||
|
creaturesPool.submit(() -> {
|
||||||
|
boolean shouldRemove = creature.shouldRemove();
|
||||||
|
if (!shouldRemove) {
|
||||||
|
creature.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (creature.shouldRemove()) {
|
||||||
|
instance.removeEntity(creature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Players
|
||||||
|
for (Player player : instance.getPlayers()) {
|
||||||
|
playersPool.submit(() -> {
|
||||||
|
boolean shouldRemove = player.shouldRemove();
|
||||||
|
if (!shouldRemove) {
|
||||||
|
player.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.shouldRemove()) {
|
||||||
|
instance.removeEntity(player);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
47
src/main/java/fr/themode/minestom/entity/ItemEntity.java
Normal file
47
src/main/java/fr/themode/minestom/entity/ItemEntity.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.item.ItemStack;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class ItemEntity extends ObjectEntity {
|
||||||
|
|
||||||
|
private ItemStack itemStack;
|
||||||
|
private boolean pickable = true;
|
||||||
|
|
||||||
|
public ItemEntity(ItemStack itemStack) {
|
||||||
|
super(34);
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Buffer getMetadataBuffer() {
|
||||||
|
Buffer buffer = super.getMetadataBuffer();
|
||||||
|
buffer.putByte((byte) 7);
|
||||||
|
buffer.putByte(METADATA_SLOT);
|
||||||
|
Utils.writeItemStack(buffer, itemStack);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getData() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItemStack() {
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPickable() {
|
||||||
|
return pickable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPickable(boolean pickable) {
|
||||||
|
this.pickable = pickable;
|
||||||
|
}
|
||||||
|
}
|
@ -2,25 +2,14 @@ package fr.themode.minestom.entity;
|
|||||||
|
|
||||||
public abstract class LivingEntity extends Entity {
|
public abstract class LivingEntity extends Entity {
|
||||||
|
|
||||||
protected float yaw, pitch;
|
|
||||||
protected boolean onGround;
|
protected boolean onGround;
|
||||||
|
|
||||||
public LivingEntity() {
|
public LivingEntity(int entityType) {
|
||||||
super();
|
super(entityType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void update();
|
|
||||||
|
|
||||||
public boolean chunkTest(double x, double z) {
|
public boolean chunkTest(double x, double z) {
|
||||||
return getInstance().getChunk((int) Math.floor(x / 16), (int) Math.floor(z / 16)) == null;
|
return getInstance().getChunk((int) Math.floor(x / 16), (int) Math.floor(z / 16)) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getYaw() {
|
|
||||||
return yaw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getPitch() {
|
|
||||||
return pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
53
src/main/java/fr/themode/minestom/entity/ObjectEntity.java
Normal file
53
src/main/java/fr/themode/minestom/entity/ObjectEntity.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Viewable;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.EntityMetaDataPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.SpawnObjectPacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
public abstract class ObjectEntity extends Entity implements Viewable {
|
||||||
|
|
||||||
|
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
public ObjectEntity(int entityType) {
|
||||||
|
super(entityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int getData();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewer(Player player) {
|
||||||
|
this.viewers.add(player);
|
||||||
|
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||||
|
|
||||||
|
SpawnObjectPacket spawnObjectPacket = new SpawnObjectPacket();
|
||||||
|
spawnObjectPacket.entityId = getEntityId();
|
||||||
|
spawnObjectPacket.uuid = getUuid();
|
||||||
|
spawnObjectPacket.type = getEntityType();
|
||||||
|
spawnObjectPacket.x = getX();
|
||||||
|
spawnObjectPacket.y = getY();
|
||||||
|
spawnObjectPacket.z = getZ();
|
||||||
|
spawnObjectPacket.yaw = getYaw();
|
||||||
|
spawnObjectPacket.pitch = getPitch();
|
||||||
|
spawnObjectPacket.data = getData();
|
||||||
|
EntityMetaDataPacket entityMetaDataPacket = new EntityMetaDataPacket();
|
||||||
|
entityMetaDataPacket.entityId = getEntityId();
|
||||||
|
entityMetaDataPacket.data = getMetadataBuffer();
|
||||||
|
playerConnection.sendPacket(spawnObjectPacket);
|
||||||
|
playerConnection.sendPacket(entityMetaDataPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeViewer(Player player) {
|
||||||
|
this.viewers.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Player> getViewers() {
|
||||||
|
return Collections.unmodifiableSet(viewers);
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,24 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
import fr.themode.minestom.Main;
|
import fr.themode.minestom.Main;
|
||||||
|
import fr.themode.minestom.bossbar.BossBar;
|
||||||
|
import fr.themode.minestom.chat.Chat;
|
||||||
import fr.themode.minestom.instance.CustomBlock;
|
import fr.themode.minestom.instance.CustomBlock;
|
||||||
import fr.themode.minestom.inventory.Inventory;
|
import fr.themode.minestom.inventory.Inventory;
|
||||||
import fr.themode.minestom.inventory.PlayerInventory;
|
import fr.themode.minestom.inventory.PlayerInventory;
|
||||||
import fr.themode.minestom.item.ItemStack;
|
import fr.themode.minestom.item.ItemStack;
|
||||||
import fr.themode.minestom.net.packet.server.play.*;
|
import fr.themode.minestom.net.packet.server.play.*;
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
import fr.themode.minestom.utils.GroupedCollections;
|
||||||
import fr.themode.minestom.utils.Position;
|
import fr.themode.minestom.utils.Position;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
public class Player extends LivingEntity {
|
public class Player extends LivingEntity {
|
||||||
|
|
||||||
private boolean isSneaking;
|
|
||||||
private boolean isSprinting;
|
|
||||||
|
|
||||||
private long lastKeepAlive;
|
private long lastKeepAlive;
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
@ -30,8 +33,11 @@ public class Player extends LivingEntity {
|
|||||||
private Position targetBlockPosition;
|
private Position targetBlockPosition;
|
||||||
private long targetBlockTime;
|
private long targetBlockTime;
|
||||||
|
|
||||||
|
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
// TODO set proper UUID
|
// TODO set proper UUID
|
||||||
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
||||||
|
super(93); // TODO correct ?
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.playerConnection = playerConnection;
|
this.playerConnection = playerConnection;
|
||||||
@ -51,11 +57,25 @@ public class Player extends LivingEntity {
|
|||||||
sendBlockBreakAnimation(targetBlockPosition, stage);// TODO send to all near players
|
sendBlockBreakAnimation(targetBlockPosition, stage);// TODO send to all near players
|
||||||
if (stage > 9) {
|
if (stage > 9) {
|
||||||
instance.setBlock(targetBlockPosition.getX(), targetBlockPosition.getY(), targetBlockPosition.getZ(), (short) 0);
|
instance.setBlock(targetBlockPosition.getX(), targetBlockPosition.getY(), targetBlockPosition.getZ(), (short) 0);
|
||||||
testParticle(targetBlockPosition.getX() + 0.5f, targetBlockPosition.getY(), targetBlockPosition.getZ() + 0.5f);
|
testParticle(targetBlockPosition.getX() + 0.5f, targetBlockPosition.getY(), targetBlockPosition.getZ() + 0.5f, targetCustomBlock.getType());
|
||||||
resetTargetBlock();
|
resetTargetBlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Item pickup
|
||||||
|
if (instance != null) {
|
||||||
|
GroupedCollections<ObjectEntity> objectEntities = instance.getObjectEntities();
|
||||||
|
for (ObjectEntity objectEntity : objectEntities) {
|
||||||
|
if (objectEntity instanceof ItemEntity) {
|
||||||
|
float distance = getDistance(objectEntity);
|
||||||
|
if (distance <= 1) { // FIXME set correct value
|
||||||
|
getInventory().addItemStack(((ItemEntity) objectEntity).getItemStack());
|
||||||
|
objectEntity.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Multiplayer sync
|
// Multiplayer sync
|
||||||
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
||||||
@ -81,7 +101,7 @@ public class Player extends LivingEntity {
|
|||||||
playerConnection.sendPacket(breakAnimationPacket);
|
playerConnection.sendPacket(breakAnimationPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testParticle(float x, float y, float z) {
|
private void testParticle(float x, float y, float z, int blockId) {
|
||||||
ParticlePacket particlePacket = new ParticlePacket();
|
ParticlePacket particlePacket = new ParticlePacket();
|
||||||
particlePacket.particleId = 3; // Block particle
|
particlePacket.particleId = 3; // Block particle
|
||||||
particlePacket.longDistance = false;
|
particlePacket.longDistance = false;
|
||||||
@ -93,11 +113,12 @@ public class Player extends LivingEntity {
|
|||||||
particlePacket.offsetZ = 0.55f;
|
particlePacket.offsetZ = 0.55f;
|
||||||
particlePacket.particleData = 0.25f;
|
particlePacket.particleData = 0.25f;
|
||||||
particlePacket.particleCount = 100;
|
particlePacket.particleCount = 100;
|
||||||
|
particlePacket.blockId = blockId;
|
||||||
playerConnection.sendPacket(particlePacket);
|
playerConnection.sendPacket(particlePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(String message) {
|
public void sendMessage(String message) {
|
||||||
ChatMessagePacket chatMessagePacket = new ChatMessagePacket("{\"text\": \"" + message + "\"}", ChatMessagePacket.Position.CHAT);
|
ChatMessagePacket chatMessagePacket = new ChatMessagePacket(Chat.rawText(message), ChatMessagePacket.Position.CHAT);
|
||||||
playerConnection.sendPacket(chatMessagePacket);
|
playerConnection.sendPacket(chatMessagePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,6 +183,10 @@ public class Player extends LivingEntity {
|
|||||||
return targetCustomBlock;
|
return targetCustomBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<BossBar> getBossBars() {
|
||||||
|
return Collections.unmodifiableSet(bossBars);
|
||||||
|
}
|
||||||
|
|
||||||
public void openInventory(Inventory inventory) {
|
public void openInventory(Inventory inventory) {
|
||||||
if (inventory == null)
|
if (inventory == null)
|
||||||
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
|
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
|
||||||
@ -207,11 +232,11 @@ public class Player extends LivingEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void refreshSneaking(boolean sneaking) {
|
public void refreshSneaking(boolean sneaking) {
|
||||||
isSneaking = sneaking;
|
sneaking = sneaking;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshSprinting(boolean sprinting) {
|
public void refreshSprinting(boolean sprinting) {
|
||||||
isSprinting = sprinting;
|
sprinting = sprinting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshKeepAlive(long lastKeepAlive) {
|
public void refreshKeepAlive(long lastKeepAlive) {
|
||||||
@ -238,6 +263,14 @@ public class Player extends LivingEntity {
|
|||||||
this.targetBlockTime = 0;
|
this.targetBlockTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refreshAddBossbar(BossBar bossBar) {
|
||||||
|
this.bossBars.add(bossBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshRemoveBossbar(BossBar bossBar) {
|
||||||
|
this.bossBars.remove(bossBar);
|
||||||
|
}
|
||||||
|
|
||||||
public long getLastKeepAlive() {
|
public long getLastKeepAlive() {
|
||||||
return lastKeepAlive;
|
return lastKeepAlive;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,79 @@ import java.util.Arrays;
|
|||||||
public enum Biome {
|
public enum Biome {
|
||||||
|
|
||||||
OCEAN(0),
|
OCEAN(0),
|
||||||
|
DEEP_OCEAN(24),
|
||||||
|
FROZEN_OCEAN(10),
|
||||||
|
DEEP_FROZEN_OCEAN(50),
|
||||||
|
COLD_OCEAN(46),
|
||||||
|
DEEP_COLD_OCEAN(49),
|
||||||
|
LUKEWARM_OCEAN(45),
|
||||||
|
DEEP_LUKEWARM_OCEAN(48),
|
||||||
|
WARM_OCEAN(44),
|
||||||
|
DEEP_WARM_OCEAN(47),
|
||||||
|
RIVER(7),
|
||||||
|
FROZEN_RIVER(11),
|
||||||
|
BEACH(16),
|
||||||
|
STONE_SHORE(25),
|
||||||
|
SNOWY_BEACH(26),
|
||||||
|
FOREST(4),
|
||||||
|
WOODED_HILLS(18),
|
||||||
|
FLOWER_FOREST(132),
|
||||||
|
BIRCH_FOREST(27),
|
||||||
|
BIRCH_FOREST_HILLS(28),
|
||||||
|
TALL_BIRCH_FOREST(155),
|
||||||
|
TALL_BIRCH_HILLS(156),
|
||||||
|
DARK_FOREST(29),
|
||||||
|
DARK_FOREST_HILLS(157),
|
||||||
|
JUNGLE(21),
|
||||||
|
JUNGLE_HILLS(22),
|
||||||
|
MODIFIED_JUNGLE(149),
|
||||||
|
JUNGLE_EDGE(23),
|
||||||
|
MODIFIED_JUNGLE_EDGE(151),
|
||||||
|
BAMBOO_JUNGLE(168),
|
||||||
|
BAMBOO_JUNGLE_HILLS(169),
|
||||||
|
TAIGA(5),
|
||||||
|
TAIGA_HILLS(19),
|
||||||
|
TAIGA_MOUNTAINS(133),
|
||||||
|
SNOWY_TAIGA(30),
|
||||||
|
SNOWY_TAIGA_HILLS(31),
|
||||||
|
SNOWY_TAIGA_MOUNTAINS(158),
|
||||||
|
GIANT_TREE_TAIGA(32),
|
||||||
|
GIANT_TREE_TAIGA_HILLS(33),
|
||||||
|
GIANT_SPRUCE_TAIGA(160),
|
||||||
|
GIANT_SPRUCE_TAIGA_HILLS(161),
|
||||||
|
MUSHROOM_FIELDS(14),
|
||||||
|
MUSHROOM_FIELDS_SHORE(15),
|
||||||
|
SWAMP(6),
|
||||||
|
SWAMP_HILLS(134),
|
||||||
|
SAVANA(35),
|
||||||
|
SAVANA_PLATEAU(36),
|
||||||
|
SHATTERED_SAVANA(163),
|
||||||
|
SHATTERED_SAVANA_PLATEAU(164),
|
||||||
PLAINS(1),
|
PLAINS(1),
|
||||||
|
SUNFLOWER_PLAINS(129),
|
||||||
|
DESERT(2),
|
||||||
|
DESERT_HILLS(17),
|
||||||
|
DESERT_LAKES(130),
|
||||||
|
SNOWY_TUNDRA(12),
|
||||||
|
SNOWY_MOUNTAINS(13),
|
||||||
|
ICE_SPIKES(140),
|
||||||
|
MOUNTAINS(3),
|
||||||
|
WOODED_MOUTAINS(34),
|
||||||
|
GRAVELLY_MOUNTAINS(131),
|
||||||
|
MODIFIED_GRAVELLY_MOUNTAINS(162),
|
||||||
|
MOUNTAIN_EDGE(20),
|
||||||
|
BADLANDS(37),
|
||||||
|
BADLANDS_PLATEAU(39),
|
||||||
|
MODIFIED_BADLANDS_PLATEAU(167),
|
||||||
|
WOODED_BADLANDS_PLATEAU(38),
|
||||||
|
MODIFIED_WOODED_BADLANDS_PLATEAU(166),
|
||||||
|
ERODED_BADLANDS(165),
|
||||||
|
NETHER(8),
|
||||||
|
THE_END(9),
|
||||||
|
SMALL_END_ISLANDS(40),
|
||||||
|
END_MIDLANDS(41),
|
||||||
|
END_HIGHLANDS(42),
|
||||||
|
END_BARRENS(43),
|
||||||
VOID(127);
|
VOID(127);
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class BlockBatch {
|
public class BlockBatch implements BlockModifier {
|
||||||
|
|
||||||
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(2);
|
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(2);
|
||||||
|
|
||||||
@ -19,12 +19,9 @@ public class BlockBatch {
|
|||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void setBlock(int x, int y, int z, short blockId) {
|
public synchronized void setBlock(int x, int y, int z, short blockId) {
|
||||||
final int chunkX = Math.floorDiv(x, 16);
|
Chunk chunk = this.instance.getChunkAt(x, z);
|
||||||
final int chunkZ = Math.floorDiv(z, 16);
|
|
||||||
Chunk chunk = this.instance.getChunk(chunkX, chunkZ);
|
|
||||||
if (chunk == null)
|
|
||||||
chunk = this.instance.createChunk(Biome.VOID, chunkX, chunkZ);
|
|
||||||
List<BlockData> blockData = this.data.getOrDefault(chunk, new ArrayList<>());
|
List<BlockData> blockData = this.data.getOrDefault(chunk, new ArrayList<>());
|
||||||
|
|
||||||
BlockData data = new BlockData();
|
BlockData data = new BlockData();
|
||||||
@ -38,6 +35,22 @@ public class BlockBatch {
|
|||||||
this.data.put(chunk, blockData);
|
this.data.put(chunk, blockData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, String blockId) {
|
||||||
|
Chunk chunk = this.instance.getChunkAt(x, z);
|
||||||
|
List<BlockData> blockData = this.data.getOrDefault(chunk, new ArrayList<>());
|
||||||
|
|
||||||
|
BlockData data = new BlockData();
|
||||||
|
data.x = x % 16;
|
||||||
|
data.y = y;
|
||||||
|
data.z = z % 16;
|
||||||
|
data.blockIdentifier = blockId;
|
||||||
|
|
||||||
|
blockData.add(data);
|
||||||
|
|
||||||
|
this.data.put(chunk, blockData);
|
||||||
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
|
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
|
||||||
Chunk chunk = entry.getKey();
|
Chunk chunk = entry.getKey();
|
||||||
@ -57,9 +70,14 @@ public class BlockBatch {
|
|||||||
|
|
||||||
private int x, y, z;
|
private int x, y, z;
|
||||||
private short blockId;
|
private short blockId;
|
||||||
|
private String blockIdentifier;
|
||||||
|
|
||||||
public void apply(Chunk chunk) {
|
public void apply(Chunk chunk) {
|
||||||
chunk.setBlock((byte) x, (byte) y, (byte) z, blockId);
|
if (blockIdentifier == null) {
|
||||||
|
chunk.setBlock((byte) x, (byte) y, (byte) z, blockId);
|
||||||
|
} else {
|
||||||
|
chunk.setBlock((byte) x, (byte) y, (byte) z, blockIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
public class BlockManager {
|
public class BlockManager {
|
||||||
|
|
||||||
private Map<Integer, CustomBlock> blocksInternalId = new HashMap<>();
|
private Map<Short, CustomBlock> blocksInternalId = new HashMap<>();
|
||||||
private Map<String, CustomBlock> blocksId = new HashMap<>();
|
private Map<String, CustomBlock> blocksId = new HashMap<>();
|
||||||
|
|
||||||
public void registerBlock(Supplier<CustomBlock> blocks) {
|
public void registerBlock(Supplier<CustomBlock> blocks) {
|
||||||
CustomBlock customBlock = blocks.get();
|
CustomBlock customBlock = blocks.get();
|
||||||
String identifier = customBlock.getIdentifier();
|
String identifier = customBlock.getIdentifier();
|
||||||
int id = customBlock.getId();
|
short id = customBlock.getId();
|
||||||
this.blocksInternalId.put(id, customBlock);
|
this.blocksInternalId.put(id, customBlock);
|
||||||
this.blocksId.put(identifier, customBlock);
|
this.blocksId.put(identifier, customBlock);
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ public class BlockManager {
|
|||||||
return blocksId.get(identifier);
|
return blocksId.get(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomBlock getBlock(int id) {
|
public CustomBlock getBlock(short id) {
|
||||||
return blocksInternalId.get(id);
|
return blocksInternalId.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
public interface BlockModifier {
|
||||||
|
|
||||||
|
void setBlock(int x, int y, int z, short blockId);
|
||||||
|
|
||||||
|
void setBlock(int x, int y, int z, String blockId);
|
||||||
|
}
|
@ -3,6 +3,7 @@ package fr.themode.minestom.instance;
|
|||||||
import fr.themode.minestom.Main;
|
import fr.themode.minestom.Main;
|
||||||
import fr.themode.minestom.entity.Entity;
|
import fr.themode.minestom.entity.Entity;
|
||||||
import fr.themode.minestom.entity.EntityCreature;
|
import fr.themode.minestom.entity.EntityCreature;
|
||||||
|
import fr.themode.minestom.entity.ObjectEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -13,12 +14,13 @@ public class Chunk {
|
|||||||
|
|
||||||
private static final int CHUNK_SIZE = 16 * 256 * 16;
|
private static final int CHUNK_SIZE = 16 * 256 * 16;
|
||||||
|
|
||||||
|
protected Set<ObjectEntity> objectEntities = new CopyOnWriteArraySet<>();
|
||||||
protected Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
protected Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||||
protected Set<Player> players = new CopyOnWriteArraySet<>();
|
protected Set<Player> players = new CopyOnWriteArraySet<>();
|
||||||
private int chunkX, chunkZ;
|
private int chunkX, chunkZ;
|
||||||
private Biome biome;
|
private Biome biome;
|
||||||
private short[] blocksId = new short[CHUNK_SIZE];
|
private short[] blocksId = new short[CHUNK_SIZE];
|
||||||
private int[] customBlocks = new int[CHUNK_SIZE];
|
private short[] customBlocks = new short[CHUNK_SIZE];
|
||||||
|
|
||||||
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
||||||
this.biome = biome;
|
this.biome = biome;
|
||||||
@ -29,9 +31,7 @@ public class Chunk {
|
|||||||
protected void setBlock(byte x, byte y, byte z, short blockId) {
|
protected void setBlock(byte x, byte y, byte z, short blockId) {
|
||||||
int index = getIndex(x, y, z);
|
int index = getIndex(x, y, z);
|
||||||
this.blocksId[index] = blockId;
|
this.blocksId[index] = blockId;
|
||||||
if (blockId == 0) {
|
this.customBlocks[index] = 0;
|
||||||
this.customBlocks[index] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBlock(byte x, byte y, byte z, String blockId) {
|
protected void setBlock(byte x, byte y, byte z, String blockId) {
|
||||||
@ -49,7 +49,7 @@ public class Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CustomBlock getCustomBlock(byte x, byte y, byte z) {
|
public CustomBlock getCustomBlock(byte x, byte y, byte z) {
|
||||||
int id = this.customBlocks[getIndex(x, y, z)];
|
short id = this.customBlocks[getIndex(x, y, z)];
|
||||||
return id != 0 ? Main.getBlockManager().getBlock(id) : null;
|
return id != 0 ? Main.getBlockManager().getBlock(id) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +66,12 @@ public class Chunk {
|
|||||||
return;
|
return;
|
||||||
this.creatures.add((EntityCreature) entity);
|
this.creatures.add((EntityCreature) entity);
|
||||||
}
|
}
|
||||||
|
} else if (entity instanceof ObjectEntity) {
|
||||||
|
synchronized (objectEntities) {
|
||||||
|
if (this.objectEntities.contains(entity))
|
||||||
|
return;
|
||||||
|
this.objectEntities.add((ObjectEntity) entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +84,10 @@ public class Chunk {
|
|||||||
synchronized (creatures) {
|
synchronized (creatures) {
|
||||||
this.creatures.remove(entity);
|
this.creatures.remove(entity);
|
||||||
}
|
}
|
||||||
|
} else if (entity instanceof ObjectEntity) {
|
||||||
|
synchronized (objectEntities) {
|
||||||
|
this.objectEntities.remove(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +107,10 @@ public class Chunk {
|
|||||||
return chunkZ;
|
return chunkZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<ObjectEntity> getObjectEntities() {
|
||||||
|
return Collections.unmodifiableSet(objectEntities);
|
||||||
|
}
|
||||||
|
|
||||||
public Set<EntityCreature> getCreatures() {
|
public Set<EntityCreature> getCreatures() {
|
||||||
return Collections.unmodifiableSet(creatures);
|
return Collections.unmodifiableSet(creatures);
|
||||||
}
|
}
|
||||||
|
71
src/main/java/fr/themode/minestom/instance/ChunkBatch.java
Normal file
71
src/main/java/fr/themode/minestom/instance/ChunkBatch.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class ChunkBatch implements BlockModifier {
|
||||||
|
|
||||||
|
private static volatile ExecutorService batchesPool = Executors.newFixedThreadPool(3);
|
||||||
|
|
||||||
|
private Instance instance;
|
||||||
|
private Chunk chunk;
|
||||||
|
|
||||||
|
private List<BlockData> dataList = new ArrayList<>();
|
||||||
|
|
||||||
|
public ChunkBatch(Instance instance, Chunk chunk) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.chunk = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, short blockId) {
|
||||||
|
BlockData data = new BlockData();
|
||||||
|
data.x = (byte) x;
|
||||||
|
data.y = (byte) y;
|
||||||
|
data.z = (byte) z;
|
||||||
|
data.blockId = blockId;
|
||||||
|
|
||||||
|
this.dataList.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, String blockId) {
|
||||||
|
BlockData data = new BlockData();
|
||||||
|
data.x = (byte) x;
|
||||||
|
data.y = (byte) y;
|
||||||
|
data.z = (byte) z;
|
||||||
|
data.blockIdentifier = blockId;
|
||||||
|
|
||||||
|
this.dataList.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
synchronized (chunk) {
|
||||||
|
batchesPool.submit(() -> {
|
||||||
|
for (BlockData data : dataList) {
|
||||||
|
data.apply(chunk);
|
||||||
|
}
|
||||||
|
instance.sendChunkUpdate(chunk); // TODO partial chunk data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlockData {
|
||||||
|
|
||||||
|
private byte x, y, z;
|
||||||
|
private short blockId;
|
||||||
|
private String blockIdentifier;
|
||||||
|
|
||||||
|
public void apply(Chunk chunk) {
|
||||||
|
if (blockIdentifier == null) {
|
||||||
|
chunk.setBlock(x, y, z, blockId);
|
||||||
|
} else {
|
||||||
|
chunk.setBlock(x, y, z, blockIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
public abstract class ChunkGenerator {
|
||||||
|
|
||||||
|
public abstract void generateChunkData(ChunkBatch batch, int chunkX, int chunkZ);
|
||||||
|
|
||||||
|
public abstract Biome getBiome(int chunkX, int chunkZ);
|
||||||
|
|
||||||
|
}
|
@ -4,14 +4,18 @@ import fr.themode.minestom.entity.Player;
|
|||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* option to set the global as "global breaking" meaning that multiple players mining the same block will break it faster (cumulation)
|
||||||
|
*/
|
||||||
public abstract class CustomBlock {
|
public abstract class CustomBlock {
|
||||||
|
|
||||||
private static final AtomicInteger idCounter = new AtomicInteger();
|
private static final AtomicInteger idCounter = new AtomicInteger();
|
||||||
|
|
||||||
private int id;
|
private short id;
|
||||||
|
|
||||||
public CustomBlock() {
|
public CustomBlock() {
|
||||||
this.id = idCounter.incrementAndGet();
|
this.id = (short) idCounter.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract short getType();
|
public abstract short getType();
|
||||||
@ -23,7 +27,7 @@ public abstract class CustomBlock {
|
|||||||
*/
|
*/
|
||||||
public abstract int getBreakDelay(Player player);
|
public abstract int getBreakDelay(Player player);
|
||||||
|
|
||||||
public int getId() {
|
public short getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,37 @@
|
|||||||
package fr.themode.minestom.instance;
|
package fr.themode.minestom.instance;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Viewable;
|
||||||
import fr.themode.minestom.entity.Entity;
|
import fr.themode.minestom.entity.Entity;
|
||||||
import fr.themode.minestom.entity.EntityCreature;
|
import fr.themode.minestom.entity.EntityCreature;
|
||||||
|
import fr.themode.minestom.entity.ObjectEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
import fr.themode.minestom.net.packet.server.play.ChunkDataPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
|
||||||
import fr.themode.minestom.utils.GroupedCollections;
|
import fr.themode.minestom.utils.GroupedCollections;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
|
|
||||||
public class Instance {
|
public class Instance implements BlockModifier {
|
||||||
|
|
||||||
private UUID uniqueId;
|
private UUID uniqueId;
|
||||||
|
|
||||||
|
private GroupedCollections<ObjectEntity> objectEntities = new GroupedCollections<>(new CopyOnWriteArrayList<>());
|
||||||
private GroupedCollections<EntityCreature> creatures = new GroupedCollections<>(new CopyOnWriteArrayList());
|
private GroupedCollections<EntityCreature> creatures = new GroupedCollections<>(new CopyOnWriteArrayList());
|
||||||
private GroupedCollections<Player> players = new GroupedCollections<>(new CopyOnWriteArrayList());
|
private GroupedCollections<Player> players = new GroupedCollections<>(new CopyOnWriteArrayList());
|
||||||
|
|
||||||
private Set<Chunk> chunksSet = new CopyOnWriteArraySet<>(); // TODO change for a map with position as key and chunk as value
|
private ChunkGenerator chunkGenerator;
|
||||||
|
private Map<Long, Chunk> chunks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public Instance(UUID uniqueId) {
|
public Instance(UUID uniqueId) {
|
||||||
this.uniqueId = uniqueId;
|
this.uniqueId = uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void setBlock(int x, int y, int z, short blockId) {
|
public synchronized void setBlock(int x, int y, int z, short blockId) {
|
||||||
Chunk chunk = getChunkAt(x, z);
|
Chunk chunk = getChunkAt(x, z);
|
||||||
synchronized (chunk) {
|
synchronized (chunk) {
|
||||||
@ -33,6 +40,7 @@ public class Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void setBlock(int x, int y, int z, String blockId) {
|
public synchronized void setBlock(int x, int y, int z, String blockId) {
|
||||||
Chunk chunk = getChunkAt(x, z);
|
Chunk chunk = getChunkAt(x, z);
|
||||||
synchronized (chunk) {
|
synchronized (chunk) {
|
||||||
@ -41,6 +49,11 @@ public class Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Chunk loadChunk(int chunkX, int chunkZ) {
|
||||||
|
Chunk chunk = getChunk(chunkX, chunkZ);
|
||||||
|
return chunk == null ? createChunk(chunkX, chunkZ) : chunk; // TODO load from file
|
||||||
|
}
|
||||||
|
|
||||||
public short getBlockId(int x, int y, int z) {
|
public short getBlockId(int x, int y, int z) {
|
||||||
Chunk chunk = getChunkAt(x, z);
|
Chunk chunk = getChunkAt(x, z);
|
||||||
return chunk.getBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
|
return chunk.getBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
|
||||||
@ -56,11 +69,7 @@ public class Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Chunk getChunk(int chunkX, int chunkZ) {
|
public Chunk getChunk(int chunkX, int chunkZ) {
|
||||||
for (Chunk chunk : getChunks()) {
|
return chunks.getOrDefault(getChunkKey(chunkX, chunkZ), null);
|
||||||
if (chunk.getChunkX() == chunkX && chunk.getChunkZ() == chunkZ)
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
return createChunk(Biome.VOID, chunkX, chunkZ); // TODO generation API
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chunk getChunkAt(double x, double z) {
|
public Chunk getChunkAt(double x, double z) {
|
||||||
@ -69,8 +78,12 @@ public class Instance {
|
|||||||
return getChunk(chunkX, chunkZ);
|
return getChunk(chunkX, chunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Chunk> getChunks() {
|
public void setChunkGenerator(ChunkGenerator chunkGenerator) {
|
||||||
return Collections.unmodifiableSet(chunksSet);
|
this.chunkGenerator = chunkGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Chunk> getChunks() {
|
||||||
|
return Collections.unmodifiableCollection(chunks.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEntity(Entity entity) {
|
public void addEntity(Entity entity) {
|
||||||
@ -79,9 +92,10 @@ public class Instance {
|
|||||||
lastInstance.removeEntity(entity);
|
lastInstance.removeEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity instanceof EntityCreature) {
|
if (entity instanceof Viewable) {
|
||||||
// TODO based on distance with players
|
// TODO based on distance with players
|
||||||
getPlayers().forEach(p -> ((EntityCreature) entity).addViewer(p));
|
Viewable viewable = (Viewable) entity;
|
||||||
|
getPlayers().forEach(p -> ((Viewable) entity).addViewer(p));
|
||||||
} else if (entity instanceof Player) {
|
} else if (entity instanceof Player) {
|
||||||
Player player = (Player) entity;
|
Player player = (Player) entity;
|
||||||
sendChunks(player);
|
sendChunks(player);
|
||||||
@ -97,15 +111,23 @@ public class Instance {
|
|||||||
if (entityInstance == null || entityInstance != this)
|
if (entityInstance == null || entityInstance != this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (entity instanceof EntityCreature) {
|
if (entity instanceof Viewable) {
|
||||||
EntityCreature creature = (EntityCreature) entity;
|
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket();
|
||||||
creature.getViewers().forEach(p -> creature.removeViewer(p));
|
destroyEntitiesPacket.entityIds = new int[]{entity.getEntityId()};
|
||||||
|
|
||||||
|
Viewable viewable = (Viewable) entity;
|
||||||
|
viewable.getViewers().forEach(p -> p.getPlayerConnection().sendPacket(destroyEntitiesPacket)); // TODO destroy batch
|
||||||
|
viewable.getViewers().forEach(p -> viewable.removeViewer(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk chunk = getChunkAt(entity.getX(), entity.getZ());
|
Chunk chunk = getChunkAt(entity.getX(), entity.getZ());
|
||||||
chunk.removeEntity(entity);
|
chunk.removeEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GroupedCollections<ObjectEntity> getObjectEntities() {
|
||||||
|
return objectEntities;
|
||||||
|
}
|
||||||
|
|
||||||
public GroupedCollections<EntityCreature> getCreatures() {
|
public GroupedCollections<EntityCreature> getCreatures() {
|
||||||
return creatures;
|
return creatures;
|
||||||
}
|
}
|
||||||
@ -118,14 +140,25 @@ public class Instance {
|
|||||||
return uniqueId;
|
return uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Chunk createChunk(Biome biome, int chunkX, int chunkZ) {
|
protected Chunk createChunk(int chunkX, int chunkZ) {
|
||||||
|
Biome biome = chunkGenerator != null ? chunkGenerator.getBiome(chunkX, chunkZ) : Biome.VOID;
|
||||||
Chunk chunk = new Chunk(biome, chunkX, chunkZ);
|
Chunk chunk = new Chunk(biome, chunkX, chunkZ);
|
||||||
|
this.objectEntities.addCollection(chunk.objectEntities);
|
||||||
this.creatures.addCollection(chunk.creatures);
|
this.creatures.addCollection(chunk.creatures);
|
||||||
this.players.addCollection(chunk.players);
|
this.players.addCollection(chunk.players);
|
||||||
this.chunksSet.add(chunk);
|
this.chunks.put(getChunkKey(chunkX, chunkZ), chunk);
|
||||||
|
if (chunkGenerator != null) {
|
||||||
|
ChunkBatch chunkBatch = createChunkBatch(chunk);
|
||||||
|
chunkGenerator.generateChunkData(chunkBatch, chunkX, chunkZ);
|
||||||
|
chunkBatch.flush();
|
||||||
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ChunkBatch createChunkBatch(Chunk chunk) {
|
||||||
|
return new ChunkBatch(this, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
protected void sendChunkUpdate(Chunk chunk) {
|
protected void sendChunkUpdate(Chunk chunk) {
|
||||||
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
|
ChunkDataPacket chunkDataPacket = new ChunkDataPacket();
|
||||||
chunkDataPacket.fullChunk = false; // TODO partial chunk data
|
chunkDataPacket.fullChunk = false; // TODO partial chunk data
|
||||||
@ -141,4 +174,8 @@ public class Instance {
|
|||||||
player.getPlayerConnection().sendPacket(chunkDataPacket);
|
player.getPlayerConnection().sendPacket(chunkDataPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getChunkKey(int chunkX, int chunkZ) {
|
||||||
|
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package fr.themode.minestom.instance.demo;
|
||||||
|
|
||||||
|
import fr.themode.minestom.instance.Biome;
|
||||||
|
import fr.themode.minestom.instance.ChunkBatch;
|
||||||
|
import fr.themode.minestom.instance.ChunkGenerator;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class ChunkGeneratorDemo extends ChunkGenerator {
|
||||||
|
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateChunkData(ChunkBatch batch, int chunkX, int chunkZ) {
|
||||||
|
for (byte x = 0; x < 16; x++)
|
||||||
|
for (byte z = 0; z < 16; z++) {
|
||||||
|
if (random.nextInt(2) == 1) {
|
||||||
|
batch.setBlock(x, (byte) 4, z, (short) 10);
|
||||||
|
} else {
|
||||||
|
batch.setBlock(x, (byte) 4, z, "custom_block");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Biome getBiome(int chunkX, int chunkZ) {
|
||||||
|
return Biome.PLAINS;
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,12 @@ public class StoneBlock extends CustomBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getType() {
|
public short getType() {
|
||||||
return 1;
|
return 117;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return "stone_block";
|
return "custom_block";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.themode.minestom.inventory;
|
package fr.themode.minestom.inventory;
|
||||||
|
|
||||||
|
import fr.themode.minestom.Viewable;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
import fr.themode.minestom.item.ItemStack;
|
import fr.themode.minestom.item.ItemStack;
|
||||||
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
|
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
|
||||||
@ -12,7 +13,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class Inventory implements InventoryModifier, InventoryClickHandler {
|
public class Inventory implements InventoryModifier, InventoryClickHandler, Viewable {
|
||||||
|
|
||||||
private static AtomicInteger lastInventoryId = new AtomicInteger();
|
private static AtomicInteger lastInventoryId = new AtomicInteger();
|
||||||
|
|
||||||
@ -81,16 +82,19 @@ public class Inventory implements InventoryModifier, InventoryClickHandler {
|
|||||||
getViewers().forEach(p -> p.getPlayerConnection().sendPacket(windowItemsPacket));
|
getViewers().forEach(p -> p.getPlayerConnection().sendPacket(windowItemsPacket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<Player> getViewers() {
|
public Set<Player> getViewers() {
|
||||||
return Collections.unmodifiableSet(viewers);
|
return Collections.unmodifiableSet(viewers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addViewer(Player player) {
|
public void addViewer(Player player) {
|
||||||
this.viewers.add(player);
|
this.viewers.add(player);
|
||||||
WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
|
WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
|
||||||
player.getPlayerConnection().sendPacket(windowItemsPacket);
|
player.getPlayerConnection().sendPacket(windowItemsPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeViewer(Player player) {
|
public void removeViewer(Player player) {
|
||||||
this.viewers.remove(player);
|
this.viewers.remove(player);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,15 @@ package fr.themode.minestom.net.packet.client.login;
|
|||||||
|
|
||||||
import fr.adamaq01.ozao.net.Buffer;
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
import fr.themode.minestom.Main;
|
import fr.themode.minestom.Main;
|
||||||
|
import fr.themode.minestom.bossbar.BarColor;
|
||||||
|
import fr.themode.minestom.bossbar.BarDivision;
|
||||||
|
import fr.themode.minestom.bossbar.BossBar;
|
||||||
import fr.themode.minestom.entity.GameMode;
|
import fr.themode.minestom.entity.GameMode;
|
||||||
|
import fr.themode.minestom.entity.ItemEntity;
|
||||||
import fr.themode.minestom.entity.Player;
|
import fr.themode.minestom.entity.Player;
|
||||||
import fr.themode.minestom.entity.demo.ChickenCreature;
|
import fr.themode.minestom.entity.demo.ChickenCreature;
|
||||||
import fr.themode.minestom.instance.Instance;
|
import fr.themode.minestom.instance.Instance;
|
||||||
|
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
|
||||||
import fr.themode.minestom.inventory.Inventory;
|
import fr.themode.minestom.inventory.Inventory;
|
||||||
import fr.themode.minestom.inventory.InventoryType;
|
import fr.themode.minestom.inventory.InventoryType;
|
||||||
import fr.themode.minestom.inventory.PlayerInventory;
|
import fr.themode.minestom.inventory.PlayerInventory;
|
||||||
@ -34,11 +39,17 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
private static Instance instance;
|
private static Instance instance;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
||||||
instance = Main.getInstanceManager().createInstance();
|
instance = Main.getInstanceManager().createInstance();
|
||||||
for (int x = -64; x < 64; x++)
|
instance.setChunkGenerator(chunkGeneratorDemo);
|
||||||
for (int z = -64; z < 64; z++) {
|
int loopStart = -4;
|
||||||
instance.setBlock(x, 4, z, (short) 10);
|
int loopEnd = 4;
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
for (int x = loopStart; x < loopEnd; x++)
|
||||||
|
for (int z = loopStart; z < loopEnd; z++) {
|
||||||
|
instance.loadChunk(x, z);
|
||||||
}
|
}
|
||||||
|
System.out.println("Time to load all chunks: " + (System.currentTimeMillis() - time) + " ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -106,7 +117,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
|
|
||||||
for (int x = 0; x < 4; x++)
|
for (int x = 0; x < 4; x++)
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
// TODO test entity
|
|
||||||
ChickenCreature chickenCreature = new ChickenCreature();
|
ChickenCreature chickenCreature = new ChickenCreature();
|
||||||
chickenCreature.refreshPosition(0 + (double) x * 1, 5, 0 + (double) z * 1);
|
chickenCreature.refreshPosition(0 + (double) x * 1, 5, 0 + (double) z * 1);
|
||||||
chickenCreature.setInstance(instance);
|
chickenCreature.setInstance(instance);
|
||||||
@ -151,6 +161,18 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
player.openInventory(inv);
|
player.openInventory(inv);
|
||||||
inv.setItemStack(1, new ItemStack(1, (byte) 2));
|
inv.setItemStack(1, new ItemStack(1, (byte) 2));
|
||||||
inv.updateItems();
|
inv.updateItems();
|
||||||
|
|
||||||
|
BossBar bossBar = new BossBar("Le titre", BarColor.BLUE, BarDivision.SEGMENT_12);
|
||||||
|
bossBar.setProgress(0.75f);
|
||||||
|
bossBar.addViewer(player);
|
||||||
|
|
||||||
|
for (int x = 0; x < 4; x++)
|
||||||
|
for (int z = 0; z < 4; z++) {
|
||||||
|
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
|
||||||
|
itemEntity.refreshPosition(x, 5, z);
|
||||||
|
itemEntity.setInstance(instance);
|
||||||
|
//itemEntity.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +25,7 @@ public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
|
|||||||
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
|
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
|
||||||
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
|
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
|
||||||
|
|
||||||
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "stone_block");
|
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "custom_block");
|
||||||
player.getInventory().refreshSlot(player.getHeldSlot());
|
player.getInventory().refreshSlot(player.getHeldSlot());
|
||||||
// TODO consume block in hand for survival players
|
// TODO consume block in hand for survival players
|
||||||
/*Random random = new Random();
|
/*Random random = new Random();
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.bossbar.BarColor;
|
||||||
|
import fr.themode.minestom.bossbar.BarDivision;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class BossBarPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public UUID uuid;
|
||||||
|
public Action action;
|
||||||
|
|
||||||
|
public String title;
|
||||||
|
public float health;
|
||||||
|
public BarColor color;
|
||||||
|
public BarDivision division;
|
||||||
|
public byte flags;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeUuid(buffer, uuid);
|
||||||
|
Utils.writeVarInt(buffer, action.ordinal());
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case ADD:
|
||||||
|
Utils.writeString(buffer, title);
|
||||||
|
buffer.putFloat(health);
|
||||||
|
Utils.writeVarInt(buffer, color.ordinal());
|
||||||
|
Utils.writeVarInt(buffer, division.ordinal());
|
||||||
|
buffer.putByte(flags);
|
||||||
|
break;
|
||||||
|
case REMOVE:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case UPDATE_HEALTH:
|
||||||
|
buffer.putFloat(health);
|
||||||
|
break;
|
||||||
|
case UPDATE_TITLE:
|
||||||
|
Utils.writeString(buffer, title);
|
||||||
|
break;
|
||||||
|
case UPDATE_STYLE:
|
||||||
|
Utils.writeVarInt(buffer, color.ordinal());
|
||||||
|
Utils.writeVarInt(buffer, division.ordinal());
|
||||||
|
break;
|
||||||
|
case UPDATE_FLAGS:
|
||||||
|
buffer.putByte(flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x0C;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
ADD,
|
||||||
|
REMOVE,
|
||||||
|
UPDATE_HEALTH,
|
||||||
|
UPDATE_TITLE,
|
||||||
|
UPDATE_STYLE,
|
||||||
|
UPDATE_FLAGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class DisplayScoreboardPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public byte position;
|
||||||
|
public String scoreName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
buffer.putByte(position);
|
||||||
|
Utils.writeString(buffer, scoreName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x42;
|
||||||
|
}
|
||||||
|
}
|
@ -7,10 +7,13 @@ import fr.themode.minestom.utils.Utils;
|
|||||||
public class EntityMetaDataPacket implements ServerPacket {
|
public class EntityMetaDataPacket implements ServerPacket {
|
||||||
|
|
||||||
public int entityId;
|
public int entityId;
|
||||||
|
public Buffer data;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Buffer buffer) {
|
public void write(Buffer buffer) {
|
||||||
Utils.writeVarInt(buffer, entityId);
|
Utils.writeVarInt(buffer, entityId);
|
||||||
|
buffer.putBuffer(data);
|
||||||
|
buffer.putByte((byte) 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -12,7 +12,8 @@ public class ParticlePacket implements ServerPacket {
|
|||||||
public float offsetX, offsetY, offsetZ;
|
public float offsetX, offsetY, offsetZ;
|
||||||
public float particleData;
|
public float particleData;
|
||||||
public int particleCount;
|
public int particleCount;
|
||||||
// TODO data
|
|
||||||
|
public int blockId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Buffer buffer) {
|
public void write(Buffer buffer) {
|
||||||
@ -26,7 +27,8 @@ public class ParticlePacket implements ServerPacket {
|
|||||||
buffer.putFloat(offsetZ);
|
buffer.putFloat(offsetZ);
|
||||||
buffer.putFloat(particleData);
|
buffer.putFloat(particleData);
|
||||||
buffer.putInt(particleCount);
|
buffer.putInt(particleCount);
|
||||||
Utils.writeVarInt(buffer, 1);
|
if (particleId == 3)
|
||||||
|
Utils.writeVarInt(buffer, blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class ScoreboardObjectivePacket implements ServerPacket {
|
||||||
|
|
||||||
|
public String objectiveName;
|
||||||
|
public byte mode;
|
||||||
|
public String objectiveValue;
|
||||||
|
public int type;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeString(buffer, objectiveName);
|
||||||
|
buffer.putByte(mode);
|
||||||
|
if (mode == 0 || mode == 2) {
|
||||||
|
Utils.writeString(buffer, objectiveValue);
|
||||||
|
Utils.writeVarInt(buffer, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x49;
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,7 @@ public class SpawnMobPacket implements ServerPacket {
|
|||||||
@Override
|
@Override
|
||||||
public void write(Buffer buffer) {
|
public void write(Buffer buffer) {
|
||||||
Utils.writeVarInt(buffer, entityId);
|
Utils.writeVarInt(buffer, entityId);
|
||||||
buffer.putLong(entityUuid.getMostSignificantBits());
|
Utils.writeUuid(buffer, entityUuid);
|
||||||
buffer.putLong(entityUuid.getLeastSignificantBits());
|
|
||||||
Utils.writeVarInt(buffer, entityType);
|
Utils.writeVarInt(buffer, entityType);
|
||||||
buffer.putDouble(x);
|
buffer.putDouble(x);
|
||||||
buffer.putDouble(y);
|
buffer.putDouble(y);
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SpawnObjectPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public int entityId;
|
||||||
|
public UUID uuid;
|
||||||
|
public int type;
|
||||||
|
public double x, y, z;
|
||||||
|
public float yaw, pitch;
|
||||||
|
public int data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeVarInt(buffer, entityId);
|
||||||
|
Utils.writeUuid(buffer, uuid);
|
||||||
|
Utils.writeVarInt(buffer, type);
|
||||||
|
buffer.putDouble(x);
|
||||||
|
buffer.putDouble(y);
|
||||||
|
buffer.putDouble(z);
|
||||||
|
buffer.putFloat(yaw);
|
||||||
|
buffer.putFloat(pitch);
|
||||||
|
buffer.putInt(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class TeamsPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public String teamName;
|
||||||
|
public Action action;
|
||||||
|
|
||||||
|
public String teamDisplayName;
|
||||||
|
public byte friendlyFlags;
|
||||||
|
public String nameTagVisibility;
|
||||||
|
public String collisionRule;
|
||||||
|
public int teamColor;
|
||||||
|
public String teamPrefix;
|
||||||
|
public String teamSuffix;
|
||||||
|
public int entityCount;
|
||||||
|
public String[] entities;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeString(buffer, teamName);
|
||||||
|
buffer.putByte((byte) action.ordinal());
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case CREATE_TEAM:
|
||||||
|
case UPDATE_TEAM_INFO:
|
||||||
|
Utils.writeString(buffer, teamDisplayName);
|
||||||
|
buffer.putByte(friendlyFlags);
|
||||||
|
Utils.writeString(buffer, nameTagVisibility);
|
||||||
|
Utils.writeString(buffer, collisionRule);
|
||||||
|
Utils.writeVarInt(buffer, teamColor);
|
||||||
|
Utils.writeString(buffer, teamPrefix);
|
||||||
|
Utils.writeString(buffer, teamSuffix);
|
||||||
|
break;
|
||||||
|
case REMOVE_TEAM:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ADD_PLAYERS_TEAM:
|
||||||
|
case REMOVE_PLAYERS_TEAM:
|
||||||
|
Utils.writeVarInt(buffer, entities.length);
|
||||||
|
for (String entity : entities) {
|
||||||
|
Utils.writeString(buffer, entity);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == Action.CREATE_TEAM) {
|
||||||
|
Utils.writeVarInt(buffer, entities.length);
|
||||||
|
for (String entity : entities) {
|
||||||
|
Utils.writeString(buffer, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x4B;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
|
CREATE_TEAM,
|
||||||
|
REMOVE_TEAM,
|
||||||
|
UPDATE_TEAM_INFO,
|
||||||
|
ADD_PLAYERS_TEAM,
|
||||||
|
REMOVE_PLAYERS_TEAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class UpdateScorePacket implements ServerPacket {
|
||||||
|
|
||||||
|
public String entityName;
|
||||||
|
public byte action;
|
||||||
|
public String objectiveName;
|
||||||
|
public int value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeString(buffer, entityName);
|
||||||
|
buffer.putByte(action);
|
||||||
|
Utils.writeString(buffer, objectiveName);
|
||||||
|
if (action != 1) {
|
||||||
|
Utils.writeVarInt(buffer, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x4C;
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import fr.themode.minestom.item.ItemStack;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
@ -136,6 +137,11 @@ public class Utils {
|
|||||||
return new Position(x, y, z);
|
return new Position(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeUuid(Buffer buffer, UUID uuid) {
|
||||||
|
buffer.putLong(uuid.getMostSignificantBits());
|
||||||
|
buffer.putLong(uuid.getLeastSignificantBits());
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeItemStack(Buffer buffer, ItemStack itemStack) {
|
public static void writeItemStack(Buffer buffer, ItemStack itemStack) {
|
||||||
if (itemStack == null) {
|
if (itemStack == null) {
|
||||||
buffer.putBoolean(false);
|
buffer.putBoolean(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user