Jump to content

wog890

Members
  • Posts

    33
  • Joined

  • Last visited

Everything posted by wog890

  1. There is an event: PlayerContainerEvent.Open I'll mess with this some, but I did find a post from 2016 when googling OpenContainerEvent It seems like he is essentially doing the same thing! Diesieben07 says that using that event won't work as expected? The only other suggestion in the post is to send a packet and use IGuiHandler to open a custom container and gui? I'll tinker with both and see what happens :-).
  2. Ahhh, that does make sense. Would you know the correct way to do this. I added player.openContainer(new RPGProvider()); just after event.setGui(); call. With the RPGProvider class being: public class RPGInventoryProvider implements INamedContainerProvider { @Override public Container createMenu(int windowId, PlayerInventory invIn, PlayerEntity player) { return new RPGInventoryContainer(windowId, invIn); } @Override public ITextComponent getDisplayName() { return new TranslationTextComponent("containers.wogmods.rpgInv"); } } I'm guessing I might be messing up the sides and need to call player.openContainer() from the server side? Do I need to have my clientEventSubscriber send a packet to the server that then calls this instead?
  3. I forgot to add the container code in case it is helpful: RPGInventoryContainer.java public class RPGInventoryContainer extends Container { private static final String [] ARMOR_SLOT_TEXTURES = new String[] { "item/empty_armor_slot_chestplate", "", "", "", "wogmods:item/empty_equip_slot_eyes", "item/empty_armor_slot_boots", "item/empty_equip_slot_glove", "item/empty_equip_slot_hat", "item/empty_armor_slot_helmet", "", "item/empty_equip_slot_ring", "item/empty_equip_slot_ring", "", "item/empty_equip_slot_bracelet"}; private static final EEquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EEquipmentSlotType[] { EEquipmentSlotType.ARMOR, EEquipmentSlotType.BELT, EEquipmentSlotType.BODY, EEquipmentSlotType.CHEST, EEquipmentSlotType.EYES, EEquipmentSlotType.FEET, EEquipmentSlotType.HANDS, EEquipmentSlotType.HEAD, EEquipmentSlotType.HEADBAND, EEquipmentSlotType.NECK, EEquipmentSlotType.RING_LEFT, EEquipmentSlotType.RING_RIGHT, EEquipmentSlotType.SHOULDERS, EEquipmentSlotType.WRIST}; private final PlayerEntity player; public RPGInventoryContainer(int windowId, PlayerInventory invIn) { this(windowId, invIn, null); } public RPGInventoryContainer(int windowId, PlayerInventory invIn, PacketBuffer extraData) { super(WogMods.RPG_INV_CONTAINER, windowId); player = invIn.player; // Places the slots for the main player inventory // Index Range: 9 - 35 for (int j=0; j<3; ++j) { for (int k=0; k<9; ++k) { this.addSlot(new Slot(invIn, k+(j+1)*9, 30+k*18, 89+j*18)); } } // Places the slots for the main player hotbar // Index Range: 0 - 8 for (int l=0; l<9; ++l) { this.addSlot(new Slot(invIn, l, 30+l*18, 147)); } // Places the offhand slot // Index Range: 40 this.addSlot(new Slot(invIn, 40, 103, 69) { @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return "item/empty_armor_slot_shield"; } }); this.player.getCapability(RPGProvider.RPG_CAP).ifPresent(rpg -> { ItemStackHandler itemstackHandler = rpg.getItemStackHandler(); // Places the many equipments slots // Index Range: 41 - 54 for (int m=0; m<14; ++m) { final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m]; this.addSlot(new SlotItemHandler(itemstackHandler, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) { public int getSlotStackLimit() { return 1; } public boolean isItemValid(ItemStack stack) { if (!(stack.getItem() instanceof RPGItem)) return false; return ((RPGItem)stack.getItem()).canEquip(slotType); } public boolean canTakeStack(PlayerEntity playerIn) { ItemStack itemstack = this.getStack(); return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn); } @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()]; } }); } }); } @Override public boolean canInteractWith(PlayerEntity playerIn) { return true; } }
  4. So I thought I had it, but its all gone soooo downhill. From your second comment I updated container registry to: @SubscribeEvent public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) { event.getRegistry().register(IForgeContainerType.create(RPGInventoryContainer::new).setRegistryName("rpg_inventory")); } The screen is now successfully opening and looks great! I then started adding the slots and ran into a weird amount of issues. I have the feeling the issues are being caused by me creating/registering the screen/container wrong or opening it wrong. I'll try to describe the issues first and then add the code I've written for opening the gui. Any help would be much appreciated. Quick description, my inventory has the default 9 slots for the hotbar, 27 slots for the inventory, 1 slot for the offhand, and then 14 custom equipment slots. None of these 14 custom slots match to a vanilla armor slot. For testing my inventory I would first use the Vanilla inventory screen to place one item in the first hotbar slot, and then 4 items in the main inventory (one in each corner). When opening my modded inventory this appears exactly as it should. Bug 1: I immediately noticed that I could not move any of my items. When clicking on a slot containing an item, nothing would happen. I then realized that if you clicked the slot directly below a slot containing an item, it would pick up the item in the slot above it. Likewise, while holding an item, clicking an empty slot will place the item into the slot above the one clicked. This was persistent whether I had all slots (vanilla and my custom), just vanilla slots, or just a single slot. Bug 2: All kinds of weird behavior on shift-click. Kinda hard to describe, so just noting it exists. Bug 3: The game crashes when I click the majority of my custom equipment slots. The error is java.lang.IndexOutOfBoundsException: Index: 46, Size: 46 I originally thought this was being caused because I was adding my equipment slots directly to the player inventory by running: //This was actually done as a for loop, but I don't have that code any longer and this gets the point across. this.player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(h -> { this.addSlot(new SlotItemHandler(h, slotType.getSlotIndex(), slotType.getX(), slotType.getY())); }); I should've read the error better. I instead added an ItemStackHandler of size 14 to my main RPGCapability and added some small code to the storage class to handle reading and writing. I then updated my container's code to: this.player.getCapability(RPGProvider.RPG_CAP).ifPresent(rpg -> { ItemStackHandler itemstackHandler = rpg.getItemStackHandler(); // Places the many equipments slots // Index Range: 0 - 13 for (int m=0; m<14; ++m) { final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m]; this.addSlot(new SlotItemHandler(itemstackHandler, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) { public int getSlotStackLimit() { return 1; } public boolean isItemValid(ItemStack stack) { if (!(stack.getItem() instanceof RPGItem)) return false; return ((RPGItem)stack.getItem()).canEquip(slotType); } public boolean canTakeStack(PlayerEntity playerIn) { ItemStack itemstack = this.getStack(); return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn); } @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()]; } }); } }); This in no way fixed the crashing and I decided that the slots were still being attached to my main player inventory. I spent an embarrassingly long time trying to fix this and then finally decided to look a little closer to the error log: ---- Minecraft Crash Report ---- // Ouch. That hurt :( Time: 10/7/19 7:53 PM Description: mouseClicked event handler java.lang.IndexOutOfBoundsException: Index: 46, Size: 46 at java.util.ArrayList.rangeCheck(Unknown Source) ~[?:1.8.0_181] {} at java.util.ArrayList.get(Unknown Source) ~[?:1.8.0_181] {} at net.minecraft.inventory.container.Container.slotClick(Container.java:258) ~[forge-1.14.4-28.0.11_mapped_snapshot_20190723-1.14.3-recomp.jar:?] {} //Line 258 of Container.java Slot slot6 = this.inventorySlots.get(slotId); I've realized it is simply that the container's inventorySlots variable is what is actually being called as out of bounds exception. I've only just hit this point, so I haven't dug any deeper into this particular issue yet. As my goal is to override the vanilla inventory screen, I am currently calling my screen by: //This is within a client only event subscriber @SubscribeEvent public static void onGuiOpenEvent(GuiOpenEvent event) { // I was having an issue with something being null and I got a little heavyhanded..... if (Minecraft.getInstance() != null && Minecraft.getInstance().player != null && event.getGui() != null) { // This checks if the player is set to default vanilla behavior or if my mod should override if (Minecraft.getInstance().player.getCapability(RPGProvider.RPG_CAP).orElse(null).isRPGActive() && event.getGui() instanceof InventoryScreen) { ClientPlayerEntity player = Minecraft.getInstance().player; // event.setGui(Screen gui) // new RPGInventoryScreen(RPGInventoryContainer container, PlayerInventory inv, ITextComponent name) // new RPGInventoryContainer(int windowId, PlayerInventory invIn) event.setGui(new RPGInventoryScreen(new RPGInventoryContainer(0, player.inventory), player.inventory, new TranslationTextComponent("demo.help.title"))); } } } Once again, sorry for the long post and rambling. I appreciate any help provided. The equipment setup is the bottleneck for me to work on any other part of what I'm doing and I'm not really sure what is wrong here or what to dive deeper into.
  5. Alrighty. Updated RPGInventoryScreen public class RPGInventoryScreen extends ContainerScreen<RPGInventoryContainer> { public RPGInventoryScreen(PlayerEntity player) { super((RPGInventoryContainer) player.openContainer, player.inventory, new TranslationTextComponent("containers.wogmods.inv")); this.passEvents = true; } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { // TODO Auto-generated method stub } } So I started attempting to register the container like so: @SubscribeEvent public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) { event.getRegistry().registerAll( RPGInventoryContainer.class ); } or @SubscribeEvent public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) { event.getRegistry().registerAll( // Just a test, would need to pass a proper inventory as the middle argument. Wasn't sure how to do this though. // Minecraft.getInstance().player.inventory would be accessing it through the ClientEntityPlayer which seems wrong... // Sides still trip me up a good bit :-/ new RPGInventoryContainer(0, null, null) ); } This of course didn't work as the event is registering ContainerTypes not Containers. Once I realized this I actually looked at what ContainerType was. Looking at that I can see it registering containers through calling something like public static final ContainerType<RepairContainer> = register("anvil", RepairContainer::new); The container type is being passed a key and creating an instance of the passed container (right), but each of these is connected to a block except for MerchantContainer. (I'm kinda just assuming that MerchantContainer is attached to villagers who trade). PlayerContainer is not registered here and because of this when constructed it simply calls super((ContainerType<?>)null, 0); Because of this I'm unsure of if I should be registering my container or not. Halfway through typing this I realized I hadn't look at McJty's example to see how he registered his container. That was stupid of me. Matching his code I now have this: @SubscribeEvent public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) { event.getRegistry().register(IForgeContainerType.create((windowId, inv, data) -> { return new RPGInventoryContainer(windowId, inv, data); }).setRegistryName("rpg_inventory")); } @ObjectHolder("wogmods:rpg_inventory") public static ContainerType<RPGInventoryContainer> RPG_INV_CONTAINER; He also states that the ContainerType is only used client side. So I can register my container if needed. Sorry for the rambling and long description. The only way I can think to describe my confusion is to go through my thought process. Thank you for the help!
  6. I'm attempting to override the default inventory GUI and replace it with my own. I have already created a simple Gui and have it implemented (opens on pressing k). I used it to test my code to override the vanilla inventory opening. In my client event subscriber I call @SubscribeEvent public static void onGuiOpenEvent(GuiOpenEvent event) { if (Minecraft.getInstance().player.getCapability(RPGProvider.RPG_CAP).orElse(null).isRPGActive() && event.getGui() instanceof InventoryScreen) { event.setGui(new AbilityScoresScreen(new TranslationTextComponent("demo.help.title"))); } } Not sure if that really is the best way, but it is working. Only downside is I can't seem to manage to have the new Gui closed when pressing "E". Now I'm trying to actually create the new inventory screen and container. I'm not finding much information on how to implement this in 1.14 and all of what I have found deals with containers tied to block tile entities. Mcjty has one of the more descriptive examples but wasn't really what I needed and didn't match to what is largely mentioned and recommended by Desht. I have created a container that is largely a mimic of PlayerContainer, but places the slots in the correct x,y points and adds my many new equipment slots. It also skips all the logic for recipe book and crafting as my screen does not need them. I've now started on the new inventory screen and am kinda stuck. The default InventoryScreen constructs with the code public InventoryScreen(PlayerEntity player) { super(player.container, player.inventory, new TranslationTextComponent("container.crafting")); this.passEvents = true; } I can largely mimic this, but need access to my container instead of the default player.container. What is the correct way to be doing this? For registering the container, or opening from the client, Desht states that I should use a constructor in the form of: public MyContainer(int windowId, PlayerInv inv, PacketBuffer extraData) { super(ContainerType<?>, windowId); doThings(); } And a second constructor for the server side. The vanilla inventory container uses the constructor below, which I mimicked and would be my server one? public PlayerContainer(PlayerInventory playerInventory, boolean localWorld, PlayerEntity playerIn) { super((ContainerType<?>)null, 0); this.isLocalWorld = localWorld; this.player = playerIn; // All the code for placing slots is after this.... } I'm kinda stuck and not sure how to progress, any help would be much appreciated. As a summery my questions are: How do I get my container when calling the constructor for my inventory screen Proper registration of my container/correct set up of multiple constructors Not fully understanding why the client and server need separate constructors (Bonus and not really important) any recommendations on how to close the screen if "E" is pressed again. Doing a simple key bind on the "E" key doesn't ever fire. I'm guessing the default open inventory is capturing it and preventing it from continuing. Below is the entire code for my container and screen (although there isn't really anything to the screen yet). RPGInventoryContainer.java package com.github.wog890.wogmods.inventory.container; import javax.annotation.Nullable; import com.github.wog890.wogmods.enums.EEquipmentSlotType; import com.github.wog890.wogmods.item.RPGItem; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class RPGInventoryContainer extends Container { private static final String [] ARMOR_SLOT_TEXTURES = new String[] { "item/empty_armor_slot_chestplate", "", "", "", "", "item/empty_armor_slot_boots", "", "item/empty_armor_slot_helmet", "", "", "", "", "", ""}; private static final EEquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EEquipmentSlotType[] { EEquipmentSlotType.ARMOR, EEquipmentSlotType.BELT, EEquipmentSlotType.BODY, EEquipmentSlotType.CHEST, EEquipmentSlotType.EYES, EEquipmentSlotType.FEET, EEquipmentSlotType.HANDS, EEquipmentSlotType.HEAD, EEquipmentSlotType.HEADBAND, EEquipmentSlotType.NECK, EEquipmentSlotType.RING_LEFT, EEquipmentSlotType.RING_RIGHT, EEquipmentSlotType.SHOULDERS, EEquipmentSlotType.WRIST}; public final boolean isLocalWorld; private final PlayerEntity player; public RPGInventoryContainer(int windowId, PlayerInventory inv, PacketBuffer extraData) { super((ContainerType<?>)null, windowId); player = inv.player; // Temporary to prevent error being fired. Will set this properly later isLocalWorld = false; } public RPGInventoryContainer(PlayerInventory invIn, boolean localWorld, PlayerEntity playerIn) { super((ContainerType<?>)null, 108); this.isLocalWorld = localWorld; this.player = playerIn; // Places the slots for the main player inventory // Index Range: 9 - 35 for (int j=0; j<3; ++j) { for (int k=0; k<9; ++k) { this.addSlot(new Slot(invIn, k+(j+1)*9, 49+k*18, 92+j*18)); } } // Places the slots for the main player hotbar // Index Range: 0 - 8 for (int l=0; l<9; ++l) { this.addSlot(new Slot(invIn, l, 49+l*18, 150)); } // Places the offhand slot // Index Range: 40 this.addSlot(new Slot(invIn, 40, 122, 72) { @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return "item/empty_armor_slot_shield"; } }); // Places the many equipments slots // Index Range: 41 - 54 for (int m=0; m<14; ++m) { final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m]; this.addSlot(new Slot(invIn, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) { public int getSlotStackLimit() { return 1; } public boolean isItemValid(ItemStack stack) { if (!(stack.getItem() instanceof RPGItem)) return false; return ((RPGItem)stack.getItem()).canEquip(slotType); } public boolean canTakeStack(PlayerEntity playerIn) { ItemStack itemstack = this.getStack(); return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn); } @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()]; } }); } } @Override public boolean canInteractWith(PlayerEntity playerIn) { return true; } } InventoryScreen.java package com.github.wog890.wogmods.client.gui.screen; import com.github.wog890.wogmods.inventory.container.RPGInventoryContainer; import net.minecraft.client.gui.DisplayEffectsScreen; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.text.TranslationTextComponent; public class RPGInventoryScreen extends DisplayEffectsScreen<RPGInventoryContainer> { public RPGInventoryScreen(PlayerEntity player) { //null needs to be my RPGInventoryContainer super(null, player.inventory, new TranslationTextComponent("containers.wogmods.inv")); this.passEvents = true; } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { // TODO Auto-generated method stub } }
  7. Thank you for responding, but the rudeness is not overly constructive. I believe my question above already showed I have a decent understanding of why static would be incorrect here, I was simply trying to double check myself as I normally program in Javascript and don't deal with static fields commonly. On the subject of type casting I certainly don't understand what is going on. I understand casting, but do not understand what is being created by the type LazyOptional and the proper way to use both as for one function I need a LazyOptional and for another I need IMana and you've said to only have a single field..... I so far have not found solid information on LazyOptional to fix this lack of understanding, but I'm still working on it. As I've said I appreciate any help, but if all you have is rudeness and not help, please just do not respond.
  8. So, I made some edits to the code below are my updated ManaProvider class and the EventHandler (it is now causing problems) ManaProvider.java public class ManaProvider implements ICapabilitySerializable<INBT> { @CapabilityInject(IMana.class) public static final Capability<IMana> MANA_CAP = null; private static final LazyOptional<IMana> holder = LazyOptional.of(Mana::new); public boolean hasCapability(Capability<?> capability, Direction side) { return capability == MANA_CAP; } @Override public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction side) { //return capability == MANA_CAP ? MANA_CAP.<T> cast(this.instance) : null; //return MANA_CAP.orEmpty(MANA_CAP, holder.cast()); return capability == MANA_CAP ? holder.cast() : LazyOptional.empty(); } @Override public INBT serializeNBT() { //return MANA_CAP.getStorage().writeNBT(MANA_CAP, (IMana) ManaProvider.holder, null); return null; } @Override public void deserializeNBT(INBT nbt) { //MANA_CAP.getStorage().readNBT(MANA_CAP, (IMana) ManaProvider.holder, null, nbt); } } EventHandler.java public class EventHandler { @SubscribeEvent public void onPlayerLogsIn(PlayerLoggedInEvent event) { PlayerEntity player = event.getPlayer(); IMana mana = (IMana) player.getCapability(ManaProvider.MANA_CAP, null); String message = String.format("Hello there, you have §7%d§r mana left", (int) mana.getMana()); player.sendMessage(new StringTextComponent(message)); } @SubscribeEvent public void onPlayerSleep(PlayerSleepInBedEvent event) { PlayerEntity player = event.getEntityPlayer(); if (player.world.isRemote) return; IMana mana = (IMana) player.getCapability(ManaProvider.MANA_CAP, null); mana.fill(50); String message = String.format("You refreshed yourself in the bed. You received 50 mana, you have §7%d§r mana left.", (int) mana.getMana()); player.sendMessage(new StringTextComponent(message)); } @SubscribeEvent public void onPlayerFalls(LivingFallEvent event) { Entity entity = event.getEntity(); if (entity.world.isRemote || !(entity instanceof ServerPlayerEntity) || event.getDistance() < 3) return; PlayerEntity player = (PlayerEntity) entity; IMana mana = (IMana) player.getCapability(ManaProvider.MANA_CAP, null); float points = mana.getMana(); float cost = event.getDistance() * 2; if (points > cost) { mana.consume(cost); String message = String.format("You absorbed fall damage. It cost §7%d§r mana, you have §7%d§r mana left.", (int) cost, (int) mana.getMana()); player.sendMessage(new StringTextComponent(message)); event.setCanceled(true); } } } I have removed the instance field and am using the handler field in the functions serializeNBT and deserializeNBT. As it is a static field I am having to access it through the class instead of this and as the function requires an instance of IMana and not LazyOptional, I'm having to cast it to IMana. (Side note, I'm pretty sure handler needs to not be static if I'm using it this way as I don't want NBT to be saved to a static, it should be individual......) When I ran this, the game crashed, and I thought the error log was saying IMana could not be cast to LazyOptional. Then I read better and realized it was erroring in the function deserializeNBT and actually said LazyOptional couldn't be cast to IMana. To try and simply find out if the getCapability function was working so I commented out the code in deserializeNBT and serializeNBT functions and had serializeNBT return null for now. (This is visible above). When I ran the game again, EventHandler onPlayerLogsIn caused the game to crash with the same error. LazyOptional cannot be cast to IMana. (Error below). I'm assuming the code should be updated from IMana mana = (IMana) player.getCapability(ManaProvider.MANA_CAP, null); to LazyOptional<IMana> mana = player.getCapability(ManaProvider.MANA_CAP, null); but then I seem to lose access to the functions within IMana...... i seriously do not understand what LazyOptional is doing. And I still have the issue of how to provide serializeNBT and deserializeNBT with an instance of IMana that is not LazyOptional. Thank you for the assistance, it is extremely appreciated. ---- Minecraft Crash Report ---- // Why is it breaking :( Time: 9/3/19 5:14 PM Description: Ticking memory connection java.lang.ClassCastException: net.minecraftforge.common.util.LazyOptional cannot be cast to com.github.wog890.wogmods.entity.player.IMana at com.github.wog890.wogmods.entity.player.EventHandler.onPlayerLogsIn(EventHandler.java:17) ~[main/:?] {}
  9. I've just recently got back into minecraft programming again and was after following the usual, make a block, make an item, make tile entity, etc I started looking at capabilities. I followed a fairly simple tutorial for adding mana to a player. I am finding very little information on this though for 1.14, but have managed to get everything functioning (haven't been able to run it to ensure this in minecraft though) except for the Capability Provider. It seems the old function used to be @CapabilityInject(IMana.class) public static final Capability<IMana> MANA_CAP = null; public <T> T getCapability(Capability<T> capability, EnumFacing facing) { return capability == MANA_CAP ? MANA_CAP.<T> cast(this.instance) : null; } I'm leaving out some stuff, but this function has changed to public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction side) { return ??? } Anyways, I don't really understand what I'm messing with here and would appreciate it if anyone could assist me in the correct manner to return an instance of IMana properly here. I messed with a few options and tried to implement things from other's code but to no avail. The entire ManaProvider class is below. If other files are needed please let me know. ManaProvider.java public class ManaProvider implements ICapabilitySerializable<INBT> { @CapabilityInject(IMana.class) public static final Capability<IMana> MANA_CAP = null; private static final LazyOptional<IMana> holder = LazyOptional.of(Mana::new); private IMana instance = MANA_CAP.getDefaultInstance(); public boolean hasCapability(Capability<?> capability, Direction side) { return capability == MANA_CAP; } @Override public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction side) { //return capability == MANA_CAP ? MANA_CAP.<T> cast(this.instance) : null; //return MANA_CAP.orEmpty(MANA_CAP, holder.cast()); return capability == MANA_CAP ? holder.cast() : LazyOptional.empty(); } @Override public INBT serializeNBT() { return MANA_CAP.getStorage().writeNBT(MANA_CAP, this.instance, null); } @Override public void deserializeNBT(INBT nbt) { MANA_CAP.getStorage().readNBT(MANA_CAP, this.instance, null, nbt); } } Follow up and not particularly relevant question. What has happened to proxies??? The section of the forge documentation for them seems to be replaced by DistExecuter, but I can't find much info on this. Thank you for any help or information!
  10. God, such a simple little thing. Thank you for the assistance! I was focused on the <? extends T> and trying to figure out if implementing was different then extending and how to handle this if it is (I'm used to Javascript not Java) and have not noticed even once that it says Callable and not Class. Option b seems to be the simplest and has appeared to work! Now your original question makes sense to me as well!
  11. That I can tell, there is only one register method in CapabilityManager.INSTANCE and it takes the above inputs. I don't see how I can use anything other than that. Sorry if I should have done a new post, I was hoping to not create a new one if a previous one was about the same issue. I'm starting simple and the basic mana tutorial for capabilities before making the capability I actually need so my current code is: Capability Interface (Class<T>) public interface IMana { public void consume(float points); public void fill(float points); public void set(float points); public float getMana(); } Capability Implementation (Callable<? extends T>) public class Mana implements IMana { public static float MAX_MANA = 250.0f; private float mana = 250.0f; @Override public void consume(float points) { this.mana -= points; if (this.mana < 0.0f) this.mana = 0.0f; } @Override public void fill(float points) { this.mana += points; if (this.mana > MAX_MANA) this.mana = MAX_MANA; } @Override public void set(float points) { this.mana = points; } @Override public float getMana() { return this.mana; } } Capability Storage (CapabilityIStorage<T>) public class ManaStorage implements IStorage<IMana> { @Override public INBTBase writeNBT(Capability<IMana> capability, IMana instance, EnumFacing side) { return new NBTTagFloat(instance.getMana()); } @Override public void readNBT(Capability<IMana> capability, IMana instance, EnumFacing side, INBTBase nbt) { instance.set(((NBTPrimitive) nbt).getFloat()); } } In my main mod class I call: CapabilityManager.INSTANCE.register(IMana.class, new ManaStorage(), Mana.class); I get the error: Nothing overly complicated going on here, but I can't figure out what the issue is. I've followed a good number of tutorials at this point trying to find what the problem is, but they handle capabilities this same way. Make an Interface, make a class that implements it, make a storage, and finally register it. Currently I'm following https://www.planetminecraft.com/blog/forge-tutorial-capability-system/. I also copied the (capabilities relevant) code from this github https://github.com/MinecraftForge/MinecraftForge/blob/1.10.x/src/test/java/net/minecraftforge/test/TestCapabilityMod.java that creates all the classes directly in the main class file and had the same error.
  12. Would you mind answering what the issue is. This same problem is driving me up a wall.
  13. float rotation = tile.getRotation() always comes out to 0. I have checked at the actual tile entity in debug though and it seems to be calculating it fine. I don't know where the tile entity is being passed for the renderAt method. I guess I always assumed it was fine since the visually connected part always works fine. I'm going to run a quick check to see if the tile entity being passed in the renderer is the tile entity for the axle. I believe if I check the id of the tile entity it should match the id of the one in the renderer. I'll post back in just a second. Update - The id's do not match, one is 63 the other is 109. This could be because I'm casting it though, I'm not sure. Also, thank you for the help.
  14. I have been using Universal Electricity to create an axle network to be able to use for things such as gates. I've been working on making the axles visually spin. The rotation of the axle is decided in updateEntity() off of the current rotation and the current RPS (revolutions per second). This seems to be working fine when I run debug in updateEntity(), but when I debug in the axle's renderer, it always shows rotation as 0. Does anyone have any idea what might be wrong or how to fix it. I'm kinda blanking on this one. Below is the code for TileEntityAxle, which is what all axles extend and contains that code, and the renderer for the wooden axle.
  15. Do you have this in-between your @Init method and your class constructor? @SidedProxy(clientSide = "wogCreeperSheep.common.core.WCSClientProxy", serverSide = "wogCreeperSheep.common.core.WCSCommonProxy") public static WCSCommonProxy proxy;
  16. I managed to solve my spawning issue. I was missing a function in my mod file for registering the entity. I'm still having troubles figuring out why my penguin is spazing out when it moves though. I have added abstract to my class method in EntityPenguin. Anyone know anything else that has to be done when creating a entity class to be extended.
  17. So continuing this highly annoying situation, I have realized that since extending EntityPenguin, my cute little animals spaz out like crazy anytime they move. Previously all the info was in one file (EntityPenguin) I only recently split it up, using EntityPenguin as the base class and, and then creating separate classes for the specific animal type. The movements were working before. I know this for a fact. They only stopped working when I started extending EntityPenguin. Anyone know what's might be going on?
  18. Sorry for posting again......... As the title says, I can't get my stupid animal to spawn naturally in the world. It appears and works fine with a spawn egg, but it won't appear naturally. My class EntityPenguin is the base class and extends EntityTameable. All other penguin types extend from it and are the classes I need to actually spawn into the world. Below is the code I am currently using to attempt to spawn the stupid animal. (I wasn't originally registering both EntityPenguin and EntityBluePenguin, but I figured that my be my issue. If anyone can let me know if this is necessary, I would appreciate. If you can help me fix the issue entirely, I would greatly appreciate it) Mod File public static int startEntityId = 400; @Init public void load(FMLInitializationEvent event) { proxy.registerRenderInformation(); EntityRegistry.registerModEntity(EntityPenguin.class, "Bass Penguin", 1, this, 0, 10, true); EntityRegistry.registerModEntity(EntityBluePenguin.class, "Penguin", 2, this, 80, 3, true); EntityRegistry.addSpawn(EntityBluePenguin.class, 10, 2, 8, EnumCreatureType.creature, BiomeGenBase.frozenOcean, BiomeGenBase.frozenRiver, BiomeGenBase.iceMountains, BiomeGenBase.icePlains, BiomeGenBase.taiga, BiomeGenBase.taigaHills); LanguageRegistry.instance().addStringLocalization("entity.wog890_WogCreeperSheep.Penguin.name", "Penguin"); registerEntityEgg(EntityBluePenguin.class, 0x27A3F5, 0xffffff); } public static void registerEntityEgg(Class<? extends Entity> entity, int primaryColor, int secondaryColor) { int id = getUniqueEntityId(); EntityList.IDtoClassMapping.put(id, entity); EntityList.entityEggs.put(id, new EntityEggInfo(id, primaryColor, secondaryColor)); } public static int getUniqueEntityId() { do { startEntityId++; } while (EntityList.getStringFromID(startEntityId) != null); return startEntityId; } Client Proxy File RenderingRegistry.registerEntityRenderingHandler(EntityPenguin.class, new RenderPenguin(new ModelPenguin(), 0.5F)); RenderingRegistry.registerEntityRenderingHandler(EntityBluePenguin.class, new RenderPenguin(new ModelPenguin(), 0.5F));
  19. I guess that is possible, but the EntityAIMate works exactly the same way, using the same function that I'm using and running the same code, so if that works (and yes I checked, it does), I don't see why mine would run on the server side. I'll see if I can check for that though. Thank you
  20. I solved the first problem. Stopped programming for just a little bit and the idea came to me! I'm still need help with the particles though.....
  21. I am working on making a mob entity that will attempt to find a mate for itself. This type of animal mates for life so obviously I need a way to save which entity is mated to which. I attempted to do it much like entities save their owner (using player.getUsername), but instead of username, because animals don't have usernames, I was using EntityID, since this also must be unique. This works great the first time and the AI with it, but if I reload the world, the entity Id's of all my animal's are different. Because of this, they re-mate. If I re-load the world, this happens again. I can't seem to find a way to create a consistent and guaranteed unique way to do this. Does anyone else have any ideas how to do this? My second issue is, when the animal first finds a mate, I would like it to release a couple heart particles, like wolves and other minecraft animals do while doing hanky panky activities. I used the following code (from EntityAIMate) Random var2 = this.theAnimal.getRNG(); for (int var3 = 0; var3 < 7; ++var3) { double var4 = var2.nextGaussian() * 0.02D; double var6 = var2.nextGaussian() * 0.02D; double var8 = var2.nextGaussian() * 0.02D; this.theWorld.spawnParticle("heart", this.theAnimal.posX + (double)(var2.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, this.theAnimal.posY + 0.5D + (double)(var2.nextFloat() * this.theAnimal.height), this.theAnimal.posZ + (double)(var2.nextFloat() * this.theAnimal.width * 2.0F) - (double)this.theAnimal.width, var4, var6, var8); } But this didn't work. Anyone know anything to help? Thanks in advanced for any and all help!
  22. Yes Sir/Mam, that makes sense now. So with your previous example, it gave four because it was returning the byte in the bit representing four, not returning the bit four places over. The only thing I don't understand is why 1111 1110 becomes a negative number, but I'm sure I can find that on the internet. I'm assuming we need a number with all ones (except for in the place we are resetting to 0) so that any other ones won't be reset. So if I wanted to change the bit representing 8 to 0, I would use, 1111 0111. I should be able to continue now!!!!!!
  23. I decided to try and step through isSitting() and setSitting(), to see if I now understand them. And I'm just going to assume I misunderstood something, since the way I'm doing it will always come up with the same return in isSitting(). If it isn't to much to ask, would you mind stepping through isSitting() and setSitting() and explaining them. If it is unreasonable, I understand.
  24. I'm still a little bit confused. If I understand correctly with the function (dataWatcher.getWatchableObjectByte(16) & 1), this means the value in the first byte of 16 (which I believe to be 10000) which would normally be 0) since the zero in that bit means false to that value. Now if it had been (17) & 1, or (10001), it would have returned 1 since a one in that bit means true to that value, and that bit represents a value of one. If I have that correct, then here is my confusion, in your example above you state (15) & 1 gives 4, but wouldn't it give 8, since the fourth bit over represents a value of 8 and the third byte over represents 4. If I am wrong in my above statements, I would appreciate it if you would explain what I've done wrong. If I am correct I hope I have not offended you, as you just saved my butt majorly. I have been looking all over the place and asking a lot of people and getting no help at all. You are amazing!
×
×
  • Create New...

Important Information

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