hugo_the_dwarf Posted October 25, 2016 Posted October 25, 2016 Hey all, I just got back into modding from a long hiatus. And with a new PC and all that all my old modding setups were wiped, so I figured I'd just bring my mod up to 1.10.2 only to find so many errors. I've cleaned up quite a few but now i'm stuck on my extended props, which I had used very heavily. I've been reading up on capabilities (forge document) not much help on the actual layout and implementation other than some vague "convert this, use this datatype" and anything I find on this forum or in example code is TileEntites or an attempt at an Entity. My IEEPs were mainly for Entities (Max Health bonus, stamina, mana, stats, skills, class, profession, etc.), but I also had a lot of code touching ItemStacks NBTs (weapon level, bonus stats, socketed items, etc) If anyone can explain the process needed: -Create a class of ICapabilityProvider? -Setup Event? or Register capability? -Etc I'd greatly appreciate it or if someone can supply a working example of a Entity and a Itemstack getting capabilities assigned I think I would be able to follow along all those given classes and update my own/created missing, sending packets to update the client(s) is easy enough it doesn't appear packets have changed much from the 1.8 version I was on to 1.10.2 Edit: If needed I could supply my code, however all of my IEEP classes and even the Item classes are rather large due to the amount of custom stats, getters, and setters and helper methods created for complex(not really that complex) calculations. Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
larsgerrits Posted October 25, 2016 Posted October 25, 2016 Have you read the part about updating from IEEP to Capabilities? There's a separate section for that: http://mcforge.readthedocs.io/en/latest/datastorage/capabilities/#migrating-from-iextendedentityproperties. Quote Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support. 1.12 -> 1.13 primer by williewillus. 1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support. http://www.howoldisminecraft1710.today/
hugo_the_dwarf Posted October 25, 2016 Author Posted October 25, 2016 I have read it, it was actually the first part I looked at, actually it was: https://mcforge.readthedocs.io/en/latest/datastorage/extendedentityproperties/ but thanks to the warning at the top I went to where you had linked. Read it from top to bottom and saw the migration part. However it still is very vague I'm still reading it over, hoping that some of it will sink in. Registration (EntityConstructing): Attaching (AttachCapabilityEvent.Entity), the real registration of the Capability happens during pre-init. I know with IEEP it was the @SubscribeEvent public void onEntityConstructing(EntityConstructing event) { // Players if ((event.getEntity() instanceof EntityPlayer) && (ExtendPlayer .get((EntityPlayer) event.getEntity()) == null)) { ExtendPlayer.register((EntityPlayer) event.getEntity()); } } but the quoted part confuses me as now I register it somewhere else, but somehow also attach it with a new event? Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
hugo_the_dwarf Posted October 27, 2016 Author Posted October 27, 2016 Unfortunately I'm not understanding how to get it to work. I'll have to rework my mod completely now, as without being able to store mana, stamina, gold, and other vital attribute stats on players and entities. Without a good reference it's impossible for me to grasp this, from the documentation all it looks like is this just handles storing items (bags, chests, etc) that is not what i'm looking for I just need to store, update, and save custom values that are unique to each player and mob so I can use them during damage and other events. Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Choonster Posted October 27, 2016 Posted October 27, 2016 You register your capability with CapabilityManager.register in preInit. You attach providers for your capability to external objects ( Entities , TileEntities , ItemStack s, etc.) when AttachCapabilitiesEvent<T> is fired. For examples of capabilities, you can look at the capability test mod or my own mod's capabilities (API, implementation). The IMaxHealth capability in my mod will probably be of particular interest, this is attached to entities to store and manage an AttributeModifier to provide bonus max health. 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
Ferrettomato Posted October 28, 2016 Posted October 28, 2016 If you need another example, the visible-source Wizardry mod has an easy-to-understand implementation of capabilities. I used it to figure out capabilities myself. Quote
hugo_the_dwarf Posted October 29, 2016 Author Posted October 29, 2016 Thanks Choonster, I tried to follow your code, however you've integrated it with a design pattern of your choosing/making and it made it a bit difficult for me to follow, at least to get the basic idea of how it should flow however your comments of where to register and what events to use is helpful. Thanks Ferrettomato, looking at the Wizardry code I believe is helping me, it's taking me a bit as my extended prop had a great deal of methods and variables so I'm slowly trying to mimic the Wizardry setup, which appears to be the very basic of how to use a capability, it's very helpful. I have a side Question while I'm plugging away at trying to get a test run of my conversion going. For ItemStacks is it better to use a Capability for storing extra data or can we still use the NBT? since my mod is Diablo and other dungeon crawl types heavy, I attach stats to items (min - max dmg, 5 base stat boosts, sockets, etc) currently my old code for ramming that data into itemstacks hasn't yelled at me yet, but I haven't gotten the old code to compile yet (starting over and moving code pieces slowly into a new project) Should I also setup a Capability for ItemStack values or keep using my NBT data code? Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Choonster Posted October 29, 2016 Posted October 29, 2016 You can still store data in ItemStack NBT, but I'd recommend using a capability if your data is complex, you intend to store the same type of data for multiple different items or you intend for other mods to interact with/extend the data. Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
hugo_the_dwarf Posted October 29, 2016 Author Posted October 29, 2016 Makes sense, really only players benefit from items with stats, but once i figure out this Capability business I will have to convert that code too. https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src/59a4ef4abd8ff735f885c7378fc7c33097be0e82/htd/rot/?at=master I've made this a public Repo so hopefully it works. I've just run into an issue of trying to look at the Capability in the FMLPlayerTick event just to see if I can pull data from it. So far class wise the project is just capabilities so far, so hopefully if anyone wants to have a look and see what I'm doing wrong should be easy to navigate EDIT: the Storage Classes save isn't complete, because I might rewrite the data and methods in the interface since I more or less copy pasted from the Extended Prop to the DefaultCapabilityAttribute but I feel like I will scrap it and redesign it when my mind isn't on "Lets get a capability working, and understand it for other capabilities" Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
SenpaiSubaraki Posted October 29, 2016 Posted October 29, 2016 https://github.com/ArtixAllMighty/Rpg-Addon-BerserkMageArcher/tree/master/subaraki/BMA/capability you cannot go any simpler. I'm only storing two integers here, so the rest stays really basic. attach on attachcapabilityevent, and register with new MyDataCapability().register(); in the mod's preinit Quote https://minecraft.curseforge.com/members/Subaraki/projects
hugo_the_dwarf Posted October 29, 2016 Author Posted October 29, 2016 Awesome that is greatly more helpful (not that the other suggestions were not helpful, I was just struggling to grasp the concepts) I just need to implement the packet usage to update the remote of any changes from the server. And figure out how to get it to work correctly with the clone event (as some stats like what class, profession, etc. should persist through death) Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 Ok I got a simple system constructed, with a packet from server to player to update their attributes, however Since player attributes are composed of "Item given Bonuses" and "Class Base Values (berserker, wizard,etc)" it works fine as I can just design a "stats changed, update player" however. Mobs get their stats when they are created, and this is causing me some grief. As I base their standard difficulty on: Their current constructed Y value (if under sea level deeper means stronger, if higher than 100(currently) higher means stronger) Using their given "depth" bonus some rand int bounds are given a range, and a baseBonus is given by how deep/high they are. I have that math down right, but Mobs don't really need to send their stats to the clients (can remain server-side as no one can look at their stats) I tried adding the rolling of stats in the Capabilities Data Constructor (used by the Provider) and reading up someone had this same issue as the attachment of capabilities is done before the entity is fully constructed (just was I gathered correct if wrong) So I tried the EntityEvent.EntityConstructing and checked some values before calling the rollStats, not much luck as I'm guessing events go: EntityConstructing AttachCapability so I don't believe I can use that, so I tried the LivingEvent.LivingUpdateEvent, checking to see if the entity is not a player, and that a certain value is at the default 0, rollStats. Issue now is that all mobs get the same stats, it's like a one time deal. EDIT I have upaded the Repo/Source https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 Post your rollStats method/code that adds/modifies the stats. Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 This Method is inside the CapAttributeData class public void rollStats(EntityLivingBase entity) { int[] attrs = new int[attributes.length]; int baseDepth = 62; int baseHeight = 100; int yHeight = (int) entity.posY; int heightBonus = yHeight < 62 ? yHeight - baseDepth : yHeight > baseHeight ? yHeight - baseHeight : 0; heightBonus = heightBonus < 0 ? heightBonus * -1 : heightBonus; int mobDifficulty = MathHelper.clamp_int(yHeight/10, 1, 25); int baseBonus = mobDifficulty * (mobDifficulty / 5); Console.out().println("Mob Stat Rolling: " +entity.getName()+ " Mob Depth: " + yHeight + " Mob Height Bonus: " + heightBonus + " Base Bonus: " + baseBonus); Random rand = new Random(); for (int index = 0; index < attrs.length; index++) { attrs[index] = (int) ((rand.nextInt(12 + heightBonus) * (mobDifficulty / 4))+baseBonus); Console.out().println("Stat "+attributeTags[index]+ ": "+attrs[index] + "-------------"); } Console.out().println("-------------------------------"); updateAttributes(attrs); } Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 Could you post updateAttributes and your LivingUpdateEvent. *Also post the console. Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 updateAttributes is also inside the CapAttributeData Class public void updateAttributes(int[] attributes) { int[] pulledAttributes = attributes; for(int index = 0; index < this.attributes.length;index++) { pulledAttributes[index] = pulledAttributes[index] > STAT_MAX_LIMIT ? STAT_MAX_LIMIT : pulledAttributes[index]; pulledAttributes[index] = pulledAttributes[index] < (STAT_MAX_LIMIT * -1) ? (STAT_MAX_LIMIT * -1) : pulledAttributes[index]; } this.attributes = pulledAttributes; dataChanged(); } public void dataChanged() { if (entity != null && !entity.worldObj.isRemote && entity instanceof EntityPlayer) { PacketManager.INSTANCE.sendTo(new CapAttributePacket(attributes), (EntityPlayerMP) entity); } } also included the dataChanged method the updated method is in "EventAddCapability" class for now as i'm just trying to get something working: @SubscribeEvent public void onEntityUpdate(LivingEvent.LivingUpdateEvent event) { if(!event.getEntityLiving().worldObj.isRemote && !(event.getEntityLiving() instanceof EntityPlayer)) { if (event.getEntityLiving().hasCapability(CapAttribute.CAPABILITY, null)) { if (event.getEntityLiving().getCapability(CapAttribute.CAPABILITY, null).attributes[0] == 0) event.getEntityLiving().getCapability(CapAttribute.CAPABILITY, null).rollStats(event.getEntityLiving()); } } } Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 When you apply the attribute you need to check if they have the attribute otherwise it will get set every update. Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 ah so you mean my current attachement: @SubscribeEvent public void onAddCapabilities(AttachCapabilitiesEvent.Entity e) { if (e.getEntity() instanceof EntityLivingBase) { EntityLivingBase ent = (EntityLivingBase)e.getEntity(); if (canHaveAttributes(ent)) { e.addCapability(CapAttributeProvider.KEY, new CapAttributeProvider(ent)); } } } I should include a "entity.hasCapability(mine,null);" I only find it strange that my Console.out().Prints seem to output the exact same value for every mob including the player (on death) Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 No that is not what I meant what does CapAttributePacket do? Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 The packet only sends the stats from the server to a client, which I have limited to only the player (or a player) currently as it's only for when I setup the GUI again so players can view their own stats. Also with some changes this is roughly my output [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:56]: Mob Stat Rolling: Chicken Mob Depth: 98 Mob Height Bonus: 0 Base Bonus: 9 [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:62]: Stat Strength: 25------------- [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:62]: Stat Dexterity: 25------------- [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:62]: Stat Intelligence: 25------------- [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:62]: Stat Vitality: 21------------- [15:39:31] [server thread/INFO] [sTDOUT]: [htd.rot.capability.CapAttributeData:rollStats:64]: ------------------------------- [15:39:37] [server thread/WARN]: Can't keep up! Did the system time change, or is the server overloaded? Running 2856ms behind, skipping 57 tick(s) [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:29]: Dead Mob: Sheep [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Strength=25 [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Dexterity=25 [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Intelligence=25 [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Vitality=21 [15:39:55] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:34]: ----------------------------------------- [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:29]: Dead Mob: Sheep [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Strength=25 [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Dexterity=25 [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Intelligence=25 [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Vitality=21 [15:39:56] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:34]: ----------------------------------------- [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:29]: Dead Mob: Sheep [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Strength=25 [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Dexterity=25 [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Intelligence=25 [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:32]: Vitality=21 [15:39:58] [server thread/INFO] [sTDOUT]: [htd.rot.events.EventEntityDeath:onEntityDied:34]: ----------------------------------------- [15:39:58] [server thread/WARN]: Can't keep up! Did the system time change, or is the server overloaded? Running 4020ms behind, skipping 80 tick(s) It generates and sets the values for just one mob in this case a chicken, then all of a sudden everyone has the same values (recorded by their death event) Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 Please post the packet. Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 packet package htd.rot.comms.packets; import htd.rot.Rot; import htd.rot.capability.CapAttribute; import htd.rot.capability.CapAttributeData; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class CapAttributePacket implements IMessage { int[] attributes = new int[CapAttributeData.attributes.length]; public CapAttributePacket(){} public CapAttributePacket(int[] attributes) { this.attributes = attributes; } @Override public void fromBytes(ByteBuf buf) { for (int index = 0; index < attributes.length; index++) { attributes[index] = buf.readInt(); } } @Override public void toBytes(ByteBuf buf) { for (int index = 0; index < attributes.length; index++) { buf.writeInt(attributes[index]); } } public static class CapAttributePacketHandler implements IMessageHandler<CapAttributePacket, IMessage> { @Override public IMessage onMessage(CapAttributePacket message, MessageContext ctx) { EntityPlayer player = Rot.proxy.getClientPlayer(); if (player != null) { player.getCapability(CapAttribute.CAPABILITY, null).attributes = message.attributes; } return null; } } } Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 packet package htd.rot.comms.packets; import htd.rot.Rot; import htd.rot.capability.CapAttribute; import htd.rot.capability.CapAttributeData; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class CapAttributePacket implements IMessage { int[] attributes = new int[CapAttributeData.attributes.length]; public CapAttributePacket(){} public CapAttributePacket(int[] attributes) { this.attributes = attributes; } @Override public void fromBytes(ByteBuf buf) { for (int index = 0; index < attributes.length; index++) { attributes[index] = buf.readInt(); } } @Override public void toBytes(ByteBuf buf) { for (int index = 0; index < attributes.length; index++) { buf.writeInt(attributes[index]); } } public static class CapAttributePacketHandler implements IMessageHandler<CapAttributePacket, IMessage> { @Override public IMessage onMessage(CapAttributePacket message, MessageContext ctx) { EntityPlayer player = Rot.proxy.getClientPlayer(); if (player != null) { player.getCapability(CapAttribute.CAPABILITY, null).attributes = message.attributes; } return null; } } } Could they have been on the same y level? Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
hugo_the_dwarf Posted November 1, 2016 Author Posted November 1, 2016 It's very possible they would be on the same Y However the roll logic is always 0-12 + (height bonus calculated via Y level being under or above the base Depth and Height) then that value is multiplied by the MobLevel (Difficulty) which can be 1 to 25 (clamped) / 4 then the baseBonus is added onto it (so if it's higher level mob it will have something always greater than 0) I added in my code to roll on attachment (so when the provider gives it out) and on the update results is I get alot of "everything is nothing" then a rare "stats rolled" but those stats are applied to everything. I may have broken it that or capabilities are shared with "all" entities (one instance to serve them all) if that's the case I want my IEEP back, at least I could have each entity own it's own unique values EDIT to your Y question I hope I was on the same page, even if they were on the same Y there should still be some randomness to their stats Quote Currently updating my Mod to 1.10.2 https://bitbucket.org/hugo_the_dwarf/riseoftristram2016/src?at=master
Animefan8888 Posted November 1, 2016 Posted November 1, 2016 It's very possible they would be on the same Y However the roll logic is always 0-12 + (height bonus calculated via Y level being under or above the base Depth and Height) then that value is multiplied by the MobLevel (Difficulty) which can be 1 to 25 (clamped) / 4 then the baseBonus is added onto it (so if it's higher level mob it will have something always greater than 0) I added in my code to roll on attachment (so when the provider gives it out) and on the update results is I get alot of "everything is nothing" then a rare "stats rolled" but those stats are applied to everything. I may have broken it that or capabilities are shared with "all" entities (one instance to serve them all) if that's the case I want my IEEP back, at least I could have each entity own it's own unique values EDIT to your Y question I hope I was on the same page, even if they were on the same Y there should still be some randomness to their stats Ok I didn't look to much in depth into your calculations so I didn't know about the randomness factor. Is it possible that attributes is a static variable? Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator.
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.