mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 19:47:44 +01:00
Added gravity
This commit is contained in:
parent
0a732034c2
commit
8b95e3881d
@ -36,7 +36,6 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
|
|
||||||
protected Instance instance;
|
protected Instance instance;
|
||||||
protected Position position;
|
protected Position position;
|
||||||
protected boolean onGround;
|
|
||||||
protected float lastX, lastY, lastZ;
|
protected float lastX, lastY, lastZ;
|
||||||
protected float lastYaw, lastPitch;
|
protected float lastYaw, lastPitch;
|
||||||
private int id;
|
private int id;
|
||||||
@ -45,6 +44,9 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
// Velocity
|
// Velocity
|
||||||
// TODO gravity implementation for entity other than players
|
// TODO gravity implementation for entity other than players
|
||||||
protected Vector velocity = new Vector(); // Movement in block per second
|
protected Vector velocity = new Vector(); // Movement in block per second
|
||||||
|
protected float gravityDragPerTick;
|
||||||
|
private int gravityTickCounter;
|
||||||
|
|
||||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||||
private Data data;
|
private Data data;
|
||||||
private Set<Entity> passengers = new CopyOnWriteArraySet<>();
|
private Set<Entity> passengers = new CopyOnWriteArraySet<>();
|
||||||
@ -104,6 +106,8 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
// Called when entity a new instance is set
|
// Called when entity a new instance is set
|
||||||
public abstract void spawn();
|
public abstract void spawn();
|
||||||
|
|
||||||
|
public abstract boolean isOnGround();
|
||||||
|
|
||||||
public void teleport(Position position, Runnable callback) {
|
public void teleport(Position position, Runnable callback) {
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
throw new IllegalStateException("You need to use Entity#setInstance before teleporting an entity!");
|
throw new IllegalStateException("You need to use Entity#setInstance before teleporting an entity!");
|
||||||
@ -114,7 +118,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
||||||
entityTeleportPacket.entityId = getEntityId();
|
entityTeleportPacket.entityId = getEntityId();
|
||||||
entityTeleportPacket.position = position;
|
entityTeleportPacket.position = position;
|
||||||
entityTeleportPacket.onGround = onGround;
|
entityTeleportPacket.onGround = isOnGround();
|
||||||
sendPacketToViewers(entityTeleportPacket);
|
sendPacketToViewers(entityTeleportPacket);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,7 +129,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
callback.run();
|
callback.run();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (isChunkUnloaded(position.getX(), position.getZ()))
|
if (ChunkUtils.isChunkUnloaded(instance, position.getX(), position.getZ()))
|
||||||
return;
|
return;
|
||||||
runnable.run();
|
runnable.run();
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
@ -210,6 +214,36 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gravity
|
||||||
|
if (!(this instanceof Player) && !noGravity && gravityDragPerTick != 0) { // Players do manage gravity client-side
|
||||||
|
Position position = getPosition();
|
||||||
|
if (!isOnGround()) {
|
||||||
|
float strength = gravityDragPerTick * gravityTickCounter;
|
||||||
|
|
||||||
|
int firstBlock = 0;
|
||||||
|
for (int y = (int) position.getY(); y > 0; y--) {
|
||||||
|
short blockId = instance.getBlockId((int) position.getX(), y, (int) position.getZ());
|
||||||
|
if (blockId != 0) {
|
||||||
|
firstBlock = y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float newY = position.getY() - strength;
|
||||||
|
newY = Math.max(newY, firstBlock);
|
||||||
|
refreshPosition(position.getX(), newY, position.getZ());
|
||||||
|
gravityTickCounter++;
|
||||||
|
if (isOnGround()) { // Round Y axis when gravity movement is done
|
||||||
|
refreshPosition(position.getX(), Math.round(position.getY()), position.getZ());
|
||||||
|
gravityTickCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this instanceof EntityCreature) // Objects are automatically updated client side
|
||||||
|
teleport(getPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// Scheduled synchronization
|
// Scheduled synchronization
|
||||||
@ -295,6 +329,10 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
this.velocityTime = 0;
|
this.velocityTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGravity(float gravityDragPerTick) {
|
||||||
|
this.gravityDragPerTick = gravityDragPerTick;
|
||||||
|
}
|
||||||
|
|
||||||
public float getDistance(Entity entity) {
|
public float getDistance(Entity entity) {
|
||||||
return getPosition().getDistance(entity.getPosition());
|
return getPosition().getDistance(entity.getPosition());
|
||||||
}
|
}
|
||||||
@ -360,18 +398,26 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
sendMetadataIndex(0);
|
sendMetadataIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOnFire() {
|
||||||
|
return onFire;
|
||||||
|
}
|
||||||
|
|
||||||
public void setGlowing(boolean glowing) {
|
public void setGlowing(boolean glowing) {
|
||||||
this.glowing = glowing;
|
this.glowing = glowing;
|
||||||
sendMetadataIndex(0);
|
sendMetadataIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGlowing() {
|
||||||
|
return glowing;
|
||||||
|
}
|
||||||
|
|
||||||
public void setNoGravity(boolean noGravity) {
|
public void setNoGravity(boolean noGravity) {
|
||||||
this.noGravity = noGravity;
|
this.noGravity = noGravity;
|
||||||
sendMetadataIndex(5);
|
sendMetadataIndex(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChunkUnloaded(float x, float z) {
|
public boolean hasNoGravity() {
|
||||||
return getInstance().getChunk((int) Math.floor(x / 16), (int) Math.floor(z / 16)) == null;
|
return noGravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPosition(float x, float y, float z) {
|
public void refreshPosition(float x, float y, float z) {
|
||||||
@ -436,6 +482,10 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refreshPosition(Position position) {
|
||||||
|
refreshPosition(position.getX(), position.getY(), position.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshView(float yaw, float pitch) {
|
public void refreshView(float yaw, float pitch) {
|
||||||
this.lastYaw = position.getYaw();
|
this.lastYaw = position.getYaw();
|
||||||
this.lastPitch = position.getPitch();
|
this.lastPitch = position.getPitch();
|
||||||
@ -554,7 +604,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
||||||
entityTeleportPacket.entityId = getEntityId();
|
entityTeleportPacket.entityId = getEntityId();
|
||||||
entityTeleportPacket.position = getPosition();
|
entityTeleportPacket.position = getPosition();
|
||||||
entityTeleportPacket.onGround = onGround;
|
entityTeleportPacket.onGround = isOnGround();
|
||||||
sendPacketToViewers(entityTeleportPacket);
|
sendPacketToViewers(entityTeleportPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,15 @@ import fr.themode.minestom.net.packet.server.play.EntityPacket;
|
|||||||
import fr.themode.minestom.net.packet.server.play.EntityRelativeMovePacket;
|
import fr.themode.minestom.net.packet.server.play.EntityRelativeMovePacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.SpawnMobPacket;
|
import fr.themode.minestom.net.packet.server.play.SpawnMobPacket;
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
import fr.themode.minestom.utils.ChunkUtils;
|
||||||
|
import fr.themode.minestom.utils.EntityUtils;
|
||||||
import fr.themode.minestom.utils.Position;
|
import fr.themode.minestom.utils.Position;
|
||||||
|
|
||||||
// TODO viewers synchronization each X ticks?
|
// TODO viewers synchronization each X ticks?
|
||||||
public abstract class EntityCreature extends LivingEntity {
|
public abstract class EntityCreature extends LivingEntity {
|
||||||
|
|
||||||
public EntityCreature(int entityType) {
|
public EntityCreature(EntityType entityType) {
|
||||||
super(entityType);
|
super(entityType.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -26,7 +28,7 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
float newY = position.getY() + y;
|
float newY = position.getY() + y;
|
||||||
float newZ = position.getZ() + z;
|
float newZ = position.getZ() + z;
|
||||||
|
|
||||||
if (isChunkUnloaded(newX, newZ))
|
if (ChunkUtils.isChunkUnloaded(getInstance(), newX, newZ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EntityRelativeMovePacket entityRelativeMovePacket = new EntityRelativeMovePacket();
|
EntityRelativeMovePacket entityRelativeMovePacket = new EntityRelativeMovePacket();
|
||||||
@ -67,4 +69,8 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
playerConnection.sendPacket(getMetadataPacket());
|
playerConnection.sendPacket(getMetadataPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnGround() {
|
||||||
|
return EntityUtils.isOnGround(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
85
src/main/java/fr/themode/minestom/entity/EntityType.java
Normal file
85
src/main/java/fr/themode/minestom/entity/EntityType.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public enum EntityType {
|
||||||
|
ARMOR_STAND(1), // Object
|
||||||
|
BAT(3),
|
||||||
|
BLAZE(4),
|
||||||
|
CAT(6),
|
||||||
|
CAVE_SPIDER(7),
|
||||||
|
CHICKEN(8),
|
||||||
|
COD(9),
|
||||||
|
COW(10),
|
||||||
|
CREEPER(11),
|
||||||
|
DONKEY(12),
|
||||||
|
DOLPHIN(13),
|
||||||
|
DROWNED(15),
|
||||||
|
ELDER_GUARDIAN(16),
|
||||||
|
ENDER_DRAGON(18),
|
||||||
|
ENDERMAN(19),
|
||||||
|
ENDERMITE(20),
|
||||||
|
EVOKER(22),
|
||||||
|
FOX(27),
|
||||||
|
GHAST(28),
|
||||||
|
GIANT(29),
|
||||||
|
GUARDIAN(30),
|
||||||
|
HORSE(31),
|
||||||
|
HUSK(32),
|
||||||
|
ILLUSIONER(33),
|
||||||
|
LLAMA(38),
|
||||||
|
MAGMA_CUBE(40),
|
||||||
|
MULE(48),
|
||||||
|
MOOSHROOM(49),
|
||||||
|
OCELOT(50),
|
||||||
|
PANDA(52),
|
||||||
|
PARROT(53),
|
||||||
|
PIG(54),
|
||||||
|
PUFFERFISH(55),
|
||||||
|
ZOMBIE_PIGMAN(56),
|
||||||
|
POLAR_BEAR(57),
|
||||||
|
RABBIT(59),
|
||||||
|
SALMON(60),
|
||||||
|
SHEEP(61),
|
||||||
|
SHULKER(62),
|
||||||
|
SILVERFISH(64),
|
||||||
|
SKELETON(65),
|
||||||
|
SKELETON_HORSE(66),
|
||||||
|
SLIME(67),
|
||||||
|
SNOW_GOLEM(69),
|
||||||
|
SPIDER(72),
|
||||||
|
SQUID(73),
|
||||||
|
STRAY(74),
|
||||||
|
TRADER_LLAMA(75),
|
||||||
|
TROPICAL_FISH(76),
|
||||||
|
TURTLE(77),
|
||||||
|
VEX(83),
|
||||||
|
VILLAGER(84),
|
||||||
|
IRON_GOLEM(85),
|
||||||
|
VINDICATOR(86),
|
||||||
|
PILLAGER(87),
|
||||||
|
WANGERING_TRADER(88),
|
||||||
|
WITCH(89),
|
||||||
|
WITHER(90),
|
||||||
|
WITHER_SKELETON(91),
|
||||||
|
WOLF(93),
|
||||||
|
ZOMBIE(94),
|
||||||
|
ZOMBIE_HORSE(95),
|
||||||
|
ZOMBIE_VILLAGER(96),
|
||||||
|
PHANTOM(97),
|
||||||
|
RAVAGER(98);
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
EntityType(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityType fromId(int id) {
|
||||||
|
return Arrays.stream(values()).filter(entityType -> entityType.id == id).findFirst().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ public class ItemEntity extends ObjectEntity {
|
|||||||
public ItemEntity(ItemStack itemStack) {
|
public ItemEntity(ItemStack itemStack) {
|
||||||
super(34);
|
super(34);
|
||||||
this.itemStack = itemStack;
|
this.itemStack = itemStack;
|
||||||
|
setGravity(0.02f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,6 +5,7 @@ import fr.themode.minestom.entity.property.Attribute;
|
|||||||
import fr.themode.minestom.event.PickupItemEvent;
|
import fr.themode.minestom.event.PickupItemEvent;
|
||||||
import fr.themode.minestom.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
import fr.themode.minestom.item.ItemStack;
|
import fr.themode.minestom.item.ItemStack;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.AnimationPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
|
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.EntityPropertiesPacket;
|
import fr.themode.minestom.net.packet.server.play.EntityPropertiesPacket;
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ public abstract class LivingEntity extends Entity {
|
|||||||
public LivingEntity(int entityType) {
|
public LivingEntity(int entityType) {
|
||||||
super(entityType);
|
super(entityType);
|
||||||
setupAttributes();
|
setupAttributes();
|
||||||
|
setGravity(0.02f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void kill();
|
public abstract void kill();
|
||||||
@ -79,11 +81,21 @@ public abstract class LivingEntity extends Entity {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void damage(float value) {
|
||||||
|
AnimationPacket animationPacket = new AnimationPacket();
|
||||||
|
animationPacket.entityId = getEntityId();
|
||||||
|
animationPacket.animation = AnimationPacket.Animation.TAKE_DAMAGE;
|
||||||
|
sendPacketToViewersAndSelf(animationPacket);
|
||||||
|
setHealth(getHealth() - value);
|
||||||
|
}
|
||||||
|
|
||||||
public float getHealth() {
|
public float getHealth() {
|
||||||
return health;
|
return health;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHealth(float health) {
|
public void setHealth(float health) {
|
||||||
|
health = Math.min(health, getMaxHealth());
|
||||||
|
|
||||||
this.health = health;
|
this.health = health;
|
||||||
if (this.health <= 0) {
|
if (this.health <= 0) {
|
||||||
kill();
|
kill();
|
||||||
|
@ -2,6 +2,7 @@ package fr.themode.minestom.entity;
|
|||||||
|
|
||||||
import fr.themode.minestom.net.packet.server.play.SpawnObjectPacket;
|
import fr.themode.minestom.net.packet.server.play.SpawnObjectPacket;
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
import fr.themode.minestom.utils.EntityUtils;
|
||||||
|
|
||||||
// TODO viewers synchronization each X ticks?
|
// TODO viewers synchronization each X ticks?
|
||||||
public abstract class ObjectEntity extends Entity {
|
public abstract class ObjectEntity extends Entity {
|
||||||
@ -31,4 +32,10 @@ public abstract class ObjectEntity extends Entity {
|
|||||||
public void removeViewer(Player player) {
|
public void removeViewer(Player player) {
|
||||||
super.removeViewer(player);
|
super.removeViewer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnGround() {
|
||||||
|
return EntityUtils.isOnGround(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import fr.themode.minestom.Main;
|
|||||||
import fr.themode.minestom.bossbar.BossBar;
|
import fr.themode.minestom.bossbar.BossBar;
|
||||||
import fr.themode.minestom.chat.Chat;
|
import fr.themode.minestom.chat.Chat;
|
||||||
import fr.themode.minestom.data.Data;
|
import fr.themode.minestom.data.Data;
|
||||||
|
import fr.themode.minestom.entity.demo.ChickenCreature;
|
||||||
import fr.themode.minestom.entity.property.Attribute;
|
import fr.themode.minestom.entity.property.Attribute;
|
||||||
import fr.themode.minestom.event.*;
|
import fr.themode.minestom.event.*;
|
||||||
import fr.themode.minestom.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
@ -13,6 +14,7 @@ import fr.themode.minestom.instance.InstanceContainer;
|
|||||||
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
|
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
|
||||||
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.net.packet.client.ClientPlayPacket;
|
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.*;
|
import fr.themode.minestom.net.packet.server.play.*;
|
||||||
@ -40,6 +42,8 @@ public class Player extends LivingEntity {
|
|||||||
private GameMode gameMode;
|
private GameMode gameMode;
|
||||||
private LevelType levelType;
|
private LevelType levelType;
|
||||||
|
|
||||||
|
protected boolean onGround;
|
||||||
|
|
||||||
private static InstanceContainer instanceContainer;
|
private static InstanceContainer instanceContainer;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -82,7 +86,7 @@ public class Player extends LivingEntity {
|
|||||||
protected boolean spawned;
|
protected boolean spawned;
|
||||||
|
|
||||||
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
||||||
super(93);
|
super(100);
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.playerConnection = playerConnection;
|
this.playerConnection = playerConnection;
|
||||||
@ -98,8 +102,11 @@ public class Player extends LivingEntity {
|
|||||||
setEventCallback(AttackEvent.class, event -> {
|
setEventCallback(AttackEvent.class, event -> {
|
||||||
Entity entity = event.getTarget();
|
Entity entity = event.getTarget();
|
||||||
if (entity instanceof EntityCreature) {
|
if (entity instanceof EntityCreature) {
|
||||||
((EntityCreature) entity).kill();
|
((EntityCreature) entity).damage(-1);
|
||||||
sendMessage("You killed an entity!");
|
Vector velocity = getPosition().clone().getDirection().multiply(6);
|
||||||
|
velocity.setY(4f);
|
||||||
|
entity.setVelocity(velocity, 150);
|
||||||
|
sendMessage("You attacked an entity!");
|
||||||
} else if (entity instanceof Player) {
|
} else if (entity instanceof Player) {
|
||||||
Player player = (Player) entity;
|
Player player = (Player) entity;
|
||||||
Vector velocity = getPosition().clone().getDirection().multiply(6);
|
Vector velocity = getPosition().clone().getDirection().multiply(6);
|
||||||
@ -145,18 +152,18 @@ public class Player extends LivingEntity {
|
|||||||
setGameMode(GameMode.SURVIVAL);
|
setGameMode(GameMode.SURVIVAL);
|
||||||
teleport(new Position(0, 66, 0));
|
teleport(new Position(0, 66, 0));
|
||||||
|
|
||||||
/*ChickenCreature chickenCreature = new ChickenCreature();
|
ChickenCreature chickenCreature = new ChickenCreature();
|
||||||
chickenCreature.refreshPosition(2, 65, 2);
|
chickenCreature.refreshPosition(2, 65, 2);
|
||||||
chickenCreature.setInstance(getInstance());
|
chickenCreature.setInstance(getInstance());
|
||||||
|
|
||||||
for (int ix = 0; ix < 4; ix++)
|
for (int ix = 0; ix < 4; ix++)
|
||||||
for (int iz = 0; iz < 4; iz++) {
|
for (int iz = 0; iz < 4; iz++) {
|
||||||
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
|
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
|
||||||
itemEntity.refreshPosition(ix, 66, iz);
|
itemEntity.refreshPosition(ix, 68, iz);
|
||||||
itemEntity.setNoGravity(true);
|
//itemEntity.setNoGravity(true);
|
||||||
itemEntity.setInstance(getInstance());
|
itemEntity.setInstance(getInstance());
|
||||||
//itemEntity.remove();
|
//itemEntity.remove();
|
||||||
}*/
|
}
|
||||||
|
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
|
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
|
||||||
@ -270,6 +277,11 @@ public class Player extends LivingEntity {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnGround() {
|
||||||
|
return onGround;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
clearBossBars();
|
clearBossBars();
|
||||||
@ -345,15 +357,12 @@ public class Player extends LivingEntity {
|
|||||||
playerConnection.sendPacket(chatMessagePacket);
|
playerConnection.sendPacket(chatMessagePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void damage(float amount) {
|
@Override
|
||||||
|
public void damage(float value) {
|
||||||
if (getGameMode() == GameMode.CREATIVE)
|
if (getGameMode() == GameMode.CREATIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AnimationPacket animationPacket = new AnimationPacket();
|
super.damage(value);
|
||||||
animationPacket.entityId = getEntityId();
|
|
||||||
animationPacket.animation = AnimationPacket.Animation.TAKE_DAMAGE;
|
|
||||||
sendPacketToViewersAndSelf(animationPacket);
|
|
||||||
setHealth(getHealth() - amount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -471,7 +480,7 @@ public class Player extends LivingEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void teleport(Position position, Runnable callback) {
|
public void teleport(Position position, Runnable callback) {
|
||||||
super.teleport(position, () -> {
|
super.teleport(position, () -> {
|
||||||
if (!instance.hasEnabledAutoChunkLoad() && isChunkUnloaded(position.getX(), position.getZ()))
|
if (!instance.hasEnabledAutoChunkLoad() && ChunkUtils.isChunkUnloaded(instance, position.getX(), position.getZ()))
|
||||||
return;
|
return;
|
||||||
updatePlayerPosition();
|
updatePlayerPosition();
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package fr.themode.minestom.entity.demo;
|
package fr.themode.minestom.entity.demo;
|
||||||
|
|
||||||
import fr.themode.minestom.entity.EntityCreature;
|
import fr.themode.minestom.entity.EntityCreature;
|
||||||
import fr.themode.minestom.utils.Vector;
|
import fr.themode.minestom.entity.EntityType;
|
||||||
|
|
||||||
public class ChickenCreature extends EntityCreature {
|
public class ChickenCreature extends EntityCreature {
|
||||||
|
|
||||||
public ChickenCreature() {
|
public ChickenCreature() {
|
||||||
super(8);
|
super(EntityType.CHICKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -43,11 +43,11 @@ public class ChickenCreature extends EntityCreature {
|
|||||||
move(x * speed, 0, z * speed);
|
move(x * speed, 0, z * speed);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
move(0, 0, speed);
|
// move(0, 0, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void spawn() {
|
public void spawn() {
|
||||||
setVelocity(new Vector(0, 1, 0), 3000);
|
// setVelocity(new Vector(0, 1, 0), 3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,12 @@ public class BlockBatch implements BlockModifier {
|
|||||||
}
|
}
|
||||||
chunk.refreshDataPacket();
|
chunk.refreshDataPacket();
|
||||||
instance.sendChunkUpdate(chunk);
|
instance.sendChunkUpdate(chunk);
|
||||||
if (isLast && callback != null)
|
if (isLast) {
|
||||||
|
// data.clear();
|
||||||
|
if (callback != null)
|
||||||
callback.run();
|
callback.run();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ public class ChunkBatch implements BlockModifier {
|
|||||||
data.apply(chunk);
|
data.apply(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dataList.clear();
|
||||||
chunk.refreshDataPacket();
|
chunk.refreshDataPacket();
|
||||||
instance.sendChunkUpdate(chunk);
|
instance.sendChunkUpdate(chunk);
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
|
@ -153,21 +153,23 @@ public abstract class Instance implements BlockModifier {
|
|||||||
lastInstance.removeEntity(entity); // If entity is in another instance, remove it from there and add it to this
|
lastInstance.removeEntity(entity); // If entity is in another instance, remove it from there and add it to this
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity instanceof Player) {
|
|
||||||
Player player = (Player) entity;
|
|
||||||
sendChunks(player);
|
|
||||||
|
|
||||||
// Send player all visible entities
|
|
||||||
long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entity.getPosition(), Main.ENTITY_VIEW_DISTANCE);
|
long[] visibleChunksEntity = ChunkUtils.getChunksInRange(entity.getPosition(), Main.ENTITY_VIEW_DISTANCE);
|
||||||
|
boolean isPlayer = entity instanceof Player;
|
||||||
|
|
||||||
|
if (isPlayer) {
|
||||||
|
sendChunks((Player) entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all visible entities
|
||||||
for (long chunkIndex : visibleChunksEntity) {
|
for (long chunkIndex : visibleChunksEntity) {
|
||||||
getEntitiesInChunk(chunkIndex).forEach(ent -> {
|
getEntitiesInChunk(chunkIndex).forEach(ent -> {
|
||||||
ent.addViewer(player);
|
if (isPlayer)
|
||||||
|
ent.addViewer((Player) entity);
|
||||||
if (ent instanceof Player) {
|
if (ent instanceof Player) {
|
||||||
player.addViewer((Player) ent);
|
entity.addViewer((Player) ent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Chunk chunk = getChunkAt(entity.getPosition());
|
Chunk chunk = getChunkAt(entity.getPosition());
|
||||||
addEntityToChunk(entity, chunk);
|
addEntityToChunk(entity, chunk);
|
||||||
|
@ -207,15 +207,19 @@ public class InstanceContainer extends Instance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendChunk(Player player, Chunk chunk) {
|
public void sendChunk(Player player, Chunk chunk) {
|
||||||
|
/*Buffer data = chunk.getFullDataPacket();
|
||||||
|
if(data == null) {
|
||||||
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
||||||
buffer.getData().retain(1).markReaderIndex();
|
chunk.setFullDataPacket(buffer);
|
||||||
player.getPlayerConnection().sendUnencodedPacket(buffer);
|
sendChunkUpdate(player, chunk);
|
||||||
buffer.getData().resetReaderIndex();
|
});
|
||||||
|
}else{
|
||||||
|
sendChunkUpdate(player, chunk);
|
||||||
|
}*/
|
||||||
|
PacketWriter.writeCallbackPacket(chunk.getFreshFullDataPacket(), buffer -> {
|
||||||
|
chunk.setFullDataPacket(buffer);
|
||||||
|
sendChunkUpdate(player, chunk);
|
||||||
});
|
});
|
||||||
// TODO use cached chunk data
|
|
||||||
/*chunkData.getData().retain(1).markReaderIndex();
|
|
||||||
player.getPlayerConnection().sendUnencodedPacket(chunkData);
|
|
||||||
chunkData.getData().resetReaderIndex();*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,6 +6,7 @@ import fr.themode.minestom.net.packet.client.play.ClientPlayerLookPacket;
|
|||||||
import fr.themode.minestom.net.packet.client.play.ClientPlayerPacket;
|
import fr.themode.minestom.net.packet.client.play.ClientPlayerPacket;
|
||||||
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionAndLookPacket;
|
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionAndLookPacket;
|
||||||
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionPacket;
|
import fr.themode.minestom.net.packet.client.play.ClientPlayerPositionPacket;
|
||||||
|
import fr.themode.minestom.utils.ChunkUtils;
|
||||||
|
|
||||||
public class PlayerPositionListener {
|
public class PlayerPositionListener {
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ public class PlayerPositionListener {
|
|||||||
|
|
||||||
private static void processMovement(Player player, float x, float y, float z, Runnable runnable) {
|
private static void processMovement(Player player, float x, float y, float z, Runnable runnable) {
|
||||||
//System.out.println("MOVEMENT PACKET " + Math.round(x) + ":" + Math.round(y) + ":" + Math.round(z));
|
//System.out.println("MOVEMENT PACKET " + Math.round(x) + ":" + Math.round(y) + ":" + Math.round(z));
|
||||||
boolean chunkTest = player.isChunkUnloaded(x, z);
|
boolean chunkTest = ChunkUtils.isChunkUnloaded(player.getInstance(), x, z);
|
||||||
if (chunkTest) {
|
if (chunkTest) {
|
||||||
player.teleport(player.getPosition());
|
player.teleport(player.getPosition());
|
||||||
return;
|
return;
|
||||||
|
@ -10,10 +10,18 @@ public class BlockPosition {
|
|||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(int x, int y, int z) {
|
public BlockPosition add(int x, int y, int z) {
|
||||||
this.x += x;
|
this.x += x;
|
||||||
this.y += y;
|
this.y += y;
|
||||||
this.z += z;
|
this.z += z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPosition subtract(int x, int y, int z) {
|
||||||
|
this.x -= x;
|
||||||
|
this.y -= y;
|
||||||
|
this.z -= z;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package fr.themode.minestom.utils;
|
package fr.themode.minestom.utils;
|
||||||
|
|
||||||
|
import fr.themode.minestom.instance.Instance;
|
||||||
|
|
||||||
public class ChunkUtils {
|
public class ChunkUtils {
|
||||||
|
|
||||||
|
public static boolean isChunkUnloaded(Instance instance, float x, float z) {
|
||||||
|
return instance.getChunk((int) Math.floor(x / 16), (int) Math.floor(z / 16)) == null;
|
||||||
|
}
|
||||||
|
|
||||||
public static long getChunkIndex(int chunkX, int chunkZ) {
|
public static long getChunkIndex(int chunkX, int chunkZ) {
|
||||||
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
|
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package fr.themode.minestom.utils;
|
|||||||
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.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
|
import fr.themode.minestom.instance.Instance;
|
||||||
|
|
||||||
public class EntityUtils {
|
public class EntityUtils {
|
||||||
|
|
||||||
@ -26,4 +27,13 @@ public class EntityUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOnGround(Entity entity) {
|
||||||
|
Instance instance = entity.getInstance();
|
||||||
|
if (instance == null)
|
||||||
|
return false;
|
||||||
|
Position position = entity.getPosition();
|
||||||
|
short blockId = instance.getBlockId(position.toBlockPosition().subtract(0, 1, 0));
|
||||||
|
return blockId != 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,13 @@ public class Position {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Position subtract(float x, float y, float z) {
|
||||||
|
this.x -= x;
|
||||||
|
this.y -= y;
|
||||||
|
this.z -= z;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public float getDistance(Position position) {
|
public float getDistance(Position position) {
|
||||||
return (float) Math.sqrt(MathUtils.square(position.getX() - getX()) + MathUtils.square(position.getY() - getY()) + MathUtils.square(position.getZ() - getZ()));
|
return (float) Math.sqrt(MathUtils.square(position.getX() - getX()) + MathUtils.square(position.getY() - getY()) + MathUtils.square(position.getZ() - getZ()));
|
||||||
}
|
}
|
||||||
@ -133,7 +140,7 @@ public class Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BlockPosition toBlockPosition() {
|
public BlockPosition toBlockPosition() {
|
||||||
return new BlockPosition((int) getX(), (int) getY(), (int) getZ());
|
return new BlockPosition((int) Math.ceil(getX()), (int) Math.ceil(getY()), (int) Math.ceil(getZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user