Jump to content

Recommended Posts

Posted

I've managed to learn most of the things myself from other modders code shared on github, but this topic is beyond my comprehension: How to make API for my mod?

I already have api subpackage with a few classes I wish to be available for outside modders, but I have no idea what is the next step :|

Posted (edited)

Don't know much on your situation, so excuse the perhaps insolent remarks. Most modders discriminate the API portions of their mod into a separate folder, where another can easily just take the code, and then copy into a separate portion of their development environment, to use. Thus, as long as the forge hooks for an API are there, then you are good to go. You could also separately compile the API, but I don't know how, no would I. 

 

As a side not, what I am referring to for the forge hooks for an API (in case you don't know) I am referring to the package-info.java files, containing @API(owner = [yourDiscriminatorName], apiVersion = [API version], provides = [your API, should probably be like the core API class name, like "MyModAPI"])

 

Beyond that, I don't know much more of what you are looking for beyond letting the world know you have a mod, and that it has an API, if other modders wish to make hook into it.

Edited by draganz
  • Like 1
Posted (edited)

Step back from the "how do I make an api jar" and look at your mod.

 

What is it that you've created that other people might want to use?

  • Did you add a machine that has some sort of recipe?
  • Did you add a machine that has some sort of recipe?
  • Do you have some capability that could be exposed?

  • Do you have some other mechanism that other mods might either want to know about, modify, supply data to, or get data from?

  • Do you have block properties that aren't vanilla?

 

First, create an API package separate form your mod. In there create interface that declares the action you want to expose.

Second, implement that interface on the class that's already handling those actions.

Third, store a reference to the instance in an API location (don't forget to instantiate it).

Fourth, convert all existing references over to use the API instead.

 

If you do things right, the game won't crash and your machine will still work. Congrats, you made an API. If you don't use your own API, you can't test it. And if you don't test it, you won't realize that something's wrong (it took Reika and I back and forth over 3 revisions of his API before I could add a recipe to the Rotary Craft Extractor).

 

You can do the same thing for block properties, capabilities, and other things as well.

 

However there's other things to keep in mind as well:

Once you've declared the interface and released it, it's effectively permanent. You've signed an API contract that says that these methods exist and are guaranteed to exist.  If you change the method signatures in the future, it won't be your mod that crashes, but the mod that tried to use your API. And users will complain to them even though it's your fault. Imagine how frustrated a player would be if that other mod author vanished from modding and you changed the API: users would be hammering a brick wall with no response, unable to use two of their favorite mods together.

 

Instead, you should mark the methods in the interface as @deprecated (so that no one else starts using them) and in the implementation, make a best-guess conversion to the new method. If it can't be done at all, then just leave an empty method stub. The two mods won't integrate as they used to, but they'd still run. You can throw warnings and log messages and non-fatal errors all you'd like, but the JVM should never crash.

Edited by Draco18s
  • Like 2

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Thank you Draco for your help. This is truly well-written guide, I really appreciate it.

I still need some time to fully understand it, but I already have a question:

What if I want to expose not only action, but also datatype?

Lets say the exposed method expects SomeClass object as its argument.

Where should I put SomeClass definition? Should it go into the same package with API class definition?

Posted (edited)

You could manually just add the class to API, or you could have the SomeClass  implement an interface, then change the argument to the interface and only add the said interface into the API; this being the more typical means that APIs are done. 

 

so like [old]: You would have to have to add the Apple class to the API,

public void fall(Apple a){
  a.fall();
  a.update();//I don't know, just making code up
}

public class Apple{
  
  //what ever code
}

but instead, you should do this [new]:

public void fall(IApple a){
  a.fall();
  a.update();
}

public interface IApple{
  void fall();
  void update();
}

This way you only add the simple interface into the API package, and it is up to the user to use. 

 

I would like to mention though, that you could also use and abstract class instead of an interface, if you wish to provide some bulk of data ahead of time, and leave it up to the user to implement (extend really). 

Edited by draganz
  • Like 1
Posted
3 hours ago, Darkos333 said:

Thank you Draco for your help. This is truly well-written guide, I really appreciate it.

I still need some time to fully understand it, but I already have a question:

What if I want to expose not only action, but also datatype?

Lets say the exposed method expects SomeClass object as its argument.

Where should I put SomeClass definition? Should it go into the same package with API class definition?

That's what I have these for:

https://github.com/Draco18s/ReasonableRealism/tree/master/src/main/java/com/draco18s/hardlib/api/internal

Notice that they're in my API package, but inside another package called "internal." In some respects they do need to be exposed, but they shouldn't be utilized directly in most cases.

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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