Skip to content

Commit

Permalink
Plugins are now loaded from jar files
Browse files Browse the repository at this point in the history
  • Loading branch information
Codepixl committed Sep 24, 2016
1 parent 0d5ee02 commit be5e7ae
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 75 deletions.
2 changes: 1 addition & 1 deletion src/net/codepixl/GLCraft/GLCraft.java
Expand Up @@ -165,7 +165,7 @@ public void init() {

initCamera();
world = new CentralManager();
String pluginsFolder = Constants.GLCRAFTDIR+"/Plugins";
String pluginsFolder = Constants.GLCRAFTDIR+"/plugins";
new File(pluginsFolder).mkdirs();
pluginManager = new PluginManager(pluginsFolder);
if(loadExtPlugins){
Expand Down
23 changes: 18 additions & 5 deletions src/net/codepixl/GLCraft/plugin/LoadedPlugin.java
@@ -1,11 +1,13 @@
package net.codepixl.GLCraft.plugin;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

import javax.swing.JOptionPane;

Expand All @@ -22,13 +24,14 @@ public class LoadedPlugin {
public String description;
public String mainClass;
public String glVersion;
ClassLoader loader;
public ClassLoader loader;
Plugin plugin;
public LoadedPlugin(String path) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{
try{
GLCraft.getGLCraft().getPluginManager().currentlyLoadingPlugin = this;
this.path = path+"/";
byte[] data = Files.readAllBytes(new File(path+"/plugin.json").toPath());
loader = new URLClassLoader(new URL[]{new URL("jar:file:"+path+"!/")}, ClassLoader.getSystemClassLoader());
InputStream jsonInputStream = loader.getResourceAsStream("plugin.json");
byte[] data = readFully(jsonInputStream);
String jsonString = new String(data,StandardCharsets.UTF_8);
JSONObject json = new JSONObject(jsonString);
this.name = json.getString("pluginName");
Expand All @@ -40,7 +43,6 @@ public LoadedPlugin(String path) throws IOException, ClassNotFoundException, Ins
JOptionPane.showMessageDialog(null, "The Plugin "+this.name+" is for a newer/older version of GLCraft. It will be deleted.", "Error", JOptionPane.ERROR_MESSAGE);
deleteDirectory(new File(path));
}else{
loader = new URLClassLoader(new URL[]{new File(path).toURL()});
plugin = (Plugin) loader.loadClass(mainClass).newInstance();
plugin.init();
}
Expand All @@ -54,6 +56,17 @@ public LoadedPlugin(String path) throws IOException, ClassNotFoundException, Ins
}
}

public static byte[] readFully(InputStream input) throws IOException{
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
return output.toByteArray();
}

public LoadedPlugin(Plugin p){
GLCraft.getGLCraft().getPluginManager().currentlyLoadingPlugin = this;
this.plugin = p;
Expand Down
44 changes: 19 additions & 25 deletions src/net/codepixl/GLCraft/plugin/PluginManager.java
@@ -1,6 +1,7 @@
package net.codepixl.GLCraft.plugin;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -55,36 +56,29 @@ public void update(){

public void loadPlugins(){
File dir = new File(path);
File[] plugins = dir.listFiles();
File[] plugins = dir.listFiles(new FilenameFilter(){

@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}

});
for(int i = 0; i < plugins.length; i++){
if(plugins[i].isDirectory()){
try {
GLCraft.renderSplashText("Loading Plugins...", plugins[i].getName());
this.loadedPlugins.add(new LoadedPlugin(plugins[i].getAbsolutePath()));
} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
GLCraft.renderSplashText("Loading Plugins...", plugins[i].getName().replaceAll(".jar", ""));
LoadedPlugin p = new LoadedPlugin(plugins[i].getAbsolutePath());
this.loadedPlugins.add(p);
this.plugins.put(p.plugin, p);
} catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
currentlyLoadingPlugin = null;
}

public String getResourceLocation(Plugin p) {
if(plugins.get(p).mainClass.equals("dev")){
return plugins.get(p).path+"/res/";
}else{
System.out.println(plugins.get(p).path);
return plugins.get(p).path;
}
}

public String getResourceLocation(){
if(currentlyLoadingPlugin.mainClass.equals("dev")){
return "res/";
}else{
System.out.println(currentlyLoadingPlugin.path);
return currentlyLoadingPlugin.path;
}
public LoadedPlugin getLoadedPlugin(Plugin p){
return this.plugins.get(p);
}
}
40 changes: 2 additions & 38 deletions src/net/codepixl/GLCraft/plugin/PluginManagerWindow.java
Expand Up @@ -25,57 +25,21 @@

import org.json.JSONObject;

import net.codepixl.GLCraft.util.Constants;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;

public class PluginManagerWindow extends JFrame{
DefaultMutableTreeNode top;
PluginManager p;
private final JButton btnNewButton = new JButton("Add new plugin");
public PluginManagerWindow(PluginManager p) {
getContentPane().setBackground(Color.WHITE);
this.p = p;
this.setSize(356, 249);
top = new DefaultMutableTreeNode("Plugins");
addPlugins();
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser jf = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Compressed GLCraft Plugins", "glcp", "zip", "jar");
jf.setFileFilter(filter);
int returnVal = jf.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION){
File plugin = jf.getSelectedFile();
File tempFolder = new File(new File(PluginManager.path).getParentFile(),"temp");
try {
purgeDirectory(tempFolder);
Files.deleteIfExists(tempFolder.toPath());
ZipFile zip = new ZipFile(plugin);
zip.extractAll(tempFolder.getAbsolutePath());
byte[] data = Files.readAllBytes(new File(tempFolder,"plugin.json").toPath());
String jsonString = new String(data,StandardCharsets.UTF_8);
JSONObject j = new JSONObject(jsonString);
String name = j.getString("pluginName");
Files.move(tempFolder.toPath(), new File(PluginManager.path, name).toPath(), StandardCopyOption.REPLACE_EXISTING);
JOptionPane.showMessageDialog(null, "Plugin added successfully.\nRestart GLCraft.", "GLCraft", JOptionPane.INFORMATION_MESSAGE);
} catch (ZipException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
JOptionPane.showMessageDialog(null, "There was an error extracting the plugin.", "GLCraft", JOptionPane.ERROR_MESSAGE);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
JOptionPane.showMessageDialog(null, "There was an error installing the plugin.\nMake sure to remove existing plugins with the same name first.", "GLCraft", JOptionPane.ERROR_MESSAGE);
} catch(Exception e1){
e1.printStackTrace();
JOptionPane.showMessageDialog(null, "Something went horribly wrong. Make sure the plugin.json is formatted correctly.", "GLCraft", JOptionPane.ERROR_MESSAGE);
}
}
}
});
getContentPane().add(btnNewButton, BorderLayout.NORTH);

JLabel lblRestart = new JLabel("You must restart GLCraft for changes to take effect.");
JLabel lblRestart = new JLabel("Put plugins into "+Constants.GLCRAFTDIR+"plugins.");
getContentPane().add(lblRestart, BorderLayout.SOUTH);
lblRestart.setBackground(Color.WHITE);
lblRestart.setForeground(Color.RED);
Expand Down
16 changes: 16 additions & 0 deletions src/net/codepixl/GLCraft/render/PluginTexture.java
@@ -0,0 +1,16 @@
package net.codepixl.GLCraft.render;

import net.codepixl.GLCraft.GLCraft;
import net.codepixl.GLCraft.plugin.LoadedPlugin;
import net.codepixl.GLCraft.plugin.Plugin;

public class PluginTexture {
public Plugin plugin;
public String name;
public String loc;
public PluginTexture(String name, String loc, Plugin p){
this.name = name;
this.loc = loc;
this.plugin = p;
}
}
31 changes: 29 additions & 2 deletions src/net/codepixl/GLCraft/render/TextureManager.java
Expand Up @@ -4,15 +4,16 @@
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.ImageIO;

import net.codepixl.GLCraft.GLCraft;
import net.codepixl.GLCraft.plugin.LoadedPlugin;
import net.codepixl.GLCraft.plugin.Plugin;
import net.codepixl.GLCraft.util.Constants;
import net.codepixl.GLCraft.util.Spritesheet;
import net.codepixl.GLCraft.util.Texture;
Expand All @@ -23,6 +24,7 @@
public class TextureManager {
private static HashMap<String,String> textures = new HashMap<String,String>();
private static HashMap<String,float[]> atlasCoords = new HashMap<String,float[]>();
private static ArrayList<PluginTexture> pluginTextures = new ArrayList<PluginTexture>();
public static final String TILES = "textures/tiles/";
public static final String ITEMS = "textures/items/";
public static final String GUIS = "textures/gui/";
Expand Down Expand Up @@ -107,6 +109,28 @@ public static void generateAtlas(boolean regen){
y++;
}
}
Iterator<PluginTexture> it2 = pluginTextures.iterator();
while(it2.hasNext()){
PluginTexture next = it2.next();
BufferedImage image;
LoadedPlugin p = GLCraft.getGLCraft().getPluginManager().getLoadedPlugin(next.plugin);
try {
image = ImageIO.read(p.loader.getResourceAsStream(next.loc));
g.drawImage(image, x*16, y*16, null);
atlasCoords.put(next.name, new float[]{(float)x*(1f/(float)maxWidth),(float)y*(1f/(float)maxWidth)});
} catch (IOException | IllegalArgumentException e) {
e.printStackTrace();
System.err.println("Error adding "+next.name+" to texture atlas: Could not find file "+next.loc+" in plugin "+p.name+". Replacing with \"NO IMG\"");
e.printStackTrace();
g.drawImage(noimg, x*16, y*16, null);
atlasCoords.put(next.name, new float[]{(float)x*(1f/(float)maxWidth),(float)y*(1f/(float)maxWidth)});
}
x++;
if(x >= maxWidth){
x = 0;
y++;
}
}
try {
File outputfile = new File(Constants.GLCRAFTDIR,"/temp/atlas.png");
outputfile.getParentFile().mkdirs();
Expand Down Expand Up @@ -175,4 +199,7 @@ public static float[] itemStack(ItemStack i) {
public static boolean hasTexture(String name){
return textures.containsKey(name.toLowerCase());
}
public static void addPluginTexture(String name, String loc, Plugin plugin) {
pluginTextures.add(new PluginTexture(name,loc,plugin));
}
}
2 changes: 1 addition & 1 deletion src/net/codepixl/GLCraft/world/item/PluginItem.java
Expand Up @@ -23,7 +23,7 @@ public void registerItem(){
public PluginItem(Plugin p){
this.plugin = p;
if(this.getClass() != PluginItem.class){
TextureManager.addExternalTexture("items."+getTextureName(), GLCraft.getGLCraft().getPluginManager().getResourceLocation()+"textures\\items\\"+getTextureName()+".png");
TextureManager.addPluginTexture("items."+getTextureName(), "textures/items/"+getTextureName()+".png", p);
}
}
}
6 changes: 3 additions & 3 deletions src/net/codepixl/GLCraft/world/tile/PluginTile.java
Expand Up @@ -25,16 +25,16 @@ public PluginTile(Plugin p){
if(this.hasMultipleTextures()){
for(String name : this.getMultiTextureNames()){
if(!TextureManager.hasTexture("tiles."+name)){
TextureManager.addExternalTexture("tiles."+name, GLCraft.getGLCraft().getPluginManager().getResourceLocation()+"textures\\tiles\\"+name+".png");
TextureManager.addPluginTexture("tiles."+name,"textures/tiles/"+name+".png",plugin);
}
}
}else{
if(!TextureManager.hasTexture("tiles."+this.getTextureName())){
TextureManager.addExternalTexture("tiles."+this.getTextureName(), GLCraft.getGLCraft().getPluginManager().getResourceLocation()+"textures\\tiles\\"+this.getTextureName()+".png");
TextureManager.addPluginTexture("tiles."+this.getTextureName(), "textures/tiles/"+this.getTextureName()+".png",plugin);
}
}
if(!TextureManager.hasTexture("tiles."+this.getIconName())){
TextureManager.addExternalTexture("tiles."+this.getIconName(), GLCraft.getGLCraft().getPluginManager().getResourceLocation()+"textures\\tiles\\"+this.getIconName()+".png");
TextureManager.addPluginTexture("tiles."+this.getIconName(), "textures/tiles/"+this.getIconName()+".png",plugin);
}
}
}
Expand Down

1 comment on commit be5e7ae

@spike11302000
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can play in now because of the lag fixes you did

Please sign in to comment.