Posted October 5, 20186 yr Is it possible to use has/getCapability with capabilities that may or may not exist (provided by mods that may or may not be inatalled). For example if your building an energy/electricity based mod & want to support but not require RedstoneFlux & Tesla. About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 5, 20186 yr If you have code that may depend on a mod that may or may not be installed you might want to try using the @Optional annotation. There is a good explanation here: http://cazzar.net/tutorials/fml/optional-annotations-the-usages/ Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 5, 20186 yr Author Exactly what I was looking for, however how would I use it specifically with capabilities? (Its @Optional.Method seems to be the way to go, but I can’t think of how, Also it seems to have been made before capabilities were with the @Optional.Interface) About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 5, 20186 yr As far as I am aware the Optional is going away in 1.13. CapabilityInject will not insert a capability that isn't provided thus it will stay null. But that kinda requires a hard dependency anyway since you need to pass a class to the annotation. My solution would be to put all interaction with potentially present capabilities in a separate class and don't load or ever touch it if the mod providing the capability isn't present.
October 5, 20186 yr Author So I can’t do something like getCapabilityIfExists(CapabilityWhatever.WHATEVER). (Obviously) Can I do something like Capability<> potentialCapability = CapabilityRegistry.getCapability(ResourceLocation CapabilityID); if(potentialCapability!=null){ Object actualCapability = world/entity/tileEntity/player.getCapability(potentialCapability); } ...while writing that out I realised how useless having an Object that you can’t cast would be (I guess you could use reflection to find methods & invoke them) All this looks like the answer is StringlyTyped code & a bunch of reflection. 38 minutes ago, V0idWa1k3r said: My solution would be to put all interaction with potentially present capabilities in a separate class and don't load or ever touch it if the mod providing the capability isn't present. How would I use it then? (And more importantly how would I avoid loading it) How would I do something like WhateverCapability capabilityInstance = getWhateverCapabilityIfItExists() when I can’t a) import WhateverCapability (it will crash if it doesn’t exist) b) make a variable of type WhateverCapability (same reason as a) c) invoke getWhateverCapabilityIfItExists (Loading the class with crash if it doesn’t exist) About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 5, 20186 yr 27 minutes ago, Cadiboo said: How would I do something like WhateverCapability capabilityInstance = getWhateverCapabilityIfItExists() when I can’t a) import WhateverCapability (it will crash if it doesn’t exist) b) make a variable of type WhateverCapability (same reason as a) In said class you can do whatever you want to do. The class would be dependent on the api provided by another mod. 27 minutes ago, Cadiboo said: c) invoke getWhateverCapabilityIfItExists (Loading the class with crash if it doesn’t exist) Don't invoke that method unless Loader.isModLoaded returns true. Then the class will not be loaded. If you really need to interact with the capability in an another class you can create a wrapper. Example scenario: // Depends on ModA class EnergyCapabilityA { int getEnergy(); void setEnergy(int i); } // Depends on ModB class EnergyCapabilityB { int getEnergy(); void addEnergy(int i); void removeEnergy(int i); } // Your generic wrapper interface, depends on nothing interface ICompatibleEnergyCapability { int getEnergy(); void addEnergy(int i); void remEnergy(int i); } // Your wrapper provider interface, depends on nothing interface ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side); } // A custom caster class, depends on ModA class AWrapperProvider implements ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side) { EnergyCapabilityA capA = tile.getCapability(A_ENERGY_CAP, side) return new ICompatibleEnergyCapability(){ int getEnergy(){ return capA.getEnergy(); } void addEnergy(int i){ capA.setEnergy(capA.getEnergy() + i); } void remEnergy(int i){ capA.setEnergy(capA.getEnergy() - i); } } } } // A custom caster class, depends on ModB class BWrapperProvider implements ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side) { EnergyCapabilityB capB = tile.getCapability(B_ENERGY_CAP, side) return new ICompatibleEnergyCapability(){ int getEnergy(){ return capB.getEnergy(); } void addEnergy(int i){ capB.addEnergy(i); } void remEnergy(int i){ capB.removeEnergy(i); } } } } // A class containing the wrappers, depends on nothing class WrappersHolder { ICECProvider wrapperA; ICECProvider wrapperB; void init() { if (Loader.isModLoaded("ModA")) { wrapperA = Class.forName("AWrapperProvider").newInstance(); } if (Loader.isModLoaded("ModB")) { wrapperB = Class.forName("BWrapperProvider").newInstance(); } } } // Whenever you need to work with your capabilities class Worker { void work() { if (WrappersHolder.instance.wrapperA != null) { ICECProvider aProvider = WrappersHolder.instance.wrapperA; ICompatibleEnergyCapability cap = aProvider.createWrapper(tile, side); // Do whatever you want with the cap } } } This way everything is safe to use since you are not loading any classes that may or may not be present and everything is nicely in a wrapper and bound to a common interface. If you want your has/getCapability to return a capability of an another mod it is a bit more tricky but also possible by creating wrappers for those capabilities in a similar way that depend on your main capability, only constructing them if the mod is present and returning them. You would need to be careful with your Capability<> instances though. Edited October 5, 20186 yr by V0idWa1k3r
October 5, 20186 yr Author 13 minutes ago, V0idWa1k3r said: In said class you can do whatever you want to do. The class would be dependent on the api provided by another mod. Don't invoke that method unless Loader.isModLoaded returns true. Then the class will not be loaded. If you really need to interact with the capability in an another class you can create a wrapper. Example scenario: // Depends on ModA class EnergyCapabilityA { int getEnergy(); void setEnergy(int i); } // Depends on ModB class EnergyCapabilityB { int getEnergy(); void addEnergy(int i); void removeEnergy(int i); } // Your generic wrapper interface, depends on nothing interface ICompatibleEnergyCapability { int getEnergy(); void addEnergy(int i); void remEnergy(int i); } // Your wrapper provider interface, depends on nothing interface ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side); } // A custom caster class, depends on ModA class AWrapperProvider implements ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side) { EnergyCapabilityA capA = tile.getCapability(A_ENERGY_CAP, side) return new ICompatibleEnergyCapability(){ int getEnergy(){ return capA.getEnergy(); } void addEnergy(int i){ capA.setEnergy(capA.getEnergy() + i); } void remEnergy(int i){ capA.setEnergy(capA.getEnergy() - i); } } } } // A custom caster class, depends on ModB class BWrapperProvider implements ICECProvider { ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side) { EnergyCapabilityB capB = tile.getCapability(B_ENERGY_CAP, side) return new ICompatibleEnergyCapability(){ int getEnergy(){ return capB.getEnergy(); } void addEnergy(int i){ capB.addEnergy(i); } void remEnergy(int i){ capB.removeEnergy(i); } } } } // A class containing the wrappers, depends on nothing class WrappersHolder { ICECProvider wrapperA; ICECProvider wrapperB; void init() { if (Loader.isModLoaded("ModA")) { wrapperA = Class.forName("AWrapperProvider").newInstance(); } if (Loader.isModLoaded("ModB")) { wrapperB = Class.forName("BWrapperProvider").newInstance(); } } } // Whenever you need to work with your capabilities class Worker { void work() { if (WrappersHolder.instance.wrapperA != null) { ICECProvider aProvider = WrappersHolder.instance.wrapperA; ICompatibleEnergyCapability cap = aProvider.createWrapper(tile, side); // Do whatever you want with the cap } } } This way everything is safe to use since you are not loading any classes that may or may not be present and everything is nicely in a wrapper and bound to a common interface. If you want your has/getCapability to return a capability of an another mod it is a bit more tricky but also possible by creating wrappers for those capabilities in a similar way that depend on your main capability, only constructing them if the mod is present and returning them. You would need to be careful with your Capability<> instances though. Wait, Not sure I understand, (basic java) will this code load the class (I always assumed it would)? if(false){ loadClass() } Cause if it will never load the class, then half the problems solved. However, could you provide an example of how this code would be written if the capability doesn’t exist? //inside tile entity update method for(facing : EnumFacing.VALUES) { pos.offset(facing).getTile....getCapability(CapabilityEnergy.ENERGY)....transferEnergyTo(); // this should always work (let’s assume that there is a tile at the pos and bag this tile has the capability) pos.offset(facing).getTile....getCapability(CapabilityTeslaEnergy.TESLA_ENERGY)....transferEnergyTo(); // how should this code be written? } About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 5, 20186 yr 21 minutes ago, Cadiboo said: will this code load the class (I always assumed it would)? if(false){ loadClass() } By default it won't. Classes are loaded on demand. However I do not really trust this since I do not know if this is a required specification of the JVM behaviour or not. If it isn't a custom JVM provided by a third-pary may indeed load the class. If someone could link me to a specifications for this case it would be great. 23 minutes ago, Cadiboo said: However, could you provide an example of how this code would be written if the capability doesn’t exist? //inside tile entity update method for(facing : EnumFacing.VALUES) { pos.offset(facing).getTile....getCapability(CapabilityEnergy.ENERGY)....transferEnergyTo(); // this should always work (let’s assume that there is a tile at the pos and bag this tile has the capability) pos.offset(facing).getTile....getCapability(CapabilityTeslaEnergy.TESLA_ENERGY)....transferEnergyTo(); // how should this code be written? // In your TE for (EnumFacing side : EnumFacing.values()) { TileEntity tile = this.world.getTileEntity(this.pos.offset(side)); if (tile != null) { EnergyCapability energy = tile.getCapability(CapabilityEnergy.ENERGY, side.opposite()); // This if/else construct is very important because other mods may use a different energy API but still expose their energy capability as a forge energy one via a wrapper. In fact as far as I am aware all of them do. However in case they don't the else goes into play. if (energy != null) { energy.transferEnergyTo(...); } else { if (WrappersHolder.instance.teslaWrapper != null) { ICECProvider teslaProvider = WrappersHolder.instance.teslaWrapper; ICompatibleEnergyCapability cap = teslaProvider.createWrapper(tile, side); if (cap != null) { cap.transferEnergyTo(...); } else { ... } } } } } // The wrapper creation class TeslaWrapperProvider implements ICECProvider { // Since this class is loaded only if the mod is loaded it is completely safe to reference that mod in it. @CapabilityInject(Tesla.class) static final Capability<Tesla> TESLA_CAP = null; ICompatibleEnergyCapability createWrapper(TileEntity tile, EnumFacing side) { Tesla cap = tile.getCapability(TESLA_CAP, side); if (cap == null) { return null; } return new ICompatibleEnergyCapability(){ ... void transferEnergyTo(...) { cap.transferEnergyTo(...); } } } }
October 5, 20186 yr There's a way to make your own proxy system that depends on what mods are loaded instead of which side you're on. I have a tutorial here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-system-for-optional.html The basic idea is that you would have methods that in case that a certain mod is loaded would do one thing (which is safe to reference that mod's classes) and otherwise do nothing (i.e. not referencing unloaded classes). Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 5, 20186 yr 16 minutes ago, jabelar said: There's a way to make your own proxy system that depends on what mods are loaded instead of which side you're on. I have a tutorial here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-system-for-optional.html That is pretty much what I am already suggesting. The wrapper factories will be null if the mod the factory provides a wrapper for isn't loaded. There is no reason to default to an empty method instead. You can simply check for null. Your approach is also valid though.
October 5, 20186 yr 2 minutes ago, V0idWa1k3r said: That is pretty much what I am already suggesting. The wrapper factories will be null if the mod the factory provides a wrapper for isn't loaded. There is no reason to default to an empty method instead. You can simply check for null. Your approach is also valid though. Yeah, same idea. But I don't know that it is safe to assume generally assume a class isn't loaded unless a method from it is invoked. It depends on the class loader implementation and possibly the JVM implementation. Some class loaders do actually do lazy loading in advance, not sure about Minecraft's. There is also technically a difference between loading and initializing a class, so need to be careful when reading info about "loading" as some information on the web is confusing the two -- initialization definitely happens when first access to a symbol in a class happens, but loading may happen before. Lastly, even if you can trust that class isn't loaded until used you have to be careful that there are no other initializations or static references as well that might trigger it -- for example, I don't know but I suspect that having annotations like client-only annotation might cause loading. Someone with more knowledge of the Minecraft class loader would have to weigh in... If we could rely on classes only loading when referenced then we wouldn't really need the client proxy system... I think explicitly handling the mod loading in pre-init like in the tutorial is more generally "safe". Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 5, 20186 yr 4 minutes ago, jabelar said: But I don't know that it is safe to assume generally assume a class isn't loaded unless a method from it is invoked. It depends on the class loader implementation and possibly the JVM implementation. Some class loaders do actually do lazy loading in advance, not sure about Minecraft's. Yeah, exactly my point. That's why I propose all this system in the first place and even use reflection to instantinate "dangerous" classes - to not allow loading unless I want it to happen. 5 minutes ago, jabelar said: I don't know but I suspect that having annotations like client-only annotation might cause loading. Someone with more knowledge of the Minecraft class loader would have to weigh in... Those annotations are simply an indicator to the class transformer to strip the class of those methods as it is loaded via ASM. It doesn't cause class loading on it's own. As far as I am aware the only two annotations that cause class loading are @Mod and @EventBusSubscriber. 8 minutes ago, jabelar said: I think explicitly handling the mod loading in pre-init like in the tutorial is more generally "safe". My proposal relies on the init method being called at some point, preferrably at pre-init too. So what we are suggesting is essentially the same thing, I just choose to represent the mod not loaded scenario with a null instead of a dummy implementation.
October 5, 20186 yr Yeah makes sense.I wasn't really arguing that you're wrong. I just wanted to be clear about the part of the conversation where Cadiboo is "learning" that classes load when used. Which is supposed to be true, but technically "it depends". Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 6, 20186 yr Author Thanks so much, this is very very helpful! 12 hours ago, V0idWa1k3r said: if (WrappersHolder.instance.teslaWrapper != null) Could you explain this a little more? I assume it basically checks if the mod is loaded (and returns null if it isn’t), but I don’t see how or understand the naming Regarding loading/initialising, I’ve seen in the Forge code somewhere that they use Sun’s classloading methods to (I think) “load” pretty much every class without initialising or actually loading it. Edited October 6, 20186 yr by Cadiboo About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 6, 20186 yr 8 hours ago, Cadiboo said: Could you explain this a little more? I assume it basically checks if the mod is loaded (and returns null if it isn’t), but I don’t see how or understand the naming Basically it all goes down to the initial init method class WrappersHolder { ICECProvider wrapperA; ICECProvider wrapperB; void init() { if (Loader.isModLoaded("ModA")) { wrapperA = Class.forName("AWrapperProvider").newInstance(); } if (Loader.isModLoaded("ModB")) { wrapperB = Class.forName("BWrapperProvider").newInstance(); } } } By default the fields contain a null value. The init method checks if the mod is loaded and if it is assigns a new wrapper object to that field. If the mod isn't loaded then no wrapper is assigned and the field stays null. So checking for null is then the same as checking for whether the mod is loaded or not - if it is then the field won't be null. As for the naming, well you can name the fields whatever you'd like. The instance in that line is there because these fields aren't static and thus need an instance to access them. The instance is just a field declared perhaps like this: public static WrappersHolder instance = new WrappersHolder(); It is not needed, you can instead make the fields that hold the wrappers static and then you don't need an instance to access them. Edit: as for the class loading I would imagine forge scans the packages to find either more packages to scan or .class files. It then would read those .class files as a binary stream and convert them to bytecode using the ASM library. Then it is trivial to analyze that bytecode to find an annotation. If an annotation is present then the class name/path is stored somewhere to load at a later date. The bytecode is then discarded. This way the classes are never loaded since they only exist for a short amount of time as bytecode in memory, not as actual loaded classes. Edited October 6, 20186 yr by V0idWa1k3r
October 6, 20186 yr Author Ok, I think that I get the general idea thanks so much. I’ve got a couple simple questions that I’ll solve with some shotgun debugging tomorrow. About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 7, 20186 yr 2 hours ago, diesieben07 said: I recommend a system similar to @SidedProxy. Have an interface that describes your behavior and then two implementations, one for when the capability exists and one for when it does not. @CapabilityInject can be put on a method, which can then replace your default ("capability not present") implementation with one that references the capability. Yep, pretty much what I was suggesting, since I've seen you suggest it in the past. Edited October 7, 20186 yr by jabelar Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 7, 20186 yr Author How would I use Events from another mod that may or may not be installed? About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 8, 20186 yr What exactly do you mean? Do you mean the other mod has created custom events (i.e. extended the Event class) and is posting them? Check out my tutorials here: http://jabelarminecraft.blogspot.com/
October 8, 20186 yr Author 43 minutes ago, jabelar said: the other mod has created custom events (i.e. extended the Event class) and is posting them Yeah, to the EVENT_BUS About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 8, 20186 yr So basically, you want to check if there is a capability then execute code correct? I'm fairly certain you can do something along the lines of using if [Entity].hasCapability([CapabilityName]){ACTIONHERE} or to a similar effect
October 8, 20186 yr Author 3 minutes ago, NolValue said: So basically, you want to check if there is a capability then execute code correct? I'm fairly certain you can do something along the lines of using if [Entity].hasCapability([CapabilityName]){ACTIONHERE} or to a similar effect I'm not sure if the capability exists (The mod that provides the capability may not be installed). Im planning on following the advice I've been given so far and basically do what @SidedProxy does, but for the capabilities (with a bunch more wrappers probably) Edited October 8, 20186 yr by Cadiboo About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
October 8, 20186 yr In that case, that code should still work as hasCapability checks if it's there or not. If it isn't there, use an else statement to have it send a chat message stating that the player needs to install that mod
October 8, 20186 yr 2 minutes ago, NolValue said: In that case, that code should still work as hasCapability checks if it's there or not. If it isn't there, use an else statement to have it send a chat message stating that the player needs to install that mod The code will crash if the mod isn't loaded, seeing as how he would be getting the Capability from one of that mods classes, this post was so that he could find a way around that. And he has, but now he needs to know if an Event exists which as far as I know he will have to do something like Loader.isModLoaded and then only do his registration that way. 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.
October 8, 20186 yr 1 minute ago, Animefan8888 said: The code will crash if the mod isn't loaded, seeing as how he would be getting the Capability from one of that mods classes, this post was so that he could find a way around that. And he has, but now he needs to know if an Event exists which as far as I know he will have to do something like Loader.isModLoaded and then only do his registration that way. That wouldn't crash the code, hasCapability functions like a boolean from what I believe. Anyways, I'm not sure if there is any way to check if an event is there either. He'd just have to check if that other mod is there or not as you said.
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.