ItemEntity can now be merged/stacked together

This commit is contained in:
Felix Cravic 2020-05-09 21:50:48 +02:00
parent 17856c36cf
commit 889e9c5e2b
5 changed files with 118 additions and 5 deletions

View File

@ -690,7 +690,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
sendPacketToViewersAndSelf(metaDataPacket);
}
private void fillMetadataIndex(PacketWriter packet, int index) {
protected void fillMetadataIndex(PacketWriter packet, int index) {
switch (index) {
case 0:
fillStateMetadata(packet);

View File

@ -1,13 +1,18 @@
package net.minestom.server.entity;
import net.minestom.server.event.entity.EntityItemMergeEvent;
import net.minestom.server.instance.Chunk;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.StackingRule;
import net.minestom.server.network.packet.PacketWriter;
import java.util.Set;
import java.util.function.Consumer;
public class ItemEntity extends ObjectEntity {
private ItemStack itemStack;
private boolean pickable = true;
private long spawnTime;
@ -22,7 +27,51 @@ public class ItemEntity extends ObjectEntity {
@Override
public void update() {
Chunk chunk = instance.getChunkAt(getPosition());
Set<Entity> entities = instance.getChunkEntities(chunk);
for (Entity entity : entities) {
if (entity instanceof ItemEntity) {
// Do not merge with itself
if (entity == this)
continue;
ItemEntity itemEntity = (ItemEntity) entity;
if (!itemEntity.isPickable())
continue;
// Too far, do not merge
if (getDistance(itemEntity) > 1)
continue;
synchronized (this) {
synchronized (itemEntity) {
ItemStack itemStackEntity = itemEntity.getItemStack();
StackingRule stackingRule = itemStack.getStackingRule();
boolean canStack = stackingRule.canBeStacked(itemStack, itemStackEntity);
if (!canStack)
continue;
int totalAmount = stackingRule.getAmount(itemStack) + stackingRule.getAmount(itemStackEntity);
boolean canApply = stackingRule.canApply(itemStack, totalAmount);
if (!canApply)
continue;
EntityItemMergeEvent entityItemMergeEvent = new EntityItemMergeEvent(this, itemEntity);
callCancellableEvent(EntityItemMergeEvent.class, entityItemMergeEvent, () -> {
ItemStack result = stackingRule.apply(itemStack.clone(), totalAmount);
setItemStack(result);
itemEntity.remove();
});
}
}
}
}
}
@Override
@ -39,10 +88,19 @@ public class ItemEntity extends ObjectEntity {
public Consumer<PacketWriter> getMetadataConsumer() {
return packet -> {
super.getMetadataConsumer().accept(packet);
fillMetadataIndex(packet, 7);
};
}
@Override
protected void fillMetadataIndex(PacketWriter packet, int index) {
super.fillMetadataIndex(packet, index);
if (index == 7) {
packet.writeByte((byte) 7);
packet.writeByte(METADATA_SLOT);
packet.writeItemStack(itemStack);
};
}
}
@Override

View File

@ -110,6 +110,16 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
public Consumer<PacketWriter> getMetadataConsumer() {
return packet -> {
super.getMetadataConsumer().accept(packet);
fillMetadataIndex(packet, 7);
// TODO all remaining metadata
};
}
@Override
protected void fillMetadataIndex(PacketWriter packet, int index) {
super.fillMetadataIndex(packet, index);
if (index == 7) {
packet.writeByte((byte) 7);
packet.writeByte(METADATA_BYTE);
byte activeHandValue = 0;
@ -121,9 +131,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
activeHandValue += 4;
}
packet.writeByte(activeHandValue);
// TODO all remaining metadata
};
}
}
@Override

View File

@ -0,0 +1,23 @@
package net.minestom.server.event.entity;
import net.minestom.server.entity.ItemEntity;
import net.minestom.server.event.CancellableEvent;
public class EntityItemMergeEvent extends CancellableEvent {
private ItemEntity source;
private ItemEntity merged;
public EntityItemMergeEvent(ItemEntity source, ItemEntity merged) {
this.source = source;
this.merged = merged;
}
public ItemEntity getSource() {
return source;
}
public ItemEntity getMerged() {
return merged;
}
}

View File

@ -8,12 +8,36 @@ public abstract class StackingRule {
this.maxSize = maxSize;
}
/**
* @param item1 the first item
* @param item2 the second item
* @return true if both item can be stacked together (do not take their amount in consideration)
*/
public abstract boolean canBeStacked(ItemStack item1, ItemStack item2);
/**
* @param item the item to check
* @param newAmount the desired new amount
* @return true if item can have its stack size set to newAmount
*/
public abstract boolean canApply(ItemStack item, int newAmount);
/**
* At this point we know that the item can have this stack size
*
* @param item
* @param newAmount
* @return the new ItemStack with the new amount
*/
public abstract ItemStack apply(ItemStack item, int newAmount);
/**
* Used to determine the current stack size of an item
* It is possible to have it stored in its Data object, lore, etc...
*
* @param itemStack
* @return the correct size of itemStack
*/
public abstract int getAmount(ItemStack itemStack);
public int getMaxSize() {