Newer
Older
ultramine_core / build.gradle
buildscript {
	repositories {
		mavenCentral()
		mavenLocal()

		maven {
			name = "forge"
			url = "http://files.minecraftforge.net/maven"

		}
		maven {
			name = "sonatype"
			url = "https://oss.sonatype.org/content/repositories/snapshots/"

		}
	}

	dependencies {
		classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
	}
}

import net.minecraftforge.gradle.common.Constants
import net.minecraftforge.gradle.delayed.DelayedFile
import net.minecraftforge.gradle.delayed.DelayedString
import net.minecraftforge.gradle.tasks.user.reobf.ArtifactSpec
import net.minecraftforge.gradle.tasks.user.reobf.ReobfTask
import net.minecraftforge.gradle.user.UserBasePlugin
import net.minecraftforge.gradle.user.UserExtension

import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import cpw.mods.fml.relauncher.SideOnly;

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven-publish'
apply plugin: 'eclipse'

sourceCompatibility = '1.6'
targetCompatibility = '1.6'

compileJava.options.encoding = 'UTF-8'

ext.buildnumber = 0
if (System.getenv('BUILD_NUMBER') != null)
	project.buildnumber = System.getenv('BUILD_NUMBER')
else
	project.buildnumber = 'indev'

group = 'org.ultramine'
version = "${minecraft_version}-${buildnumber}"

repositories {
	maven {
		name 'forge'
		url 'http://files.minecraftforge.net/maven'
	}
	mavenCentral()
	maven {
		name 'sonatypeSnapshot'
		url 'https://oss.sonatype.org/content/repositories/snapshots/'
	}
	maven {
		name 'minecraft'
		url 'https://libraries.minecraft.net/'
	}
}

dependencies {
	compile 'net.minecraft:launchwrapper:1.11'
	compile 'com.google.code.findbugs:jsr305:1.3.9'
	compile 'org.ow2.asm:asm-debug-all:5.0.3'
	compile 'com.typesafe.akka:akka-actor_2.11:2.3.3'
	compile 'com.typesafe:config:1.2.1'
	compile 'org.scala-lang:scala-actors-migration_2.11:1.1.0'
	compile 'org.scala-lang:scala-compiler:2.11.1'
	compile 'org.scala-lang.plugins:scala-continuations-library_2.11:1.0.2'
	compile 'org.scala-lang.plugins:scala-continuations-plugin_2.11.1:1.0.2'
	compile 'org.scala-lang:scala-library:2.11.1'
	compile 'org.scala-lang:scala-parser-combinators_2.11:1.0.1'
	compile 'org.scala-lang:scala-reflect:2.11.1'
	compile 'org.scala-lang:scala-swing_2.11:1.0.1'
	compile 'org.scala-lang:scala-xml_2.11:1.0.2'
	compile 'net.sf.jopt-simple:jopt-simple:4.5'
	compile 'lzma:lzma:0.0.1'
	compile 'com.mojang:realms:1.3.5'
	compile 'org.apache.commons:commons-compress:1.8.1'
	compile 'org.apache.httpcomponents:httpclient:4.3.3'
	compile 'commons-logging:commons-logging:1.1.3'
	compile 'org.apache.httpcomponents:httpcore:4.3.2'
	compile 'java3d:vecmath:1.3.1'
	compile 'net.sf.trove4j:trove4j:3.0.3'
	compile 'com.ibm.icu:icu4j-core-mojang:51.2'
	compile 'com.paulscode:codecjorbis:20101023'
	compile 'com.paulscode:codecwav:20101023'
	compile 'com.paulscode:libraryjavasound:20101123'
	compile 'com.paulscode:librarylwjglopenal:20100824'
	compile 'com.paulscode:soundsystem:20120107'
	compile 'io.netty:netty-all:4.0.10.Final'
	compile 'com.google.guava:guava:17.0'
	compile 'org.apache.commons:commons-lang3:3.3.2'
	compile 'commons-io:commons-io:2.4'
	compile 'commons-codec:commons-codec:1.9'
	compile 'net.java.jinput:jinput:2.0.5'
	compile 'net.java.jutils:jutils:1.0.0'
	compile 'com.google.code.gson:gson:2.2.4'
	compile 'com.mojang:authlib:1.5.16'
	compile 'org.apache.logging.log4j:log4j-api:2.0-beta9'
	compile 'org.apache.logging.log4j:log4j-core:2.0-beta9'
	compile 'org.lwjgl.lwjgl:lwjgl:2.9.1'
	compile 'org.lwjgl.lwjgl:lwjgl_util:2.9.1'
	compile 'tv.twitch:twitch:5.16'

	compile 'org.yaml:snakeyaml:1.16'
	compile 'com.lmax:disruptor:3.2.1'
	compile 'org.apache.commons:commons-dbcp2:2.1.1'
	
	runtime 'mysql:mysql-connector-java:5.1.31'

	testCompile "org.codehaus.groovy:groovy-all:2.3.0"
	testCompile "org.spockframework:spock-core:1.0-groovy-2.0-SNAPSHOT"
	testCompile 'junit:junit:4.5'

	testRuntime "cglib:cglib-nodep:2.2.2"
	testRuntime "org.objenesis:objenesis:1.2"
}

task processServerResources(type: ProcessResources) {
	exclude 'assets/minecraft/font'
	exclude 'assets/minecraft/shaders'
	exclude 'assets/minecraft/texts'
	exclude 'assets/minecraft/textures'
	exclude 'assets/fml/textures'
}

task processClientResources(type: ProcessResources) {
	exclude 'org/ultramine/defaults'
}

task jar_server(type: Jar) {
	manifest {
		attributes(
			'Main-Class': 'cpw.mods.fml.relauncher.ServerLaunchWrapper',
			'TweakClass': 'cpw.mods.fml.common.launcher.FMLTweaker',
			'Class-Path': configurations.runtime.collect { 'libraries/' + it.getName() }.join(' ')
		)
	}
}

//

project.getExtensions().create(Constants.EXT_NAME_MC, UserExtension, { return project } as UserBasePlugin)

jar {
	classifier = 'dev'
}

task classesJar(type: Zip) {
	from sourceSets.main.output.classesDir
	classifier = 'classes'
	version = ''
	destinationDir = new File(buildDir, getName())
	dependsOn(classes)
}

task reobf(type: ReobfTask) {
	setMcVersion(delayedString(minecraft_version));
	setExceptorCfg(delayedFile('conf/srg.exc'))
	setSrg(delayedFile('conf/mcp2notch.srg'))
	reobf(classesJar, new Action<ArtifactSpec>() {
		@Override
		public void execute(ArtifactSpec spec)
		{
			JavaPluginConvention javaConv = (JavaPluginConvention) getConvention().getPlugins().get("java")
			spec.setClasspath(javaConv.getSourceSets().getByName("main").getCompileClasspath())
			spec.setArchiveName(null);
			spec.setClassifier('reobf');
		}
	})

	mustRunAfter("test")
}

task sidesplit(type: SideSplitTask) {
	sidesplit(reobf)
}

processServerResources {
	from sourceSets.main.resources.srcDirs
	into new File(buildDir, 'resources_server')
}

processClientResources {
	from sourceSets.main.resources.srcDirs
	into new File(buildDir, 'resources_client')
}

jar_server {
	from fileTree(sidesplit.getServerClasses()), processServerResources
	classifier = 'server'
	dependsOn(sidesplit, processServerResources)
}

task jar_client(type: Jar) {
	from fileTree(sidesplit.getClientClasses()), processClientResources
	classifier = 'client'
	dependsOn(sidesplit, processClientResources)
}

task jar_source(type: Jar) {
	from sourceSets.main.allSource
	classifier = 'sources'
}

assemble.dependsOn(jar_server, jar_client)

publishing {
	tasks.publish.dependsOn(jar, jar_source)
	publications {
		mavenJava(MavenPublication) {
			from components.java
			artifacts.matching({
				it.classifier == "dev"
			}).all({
				it.classifier = null
			})
			artifact jar_source
		}
	}
	repositories {
		if (project.hasProperty('mavendir')) {
			maven {
				url mavendir
			}
		}
	}
}

task dumpLibs(type: Copy) {
	into "$buildDir/libs/libraries"
	from configurations.runtime
}

def delayedFile(String path) {
	new DelayedFile(project, path) {
		@Override
		File resolveDelayed() {
			return file(path)
		}
	}
}

def delayedString(String str) {
	new DelayedString(project, str) {
		@Override
		String resolveDelayed() {
			return str
		}
	}
}

class SideSplitTask extends DefaultTask {
	private static final String SIDEONLY_DESK = Type.getDescriptor(SideOnly.class);
	private ReobfTask reobf;
	private File taskDir = new File(getProject().buildDir, getName());
	private File classes_server = new File(taskDir, "classes_server");
	private File classes_client = new File(taskDir, "classes_client");

	def sidesplit(ReobfTask reobf) {
		this.reobf = reobf;
		getInputs().files({reobf.getObfuscatedFiles()});
		getOutputs().files(classes_server, classes_client);
		dependsOn(reobf);
	}

	def getServerClasses() {
		classes_server
	}

	def getClientClasses() {
		classes_client
	}

	@TaskAction
	def doSplit() {
		File toSplit =  reobf.getObfuscatedFiles().getSingleFile();
		File toSplitemp = File.createTempFile("tosplit", ".jar", getTemporaryDir());
		Files.copy(toSplit, toSplitemp);

		classes_server.mkdirs();
		classes_client.mkdirs();
		FileUtils.cleanDirectory(classes_server);
		FileUtils.cleanDirectory(classes_client);
		ZipInputStream zipIn = new ZipInputStream(new FileInputStream(toSplitemp));
		ZipEntry entry = null;
		while ((entry = zipIn.getNextEntry()) != null) {
			if(entry.isDirectory())
				continue;
			byte[] common = ByteStreams.toByteArray(zipIn);
			zipIn.closeEntry();
			if(entry.getName().endsWith('.class')) {
				byte[] server_cls = processClass(common, 'SERVER');
				byte[] client_cls = processClass(common, 'CLIENT');
				if(server_cls != null)
					addEntry(classes_server, entry, server_cls);
				if(client_cls != null)
					addEntry(classes_client, entry, client_cls);
			} else {
				addEntry(classes_server, entry, common);
				addEntry(classes_client, entry, common);
			}
		}

		zipIn.close();
		toSplitemp.delete();
	}
	
	private void addEntry(File dir, ZipEntry entry, byte[] contents) {
		File file = new File(dir, entry.getName());
		file.getParentFile().mkdirs();
		Files.write(contents, file);
	}

	private byte[] processClass(byte[] input, String side) {
		ClassNode classNode = new ClassNode();
		ClassReader classReader = new ClassReader(input);
		classReader.accept(classNode, 0);

		if(remove((List<AnnotationNode>)classNode.visibleAnnotations, side))
			return null;

		Iterator<FieldNode> fields = classNode.fields.iterator();
		while(fields.hasNext()) {
			FieldNode field = fields.next();
			if(remove((List<AnnotationNode>)field.visibleAnnotations, side))
				fields.remove();
		}
		Iterator<MethodNode> methods = classNode.methods.iterator();
		while(methods.hasNext()) {
			MethodNode method = methods.next();
			if(remove((List<AnnotationNode>)method.visibleAnnotations, side))
				methods.remove();
		}

		ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
		classNode.accept(writer);
		return writer.toByteArray();
	}
	
	private boolean remove(List<AnnotationNode> anns, String side) {
		if(anns == null)
			return false;
		for(AnnotationNode ann : anns) {
			if(ann.desc.equals(SIDEONLY_DESK) && ann.values != null) {
				for (int x = 0; x < ann.values.size() - 1; x += 2) {
					Object key = ann.values.get(x);
					Object value = ann.values.get(x+1);
					if (key instanceof String && key.equals('value')) {
						if (value instanceof String[] ) {
							if (!((String[])value)[1].equals(side)) {
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}
}