From 9f242146819f508d39994c44d4757d25ebee2bbd Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Wed, 5 Jul 2017 19:14:44 +0200 Subject: [PATCH 01/10] Add off_hand (shield) support for armorstands also add equipment sounds closes #471 --- .../entity/objects/GlowArmorStand.java | 205 ++++++++++-------- .../play/player/InteractEntityHandler.java | 42 ++-- start.sh | 2 +- 3 files changed, 133 insertions(+), 116 deletions(-) diff --git a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java index 213815e23f..c5262423f4 100644 --- a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java +++ b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java @@ -1,41 +1,25 @@ package net.glowstone.entity.objects; -import com.flowpowered.network.Message; -import net.glowstone.EventFactory; -import net.glowstone.GlowWorld; -import net.glowstone.entity.GlowLivingEntity; -import net.glowstone.entity.GlowPlayer; -import net.glowstone.entity.meta.MetadataIndex; -import net.glowstone.entity.meta.MetadataIndex.ArmorStandFlags; -import net.glowstone.entity.meta.MetadataIndex.StatusFlags; -import net.glowstone.net.message.play.entity.DestroyEntitiesMessage; -import net.glowstone.net.message.play.entity.EntityEquipmentMessage; -import net.glowstone.net.message.play.entity.EntityMetadataMessage; -import net.glowstone.net.message.play.entity.SpawnObjectMessage; -import net.glowstone.net.message.play.player.InteractEntityMessage; -import net.glowstone.net.message.play.player.InteractEntityMessage.Action; -import net.glowstone.util.InventoryUtil; -import net.glowstone.util.Position; -import org.bukkit.Effect; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeInstance; +import com.flowpowered.network.*; +import java.util.*; +import net.glowstone.*; +import net.glowstone.entity.*; +import net.glowstone.entity.meta.*; +import net.glowstone.entity.meta.MetadataIndex.*; +import net.glowstone.inventory.*; +import net.glowstone.net.message.play.entity.*; +import net.glowstone.net.message.play.player.*; +import net.glowstone.net.message.play.player.InteractEntityMessage.*; +import net.glowstone.util.*; +import org.bukkit.*; +import org.bukkit.attribute.*; import org.bukkit.entity.*; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.player.PlayerArmorStandManipulateEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scoreboard.Criterias; -import org.bukkit.scoreboard.Objective; -import org.bukkit.util.EulerAngle; - -import java.util.Arrays; -import java.util.List; -import java.util.UUID; +import org.bukkit.event.entity.*; +import org.bukkit.event.entity.EntityDamageEvent.*; +import org.bukkit.event.player.*; +import org.bukkit.inventory.*; +import org.bukkit.scoreboard.*; +import org.bukkit.util.*; public class GlowArmorStand extends GlowLivingEntity implements ArmorStand { @@ -54,8 +38,8 @@ public class GlowArmorStand extends GlowLivingEntity implements ArmorStand { } - private final ItemStack[] equipment = new ItemStack[5]; - private final boolean[] changedEquip = new boolean[5]; + private final ItemStack[] equipment = new ItemStack[6]; + private final boolean[] changedEquip = new boolean[6]; private final EulerAngle[] pose = new EulerAngle[6]; private boolean isMarker; @@ -71,7 +55,7 @@ public GlowArmorStand(Location location) { super(location, 2); System.arraycopy(defaultPose, 0, pose, 0, 6); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < equipment.length; i++) { changedEquip[i] = false; } } @@ -79,7 +63,7 @@ public GlowArmorStand(Location location) { @Override public void reset() { super.reset(); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < equipment.length; i++) { changedEquip[i] = false; } if (needsKill) needsKill = false; @@ -165,8 +149,9 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { if (player.getGameMode() == GameMode.SPECTATOR || isMarker) return false; if (msg.getAction() == Action.INTERACT_AT.ordinal()) { if (InventoryUtil.isEmpty(player.getItemInHand())) { - int slot = getEditSlot(msg.getTargetY()); - PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, InventoryUtil.itemOrEmpty(null), InventoryUtil.itemOrEmpty(equipment[slot]), EquipmentSlot.values()[slot]); + EquipmentSlot slot = getEditSlot(msg.getTargetY()); + + PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, InventoryUtil.itemOrEmpty(null), InventoryUtil.itemOrEmpty(getItem(slot)), slot); EventFactory.callEvent(event); if (event.isCancelled()) { @@ -177,18 +162,17 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { return false; } - ItemStack stack = equipment[slot]; + ItemStack stack = getItem(slot); player.setItemInHand(stack); - equipment[slot] = InventoryUtil.createEmptyStack(); - changedEquip[slot] = true; + setItem(slot, InventoryUtil.createEmptyStack()); return true; } else { - int slot = getEquipType(player.getItemInHand().getType()); - if (slot == 0 && !hasArms) { + EquipmentSlot slot = getEquipType(player.getItemInHand().getType()); + if ((slot == EquipmentSlot.HAND || slot == EquipmentSlot.OFF_HAND) && !hasArms) { return false; } - PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, player.getItemInHand(), InventoryUtil.itemOrEmpty(equipment[slot]), EquipmentSlot.values()[slot]); + PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, player.getItemInHand(), InventoryUtil.itemOrEmpty(getItem(slot)), slot); EventFactory.callEvent(event); if (event.isCancelled()) { @@ -208,21 +192,44 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { if (stack.getAmount() > 1) { return false; } - back = equipment[slot]; + back = getItem(slot); } if (!InventoryUtil.isEmpty(back)) { player.setItemInHand(back); } - equipment[slot] = stack; - changedEquip[slot] = true; + setItem(slot, stack); + player.playSound(location, getEquipSound(stack.getType()), SoundCategory.NEUTRAL, 1, 1); return true; } } return false; } - private int getEquipType(Material mat) { + private Sound getEquipSound(Material mat) { + if (mat == Material.ELYTRA) { + return Sound.ITEM_ARMOR_EQUIP_ELYTRA; + } + if (ClothType.LEATHER.matches(mat)) { + return Sound.ITEM_ARMOR_EQUIP_LEATHER; + } + if (ClothType.CHAINMAIL.matches(mat)) { + return Sound.ITEM_ARMOR_EQUIP_CHAIN; + } + if (ClothType.IRON.matches(mat)) { + return Sound.ITEM_ARMOR_EQUIP_IRON; + } + if (ClothType.GOLD.matches(mat)) { + return Sound.ITEM_ARMOR_EQUIP_GOLD; + } + if (ClothType.DIAMOND.matches(mat)) { + return Sound.ITEM_ARMOR_EQUIP_DIAMOND; + } + + return Sound.ITEM_ARMOR_EQUIP_GENERIC; + } + + private EquipmentSlot getEquipType(Material mat) { switch (mat) { case IRON_HELMET: case LEATHER_HELMET: @@ -231,47 +238,50 @@ private int getEquipType(Material mat) { case DIAMOND_HELMET: case PUMPKIN: case SKULL_ITEM: - return 4; + return EquipmentSlot.HEAD; case IRON_CHESTPLATE: case GOLD_CHESTPLATE: case LEATHER_CHESTPLATE: case CHAINMAIL_CHESTPLATE: case DIAMOND_CHESTPLATE: - return 3; + case ELYTRA: + return EquipmentSlot.CHEST; case IRON_LEGGINGS: case GOLD_LEGGINGS: case LEATHER_LEGGINGS: case CHAINMAIL_LEGGINGS: case DIAMOND_LEGGINGS: - return 2; + return EquipmentSlot.LEGS; case IRON_BOOTS: case GOLD_BOOTS: case LEATHER_BOOTS: case CHAINMAIL_BOOTS: case DIAMOND_BOOTS: - return 1; + return EquipmentSlot.FEET; + case SHIELD: + return EquipmentSlot.OFF_HAND; default: - return 0; + return EquipmentSlot.HAND; } } - private int getEditSlot(float height) { - int slot = 0; + private EquipmentSlot getEditSlot(float height) { if (isSmall) height *= 2; - if (height >= 0.1 && height < 0.1 + (isSmall ? 0.8 : 0.45) && !isEmpty(1)) { - slot = 1; - } else if (height >= 0.9 + (isSmall ? 0.3 : 0) && height < 0.9 + (isSmall ? 1 : 0.7) && !isEmpty(3)) { - slot = 3; - } else if (height >= 0.4 && height < 0.4 + (isSmall ? 1 : 0.8) && !isEmpty(2)) { - slot = 2; - } else if (height >= 1.6 && !isEmpty(4)) { - slot = 4; + + if (height >= 0.1 && height < 0.1 + (isSmall ? 0.8 : 0.45) && !isEmpty(EquipmentSlot.FEET)) { + return EquipmentSlot.FEET; + } else if (height >= 0.9 + (isSmall ? 0.3 : 0) && height < 0.9 + (isSmall ? 1 : 0.7) && !isEmpty(EquipmentSlot.CHEST)) { + return EquipmentSlot.CHEST; + } else if (height >= 0.4 && height < 0.4 + (isSmall ? 1 : 0.8) && !isEmpty(EquipmentSlot.LEGS)) { + return EquipmentSlot.LEGS; + } else if (height >= 1.6 && !isEmpty(EquipmentSlot.HEAD)) { + return EquipmentSlot.HEAD; } - return slot; + return EquipmentSlot.HAND; } - private boolean isEmpty(int slot) { - return InventoryUtil.isEmpty(equipment[slot]); + private boolean isEmpty(EquipmentSlot slot) { + return InventoryUtil.isEmpty(getItem(slot)); } @Override @@ -299,27 +309,30 @@ public List createSpawnMessage() { int pitch = Position.getIntPitch(location); return Arrays.asList( - new SpawnObjectMessage(id, UUID.randomUUID(), 78, x, y, z, pitch, yaw), // TODO: once UUID is documented, actually use the appropriate ID here - new EntityMetadataMessage(id, metadata.getEntryList()), - new EntityEquipmentMessage(id, EntityEquipmentMessage.HELD_ITEM, getItemInHand()), - new EntityEquipmentMessage(id, EntityEquipmentMessage.BOOTS_SLOT, getBoots()), - new EntityEquipmentMessage(id, EntityEquipmentMessage.LEGGINGS_SLOT, getLeggings()), - new EntityEquipmentMessage(id, EntityEquipmentMessage.CHESTPLATE_SLOT, getChestplate()), - new EntityEquipmentMessage(id, EntityEquipmentMessage.HELMET_SLOT, getHelmet()) + new SpawnObjectMessage(id, UUID.randomUUID(), 78, x, y, z, pitch, yaw), // TODO: once UUID is documented, actually use the appropriate ID here + new EntityMetadataMessage(id, metadata.getEntryList()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.HELD_ITEM, getItemInHand()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.BOOTS_SLOT, getBoots()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.LEGGINGS_SLOT, getLeggings()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.CHESTPLATE_SLOT, getChestplate()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.HELMET_SLOT, getHelmet()) ); } @Override public List createUpdateMessage() { List messages = super.createUpdateMessage(); - for (int i = 0; i < 5; i++) { - if (changedEquip[i]) { - messages.add(new EntityEquipmentMessage(id, i, equipment[i])); + messages.add(new EntityMetadataMessage(id, metadata.getEntryList())); + for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { + int slot = equipmentSlot.ordinal(); + if (changedEquip[slot]) { + messages.add(new EntityEquipmentMessage(id, slot, getItem(equipmentSlot))); } } if (needsKill) { messages.add(new DestroyEntitiesMessage(Arrays.asList(id))); } + return messages; } @@ -335,57 +348,61 @@ public Location getOrigin() { @Override public ItemStack getItemInHand() { - return equipment[0]; + return getItem(EquipmentSlot.HAND); } @Override public void setItemInHand(ItemStack item) { - equipment[0] = item; - changedEquip[0] = true; + setItem(EquipmentSlot.HAND, item); } @Override public ItemStack getBoots() { - return equipment[1]; + return getItem(EquipmentSlot.FEET); } @Override public void setBoots(ItemStack item) { - equipment[1] = item; - changedEquip[1] = true; + setItem(EquipmentSlot.FEET, item); } @Override public ItemStack getLeggings() { - return equipment[2]; + return getItem(EquipmentSlot.LEGS); } @Override public void setLeggings(ItemStack item) { - equipment[2] = item; - changedEquip[2] = true; + setItem(EquipmentSlot.LEGS, item); } @Override public ItemStack getChestplate() { - return equipment[3]; + return getItem(EquipmentSlot.CHEST); } @Override public void setChestplate(ItemStack item) { - equipment[3] = item; - changedEquip[3] = true; + setItem(EquipmentSlot.CHEST, item); } @Override public ItemStack getHelmet() { - return equipment[4]; + return getItem(EquipmentSlot.HEAD); } @Override public void setHelmet(ItemStack item) { - equipment[4] = item; - changedEquip[4] = true; + setItem(EquipmentSlot.HEAD, item); + } + + private ItemStack getItem(EquipmentSlot slot) { + return equipment[slot.ordinal()]; + } + + private void setItem(EquipmentSlot slot, ItemStack item) { + equipment[slot.ordinal()] = item; + changedEquip[slot.ordinal()] = true; } @Override diff --git a/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java b/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java index 580723b176..2e61f305c7 100644 --- a/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java +++ b/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java @@ -1,24 +1,20 @@ package net.glowstone.net.handler.play.player; -import com.flowpowered.network.MessageHandler; -import net.glowstone.EventFactory; -import net.glowstone.GlowServer; -import net.glowstone.constants.AttackDamage; -import net.glowstone.entity.GlowEntity; -import net.glowstone.entity.GlowLivingEntity; -import net.glowstone.entity.GlowPlayer; -import net.glowstone.net.GlowSession; -import net.glowstone.net.message.play.player.InteractEntityMessage; -import net.glowstone.net.message.play.player.InteractEntityMessage.Action; -import net.glowstone.util.InventoryUtil; -import org.bukkit.GameMode; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.EntityType; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.inventory.ItemStack; +import com.flowpowered.network.*; +import net.glowstone.*; +import net.glowstone.constants.*; +import net.glowstone.entity.*; +import net.glowstone.net.*; +import net.glowstone.net.message.play.player.*; +import net.glowstone.net.message.play.player.InteractEntityMessage.*; +import net.glowstone.util.*; +import org.bukkit.*; +import org.bukkit.enchantments.*; +import org.bukkit.entity.*; +import org.bukkit.event.entity.EntityDamageEvent.*; +import org.bukkit.event.player.*; +import org.bukkit.inventory.*; +import org.bukkit.util.*; //import org.bukkit.event.player.PlayerInteractAtEntityEvent; @@ -74,9 +70,13 @@ public void handle(GlowSession session, InteractEntityMessage message) { } } } else if (message.getAction() == Action.INTERACT_AT.ordinal()) { - //todo: Handle hand variable - // todo: Interaction with entity at a specified location (X, Y, and Z are present in the message) // used for adjusting specific portions of armor stands + PlayerInteractAtEntityEvent event = new PlayerInteractAtEntityEvent(player, possibleTarget, new Vector(message.getTargetX(), message.getTargetY(), message.getTargetZ())); + EventFactory.callEvent(event); + + if (!event.isCancelled()) { + possibleTarget.entityInteract(player, message); + } } else if (message.getAction() == Action.INTERACT.ordinal()) { //Todo: Handle hand variable PlayerInteractEntityEvent event = new PlayerInteractEntityEvent(player, possibleTarget); diff --git a/start.sh b/start.sh index 87c634cb5a..1858ef8f33 100755 --- a/start.sh +++ b/start.sh @@ -1,2 +1,2 @@ #!/bin/sh -java -Xms1G -Xmx1G -XX:+UseG1GC -jar glowstone.jar +java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms1G -Xmx1G -XX:+UseG1GC -jar glowstone.jar From 85e036b512639e91d635aeb31b7940db7fcdaa52 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Wed, 5 Jul 2017 23:48:54 +0200 Subject: [PATCH 02/10] Implement ArmorStand.getEquipment() --- .../entity/objects/GlowArmorStand.java | 74 +++---- .../inventory/GlowEntityEquipment.java | 194 ++++++++++++++++++ 2 files changed, 224 insertions(+), 44 deletions(-) create mode 100644 src/main/java/net/glowstone/inventory/GlowEntityEquipment.java diff --git a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java index c5262423f4..2d7351ab6e 100644 --- a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java +++ b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java @@ -38,8 +38,7 @@ public class GlowArmorStand extends GlowLivingEntity implements ArmorStand { } - private final ItemStack[] equipment = new ItemStack[6]; - private final boolean[] changedEquip = new boolean[6]; + private final GlowEntityEquipment equipment; private final EulerAngle[] pose = new EulerAngle[6]; private boolean isMarker; @@ -54,18 +53,16 @@ public class GlowArmorStand extends GlowLivingEntity implements ArmorStand { public GlowArmorStand(Location location) { super(location, 2); + equipment = new GlowEntityEquipment(this); + System.arraycopy(defaultPose, 0, pose, 0, 6); - for (int i = 0; i < equipment.length; i++) { - changedEquip[i] = false; - } + this.getEquipmentMonitor().resetChanges(); } @Override public void reset() { super.reset(); - for (int i = 0; i < equipment.length; i++) { - changedEquip[i] = false; - } + this.getEquipmentMonitor().resetChanges(); if (needsKill) needsKill = false; } @@ -135,8 +132,8 @@ private void setHealth(double health, boolean drop) { private void kill(boolean dropArmorStand) { active = false; ((GlowWorld) location.getWorld()).showParticle(location.clone().add(0, 1.317, 0), Effect.TILE_DUST, Material.WOOD.getId(), 0, 0.125f, 0.494f, 0.125f, 0.1f, 10, 10); - for (ItemStack stack : equipment) { - if (stack == null || stack.getType() == Material.AIR) continue; + for (ItemStack stack : equipment.getArmorContents()) { + if (InventoryUtil.isEmpty(stack)) continue; getWorld().dropItemNaturally(location, stack); } if (dropArmorStand) { @@ -151,7 +148,7 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { if (InventoryUtil.isEmpty(player.getItemInHand())) { EquipmentSlot slot = getEditSlot(msg.getTargetY()); - PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, InventoryUtil.itemOrEmpty(null), InventoryUtil.itemOrEmpty(getItem(slot)), slot); + PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, InventoryUtil.itemOrEmpty(null), InventoryUtil.itemOrEmpty(equipment.getItem(slot)), slot); EventFactory.callEvent(event); if (event.isCancelled()) { @@ -162,9 +159,9 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { return false; } - ItemStack stack = getItem(slot); + ItemStack stack = equipment.getItem(slot); player.setItemInHand(stack); - setItem(slot, InventoryUtil.createEmptyStack()); + equipment.setItem(slot, InventoryUtil.createEmptyStack()); return true; } else { EquipmentSlot slot = getEquipType(player.getItemInHand().getType()); @@ -172,7 +169,7 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { return false; } - PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, player.getItemInHand(), InventoryUtil.itemOrEmpty(getItem(slot)), slot); + PlayerArmorStandManipulateEvent event = new PlayerArmorStandManipulateEvent(player, this, player.getItemInHand(), InventoryUtil.itemOrEmpty(equipment.getItem(slot)), slot); EventFactory.callEvent(event); if (event.isCancelled()) { @@ -192,13 +189,13 @@ public boolean entityInteract(GlowPlayer player, InteractEntityMessage msg) { if (stack.getAmount() > 1) { return false; } - back = getItem(slot); + back = equipment.getItem(slot); } if (!InventoryUtil.isEmpty(back)) { player.setItemInHand(back); } - setItem(slot, stack); + equipment.setItem(slot, stack); player.playSound(location, getEquipSound(stack.getType()), SoundCategory.NEUTRAL, 1, 1); return true; } @@ -281,7 +278,7 @@ private EquipmentSlot getEditSlot(float height) { } private boolean isEmpty(EquipmentSlot slot) { - return InventoryUtil.isEmpty(getItem(slot)); + return InventoryUtil.isEmpty(equipment.getItem(slot)); } @Override @@ -322,15 +319,8 @@ public List createSpawnMessage() { @Override public List createUpdateMessage() { List messages = super.createUpdateMessage(); - messages.add(new EntityMetadataMessage(id, metadata.getEntryList())); - for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { - int slot = equipmentSlot.ordinal(); - if (changedEquip[slot]) { - messages.add(new EntityEquipmentMessage(id, slot, getItem(equipmentSlot))); - } - } if (needsKill) { - messages.add(new DestroyEntitiesMessage(Arrays.asList(id))); + messages.add(new DestroyEntitiesMessage(Collections.singletonList(id))); } return messages; @@ -348,61 +338,52 @@ public Location getOrigin() { @Override public ItemStack getItemInHand() { - return getItem(EquipmentSlot.HAND); + return equipment.getItemInHand(); } @Override public void setItemInHand(ItemStack item) { - setItem(EquipmentSlot.HAND, item); + equipment.setItemInHand(item); } @Override public ItemStack getBoots() { - return getItem(EquipmentSlot.FEET); + return equipment.getBoots(); } @Override public void setBoots(ItemStack item) { - setItem(EquipmentSlot.FEET, item); + equipment.setBoots(item); } @Override public ItemStack getLeggings() { - return getItem(EquipmentSlot.LEGS); + return equipment.getLeggings(); } @Override public void setLeggings(ItemStack item) { - setItem(EquipmentSlot.LEGS, item); + equipment.setLeggings(item); } @Override public ItemStack getChestplate() { - return getItem(EquipmentSlot.CHEST); + return equipment.getChestplate(); } @Override public void setChestplate(ItemStack item) { - setItem(EquipmentSlot.CHEST, item); + equipment.setChestplate(item); } @Override public ItemStack getHelmet() { - return getItem(EquipmentSlot.HEAD); + return equipment.getHelmet(); } @Override public void setHelmet(ItemStack item) { - setItem(EquipmentSlot.HEAD, item); - } - - private ItemStack getItem(EquipmentSlot slot) { - return equipment[slot.ordinal()]; - } - - private void setItem(EquipmentSlot slot, ItemStack item) { - equipment[slot.ordinal()] = item; - changedEquip[slot.ordinal()] = true; + equipment.setHelmet(item); } @Override @@ -591,4 +572,9 @@ public int getArrowsStuck() { public void setArrowsStuck(int i) { } + + @Override + public EntityEquipment getEquipment() { + return this.equipment; + } } diff --git a/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java new file mode 100644 index 0000000000..e7704dc5cc --- /dev/null +++ b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java @@ -0,0 +1,194 @@ +package net.glowstone.inventory; + +import net.glowstone.util.*; +import org.bukkit.entity.*; +import org.bukkit.inventory.*; + +public class GlowEntityEquipment implements EntityEquipment { + + private ItemStack[] slots = new ItemStack[6]; + private Entity holder; + + public GlowEntityEquipment(Entity holder) { + this.holder = holder; + } + + public ItemStack getItem(EquipmentSlot slot) { + return slots[slot.ordinal()]; + } + + public void setItem(EquipmentSlot slot, ItemStack item) { + slots[slot.ordinal()] = item; + } + + @Override + public ItemStack getItemInMainHand() { + return getItem(EquipmentSlot.HAND); + } + + @Override + public void setItemInMainHand(ItemStack itemStack) { + setItem(EquipmentSlot.HAND, itemStack); + } + + @Override + public ItemStack getItemInOffHand() { + return getItem(EquipmentSlot.OFF_HAND); + } + + @Override + public void setItemInOffHand(ItemStack itemStack) { + setItem(EquipmentSlot.OFF_HAND, itemStack); + } + + @Override + public ItemStack getItemInHand() { + return getItemInMainHand(); + } + + @Override + public void setItemInHand(ItemStack itemStack) { + setItemInMainHand(itemStack); + } + + @Override + public ItemStack getHelmet() { + return getItem(EquipmentSlot.HEAD); + } + + @Override + public void setHelmet(ItemStack itemStack) { + setItem(EquipmentSlot.HEAD, itemStack); + } + + @Override + public ItemStack getChestplate() { + return getItem(EquipmentSlot.CHEST); + } + + @Override + public void setChestplate(ItemStack itemStack) { + setItem(EquipmentSlot.CHEST, itemStack); + } + + @Override + public ItemStack getLeggings() { + return getItem(EquipmentSlot.LEGS); + } + + @Override + public void setLeggings(ItemStack itemStack) { + setItem(EquipmentSlot.LEGS, itemStack); + } + + @Override + public ItemStack getBoots() { + return getItem(EquipmentSlot.FEET); + } + + @Override + public void setBoots(ItemStack itemStack) { + setItem(EquipmentSlot.FEET, itemStack); + } + + @Override + public ItemStack[] getArmorContents() { + ItemStack[] armor = new ItemStack[4]; + for (int i = 0; i < 4; i++) { + armor[i] = getItem(EquipmentSlot.values()[EquipmentSlot.FEET.ordinal() + i]); + } + return armor; + } + + @Override + public void setArmorContents(ItemStack[] itemStacks) { + if (itemStacks.length != slots.length) { + throw new IllegalArgumentException("Length of armor must be " + slots.length); + } + for (EquipmentSlot slot : EquipmentSlot.values()) { + setItem(slot, itemStacks[slot.ordinal()]); + } + } + + @Override + public void clear() { + for (EquipmentSlot slot : EquipmentSlot.values()) { + setItem(slot, InventoryUtil.createEmptyStack()); + } + } + + @Override + public float getItemInHandDropChance() { + return 1; + } + + @Override + public void setItemInHandDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getItemInMainHandDropChance() { + return 1; + } + + @Override + public void setItemInMainHandDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getItemInOffHandDropChance() { + return 1; + } + + @Override + public void setItemInOffHandDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getHelmetDropChance() { + return 1; + } + + @Override + public void setHelmetDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getChestplateDropChance() { + return 1; + } + + @Override + public void setChestplateDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getLeggingsDropChance() { + return 1; + } + + @Override + public void setLeggingsDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public float getBootsDropChance() { + return 1; + } + + @Override + public void setBootsDropChance(float chance) { + throw new UnsupportedOperationException(); + } + + @Override + public Entity getHolder() { + return this.holder; + } +} From 19a0c759a1b40f43cbacae8785cc90570364f699 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Thu, 6 Jul 2017 18:51:02 +0200 Subject: [PATCH 03/10] Fix some imports some javadocs fix implementation of setArmorContents --- .../entity/objects/GlowArmorStand.java | 66 +++++++++++++------ .../inventory/GlowEntityEquipment.java | 27 ++++++-- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java index 2d7351ab6e..0640c27c7e 100644 --- a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java +++ b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java @@ -1,25 +1,51 @@ package net.glowstone.entity.objects; -import com.flowpowered.network.*; -import java.util.*; -import net.glowstone.*; -import net.glowstone.entity.*; -import net.glowstone.entity.meta.*; -import net.glowstone.entity.meta.MetadataIndex.*; -import net.glowstone.inventory.*; -import net.glowstone.net.message.play.entity.*; -import net.glowstone.net.message.play.player.*; -import net.glowstone.net.message.play.player.InteractEntityMessage.*; -import net.glowstone.util.*; -import org.bukkit.*; -import org.bukkit.attribute.*; -import org.bukkit.entity.*; -import org.bukkit.event.entity.*; -import org.bukkit.event.entity.EntityDamageEvent.*; -import org.bukkit.event.player.*; -import org.bukkit.inventory.*; -import org.bukkit.scoreboard.*; -import org.bukkit.util.*; + +import com.flowpowered.network.Message; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import net.glowstone.EventFactory; +import net.glowstone.GlowWorld; +import net.glowstone.entity.GlowLivingEntity; +import net.glowstone.entity.GlowPlayer; +import net.glowstone.entity.meta.MetadataIndex; +import net.glowstone.entity.meta.MetadataIndex.ArmorStandFlags; +import net.glowstone.entity.meta.MetadataIndex.StatusFlags; +import net.glowstone.inventory.ClothType; +import net.glowstone.inventory.GlowEntityEquipment; +import net.glowstone.net.message.play.entity.DestroyEntitiesMessage; +import net.glowstone.net.message.play.entity.EntityEquipmentMessage; +import net.glowstone.net.message.play.entity.EntityMetadataMessage; +import net.glowstone.net.message.play.entity.SpawnObjectMessage; +import net.glowstone.net.message.play.player.InteractEntityMessage; +import net.glowstone.net.message.play.player.InteractEntityMessage.Action; +import net.glowstone.util.InventoryUtil; +import net.glowstone.util.Position; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scoreboard.Criterias; +import org.bukkit.scoreboard.Objective; +import org.bukkit.util.EulerAngle; public class GlowArmorStand extends GlowLivingEntity implements ArmorStand { diff --git a/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java index e7704dc5cc..fd8e51526b 100644 --- a/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java +++ b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java @@ -1,8 +1,10 @@ package net.glowstone.inventory; -import net.glowstone.util.*; -import org.bukkit.entity.*; -import org.bukkit.inventory.*; +import net.glowstone.util.InventoryUtil; +import org.bukkit.entity.Entity; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; public class GlowEntityEquipment implements EntityEquipment { @@ -13,10 +15,20 @@ public GlowEntityEquipment(Entity holder) { this.holder = holder; } + /** + * Returns the ItemStack found in the slot at the given EquipmentSlot + * @param slot The EquipmentSlot of the Slot's ItemStack to return + * @return The ItemStack in the slot, or null, if no item is in this slot. + */ public ItemStack getItem(EquipmentSlot slot) { return slots[slot.ordinal()]; } + /** + * Stores the ItemStack at the given index of the inventory. + * @param slot The EquipmentSlot where to put the ItemStack + * @param item The ItemStack to set + */ public void setItem(EquipmentSlot slot, ItemStack item) { slots[slot.ordinal()] = item; } @@ -94,8 +106,9 @@ public void setBoots(ItemStack itemStack) { @Override public ItemStack[] getArmorContents() { ItemStack[] armor = new ItemStack[4]; - for (int i = 0; i < 4; i++) { - armor[i] = getItem(EquipmentSlot.values()[EquipmentSlot.FEET.ordinal() + i]); + int feet = EquipmentSlot.FEET.ordinal(); + for (int i = feet; i < slots.length; i++) { + armor[i - feet] = getItem(EquipmentSlot.values()[i]); } return armor; } @@ -105,8 +118,8 @@ public void setArmorContents(ItemStack[] itemStacks) { if (itemStacks.length != slots.length) { throw new IllegalArgumentException("Length of armor must be " + slots.length); } - for (EquipmentSlot slot : EquipmentSlot.values()) { - setItem(slot, itemStacks[slot.ordinal()]); + for (int i = EquipmentSlot.FEET.ordinal(); i < slots.length; i++) { + setItem(EquipmentSlot.values()[i], itemStacks[i]); } } From a0279d76da11b3b6df65848049efc739be2847a2 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Thu, 6 Jul 2017 19:49:02 +0200 Subject: [PATCH 04/10] Implement drop chances --- .../inventory/GlowEntityEquipment.java | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java index fd8e51526b..7788938fe0 100644 --- a/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java +++ b/src/main/java/net/glowstone/inventory/GlowEntityEquipment.java @@ -1,5 +1,7 @@ package net.glowstone.inventory; +import lombok.AllArgsConstructor; +import net.glowstone.constants.ItemIds; import net.glowstone.util.InventoryUtil; import org.bukkit.entity.Entity; import org.bukkit.inventory.EntityEquipment; @@ -8,7 +10,7 @@ public class GlowEntityEquipment implements EntityEquipment { - private ItemStack[] slots = new ItemStack[6]; + private Entry[] slots = new Entry[6]; private Entity holder; public GlowEntityEquipment(Entity holder) { @@ -18,19 +20,40 @@ public GlowEntityEquipment(Entity holder) { /** * Returns the ItemStack found in the slot at the given EquipmentSlot * @param slot The EquipmentSlot of the Slot's ItemStack to return - * @return The ItemStack in the slot, or null, if no item is in this slot. + * @return The ItemStack in the slot */ public ItemStack getItem(EquipmentSlot slot) { + Entry slotEntry = getSlotEntry(slot); + ItemStack stack = slotEntry != null ? slotEntry.item : null; + return InventoryUtil.itemOrEmpty(stack); + } + + private Entry getSlotEntry(EquipmentSlot slot) { return slots[slot.ordinal()]; } + private float getDropChance(EquipmentSlot slot) { + Entry slotEntry = getSlotEntry(slot); + return slotEntry == null ? 1F : slotEntry.dropChance; + } + /** * Stores the ItemStack at the given index of the inventory. * @param slot The EquipmentSlot where to put the ItemStack * @param item The ItemStack to set */ public void setItem(EquipmentSlot slot, ItemStack item) { - slots[slot.ordinal()] = item; + Entry entry = new Entry(ItemIds.sanitize(item), 1f); + slots[slot.ordinal()] = entry; + } + + private void setDropChance(EquipmentSlot slot, float chance) { + Entry slotEntry = getSlotEntry(slot); + if (slotEntry == null) { + return; + } + + slotEntry.dropChance = chance; } @Override @@ -132,76 +155,82 @@ public void clear() { @Override public float getItemInHandDropChance() { - return 1; + return getDropChance(EquipmentSlot.HAND); } @Override public void setItemInHandDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.HAND, chance); } @Override public float getItemInMainHandDropChance() { - return 1; + return getItemInHandDropChance(); } @Override public void setItemInMainHandDropChance(float chance) { - throw new UnsupportedOperationException(); + setItemInHandDropChance(chance); } @Override public float getItemInOffHandDropChance() { - return 1; + return getDropChance(EquipmentSlot.OFF_HAND); } @Override public void setItemInOffHandDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.OFF_HAND, chance); } @Override public float getHelmetDropChance() { - return 1; + return getDropChance(EquipmentSlot.HEAD); } @Override public void setHelmetDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.HEAD, chance); } @Override public float getChestplateDropChance() { - return 1; + return getDropChance(EquipmentSlot.CHEST); } @Override public void setChestplateDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.CHEST, chance); } @Override public float getLeggingsDropChance() { - return 1; + return getDropChance(EquipmentSlot.LEGS); } @Override public void setLeggingsDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.LEGS, chance); } @Override public float getBootsDropChance() { - return 1; + return getDropChance(EquipmentSlot.FEET); } @Override public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException(); + setDropChance(EquipmentSlot.FEET, chance); } @Override public Entity getHolder() { return this.holder; } + + @AllArgsConstructor + private class Entry { + private ItemStack item; + private float dropChance; + } } From a569c6c26f045ac53217477d461a00c0777581db Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Thu, 6 Jul 2017 20:39:03 +0200 Subject: [PATCH 05/10] Store offhand equipment implemented the HandItems, ArmorItems --- .../io/entity/LivingEntityStore.java | 115 +++++++++++++----- 1 file changed, 83 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/glowstone/io/entity/LivingEntityStore.java b/src/main/java/net/glowstone/io/entity/LivingEntityStore.java index 49c703de49..470505861c 100644 --- a/src/main/java/net/glowstone/io/entity/LivingEntityStore.java +++ b/src/main/java/net/glowstone/io/entity/LivingEntityStore.java @@ -8,6 +8,7 @@ import net.glowstone.util.nbt.CompoundTag; import net.glowstone.util.nbt.TagType; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -95,26 +96,7 @@ public void load(T entity, CompoundTag compound) { EntityEquipment equip = entity.getEquipment(); if (equip != null) { - if (compound.isList("Equipment", TagType.COMPOUND)) { - List list = compound.getCompoundList("Equipment"); - if (list.size() == 5) { - equip.setItemInHand(NbtSerialization.readItem(list.get(0))); - equip.setBoots(NbtSerialization.readItem(list.get(1))); - equip.setLeggings(NbtSerialization.readItem(list.get(2))); - equip.setChestplate(NbtSerialization.readItem(list.get(3))); - equip.setHelmet(NbtSerialization.readItem(list.get(4))); - } - } - if (compound.isList("DropChances", TagType.FLOAT)) { - List list = compound.getList("DropChances", TagType.FLOAT); - if (list.size() == 5) { - equip.setItemInHandDropChance(list.get(0)); - equip.setBootsDropChance(list.get(1)); - equip.setLeggingsDropChance(list.get(2)); - equip.setChestplateDropChance(list.get(3)); - equip.setHelmetDropChance(list.get(4)); - } - } + loadEquipment(entity, equip, compound); } if (compound.isByte("CanPickUpLoot")) { entity.setCanPickupItems(compound.getBool("CanPickUpLoot")); @@ -148,6 +130,68 @@ public void load(T entity, CompoundTag compound) { } } + private void loadEquipment(T entity, EntityEquipment equip, CompoundTag compound) { + // Deprecated since 15w31a, left here for compatibilty for now + if (compound.isList("Equipment", TagType.COMPOUND)) { + List list = compound.getCompoundList("Equipment"); + if (list.size() == 5) { + equip.setItemInHand(NbtSerialization.readItem(list.get(0))); + equip.setBoots(NbtSerialization.readItem(list.get(1))); + equip.setLeggings(NbtSerialization.readItem(list.get(2))); + equip.setChestplate(NbtSerialization.readItem(list.get(3))); + equip.setHelmet(NbtSerialization.readItem(list.get(4))); + } + } + // Deprecated since 15w31a, left here for compatibilty for now + if (compound.isList("DropChances", TagType.FLOAT)) { + List list = compound.getList("DropChances", TagType.FLOAT); + if (list.size() == 5) { + equip.setItemInHandDropChance(list.get(0)); + equip.setBootsDropChance(list.get(1)); + equip.setLeggingsDropChance(list.get(2)); + equip.setChestplateDropChance(list.get(3)); + equip.setHelmetDropChance(list.get(4)); + } + } + + if (compound.isList("HandItems", TagType.COMPOUND)) { + List list = compound.getCompoundList("HandItems"); + if (list.size() == 2) { + equip.setItemInMainHand(NbtSerialization.readItem(list.get(0))); + equip.setItemInOffHand(NbtSerialization.readItem(list.get(1))); + } + } + if (compound.isList("ArmorItems", TagType.COMPOUND)) { + List list = compound.getCompoundList("ArmorItems"); + if (list.size() == 4) { + equip.setBoots(NbtSerialization.readItem(list.get(0))); + equip.setLeggings(NbtSerialization.readItem(list.get(1))); + equip.setChestplate(NbtSerialization.readItem(list.get(2))); + equip.setHelmet(NbtSerialization.readItem(list.get(3))); + } + } + + // set of dropchances on a player throws an UnsupportedOperationException + if (!(entity instanceof Player)) { + if (compound.isList("HandDropChances", TagType.FLOAT)) { + List list = compound.getList("HandDropChances", TagType.FLOAT); + if (list.size() == 2) { + equip.setItemInHandDropChance(list.get(0)); + equip.setItemInOffHandDropChance(list.get(1)); + } + } + if (compound.isList("ArmorDropChances", TagType.FLOAT)) { + List list = compound.getList("ArmorDropChances", TagType.FLOAT); + if (list.size() == 4) { + equip.setBootsDropChance(list.get(0)); + equip.setLeggingsDropChance(list.get(1)); + equip.setChestplateDropChance(list.get(2)); + equip.setHelmetDropChance(list.get(3)); + } + } + } + } + @Override public void save(T entity, CompoundTag tag) { super.save(entity, tag); @@ -208,19 +252,26 @@ public void save(T entity, CompoundTag tag) { EntityEquipment equip = entity.getEquipment(); if (equip != null) { - tag.putCompoundList("Equipment", Arrays.asList( - NbtSerialization.writeItem(equip.getItemInHand(), -1), - NbtSerialization.writeItem(equip.getBoots(), -1), - NbtSerialization.writeItem(equip.getLeggings(), -1), - NbtSerialization.writeItem(equip.getChestplate(), -1), - NbtSerialization.writeItem(equip.getHelmet(), -1) + tag.putCompoundList("HandItems", Arrays.asList( + NbtSerialization.writeItem(equip.getItemInMainHand(), -1), + NbtSerialization.writeItem(equip.getItemInOffHand(), -1) + )); + tag.putCompoundList("ArmorItems", Arrays.asList( + NbtSerialization.writeItem(equip.getBoots(), -1), + NbtSerialization.writeItem(equip.getLeggings(), -1), + NbtSerialization.writeItem(equip.getChestplate(), -1), + NbtSerialization.writeItem(equip.getHelmet(), -1) + )); + + tag.putList("HandDropChances", TagType.FLOAT, Arrays.asList( + equip.getItemInMainHandDropChance(), + equip.getItemInOffHandDropChance() )); - tag.putList("DropChances", TagType.FLOAT, Arrays.asList( - equip.getItemInHandDropChance(), - equip.getBootsDropChance(), - equip.getLeggingsDropChance(), - equip.getChestplateDropChance(), - equip.getHelmetDropChance() + tag.putList("ArmorDropChances", TagType.FLOAT, Arrays.asList( + equip.getBootsDropChance(), + equip.getLeggingsDropChance(), + equip.getChestplateDropChance(), + equip.getHelmetDropChance() )); } tag.putBool("CanPickUpLoot", entity.getCanPickupItems()); From d105bd9b49a07c83714d9d6e6a978b6e996f1a14 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Thu, 6 Jul 2017 20:39:28 +0200 Subject: [PATCH 06/10] Actually send the of hand item on armor stand spawn --- src/main/java/net/glowstone/entity/objects/GlowArmorStand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java index 0640c27c7e..6f6a98cb6f 100644 --- a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java +++ b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java @@ -335,6 +335,7 @@ public List createSpawnMessage() { new SpawnObjectMessage(id, UUID.randomUUID(), 78, x, y, z, pitch, yaw), // TODO: once UUID is documented, actually use the appropriate ID here new EntityMetadataMessage(id, metadata.getEntryList()), new EntityEquipmentMessage(id, EntityEquipmentMessage.HELD_ITEM, getItemInHand()), + new EntityEquipmentMessage(id, EntityEquipmentMessage.OFF_HAND, equipment.getItemInOffHand()), new EntityEquipmentMessage(id, EntityEquipmentMessage.BOOTS_SLOT, getBoots()), new EntityEquipmentMessage(id, EntityEquipmentMessage.LEGGINGS_SLOT, getLeggings()), new EntityEquipmentMessage(id, EntityEquipmentMessage.CHESTPLATE_SLOT, getChestplate()), From eb897271236f93b9400b266390005d37a04fac94 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Thu, 6 Jul 2017 21:03:16 +0200 Subject: [PATCH 07/10] revert changes in start.sh --- start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.sh b/start.sh index 1858ef8f33..87c634cb5a 100755 --- a/start.sh +++ b/start.sh @@ -1,2 +1,2 @@ #!/bin/sh -java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms1G -Xmx1G -XX:+UseG1GC -jar glowstone.jar +java -Xms1G -Xmx1G -XX:+UseG1GC -jar glowstone.jar From 9fa1a69b65ab7d736b8a33daf2ec27a96888d895 Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Fri, 7 Jul 2017 17:33:11 +0200 Subject: [PATCH 08/10] fix imports don't call equipmentmonitor.reset() twice --- .../entity/objects/GlowArmorStand.java | 2 - .../play/player/InteractEntityHandler.java | 38 ++++++++++--------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java index 6f6a98cb6f..35fd979081 100644 --- a/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java +++ b/src/main/java/net/glowstone/entity/objects/GlowArmorStand.java @@ -1,6 +1,5 @@ package net.glowstone.entity.objects; - import com.flowpowered.network.Message; import java.util.Arrays; import java.util.Collections; @@ -88,7 +87,6 @@ public GlowArmorStand(Location location) { @Override public void reset() { super.reset(); - this.getEquipmentMonitor().resetChanges(); if (needsKill) needsKill = false; } diff --git a/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java b/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java index 2e61f305c7..4882b88d75 100644 --- a/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java +++ b/src/main/java/net/glowstone/net/handler/play/player/InteractEntityHandler.java @@ -1,22 +1,26 @@ package net.glowstone.net.handler.play.player; -import com.flowpowered.network.*; -import net.glowstone.*; -import net.glowstone.constants.*; -import net.glowstone.entity.*; -import net.glowstone.net.*; -import net.glowstone.net.message.play.player.*; -import net.glowstone.net.message.play.player.InteractEntityMessage.*; -import net.glowstone.util.*; -import org.bukkit.*; -import org.bukkit.enchantments.*; -import org.bukkit.entity.*; -import org.bukkit.event.entity.EntityDamageEvent.*; -import org.bukkit.event.player.*; -import org.bukkit.inventory.*; -import org.bukkit.util.*; - -//import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import com.flowpowered.network.MessageHandler; +import net.glowstone.EventFactory; +import net.glowstone.GlowServer; +import net.glowstone.constants.AttackDamage; +import net.glowstone.entity.GlowEntity; +import net.glowstone.entity.GlowLivingEntity; +import net.glowstone.entity.GlowPlayer; +import net.glowstone.net.GlowSession; +import net.glowstone.net.message.play.player.InteractEntityMessage; +import net.glowstone.net.message.play.player.InteractEntityMessage.Action; +import net.glowstone.util.InventoryUtil; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.Statistic; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.EntityType; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; public final class InteractEntityHandler implements MessageHandler { From a02ebee18803f0f844d80be30a71b7b8f491d37a Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Fri, 7 Jul 2017 18:00:45 +0200 Subject: [PATCH 09/10] Don't save equipment in armorstandstore we already do that properly in the livingentity Also don't save the *Items and *Chances Tag for a player, since he can never have these tags --- .../net/glowstone/io/entity/ArmorStandStore.java | 16 ---------------- .../glowstone/io/entity/HumanEntityStore.java | 6 ++++-- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/glowstone/io/entity/ArmorStandStore.java b/src/main/java/net/glowstone/io/entity/ArmorStandStore.java index eaa33e51ac..d838b20b06 100644 --- a/src/main/java/net/glowstone/io/entity/ArmorStandStore.java +++ b/src/main/java/net/glowstone/io/entity/ArmorStandStore.java @@ -1,7 +1,6 @@ package net.glowstone.io.entity; import net.glowstone.entity.objects.GlowArmorStand; -import net.glowstone.io.nbt.NbtSerialization; import net.glowstone.util.nbt.CompoundTag; import net.glowstone.util.nbt.TagType; import org.bukkit.Location; @@ -25,14 +24,6 @@ public GlowArmorStand createEntity(Location location, CompoundTag compound) { @Override public void load(GlowArmorStand entity, CompoundTag tag) { super.load(entity, tag); - if (tag.isList("Equipment", TagType.COMPOUND)) { - List equip = tag.getCompoundList("Equipment"); - entity.setItemInHand(NbtSerialization.readItem(equip.get(0))); - entity.setBoots(NbtSerialization.readItem(equip.get(1))); - entity.setLeggings(NbtSerialization.readItem(equip.get(2))); - entity.setChestplate(NbtSerialization.readItem(equip.get(3))); - entity.setHelmet(NbtSerialization.readItem(equip.get(4))); - } if (tag.containsKey("Marker")) { entity.setMarker(tag.getBool("Marker")); } @@ -64,13 +55,6 @@ public void load(GlowArmorStand entity, CompoundTag tag) { @Override public void save(GlowArmorStand entity, CompoundTag tag) { super.save(entity, tag); - tag.putCompoundList("Equipment", Arrays.asList( - NbtSerialization.writeItem(entity.getItemInHand(), -1), - NbtSerialization.writeItem(entity.getBoots(), -1), - NbtSerialization.writeItem(entity.getLeggings(), -1), - NbtSerialization.writeItem(entity.getChestplate(), -1), - NbtSerialization.writeItem(entity.getHelmet(), -1) - )); tag.putBool("Marker", entity.isMarker()); tag.putBool("Invisible", !entity.isVisible()); tag.putBool("NoBasePlate", !entity.hasBasePlate()); diff --git a/src/main/java/net/glowstone/io/entity/HumanEntityStore.java b/src/main/java/net/glowstone/io/entity/HumanEntityStore.java index 277beda0ca..4940cc3f8a 100644 --- a/src/main/java/net/glowstone/io/entity/HumanEntityStore.java +++ b/src/main/java/net/glowstone/io/entity/HumanEntityStore.java @@ -68,8 +68,10 @@ public void save(T entity, CompoundTag tag) { // humans don't have these properties tag.remove("CustomName"); tag.remove("CustomNameVisible"); - tag.remove("Equipment"); - tag.remove("DropChances"); + tag.remove("HandItems"); + tag.remove("ArmorItems"); + tag.remove("HandDropChances"); + tag.remove("ArmorDropChances"); tag.remove("CanPickUpLoot"); tag.remove("PersistenceRequired"); tag.remove("Leashed"); From f35be0b822645ff4a43a11daa32bb0fc3c3090af Mon Sep 17 00:00:00 2001 From: Martin Panzer Date: Fri, 7 Jul 2017 19:56:56 +0200 Subject: [PATCH 10/10] Handle *Items and *Drops Tags with variable sized lists order of the lists musts still be correct, e.g. feet must be before leg If no Item or dropChance is available, load an empty Itemstack or 1f respectively --- .../io/entity/LivingEntityStore.java | 88 ++++++++++++------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/src/main/java/net/glowstone/io/entity/LivingEntityStore.java b/src/main/java/net/glowstone/io/entity/LivingEntityStore.java index 470505861c..72272c831f 100644 --- a/src/main/java/net/glowstone/io/entity/LivingEntityStore.java +++ b/src/main/java/net/glowstone/io/entity/LivingEntityStore.java @@ -5,11 +5,13 @@ import net.glowstone.entity.AttributeManager.Property; import net.glowstone.entity.GlowLivingEntity; import net.glowstone.io.nbt.NbtSerialization; +import net.glowstone.util.InventoryUtil; import net.glowstone.util.nbt.CompoundTag; import net.glowstone.util.nbt.TagType; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -134,64 +136,82 @@ private void loadEquipment(T entity, EntityEquipment equip, CompoundTag compound // Deprecated since 15w31a, left here for compatibilty for now if (compound.isList("Equipment", TagType.COMPOUND)) { List list = compound.getCompoundList("Equipment"); - if (list.size() == 5) { - equip.setItemInHand(NbtSerialization.readItem(list.get(0))); - equip.setBoots(NbtSerialization.readItem(list.get(1))); - equip.setLeggings(NbtSerialization.readItem(list.get(2))); - equip.setChestplate(NbtSerialization.readItem(list.get(3))); - equip.setHelmet(NbtSerialization.readItem(list.get(4))); - } + + equip.setItemInHand(getItem(list, 0)); + equip.setBoots(getItem(list, 1)); + equip.setLeggings(getItem(list, 2)); + equip.setChestplate(getItem(list, 3)); + equip.setHelmet(getItem(list, 4)); } // Deprecated since 15w31a, left here for compatibilty for now if (compound.isList("DropChances", TagType.FLOAT)) { List list = compound.getList("DropChances", TagType.FLOAT); - if (list.size() == 5) { - equip.setItemInHandDropChance(list.get(0)); - equip.setBootsDropChance(list.get(1)); - equip.setLeggingsDropChance(list.get(2)); - equip.setChestplateDropChance(list.get(3)); - equip.setHelmetDropChance(list.get(4)); - } + + equip.setItemInHandDropChance(getOrDefault(list, 0, 1f)); + equip.setBootsDropChance(getOrDefault(list, 1, 1f)); + equip.setLeggingsDropChance(getOrDefault(list, 2, 1f)); + equip.setChestplateDropChance(getOrDefault(list, 3, 1f)); + equip.setHelmetDropChance(getOrDefault(list, 4, 1f)); } if (compound.isList("HandItems", TagType.COMPOUND)) { List list = compound.getCompoundList("HandItems"); - if (list.size() == 2) { - equip.setItemInMainHand(NbtSerialization.readItem(list.get(0))); - equip.setItemInOffHand(NbtSerialization.readItem(list.get(1))); - } + + equip.setItemInMainHand(getItem(list, 0)); + equip.setItemInOffHand(getItem(list, 1)); } if (compound.isList("ArmorItems", TagType.COMPOUND)) { List list = compound.getCompoundList("ArmorItems"); - if (list.size() == 4) { - equip.setBoots(NbtSerialization.readItem(list.get(0))); - equip.setLeggings(NbtSerialization.readItem(list.get(1))); - equip.setChestplate(NbtSerialization.readItem(list.get(2))); - equip.setHelmet(NbtSerialization.readItem(list.get(3))); - } + + equip.setBoots(getItem(list, 0)); + equip.setLeggings(getItem(list, 1)); + equip.setChestplate(getItem(list, 2)); + equip.setHelmet(getItem(list, 3)); } // set of dropchances on a player throws an UnsupportedOperationException if (!(entity instanceof Player)) { if (compound.isList("HandDropChances", TagType.FLOAT)) { List list = compound.getList("HandDropChances", TagType.FLOAT); - if (list.size() == 2) { - equip.setItemInHandDropChance(list.get(0)); - equip.setItemInOffHandDropChance(list.get(1)); - } + + equip.setItemInHandDropChance(getOrDefault(list, 0, 1f)); + equip.setItemInOffHandDropChance(getOrDefault(list, 1, 1f)); } if (compound.isList("ArmorDropChances", TagType.FLOAT)) { List list = compound.getList("ArmorDropChances", TagType.FLOAT); - if (list.size() == 4) { - equip.setBootsDropChance(list.get(0)); - equip.setLeggingsDropChance(list.get(1)); - equip.setChestplateDropChance(list.get(2)); - equip.setHelmetDropChance(list.get(3)); - } + + equip.setBootsDropChance(getOrDefault(list, 0, 1f)); + equip.setLeggingsDropChance(getOrDefault(list, 1, 1f)); + equip.setChestplateDropChance(getOrDefault(list, 2, 1f)); + equip.setHelmetDropChance(getOrDefault(list, 3, 1f)); } } } + private ItemStack getItem(List list, int index) { + if (list == null) { + return InventoryUtil.createEmptyStack(); + } + + if (index >= list.size()) { + return InventoryUtil.createEmptyStack(); + } + + return NbtSerialization.readItem(list.get(index)); + } + + private float getOrDefault(List list, int index, float defaultValue) { + if (list == null) { + return defaultValue; + } + + if (index >= list.size()) { + return defaultValue; + } + + return list.get(index); + } + @Override public void save(T entity, CompoundTag tag) { super.save(entity, tag);