Jump to content

Zorochase

Members
  • Posts

    17
  • Joined

  • Last visited

  • Days Won

    1

Zorochase last won the day on February 22 2020

Zorochase had the most liked content!

Zorochase's Achievements

Tree Puncher

Tree Puncher (2/8)

3

Reputation

  1. Just as you said, sending the packet worked. The data now syncs correctly. Thanks for your help!
  2. Here's what I changed them to: @Nullable @Override public CompoundNBT getShareTag(ItemStack stack) { CompoundNBT nbt = stack.getOrCreateTag(); stack.getCapability(Capabilities.TEST_CAPABILITY_CAPABILITY).ifPresent( handler -> { nbt.put("cap_sync", Objects.requireNonNull(Capabilities.TEST_CAPABILITY_CAPABILITY.writeNBT(handler, null))); } ); return nbt; } @Override public void readShareTag(ItemStack stack, @Nullable CompoundNBT nbt) { super.readShareTag(stack, nbt); if (nbt != null) { stack.getCapability(Capabilities.TEST_CAPABILITY_CAPABILITY).ifPresent( handler -> { Capabilities.TEST_CAPABILITY_CAPABILITY.readNBT(handler, null, nbt.get("cap_sync")); } ); } } This works in both singleplayer and multiplayer, but only when I move the item to a different slot in my inventory after pressing the key to decrement testValueA. Chances are I'm either still not grasping something about what you said or my keypress code is wrong (if anything when I get the player's currently held stack).
  3. Further testing revealed it only sometimes works in singleplayer... It can take anywhere between 1-4 attempts before it actually saves. What is going on??
  4. Hello, again In my last post I got up to the point where I needed to sync data for a capability attached to a custom sword to the client. I spent what free time I had the past few days trying to figure out how to do this. I started a different mod separate from my real project so that I could figure this out on a clean slate, here's its repository: https://github.com/Zorochase/CapabilityLearning1144 I read through this post, where it was explained that there are two ways to sync capability data to the client, one way being to override getShareTag and readShareTag. In the mod above I created an example capability that stores a couple values. The capability is attached to a BasicTestItem. I set up some keybinds so I could see the values change in-game. In a singleplayer world, I can, for example, press a key to decrement one of the values, leave and come back, and it remains as what it was changed to. However, in multiplayer, I can change the value and see it change just as I can in singleplayer but it doesn't save when I leave. It just resets to the initial value. Here are my item's getShareTag and readShareTag methods: @Nullable @Override public CompoundNBT getShareTag(ItemStack stack) { CompoundNBT nbt = super.getShareTag(stack); if (nbt != null) { stack.getCapability(Capabilities.TEST_CAPABILITY_CAPABILITY).ifPresent( (iTestCapability) -> { nbt.putInt("testValueA", iTestCapability.getTestValueA()); nbt.putBoolean("testValueB", iTestCapability.getTestValueB()); } ); } return nbt; } @Override public void readShareTag(ItemStack stack, @Nullable CompoundNBT nbt) { if (nbt != null) { stack.getCapability(Capabilities.TEST_CAPABILITY_CAPABILITY).ifPresent( (iTestCapability -> { iTestCapability.setTestValueA(nbt.getInt("testValueA")); iTestCapability.setTestValueB(nbt.getBoolean("testValueB")); }) ); } } (I tried a different implementation for each, and commented them out. You can see the commented code in the repository.) My questions are: Is overriding getShareTag and readShareTag enough to sync an ItemStack's capability to the client? If not, how and when do I send a packet to update the data? (When I ask how, I'm not asking you to spoon-feed me code. I'd appreciate links to resources for learning this for modern Minecraft. Not for pre-1.12.2. And no, the docs aren't everything for a beginner like myself.) If so, what's wrong with the code I wrote? Am I missing anything? Am I correct in assuming syncing the data to the client is how the data is saved? As always, any help I may get will be appreciated.
  5. I thought so, but I don't know how... been looking around for ways to do that but I haven't found anything specific to my situation, just for PlayerEntities. EDIT: Nevermind, I've got myself on the right path now. Once again, thank you so much for your help. It will take me time to fully understand all the concepts I've come across but I know where to take it from here.
  6. My project was a bit messy, so I didn't have one. I cleaned it up a bit and made one, here's the link: https://github.com/Zorochase/Oneirocraft I found out that the same issue from before wasn't totally fixed; wrapping the provider in a supplier only worked for initCapabilities (which I actually always had, I just added attachCapabilities later on because I wasn't sure whether it was necessary). That didn't actually ensure that the capability was set before the sword's other methods (I.E. addInformation) were called. EDIT: As of this edit, the code you see on Github now correctly prints the amount of juice stored in the custom sword... but it doesn't update when I kill an entity, even though it should. It only updates when you leave the world and come back. This is the only known issue now.
  7. After messing with the code a little more, (I think) I figured out I wasn't supposed to use .map to access the getJuice method. However, I tried a few variations of the following code, and it only, funny enough, produced another NullPointerException. Here's what I last tried: @Override public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) { if (stack.getCapability(JuicedItemProvider.JUICED_ITEM_CAPABILITY).isPresent()) { stack.getCapability(JuicedItemProvider.JUICED_ITEM_CAPABILITY).ifPresent(juicedItem -> { int storedJuice = juicedItem.getJuice(); tooltip.add(new TranslationTextComponent(String.valueOf(storedJuice)).applyTextStyle(TextFormatting.AQUA)); }); } } I'm pretty sure there's no reason for me to check isPresent first. I left that out, produced the same error. I moved tooltip.add outside the lambda and made storedJuice an AtomicInteger, same error. I'm still using the same updated provider from the above reply. Here's the new error: https://pastebin.com/LJkhRes3
  8. Alright, so applying your suggestion to my code did fix the error. However, there's another problem, and I'm not sure exactly what's causing it. It could be an issue with my capability's storage class, it could be that I'm not attaching the capability properly, or something else, but when I went to check my custom sword in-game, instead of printing the amount of "juice" it was supposed to store (juice is just another word for energy; it's just an int value) in the sword's tooltip, it just printed this: https://imgur.com/a/vOUhiDo Here's my updated Provider class, in case that could have an effect on the above issue: package zorochase.oneirocraft.capability; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.function.Supplier; public class JuicedItemProvider implements ICapabilityProvider { private Supplier<IJuicedItem> juicedItemSupplier; @CapabilityInject(IJuicedItem.class) public static Capability<IJuicedItem> JUICED_ITEM_CAPABILITY = null; public JuicedItemProvider() { this(() -> JUICED_ITEM_CAPABILITY.getDefaultInstance()); } JuicedItemProvider(Supplier<IJuicedItem> sup) { this.juicedItemSupplier = sup; } private LazyOptional<IJuicedItem> capability = LazyOptional.of(() -> juicedItemSupplier.get()); @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { return cap == JUICED_ITEM_CAPABILITY ? capability.cast() : LazyOptional.empty(); } } Here's the storage class: package zorochase.oneirocraft.capability; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import javax.annotation.Nullable; public class JuicedItemStorage implements Capability.IStorage<IJuicedItem> { @Nullable @Override public INBT writeNBT(Capability<IJuicedItem> capability, IJuicedItem instance, Direction side) { CompoundNBT tag = new CompoundNBT(); tag.putInt("juice", instance.getJuice()); tag.putInt("maxJuiceTransferable", instance.getMaxJuiceTransferable()); tag.putBoolean("empowered", instance.getIsEmpowered()); return tag; } @Override public void readNBT(Capability<IJuicedItem> capability, IJuicedItem instance, Direction side, INBT nbt) { CompoundNBT tag = (CompoundNBT) nbt; instance.setJuice(tag.getInt("juice")); instance.setJuiceTransferLimit(tag.getInt("maxJuiceTransferable")); instance.setEmpowered(tag.getBoolean("empowered")); } } Here's how I'm printing the sword's "juice": @Override public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) { tooltip.add( new TranslationTextComponent( String.valueOf( stack.getCapability(JuicedItemProvider.JUICED_ITEM_CAPABILITY).map(IJuicedItem::getJuice) ) ).applyTextStyle(TextFormatting.AQUA) ); } And here's what I did to attach it in my main class: @SubscribeEvent public static void onAttachCapabilities(AttachCapabilitiesEvent<ItemStack> event) { Item item = event.getObject().getItem(); if (item instanceof DreamsteelSwordItem) { event.addCapability(new ResourceLocation(Oneirocraft.MOD_ID, "juiceditem"), new JuicedItemProvider()); } } Again, I really do appreciate your help. I apologize for requesting it continually, it's only because I'm having a hard time wrapping my head around this concept.
  9. Thanks for your response. I understand what you mean, but I couldn't quite figure out how to wrap it correctly. Would you be able to show me an example of how you did it?
  10. In my capability's Provider class, I set JUICED_ITEM_CAPABILITY to null. This caused the NullPointerException, which I half expected, but only half because that was how it was done for CapabilityEnergy, and I'm not sure why. I've tried making it final, and I've tried leaving it unassigned, but neither worked. I'm relatively new to the capability system and I clearly still don't understand it in full. I've read through this topic in full, as well as the docs, but nothing I read lead me to any other possible fix. Here's my capability's provider class: package zorochase.oneirocraft.capability; import net.minecraft.nbt.INBT; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.util.LazyOptional; public class JuicedItemProvider implements ICapabilitySerializable<INBT> { @CapabilityInject(IJuicedItem.class) public static Capability<IJuicedItem> JUICED_ITEM_CAPABILITY = null; private LazyOptional<IJuicedItem> instance = LazyOptional.of(JUICED_ITEM_CAPABILITY::getDefaultInstance); @Override public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) { return cap == JUICED_ITEM_CAPABILITY ? instance.cast() : LazyOptional.empty(); } @Override public INBT serializeNBT() { return JUICED_ITEM_CAPABILITY.getStorage().writeNBT(JUICED_ITEM_CAPABILITY, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null); } @Override public void deserializeNBT(INBT nbt) { JUICED_ITEM_CAPABILITY.getStorage().readNBT(JUICED_ITEM_CAPABILITY, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null, nbt); } } I tried attaching the capability to a custom sword like so: @Override public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) { return new JuicedItemProvider(); } I also registered the capability in my main mod class like so: @SubscribeEvent public static void onCommonSetup(FMLCommonSetupEvent event) { CapabilityManager.INSTANCE.register(IJuicedItem.class, new JuicedItemStorage(), JuicedItemImpl::new); } Here is the full crash report, if necessary. If I do get any help, I'd really appreciate it.
  11. Last bump... it'd really be nice to at least know whether I should report this as a bug with Forge...
  12. An ItemEntity is the entity that's created when you drop an item in the world, when a block breaks drops itself, etc..
  13. Hello, I've made a simple custom ItemEntity that can't catch on fire. Here's the code for it: package zorochase.yanm.item; import net.minecraft.entity.EntityType; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraft.world.World; public class FireproofItemEntity extends ItemEntity { public FireproofItemEntity(World worldIn, double x, double y, double z, ItemStack stack) { super(worldIn, x, y, z, stack); } public FireproofItemEntity(EntityType<?> entityType, World world) { super((EntityType<? extends ItemEntity>)entityType, world); } @Override public boolean attackEntityFrom(DamageSource p_70097_1_, float p_70097_2_) { if (!p_70097_1_.isFireDamage()) { return super.attackEntityFrom(p_70097_1_, p_70097_2_); } return false; } } Here's how it was registered (taken from my main mod class): @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public static class RegistryEvents { @SubscribeEvent public static void onEntityRegistry(final RegistryEvent.Register<EntityType<?>> entityRegistryEvent) { entityRegistryEvent.getRegistry().register( EntityType.Builder .create(FireproofItemEntity::new, EntityClassification.MISC) .build(YetAnotherNetheriteMod.MODID + ":fireproof_item_entity") .setRegistryName(YetAnotherNetheriteMod.MODID, "fireproof_item_entity") ); } } I also have a FireproofItem class that I use for all items I want to be fireproof when dropped, here's its code: package zorochase.yanm.item; import net.minecraft.entity.Entity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import zorochase.yanm.YetAnotherNetheriteMod; import javax.annotation.Nullable; public class FireproofItem extends Item { public FireproofItem(String registryName) { super(new Item.Properties().group(YetAnotherNetheriteMod.MOD_TAB)); setRegistryName(YetAnotherNetheriteMod.MODID, registryName); } @Nullable @Override public Entity createEntity(World world, Entity location, ItemStack itemstack) { FireproofItemEntity custom = new FireproofItemEntity(world, location.posX, location.posY, location.posZ, itemstack); custom.setMotion(location.getMotion()); custom.setDefaultPickupDelay(); return custom; } @Override public boolean hasCustomEntity(ItemStack stack) { return true; } } All of this works just fine, so long as I don't leave a FireproofItem on the ground before quitting the game/to the main menu. If I do, and I try to load the world again, it freezes on 100%. I have no idea what could be causing this. Somebody else on these forums had the same issue a few months ago, but it seems they were also unable to figure it out. That or if they did they never replied with their fix. Any help would really be appreciated, as this is a feature I'd really rather not leave out.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.