Java has a very useful modules system that allows you to write “plug-ins” for an application using the Reflection API. It can be used for a variety of things and in terms of gaming, it can be used for these:
- Quests
- New Gamemodes
- New Entities
And a lot more stuff, just to give you an idea. Note that this isn’t restricted to gaming, and has even more uses in software engineering itself. There are a few reasons why we would want to use this plugin system. First of all, you don’t need to write your own scripting language or whatever for something huge. Then, its really quick and fast to set up, and it makes a whole lot of sense.
However, there are some disadvantages as well. Since Java uses the JAR format, it can easily be modified without security like obfuscation and hash checking with the internet. Also, if you are going to open your API to developers, you have to make sure public fields are public, private fields are private, and protected fields are protected. Otherwise they get access to a whole bunch of things that can ruin the game. That’s about it for explanations. Now let’s get to the real code.
So, first, we have to make an API. Most of it will probably already have been done. I will be presenting a small quests system in this. In my project, I’ve defined a Quest class as follows:
public class Quest {
private int id;
private int position;
private QuestRunner qr;
public void init(QuestRunner qr) {
this.qr = qr;
}
public void setID(int id) {
this.id = id;
}
public void nextPosition() {
position++;
}
public int getID() {
return id;
}
public int getPosition() {
return position;
}
public List<Command> nextEvent() {
...
return commands;
}
}
I included a QuestRunner class(shown later) in the Quest file so the class can add events to the event buffer in the QuestRunner. Events in this term means like things to do like display text, move a character here, start another event, start a battle, etc.
For simplicity’s sake, I’ve also defined a QuestController class, that “controls” the quest, or just organizes them:
import java.util.ArrayList;
import java.util.List;
public class QuestController {
private List<Quest> quests;
public QuestController() {
quests = new ArrayList<Quest>();
}
public Quest getQuestWithID(int id) {
for(Quest q : quests)
if(q.getID() == id)
return q;
return null;
}
}
Now, there’s also a class called QuestRunner, that runs the events produced by the quest:
import java.util.ArrayList;
import java.util.List;
public class QuestRunner {
private List<Command> eventbuffer;
public QuestRunner() {
eventbuffer = new ArrayList<Command>();
}
public void runEvents(List<Command> event) {
for(Command comm: event) {
eventbuffer.add(comm);
}
event.clear();
}
public class Command {
private int command;
private String params;
public Command(int c, String p) {
this.command = c;
this.params = p;
}
}
}
I’ve only given enough information in the class so an API can be written with it, not its actual functionality, just to note. Now, I export it as a JAR(not a runnable jar). Unselect all the files, and then I go select only Quest, QuestController, and QuestRunner. This will only make these classes available in the API. So now I export it, and I now have a quest API that can be used in another project.
Note that I the only reason I export as a JAR is for simplicity here. You can export your entire project and the API will have everything available, but usually you’d need to make sure all the visibilities of fields are correct.
So, now, you can make a new project, maybe name it “Quests”. In here, make a new class that extends Quest. Do stuff in it, add to the storyline etc. Now you can export it as a JAR including only what classes you need.
Now, back in your main game, you can make use of this JAR file you exported with a URLClassLoader object. Basically it allows you to open a JAR file and get a class:
URLClassLoader classLoader = URLClassLoader .newInstance(new URL[] { new URL("file:./quests/TheStolenJewel.jar") };
The jar is loaded here, so now we can load it into an actual Quest object using the reflection API!:
Class<?> clazz = classLoader.loadClass("com.jgo.games.quests.MainQuest");
Quest quest = (Quest) clazz.newInstance();
quest.init(questrunner);
Notice that the name of the class must be the same for each quest, but you can do some nifty stuff with config files to change that.
So that’s it! You have a quest object, now you can do whatever you want with it, just like a real class!
Now you can play with this new thing and do it for anything you want!
Thanks for reading! =) Tell me if I’ve done any errors, I’ll fix it right away.