Custom food animation delay + PlayerEatEvent

This commit is contained in:
Felix Cravic 2020-05-12 14:12:17 +02:00
parent f5d4cba29d
commit 37add239f8
8 changed files with 122 additions and 25 deletions

View File

@ -10,6 +10,7 @@ import net.minestom.server.entity.*;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.event.entity.AttackEvent;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.ItemUpdateStateEvent;
import net.minestom.server.event.item.PickupItemEvent;
import net.minestom.server.event.player.*;
import net.minestom.server.instance.Chunk;
@ -177,7 +178,7 @@ public class PlayerInit {
});
player.addEventCallback(PlayerSpawnEvent.class, event -> {
player.setGameMode(GameMode.SURVIVAL);
player.setGameMode(GameMode.CREATIVE);
player.teleport(new Position(0, 75, 0));
ItemStack item = new ItemStack(Material.STONE, (byte) 43);
@ -231,6 +232,14 @@ public class PlayerInit {
player.sendMessage("Using item on block: " + useEvent.getItemStack().getMaterial() + " at " + useEvent.getPosition() + " on face " + useEvent.getBlockFace());
});
player.addEventCallback(ItemUpdateStateEvent.class, event -> {
System.out.println("ITEM UPDATE STATE");
});
player.addEventCallback(PlayerEatEvent.class, event -> {
System.out.println("PLAYER EAT EVENT");
});
player.addEventCallback(PlayerChunkUnloadEvent.class, event -> {
Instance instance = player.getInstance();

View File

@ -55,7 +55,6 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
// Velocity
protected Vector velocity = new Vector(); // Movement in block per second
protected float gravityDragPerTick;
private int gravityTickCounter;
private Set<Player> viewers = new CopyOnWriteArraySet<>();
private Data data;

View File

@ -11,17 +11,16 @@ import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.property.Attribute;
import net.minestom.server.entity.vehicle.PlayerVehicleInformation;
import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.ItemUpdateStateEvent;
import net.minestom.server.event.item.PickupExperienceEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.event.player.PlayerRespawnEvent;
import net.minestom.server.event.player.PlayerSpawnEvent;
import net.minestom.server.event.player.PlayerTickEvent;
import net.minestom.server.event.player.*;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.play.*;
@ -73,12 +72,16 @@ public class Player extends LivingEntity {
private int food;
private float foodSaturation;
private long startEatingTime;
private long eatingTime = 1000L;
private boolean isEating;
// CustomBlock break delay
private CustomBlock targetCustomBlock;
private BlockPosition targetBlockPosition;
private long targetBlockTime;
private byte targetLastStage;
private int timeBreak;
private int blockBreakTime;
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
private Team team;
@ -149,7 +152,7 @@ public class Player extends LivingEntity {
if (targetCustomBlock != null) {
int animationCount = 10;
long since = System.currentTimeMillis() - targetBlockTime;
byte stage = (byte) (since / (timeBreak / animationCount));
byte stage = (byte) (since / (blockBreakTime / animationCount));
if (stage != targetLastStage) {
sendBlockBreakAnimation(targetBlockPosition, stage);
}
@ -182,6 +185,24 @@ public class Player extends LivingEntity {
}
}
// Eating animation
if (isEating()) {
if (System.currentTimeMillis() - startEatingTime >= eatingTime) {
refreshEating(false);
triggerStatus((byte) 9); // Mark item use as finished
ItemUpdateStateEvent itemUpdateStateEvent = callItemUpdateStateEvent(true);
ItemStack foodItem = itemUpdateStateEvent.getItemStack();
boolean isFood = foodItem.getMaterial().isFood();
if (isFood) {
PlayerEatEvent playerEatEvent = new PlayerEatEvent(foodItem);
callEvent(PlayerEatEvent.class, playerEatEvent);
}
}
}
// Tick event
callEvent(PlayerTickEvent.class, new PlayerTickEvent());
@ -564,6 +585,19 @@ public class Player extends LivingEntity {
sendUpdateHealthPacket();
}
public boolean isEating() {
return isEating;
}
/**
* Used to change the eating time animation
*
* @param eatingTime the eating time in milliseconds
*/
public void setEatingTime(long eatingTime) {
this.eatingTime = eatingTime;
}
public boolean dropItem(ItemStack item) {
ItemDropEvent itemDropEvent = new ItemDropEvent(item);
callEvent(ItemDropEvent.class, itemDropEvent);
@ -995,17 +1029,50 @@ public class Player extends LivingEntity {
public void refreshHeldSlot(short slot) {
this.heldSlot = slot;
syncEquipment(EntityEquipmentPacket.Slot.MAIN_HAND);
refreshEating(false);
}
public void refreshOpenInventory(Inventory openInventory) {
this.openInventory = openInventory;
}
public void refreshEating(boolean isEating) {
this.isEating = isEating;
if (isEating) {
this.startEatingTime = System.currentTimeMillis();
} else {
this.startEatingTime = 0;
}
}
public ItemUpdateStateEvent callItemUpdateStateEvent(boolean allowFood) {
Material mainHandMat = Material.fromId(getItemInMainHand().getMaterialId());
Material offHandMat = Material.fromId(getItemInOffHand().getMaterialId());
boolean isOffhand = offHandMat.hasState();
ItemStack updatedItem = isOffhand ? getItemInOffHand() :
mainHandMat.hasState() ? getItemInMainHand() : null;
if (updatedItem == null) // No item with state, cancel
return null;
boolean isFood = updatedItem.getMaterial().isFood();
if (isFood && !allowFood)
return null;
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(updatedItem,
isOffhand ? Hand.OFF : Hand.MAIN);
callEvent(ItemUpdateStateEvent.class, itemUpdateStateEvent);
return itemUpdateStateEvent;
}
public void refreshTargetBlock(CustomBlock targetCustomBlock, BlockPosition targetBlockPosition, int breakTime) {
this.targetCustomBlock = targetCustomBlock;
this.targetBlockPosition = targetBlockPosition;
this.targetBlockTime = targetBlockPosition == null ? 0 : System.currentTimeMillis();
this.timeBreak = breakTime;
this.blockBreakTime = breakTime;
}
public void resetTargetBlock() {

View File

@ -1,21 +1,28 @@
package net.minestom.server.event.item;
import net.minestom.server.entity.Player;
import net.minestom.server.event.Event;
import net.minestom.server.item.ItemStack;
public class ItemUpdateStateEvent extends Event {
private ItemStack itemStack;
private Player.Hand hand;
private boolean handAnimation;
public ItemUpdateStateEvent(ItemStack itemStack) {
public ItemUpdateStateEvent(ItemStack itemStack, Player.Hand hand) {
this.itemStack = itemStack;
this.hand = hand;
}
public ItemStack getItemStack() {
return itemStack;
}
public Player.Hand getHand() {
return hand;
}
public void setHandAnimation(boolean handAnimation) {
this.handAnimation = handAnimation;
}

View File

@ -0,0 +1,17 @@
package net.minestom.server.event.player;
import net.minestom.server.event.Event;
import net.minestom.server.item.ItemStack;
public class PlayerEatEvent extends Event {
private ItemStack foodItem;
public PlayerEatEvent(ItemStack foodItem) {
this.foodItem = foodItem;
}
public ItemStack getFoodItem() {
return foodItem;
}
}

View File

@ -10,7 +10,6 @@ import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.network.packet.client.play.ClientPlayerDiggingPacket;
import net.minestom.server.network.packet.server.play.AcknowledgePlayerDiggingPacket;
import net.minestom.server.network.packet.server.play.EntityEffectPacket;
@ -52,7 +51,7 @@ public class PlayerDiggingListener {
}
addEffect(player);
} else {
if(Block.fromId(instance.getBlockId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())).breaksInstantaneously()) {
if (Block.fromId(instance.getBlockId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())).breaksInstantaneously()) {
if (player.getCustomBlockTarget() != null) {
player.resetTargetBlock();
removeEffect(player);
@ -100,20 +99,18 @@ public class PlayerDiggingListener {
dropItem(player, droppedItemStack2, handItem);
break;
case UPDATE_ITEM_STATE:
Material mainHandMat = Material.fromId(mainHand.getMaterialId());
Material offHandMat = Material.fromId(offHand.getMaterialId());
boolean isOffhand = offHandMat.hasState();
player.refreshEating(false);
ItemUpdateStateEvent itemUpdateStateEvent = player.callItemUpdateStateEvent(false);
ItemStack updatedItem = isOffhand ? offHand :
mainHandMat.hasState() ? mainHand : null;
if (updatedItem == null) // No item with state, cancel
return;
if (itemUpdateStateEvent == null) {
player.refreshActiveHand(true, false, false);
player.sendPacketToViewers(player.getMetadataPacket());
} else {
boolean isOffHand = itemUpdateStateEvent.getHand() == Player.Hand.OFF;
player.refreshActiveHand(itemUpdateStateEvent.hasHandAnimation(), isOffHand, false);
player.sendPacketToViewers(player.getMetadataPacket());
}
ItemUpdateStateEvent itemUpdateStateEvent = new ItemUpdateStateEvent(updatedItem);
player.callEvent(ItemUpdateStateEvent.class, itemUpdateStateEvent);
player.refreshActiveHand(itemUpdateStateEvent.hasHandAnimation(), isOffhand, false);
player.sendPacketToViewers(player.getMetadataPacket());
break;
case SWAP_ITEM_HAND:
PlayerSwapItemEvent swapItemEvent = new PlayerSwapItemEvent(offHand.clone(), mainHand.clone());

View File

@ -77,6 +77,7 @@ public class UseItemListener {
armAnimationEvent = new ArmAnimationEvent(ArmAnimationEvent.ArmAnimationType.TRIDENT);
} else if (material.isFood()) {
armAnimationEvent = new ArmAnimationEvent(ArmAnimationEvent.ArmAnimationType.EAT);
player.refreshEating(true);
}
if (armAnimationEvent != null)

View File

@ -15,7 +15,7 @@ public class ClientPacketsHandler {
}
public ClientPacket getPacketInstance(int id) {
//System.out.println("RECEIVED PACKET 0x" + Integer.toHexString(id));
// System.out.println("RECEIVED PACKET 0x" + Integer.toHexString(id));
if (id > SIZE)
throw new IllegalStateException("Packet ID 0x" + Integer.toHexString(id) + " has been tried to be parsed, debug needed");