Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. In coding there are many ways to achieve the same thing, and some of it is just preference and some of it is situational. Regarding preference, as diesieben07 mentioned earlier there is some argument remaining about the best way to do this and the terminology but most people have found a way that works for them and stuck with it. In the end, the main point is that the proxy annotation allows you to point to a class that is loaded differently depending on which logical side is running. It is particularly useful for code that has the name but you want to operate differently on each side, because if there is code that is only run on one side you can just annotate it directly (that is why you also see methods, fields and classes with sided annotation sprinkled through other classes). The FML Lifecycle events (a.k.a. pre-init, init, post-init, etc.) are commonly ones that you collect in the proxy although some people find cases where they have other custom methods they want to run differently on each side and so also collect those there. From there you can do many things so long as you collect all your sided code accordingly and respect the regular rules of Java inheritance. If it works, it is valid. Whether it is the best way depends on philosophy and situation.
  2. If you want to move all spawn eggs then you can just call the public method Items.SPAWN_EGG.setCreativeTab(your custom tab here). However, I assume that you just want to do that only for spawn eggs for your custom entities. There might be an easy way to do it but as far as I can tell the EntityRegistry spawn eggs all use the vanilla instance, so I've always done it by making my own custom spawn egg that extends the vanilla ItemMonsterPlacer. I haven't done that in recent versions but "in the old days" there was a time that you had to make custom spawn eggs for your custom entities before they added the hooks. I still have some tutorial information posted at http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-creating-custom.html The code was posted for version 1.7.10 so you might need to do a bit of updating but I think the overall concept should still work.
  3. Actually not quite because I also didn't want it to toggle if only the main hand is empty. Like if the player has a breeding item in the off hand I didn't want sit to toggle. So basically when it fires I check that both hands are empty and then further do nothing if the hand is the off hand. I got it working well, just the fact that the vanilla code should not work is driving me crazy!
  4. 1. Yes. 2. It does matter if you ever want to check config during registration or other loading events. Right now you might not care, but probably best to do it a way that is "future proof" to avoid headache later. 3. What happens if you click on the mod Options button in the ingame or mod loading screen? Nothing? Do you want users to be able to change config that way as well? I don't really have any other ideas of what might be going wrong for you. You can look at one of my working mods to see if anything else stands out for you on what I do differently. https://github.com/jabelar/WildAnimalsPlus-1.12.1
  5. I know but that isn't my code -- that is the vanilla code! It works but it shouldn't. I think it should do what you said -- it will toggle twice and cancel, but it doesn't. In my own entity I fixed it just like you said -- I only toggle if both hands are empty. But why is the vanilla code working?
  6. So I'm updating my 1.7.10 mods to 1.12.1 and having a funny problem with the fact that now there are two hands to check during entity interactions. In my mod I replicate (mostly) the EntityWolf sitting behavior. Basically it "toggles" -- if player interacts with nothing in the players hand(s) and if the entity is sitting it should stop sitting and if not sitting it should start sitting. However, for me the sitting wasn't working and I traced it down to the fact that processInteract() fires twice -- once for each hand -- and so it was toggling twice and basically cancelling itself. Now I know how to fix this -- I can check both hands. But the interesting thing is that I basically copied EntityWolf and so I wanted to see how they handled it and why my entity acts differently. The weird thing is that as far as I can see the EntityWolf code would have the same problem -- it fires twice and only checks one hand at a time. Here is the code from EntityWolf: public boolean processInteract(EntityPlayer player, EnumHand hand) { ItemStack itemstack = player.getHeldItem(hand); if (this.isTamed()) { if (!itemstack.isEmpty()) { if (itemstack.getItem() instanceof ItemFood) { ItemFood itemfood = (ItemFood)itemstack.getItem(); if (itemfood.isWolfsFavoriteMeat() && ((Float)this.dataManager.get(DATA_HEALTH_ID)).floatValue() < 20.0F) { if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); } this.heal((float)itemfood.getHealAmount(itemstack)); return true; } } else if (itemstack.getItem() == Items.DYE) { EnumDyeColor enumdyecolor = EnumDyeColor.byDyeDamage(itemstack.getMetadata()); if (enumdyecolor != this.getCollarColor()) { this.setCollarColor(enumdyecolor); if (!player.capabilities.isCreativeMode) { itemstack.shrink(1); } return true; } } } if (this.isOwner(player) && !this.world.isRemote && !this.isBreedingItem(itemstack)) { this.aiSit.setSitting(!this.isSitting()); this.isJumping = false; this.navigator.clearPathEntity(); this.setAttackTarget((EntityLivingBase)null); } } You can see that the whole code will only check the hand passed in and if the wolf is tamed and there is nothing in that hand it will toggle the sitting. And the setSitting() method called is a simple setter that doesn't do any additional check to prevent toggling. How the heck is that working? I actually think it doesn't really work but that the aiSit code is somehow correcting it elsewhere. The difference in my entity is that I keep track of sitting within my class, not the AI class, so probaly it has to do with that. However, still seems mysterious to me. What am I missing? I can easily fix it in my code but am extremely curious about how it can possibly work in the vanilla code...
  7. It works for me, but I do a few additional things: The method where you save should be called from an onConfigurationChangedEvent handler. I do the stuff you do in postInit in the preInit. It may not matter for some cases, but I often use configuration during other loading stages (like I use configuration to register different items and such) so I like to have it available in preinit. I put a default asset file in my resources with default values. I think the config system will create one if it doesn't exist, but seems safer to me. You would create a "config" folder in your assets and name the file with same name as your modid with .cfg extension. And in the file put something like: # Configuration file #################### # general #################### general { B:testBol=false } Now, the next thing is the configuration system is intended for things that get changed using the configuration GUI, not changed in your code elsewhere. Do you also have a GuiConfig class and gui factory registered? I suppose it should be okay to just call the setTestBol() method anywhere from your code, but I don't do that -- config for me can only be changed through the GUI or through direct editing of the .cfg file. Note there is now a new @Config system I haven't tried yet which may make this all easier (or not). There are other threads about it and Choonster seems to be familiar with it.
  8. Sorry it should actually be super.preInit(e) You need to call the super method, not the super constructor. Also, you're right it is probably better to call it before the initModels().
  9. I meant regular event handler registration. He was treating it like a regular registration. I seem to remember that problems could arise if you registered those at preInit time, although I can't remember and it may not matter or perhaps doesn't matter any more. I've never had trouble registering regular event handler on init. As mentioned the registry events don't need explicit registration since the annotation takes care of that, so shouldn't be in preInit or init. I suppose technically they're also on the same bus, but they're now handled somewhat separately.
  10. When you call the super method, you do it by passing the parameter through. Since your ClientProxy extends CommonProxy, iyou want to run the CommonProxy preInit() as well to make sure the actual entity is registered on the client. Like this ModEntities.initModels(); super(e); ISo you're passing the event to the common proxy method.
  11. IYour getting close but there are a couple things that are suspicious to me. I'm assuming that youre Reference.CLIENTPROXY and Reference.SERVERPROXY are strings with full package and class names, but after that: 1) I usually register my event listener to the bus in the init() rather than the preinit() handling method. I'm not sure where I learned that, but it has always worked for me and you might run into trouble (or maybe not) at that point. The registry method in 1.12.1 actually doesn't need you to register the handler class directly to the bus. Instead you use an @ObjectHolder annotation and another type of subscription. In other words, you don't register the registry rather it registers itself based on annotation. I'm sure Draco's examples are good so look at them more closely.
  12. what's in your common proxy class? Also, which version of Minecraft are you modding? If you're using 1.11 or more recent then there is a newer way of registering render handlers using a "factory" method. Not sure if it helps but you can look at my code for one of my entity mods here: https://github.com/jabelar/WildAnimalsPlus-1.12.1/blob/master/src/main/java/com/blogspot/jabelarminecraft/wildanimals/proxy/ClientProxy.java
  13. That is a valid approach. There are a lot of different approaches. Some people combine some registration code in each item class, I just list it out directly in my event handler. One philosophy I have is that although I like the idea of putting things in lists and iterating, it is also no effort at all to cut and paste in an IDE and you have to create the list anyway so it doesn't save you that much to put it in a list rather than just have a line to register each item. For me, iterating through a list is more efficient when you're doing several lines of processing. If you're doing a single line then you don't save much. Cut and paste can of course introduce errors sometimes, but when all the lines are one after another that is easy to catch. My basic approach is to create all my instances in a ModItems class, and then have a registerItems() method in that class that I call from my proxy (in older versions) and from my registry event handler in more recent versions. I sometimes make my ModItems class also the event subscriber. In programming there are a lot of ways to achieve the same thing and a lot is just personal preference. I rarely do mods with more than a half dozen items so I don't get too fancy with organizing it. If you're doing a major item overhaul mod then of course you need to architect things for greater convenience.
  14. I think the problem may be that in your client proxy you don't call the super method for the preinit() method. The way you're doing it you're registering the entity model and renderer on the client but not the entity itself.
  15. I've got various tutorials here: http://jabelarminecraft.blogspot.com/ Some information is still for older versions, but I've updated a fair bit and also a lot of stuff is still relevant or close to 1.12 approach. It might be helpful.
  16. Thanks, you're doing it exactly the same way I am for the reflection. So I'll consider it a reasonable approach then. Thanks for the confirmation.
  17. The error is that you don't have any backslash mod at all.
  18. I'm porting my mods to 1.12.1 and moving achievements to advancements. I understand that many advancements can be implemented just by using JSON, and there are a lot of interesting vanilla triggers, but my advancements are usually more complex. As an example, I've got mobs with their own taming system that don't extend ITameable so the vanilla tame_an_animal trigger won't fire but I want to make similar advancement (taming eagles leads to "falconer" advancement, taming a big cat leads to "lion tamer" advancement). There probably is a way to wrangle NBT to use JSON only, but it is much easier for me just to fire a trigger that doesn't need further testing... So i decided to make my own flexible custom criterion system. It works fine but I'm wondering if I'm reinventing something or if there are other side effects of my approach. My main idea is that I want to fire criteria that don't need testing. In other words, I fire the "tame_bird" using my TAME_BIRD.trigger() method and only pass it the player since that is minimum needed to attach the trigger to the player. Everytime I trigger it will test as true -- no other predicate testing. To make it flexible, I have a single criteria class which has constructor to take in the name (i.e. the "tame_bird") so that associated JSON will work. The JSON is very simple. Just has the display and parent and then associated the criteria with the single trigger. The only hurdle I faced was registering a custom criterion. As far as I could tell, there is no registry event for it and the registry field and the register method on the build-in registry (CriteriaTriggers class) are private. So I used some simple Java Reflection and it worked fine. So everything works -- trigger fires and the advancement works as expected, shows toast message, is displayed in advancement tree, so forth. But I have two questions: 1) Does forge provide a method for registering custom criteria? Any time I use reflection I assume I'm missing out on some hook that already exists... 2) Is there any side effect for not using predicates in my test method? Would it affect my (or resource packs') ability to combine criteria in a more complicated JSON? Otherwise it is really slick system. I simply register a new instance with new name, trigger it wherever I want in code, and copy a very simple JSON to hook it into the advancement tree.
  19. you can look at mrcrayfish's furniture mod code, he has a good mirror block: https://github.com/MrCrayfish/MrCrayfishFurnitureMod/blob/master/src/main/java/com/mrcrayfish/furniture/blocks/BlockMirror.java
  20. I don't think you read the OP's problem carefully. He's not worried about vanilla blocks, he's handled that. He's worried about other mods that manipulate drops in the harvest event. So I think you need to process the event further (as the methods you mentioned aren't relevant) after the other mod's manipulation. I would basically find all the other mods' blocks in the registry and do a sort of test where I take a location in the world and during one tick successively place each block then break them and handle the harvest event with the low priority and receive canceled annotation I suggested.
  21. Events are fired across each mod in succession meaning that if you handle the event after another mod then you will have access to any changes it made to the drops for that event. A lot of people don't realize that you can change the priority of your subscribe so that it processes after or before other mods -- or at least has a better chance to (if other mod also sets the priority then it is a matter of which mod loads first I think so you would have to control the order the mods actually load). So in your case you want it to load after. Plus you need to handle the case where the previous mod tries to cancel the event (which would normally prevent you from getting it) using the receive cancelled option. Simply create an event handler annotated with @SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true) In that you can grab the event.getDrops() and do something with it.
  22. I guess my question is -- do you want to prevent the player from going somewhere that cannot be loaded, do you want to just somehow queue up the teleport until the chunk is loaded, or do you want to load some sort of default "filler" in the case where it won't load? Personally if the network is down then I think you should prevent the player from going somewhere where you don't have info. Alternatively when network is down you should just render a default chunk (maybe flat so it is obvious that there is a problem). IIn any case, you should be able to handle any error and prevent crashes. What error specifically were you seeing and did you try to catch it.
  23. Okay, but I assume that the fact that they are backwards was a mistake someone made along the way? Or someone was trying to do something clever with bit-wise operations? Even the DyeUtils methods really aren't commented clearly. The getColorFromStack() method doesn't mention that it only works for things that have been dyed and not for dyes themselves. And the words "metadata" and "damage value" are often used interchangeably. Even in the link you sent for the block colors calls it the "damage value"... Oh well, part of the fun of modding is finding these little nuances in the code.
  24. I was making a color changing collar for my entity, similar to wolf, and I took the dye item stack in the players hand used the EnumDyeColor.byMetaData() method and found that it was mixing up the colors -- it would do orange when I was holding red, it would do lime when holding magenta. Looking at the EnumDyeColor class I see that they have tables for both looking up dye color by meta and by damage and they are inverted. So my solution is obviously to use the byDyeDamage() method which works, but it made me curious as to why they have both. For example, the DyeUtils getColorFromStack() method uses the byMetaDAta() method which is why I initially tried that. But that actually returns the wrong value if you're holding dye ... I see both methods are used throughout the code. Is there any guideline as to when to use which?
  25. I think JSONToNBT does not take in a whole JSON file, but rather takes in a single JSON tag. So I think you need to run it on the result of somthing like JsonUtils.getString(object, "tag") where object is of type JSON Object. In other words, it just takes in the string value of the the element. Look at the SetNBT class that extends LootFunction
×
×
  • Create New...

Important Information

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