Jump to content

Zorochase

Members
  • Posts

    17
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Zorochase

  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.
  14. Thank you for your response. After reading through the docs (again) I'm still not sure how to actually initialize a capability when overriding initCapabilities. This is what I tried: @Nullable @Override public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) { return new ICapabilityProvider() { @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if (cap == CapabilityEnergy.ENERGY) { // If not new ChromiumSwordItem(), what should I put here? (If that's causing the issue...) return LazyOptional.of(() -> new ChromiumSwordItem()).cast(); } return LazyOptional.empty(); } }; } This is how I displayed the energy inside the tooltip: @Override public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) { super.addInformation(stack, worldIn, tooltip, flagIn); stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(e -> tooltip.add(new TranslationTextComponent(String.valueOf(e.getEnergyStored())))); } This is how I extracted energy: @Override public boolean hitEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) { // Instead of false, check if the player is in creative stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(e -> e.extractEnergy(maxExtract, false)); return super.hitEntity(stack, target, attacker); } I'm not sure if I'm doing all of this wrong or only parts of it are incorrect, but now instead of extracting energy, when I hit an entity, no energy is extracted. I can't tell if that's because I extracted the energy wrong, I'm displaying it wrong in the tooltip, incorrectly initialized the energy capability, or any mixture of the three.
  15. Hello, I am currently working on a mod similar to TeamCofH's Redstone Arsenal mod (but without being able to empower tools). I am somewhat new to modding; I've created small, simple mods for personal use in the past, but I wanted to try to branch out with this one. So far, I have a basic sword that cannot break or be damaged on use. I've taken the implementation of the IEnergyStorage interface from the sample EnergyStorage class, but every ItemStack of my sword item retains the same amount of energy and depletes even if it wasn't the specific stack used to damage an entity. (I.E. If one stack starts with 320,000 FE and loses 400 FE when damaging an entity, every other stack will also lose 400 FE and contain 319,600 FE). The amount of energy stored in each stack isn't even saved when I close the game and launch it again. This behavior leads me to a few questions: How do I tell Forge that I'm trying to make use of the Energy capability? How do I properly store the amount of energy for any given ItemStack of the sword/axe/pickaxe etc.. (with NBT?), and access it or modify it with the implemented methods (I.E. extractEnergy, getEnergyStored) (I am aware that in order to display the stored energy in the tooltip, I'd have to @Override the addInformation method. I just need to know how to access the energy stored/max capacity to display it for each ItemStack) What else am I missing or not understanding? What should I do to improve my code? I'm sorry if this is a lot to ask, but my modding experience is limited and I've really never dealt with more complicated concepts like this. I tried looking around both these forums and Google to find answers, but as I expected I could find nothing for Minecraft 1.14.4 in particular, or anything in general dealing with both tools and the energy capability. I've also looked through Forge's documentation, but either it was too vague to help me figure out what to do, or I just didn't understand it well enough. I'm not sure where else I should look to start learning more, especially for newer Minecraft versions (1.13+). I would really appreciate any help. Here's my code: public class ChromiumSwordItem extends SwordItem implements IEnergyStorage { protected int energy; protected int capacity; protected int maxReceive; protected int maxExtract; public ChromiumSwordItem() { super( new ChromiumTier(), 0, 6.0f, new Item.Properties() .group(ChromiumArsenal.CREATIVE_TAB) .maxDamage(0) .defaultMaxDamage(0) .setNoRepair() .rarity(Rarity.UNCOMMON) ); setRegistryName("chromium_sword"); capacity = 320000; maxReceive = 400; maxExtract = 320; // energy = Math.max(0 , Math.min(capacity, energy)); // Start all Chromium Swords with maximum energy for testing energy = capacity; } @Override public int receiveEnergy(int maxReceive, boolean simulate) { if (!canReceive()) return 0; int energyReceived = Math.min(capacity - energy, Math.min(this.maxReceive, maxReceive)); if (!simulate) energy += energyReceived; return energyReceived; } @Override public int extractEnergy(int maxExtract, boolean simulate) { if (!canExtract()) return 0; int energyExtracted = Math.min(energy, Math.min(this.maxExtract, maxExtract)); if (!simulate) energy -= energyExtracted; return energyExtracted; } @Override public int getEnergyStored() { return energy; } @Override public int getMaxEnergyStored() { return capacity; } @Override public boolean canExtract() { return this.maxExtract > 0; } @Override public boolean canReceive() { return this.maxReceive > 0; } // TODO: Override addInformation, hitEntity, durability bar stuff }
×
×
  • Create New...

Important Information

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