- 205
- 12
- 103
Привет. Недавно решил попробовать использовать НБТ не только на мобах, но и на предметах, и... У меня это не получилось.
Задача:
Есть баблс (фенечка для мода Baubles), которую можно экипировать в слот тела, эта фенечка обладает значением счетчика времени и количеством убитых мобов. При убийстве моба счетчик повышается на 1 единицу. Если в течение 10 секунд после убийства моба не убить еще одного моба - счетчик понизится на 1. Затем урон игрока просто повышается на 10% от основного урона оружия за каждую единицу счетчика.
Проблема:
Запись данных счетчика времени и убитых мобов в НБТ предмета, а не в глобальные переменные. Я нагородил кучу утилитарных методов (хотя, подозреваю, что подобное до меня уже изобрели), но так и не смог получить итемстак предмета в инвентаре баблса конкретного игрока. В результате мои НБТ данные не изменяются при убийстве мобов или обновлении игрока, а значит, предмет не работает и вовсе.
Код всего класса с последними моими (неудачными) попытками нагородить хоть что-то, чтоб оно работало:
Задача:
Есть баблс (фенечка для мода Baubles), которую можно экипировать в слот тела, эта фенечка обладает значением счетчика времени и количеством убитых мобов. При убийстве моба счетчик повышается на 1 единицу. Если в течение 10 секунд после убийства моба не убить еще одного моба - счетчик понизится на 1. Затем урон игрока просто повышается на 10% от основного урона оружия за каждую единицу счетчика.
Проблема:
Запись данных счетчика времени и убитых мобов в НБТ предмета, а не в глобальные переменные. Я нагородил кучу утилитарных методов (хотя, подозреваю, что подобное до меня уже изобрели), но так и не смог получить итемстак предмета в инвентаре баблса конкретного игрока. В результате мои НБТ данные не изменяются при убийстве мобов или обновлении игрока, а значит, предмет не работает и вовсе.
Код всего класса с последними моими (неудачными) попытками нагородить хоть что-то, чтоб оно работало:
SoulEngineItem:
public class SoulEngineItem extends ItemBase implements IBauble {
private static final String TAG_UPDATE_TIME = "update_time";
private static final String TAG_KILLED_COUNT = "killed_count";
public SoulEngineItem() {
this.setRegistryName("soul_engine");
this.setUnlocalizedName("soul_engine");
}
@Override
public BaubleType getBaubleType(ItemStack itemStack) {
return BaubleType.BODY;
}
@Override
public void onEquipped(ItemStack itemstack, EntityLivingBase player) {
NBTTagCompound nbtTagCompound = itemstack.getTagCompound();
if (nbtTagCompound == null) {
nbtTagCompound = new NBTTagCompound();
itemstack.setTagCompound(nbtTagCompound);
}
nbtTagCompound.setInteger(TAG_KILLED_COUNT, 0);
nbtTagCompound.setInteger(TAG_UPDATE_TIME, 0);
}
@Override
public void onUnequipped(ItemStack itemstack, EntityLivingBase player) {
NBTTagCompound nbtTagCompound = itemstack.getTagCompound();
if (nbtTagCompound == null) {
nbtTagCompound = new NBTTagCompound();
itemstack.setTagCompound(nbtTagCompound);
}
nbtTagCompound.setInteger(TAG_KILLED_COUNT, 0);
nbtTagCompound.setInteger(TAG_UPDATE_TIME, 0);
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (!world.isRemote) {
IBaublesItemHandler baubles = BaublesApi.getBaublesHandler(player);
for (int i = 0; i < baubles.getSlots(); ++i) {
if ((baubles.getStackInSlot(i) == null || baubles.getStackInSlot(i).isEmpty()) && baubles.isItemValidForSlot(i, player.getHeldItem(hand), player)) {
baubles.setStackInSlot(i, player.getHeldItem(hand).copy());
if (!player.capabilities.isCreativeMode) {
player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY);
}
this.onEquipped(player.getHeldItem(hand), player);
break;
}
}
}
return new ActionResult(EnumActionResult.SUCCESS, player.getHeldItem(hand));
}
public static int getUpdateTime(NBTTagCompound nbtTagCompound) {
if (nbtTagCompound != null && nbtTagCompound.hasKey(TAG_UPDATE_TIME)) {
return nbtTagCompound.getInteger(TAG_UPDATE_TIME);
} else {
return 0;
}
}
public static int getKilledCount(NBTTagCompound nbtTagCompound) {
if (nbtTagCompound != null && nbtTagCompound.hasKey(TAG_KILLED_COUNT)) {
return nbtTagCompound.getInteger(TAG_KILLED_COUNT);
} else {
return 0;
}
}
public static void setUpdateTime(NBTTagCompound nbtTagCompound, int time) {
if (nbtTagCompound != null) {
if (nbtTagCompound.hasKey(TAG_KILLED_COUNT)) {
nbtTagCompound.setInteger(TAG_UPDATE_TIME, time);
} else {
nbtTagCompound.setInteger(TAG_UPDATE_TIME, 0);
}
}
}
public static void setKilledCount(NBTTagCompound nbtTagCompound, int count) {
if (nbtTagCompound != null) {
if (nbtTagCompound.hasKey(TAG_KILLED_COUNT)) {
nbtTagCompound.setInteger(TAG_KILLED_COUNT, count);
} else {
nbtTagCompound.setInteger(TAG_KILLED_COUNT, 0);
}
}
}
public static ItemStack getBauble(EntityPlayer player, ItemStack itemStack) { //Проблема, полагаю, в этом методе и его использовании в ивентах
if (player != null) {
IBaublesItemHandler baubles = BaublesApi.getBaublesHandler(player);
for (int i = 0; i < baubles.getSlots(); ++i) {
if (baubles.getStackInSlot(i) == itemStack) {
return baubles.getStackInSlot(i);
} else {
return ItemStack.EMPTY;
}
}
}
return ItemStack.EMPTY;
}
@Mod.EventBusSubscriber
public static class SoulEngineServerEvents {
@SubscribeEvent
public void onEntityKill(LivingDeathEvent event) {
if (event.getSource().getTrueSource() instanceof EntityPlayer && !(event.getSource().getTrueSource() instanceof FakePlayer)) {
EntityPlayer source = (EntityPlayer) event.getSource().getTrueSource();
if (BaublesApi.isBaubleEquipped(source, ItemRegistry.SOUL_ENGINE) != -1) {
NBTTagCompound nbtTagCompound = getBauble(source, new ItemStack(ItemRegistry.SOUL_ENGINE)).getTagCompound();
if (getKilledCount(nbtTagCompound) < 10 && getUpdateTime(nbtTagCompound) >= 0) {
setKilledCount(nbtTagCompound, getKilledCount(nbtTagCompound) + 1);
setUpdateTime(nbtTagCompound, 200);
}
}
}
}
@SubscribeEvent
public void onUpdate(LivingEvent.LivingUpdateEvent event) {
if (event.getEntity() instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) event.getEntity();
if (BaublesApi.isBaubleEquipped(player, ItemRegistry.SOUL_ENGINE) != -1) {
NBTTagCompound nbtTagCompound = getBauble(player, new ItemStack(ItemRegistry.SOUL_ENGINE)).getTagCompound();
if (getUpdateTime(nbtTagCompound) > 0) {
setUpdateTime(nbtTagCompound, getUpdateTime(nbtTagCompound) - 1);
} else if (getUpdateTime(nbtTagCompound) == 0 && getKilledCount(nbtTagCompound) > 0) {
setKilledCount(nbtTagCompound, getKilledCount(nbtTagCompound) - 1);
setUpdateTime(nbtTagCompound, 200);
}
}
}
}
@SubscribeEvent
public void onEntityDamage(LivingHurtEvent event) {
if (event.getSource().getTrueSource() instanceof EntityPlayer && !(event.getSource().getTrueSource() instanceof FakePlayer)) {
EntityPlayer source = (EntityPlayer) event.getSource().getTrueSource();
NBTTagCompound nbtTagCompound = getBauble(source, new ItemStack(ItemRegistry.SOUL_ENGINE)).getTagCompound();
if (BaublesApi.isBaubleEquipped(source, ItemRegistry.SOUL_ENGINE) != -1 && getKilledCount(nbtTagCompound) > 0) {
event.setAmount((float) (event.getAmount() + getKilledCount(nbtTagCompound) * (event.getAmount() * 0.3)));
}
}
}
}
}