Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. I'm not totally sure but I assume that the KeyInputEvent only fires on the client side, so should be safe (or you can ensure it is safe with a @SideOnly(Side.CLIENT) annotation on the handler) to call Minecraft.getMinecraft().thePlayer to get the player.
  2. Maybe I should clarify what I'm trying to generalize. This is my current thought/development process (incorporating all your feedback above) on whether to receive canceled. 1. For tick type (i.e. continuously firing) events, if you can tolerate missing occasional ticks, then just @SubscribeEvent with default settings (normal priority, no received cancelled). If you can't handle missing them follow the rest of the flow below 2. For other event types, default to receiveCanceled=true unless you can tolerate missing some events (in which case just use default settings). In the handling method for those where you have receiveCanceled=true, check for isCanceled() and output console message if detect a cancelled event. Otherwise (for now, resolving incompatibility comes later) let your handling code continue even if receiving cancelled event. 3. For priority, leave at default unless you're cancelling the event. If you're cancelling the event, follow the logic that Sequitiri mentions above to figure out if raising or lowering priority makes sense. (Of course if you have reasons within your own mod to have multiple handlers for same event, you may also want to modify priority to control their order.) 4. Test for compatibility with other mods that are common or that you care about running together. Look for cases (based on your console message) where the other mods are cancelling events. Modify your code accordingly, ideally in conversation with the other mod's authors. It just seems to me that going through process where you are aware of the interactions (i.e. due to receiveCanceled=true) is highly preferable to having silent interactions... But there seems to be quite the outcry from expert coders about my suggesting this, so I guess I need to think about it further.
  3. But why would you assume that another mod's reason for cancelling any more valid than yours? I think it is all very polite to assume that all other mods are more important than yours, but that doesn't seem very logical to me. Also as I said before, I have to assume they are mostly cancelling in order to prevent vanilla behavior, not necessarily all other mods. I really don't understand what case where you're handling an event where you could tolerate it being cancelled? Especially without even knowing it is canceled? If your mod's functionality is cancelled, you're basically saying your mod might as well not be installed. Certainly, if you know what the other mod is actually doing then you can judge it correctly and decide to defer to their priority and cancellation. For example maybe they're doing a similar thing to yours, or maybe the result of both handling would be weird. But resolving that, to me, is a secondary activity related to resolving specific mod compatibility problems. I must be missing something about why people cancel events, or specifically "not every time" as you said. I've mostly done cancellation to fully replace vanilla handling which means handling every time. Like if I'm changing the rendering in major overhaul, or I'm freezing the motion of an entity, I would cancel the event. And for those events I handle without cancelling, I still expect to handle them every time. Every time an Item breaks maybe I do something special, or every time and Entity spawns. I wouldn't want to miss any. I understand with tick events you can recover if you only get them occasionally, but I'm worried about events that are only single-fire. Can you give me some examples of (non-tick-type) handling where you could tolerate being cancelled without breaking your functionality? Sure, but resolving weird effects is an activity you do when mod incompatibilities are reported, because it is very situational. I don't think the general solution to avoiding weird effects is to always let other mods do what they want.
  4. I can't think of many situations where a modder can tolerate to have an event that they are handling cancelled -- I mean you're handling the event for a reason and missing it will presumably break some feature of your mod. I expect most mods that cancel the event are doing so to prevent the vanilla behavior, not other mods. I really think most people should want to receive cancelled events -- it can't really hurt and can definitely help. Regarding priority, I think it depends on whether your handler does any cancellation itself. If you don't cancel the event, then I think it is reasonable to set to HIGHEST because you'll still be passing the event to others and you minimize the risk of being cancelled yourself. However, I suppose as long as you receive cancelled events then I guess it doesn't matter much what your priority is. In the end though, full mod compatibility is a case by case thing that probably needs some discussion between mod authors or at least needs some understanding of the specific case. It would also be interesting to come up with a scheme that mitigates compatibility issues by setting receiveCanceled=true, checking isCanceled() and then checking what other mods are loaded (sadly the listener bus seems to be private so can't be analyzed directly) to guess which one is the "culprit" causing the cancelation. So I think I'm going to go with the philosophy of always receiveCanceled but priority=EventPriority.NORMAL unless there is reason to do otherwise.
  5. I believe you can manually post events to the bus. Try posting a NameFormat for that player.
  6. Note that some mods provide an "API" which is a public way to interact with their mod. It depends on whether you want the deobfuscated code so you can study/copy/steal it or whether you just want to be able to interact with it.
  7. We already went through this idea -- the problem is that would block all entities, including players. He wants to only block certain mobs from crossing.
  8. The crash report indicates you have an instantiation exception for the PacketDisabled class. I think you need to add a default constructor to the PacketDisabled class: public PacketDisabled() { }
  9. Yeah, I was kinda expecting this was an "it depends" question. Since the posting of events is just code scattered throughout the source I could see where it might be implemented inconsistently. Of course the other point is that you can (like Sequituri mentions) subscribe to canceled events anyway (probably recommended for all your subscriptions if you're worried about other mods canceling events). So I think the recommended thing to do is to subscribe at HIGHEST and receiveCanceled=true and if you run across known mod incompatibilities you could check isCanceled() and if that is true you can see what mods are loaded and try to figure out how to modify your handling if necessary.
  10. Well, the people doing the naming are working hard so I won't be too critical. And I can see why whoever was figuring out the deobfuscation might have thought IAnimal was a suitable name if the first entity they saw extend it was EntityAnimal. The rest of the entities mostly inherit it from IMob so not as clear that the interface was implemented by classes beyond EntityAnimal. So if you were working on MCP and trying to figure out what the interface did it would be easy to start with assumption that it was related to animals. But yeah this is second questionable naming I've found. One I mentioned before is flat-out wrong -- the isClientWorld() method in EntityLivingBase has the logic backwards (it returns true if on server world). Similarly, block method names related to "solid", "collidable", "normalCube", "opaque" and stuff are all probably slightly misnamed because everyone assumes they have to do with pathfinding or colliding with blocks when instead they can be related to other more nuanced meaning. Anyway, I'm definitely getting more cautious about using any field or method without inspecting the implementation carefully. I was surprised by some modders who don't use decomp workspace and instead use dev workspace (without source attached). Seems a little risky to trust the methods functionality based on their deobfuscated names...
  11. The IAnimal interface is kind of wierdly used. Or maybe more likely it is weirdly named by MCP. Normally an interface is used to define the common public methods for a set of classes. It can also be used as a "grouping" mechanism for classes that aren't otherwise in common inheritance -- in other words you can use instanceof to check for implementation of an interface. It seems that IAnimal is empty (no methods) so is used simply for grouping (I'll get to that in a sec). A true "IAnimal" would be expected to define those methods actually used by EntityAnimal, like for mating. However it doesn't so is really just a grouping interface. Now EntityAnimal does in fact implement IAnimal. However, IMob extends IAnimal so that means that all EntityMob subclasses are also instanceof IAnimal, as are boss entities. And EntityAmbientCreature also implements IAnimal. So that is fine, but this is so broad that it doesn't have that much in common, and it doesn't enforce an actual animal-like interface -- i.e. Zombies implement IAnimal (through extension by IMob) but don't mate like EntityAnimal does. As far as I can tell, the only real use of IAnimal is in EntityTracker where it checks for instanceof IAnimal and considers it something that should be tracked. So it seems that IAnimal was really misnamed. It should just be called ITrackable or similar. It has nothing to do specifically with "animals" except for fact that EntityAnimal is one of many classes that implement it. Any thoughts? Do others agree?
  12. Perfect. In 1.7.2 the annotation has changed to @Subscribe but I checked it out more closely and there is indeed ability to put priority, where EventPriority enum s defined as possible: public enum EventPriority { /*Priority of event listeners, listeners will be sorted with respect to this priority level. * * Note: * Due to using a ArrayList in the ListenerList, * these need to stay in a contiguous index starting at 0. {Default ordinal} */ HIGHEST, //First to execute HIGH, NORMAL, LOW, LOWEST //Last to execute } Of course this is still a bit silly because every mod author can make their event handlers highest priority, and in that case I think it would still end up the way I mentioned -- i.e. handled in order that mods register their handlers. So the result is that there is no guarantee that another mod won't intercept your handling. But I guess that is standard kind of issue related to mod compatibility... Still interested if people know the answer to #2.
  13. Actually it is a dumb implementation -- it shouldn't be sensitive to final white space near the = assignment. Pretty much every person does this wrong the first time, and then again later when they forget.
  14. Sorry if this has been asked before, but quick search didn't find it. And too lazy to experiment ... Question 1. If one mod cancels an event, it is cancelled for other mods as well, right? I assume that the mod that gets priority is the one that registers the handler first, which (since most mods register them during the FMLInitializationEvent) is normally based on the order that mods are loaded, right? Question 2. If there is a series of event subclasses, like Pre and Post, or Start and Finish, does cancelling the earlier event also cancel the later event? I'm assuming so as it would presumably break the vanilla code if the expected earlier code doesn't run, but this also seems problematic -- if I handle a Pre event and cancel the vanilla handling then I can't do any Post event (or I guess I would have to fire that myself?).
  15. Well, if for "easy" you mean less typing, then probably not unless all the entities shared something in common that made them different than all other entities. For example, if you wanted to check for all EntityMob then you wouldn't have to list all the mobs. But sometimes in computer programming you just have to list out all the cases and handle them.
  16. I think the problem is that you're returning from the method as soon as you find a match, and worse you're checking for wooden first. I think the way you've got it coded will probably return the first sword of any type (not the best). If you're trying to find the best one, you need to loop through the whole inventory only looking for the best sword, and then loop through the whole inventory again looking for the next best, and so on.
  17. The bat movement is directly coded in its updateAITasks() method. In that event you can see that the motion fields get updated with some randomness to give the fluttery flight of the bat. Additionally some motionY randomness is added in the onUpdate() method. So to freeze the bat I think you can force the motionX, motionY, and motionZ all to be 0. You may need to also set the poxX = prevPosX, etc. as the position might change a bit before potion effect is processed -- not sure about that. In fact, for the freezing effect generally I don't think you should change the movementSpeed, which technically is an attribute -- it doesn't represent the speed the entity is actually moving, but instead represents the speed the entity might move. The actual speed of the entity is reflected by motionX, motionY, motionZ for the most part. Anyway, I think clearing the motion fields and resetting the position fields to previous value should generally "freeze" all types of entity. For the teleporting of an Enderman, that occurs in the EntityEnderman onLivingUpdate() method. To modify that I think you have to create an event handler for the LivingUpdateEvent and check if the entityLiving is instanceof EntityEnderman and then check if potion effect is active on it and if it is then cancel the update processing.
  18. Create Entity Extended Properties For most custom entities, you'll add fields to hold information that is specific to your entity. This information is not automatically saved or synced, so you need to make sure that happens. You can also create extended version of vanilla enities, including the player -- check out CoolAlias' tutorial: http://www.minecraftforum.net/topic/1952901-172164-eventhandler-and-iextendedentityproperties/ There is an interface provided called IExtendedEntityProperties that helps handle these properties. I explain how to use that here. Create A Class That Implements IExtendedEntityProperties In that class, create protected fields for the entity and the world. Eclipse should give you a warning about unimplemented methods, so accept its suggested fix to create those methods for your. In the init() method copy the entity and world parameters to the associated fields In the saveNBTData() method, use the compound.setxxx() type methods (where xxx should be replaced with the data type) to take each entity field getter and store it in NBT tag of similar name. In the loadNBTData() method, use the entity’s setter methods and grab the compound.getxxx() methods (where xxx should be replaced with the data type) to retrieve each tagged data. Example (in this case scaleFactor, rearingCounter, etc. are my custom properties, and the EntityHerdAnimal and EntityElephant are my custom entities -- replace with your own stuff): public class ExtendedPropertiesHerdAnimal implements IExtendedEntityProperties { public final static String extendedPropertiesName = "extendedPropertiesWildAnimal"; protected EntityHerdAnimal theEntity; protected World theWorld; @Override public void saveNBTData(NBTTagCompound parCompound) { // DEBUG System.out.println("ExtendedPropertiesHerdAnimal saveNBTData()"); // good idea to keep your extended properties in a sub-compound to // avoid conflicts with other possible extended properties, // even from other mods (like if a mod extends all EntityAnimal) NBTTagCompound compound = new NBTTagCompound(); parCompound.setTag(extendedPropertiesName, compound); // set as a sub-compound compound.setFloat("scaleFactor", theEntity.getScaleFactor()); compound.setInteger("rearingCounter", theEntity.getRearingCounter()); compound.setInteger("rearingTicksMax", theEntity.getRearingTicksMax()); compound.setBoolean("isRearing", theEntity.isRearing()); } @Override public void loadNBTData(NBTTagCompound parCompound) { // DEBUG System.out.println("ExtendedPropertiesHerdAnimal loadNBTData()"); // Get the sub-compound NBTTagCompound compound = (NBTTagCompound) parCompound.getTag(extendedPropertiesName); theEntity.setScaleFactor(compound.getFloat("scaleFactor")); theEntity.setRearingCounter(compound.getInteger("rearingCounter")); theEntity.setRearingTicksMax(compound.getInteger("rearingTicksMax")); theEntity.setRearing(compound.getBoolean("isRearing")); } @Override public void init(Entity entity, World world) { // DEBUG System.out.println("ExtendedPropertiesHerdAnimal init()"); theEntity = (EntityElephant)entity; theWorld = world; } } Register Entity Extended Properties To ensure that the extended properties are activated, you need to register them. In your mod’s custom event handler class (the one that is subscribed to the EVENT_BUS) subscribe to the onEntityConstructing() event. Inside the method subscribed to the event, for each entity that you want to have extended properties check that the entity is of the type you want to register, then register the associated extended properties class. Example: @SubscribeEvent public void onEntityConstructing(EntityConstructing event) { // Register extended entity properties // Herd animals if (event.entity instanceof EntityHerdAnimal) { // DEBUG System.out.println("OnEntityConstructing register HerdAnimals extended properties"); event.entity.registerExtendedProperties("ExtendedPropertiesHerdAnimal", new ExtendedPropertiesHerdAnimal()); } } }
  19. Thanks! This is pretty much what I expected but it is a lot better having confidence, especially on the topic of how the parent and subclasses work with respect to handling. One further question though: it seems that some parent classes get fired and others don't, or at least I've had trouble subscribing to them. For example subscribing to GuiScreenEvent seems to give me an error when registering my handler, but subscribing to GuiScreenEvent.ActionPerformed works fine. Is there any specific reasoning behind this?
  20. Sorry to pile on this thread, but I have some questions in following this thread. First of all, there are two event types that extend RenderGuiOverlayEvent.Pre: Chat and Text Question #1) Does the parent event (in this case the Pre event) fire when each of the Chat and Text events are posted, or are they considered fully separate postings? Question #2) I think this is related to the first, but those extended class events canceled if RenderGuiOverlayEvent.Pre is canceled? It is not clear to me that canceling a parent event necessarily cancels any extended classes since I assume the extended classes could be posted independently. So I guess my actual question is whether canceling a parent event cancels the extended classes? Question #3) Since there is a type field for the Pre event, that implies it is called for each element. But then in this thread you mentioned that the "ALL" type is posted first. I don't quite understand what it means to post an ALL type then post each separate type. I mean if there is already an event meant for all, why would there be separate elements posted as well? I just don't understand the utility of having an "ALL" if you also get each separate element type. Question #4) Is there any practical difference between handling the Pre event and checking for types CHAT and TEXT versus handling the events for Chat and Text directly? Sorry for all these questions, but I'm just really starting to dig into event processing again.
  21. You'd think. But there seem to be a lot of people asking questions without much knowledge of Java. You seem to have a lot of patience for noobs today but some of these threads make me laugh -- i see you tell them exactly what to do and they do something different then you tell them again and they do something different...
  22. Thanks. I see it was actually fixed (I thought maybe the solution was just a different approach or work around). Great to see such responsiveness in getting fixes into the actual active codebase!
  23. Generally, but the details are different. For example back then people used @ForgeSubscribe annotation, now it is @SubscribeEvent, also I think some of the actual available events are different. There is the FML bus now too, etc.
  24. Did you do have the @SubscribeEvent annotation on the method? Did you register the handling class on the right event bus? Also, I usually put in a System.out.println("PlayerDestroyItemEvent handler called"); type of console message in the method to confirm whether the handler is actually being called.
×
×
  • Create New...

Important Information

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