Skip to content

Commit

Permalink
Clean up the code a bit. We don't need copyrights everywhere, we don't
Browse files Browse the repository at this point in the history
need verbose imports. License hasn't been agreed upon yet either.
  • Loading branch information
cpw committed Aug 18, 2017
1 parent e6996e6 commit f056ae3
Show file tree
Hide file tree
Showing 44 changed files with 617 additions and 2,291 deletions.
504 changes: 0 additions & 504 deletions LICENSE

This file was deleted.

5 changes: 5 additions & 0 deletions codestyle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<code_scheme name="codestyle">
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="USE_SINGLE_CLASS_IMPORTS" value="false" />
</code_scheme>
72 changes: 18 additions & 54 deletions src/main/java/cpw/mods/modlauncher/ArgumentHandler.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
/*
* Modlauncher - utility to launch Minecraft-like game environments with runtime transformation
* Copyright ©2016-2017 cpw and others
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

package cpw.mods.modlauncher;

import cpw.mods.modlauncher.api.IEnvironment;
import cpw.mods.modlauncher.api.ITransformationService;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import cpw.mods.modlauncher.api.*;
import joptsimple.*;

import javax.annotation.Nonnull;
import java.io.File;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import javax.annotation.*;
import java.io.*;
import java.util.*;
import java.util.function.*;

public class ArgumentHandler
{
public class ArgumentHandler {
private String[] args;
private OptionSet optionSet;
private OptionSpec<String> profileOption;
Expand All @@ -43,13 +18,11 @@ public class ArgumentHandler
private OptionSpec<String> nonOption;
private OptionSpec<String> launchTarget;

void setArgs(String[] args)
{
void setArgs(String[] args) {
this.args = args;
}

void processArguments(Environment env, Consumer<OptionParser> parserConsumer, BiConsumer<OptionSet, BiFunction<String, OptionSet, ITransformationService.OptionResult>> resultConsumer)
{
void processArguments(Environment env, Consumer<OptionParser> parserConsumer, BiConsumer<OptionSet, BiFunction<String, OptionSet, ITransformationService.OptionResult>> resultConsumer) {
final OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
profileOption = parser.accepts("version", "The version we launched with").withRequiredArg();
Expand All @@ -67,48 +40,39 @@ void processArguments(Environment env, Consumer<OptionParser> parserConsumer, Bi
resultConsumer.accept(this.optionSet, this::optionResults);
}

File[] getSpecialJars()
{
File[] getSpecialJars() {
return this.optionSet.valuesOf(minecraftJarOption).toArray(new File[0]);
}

String getLaunchTarget()
{
String getLaunchTarget() {
return this.optionSet.valueOf(launchTarget);
}

private ITransformationService.OptionResult optionResults(String serviceName, OptionSet set)
{
return new ITransformationService.OptionResult()
{
private ITransformationService.OptionResult optionResults(String serviceName, OptionSet set) {
return new ITransformationService.OptionResult() {
@Nonnull
@Override
public <V> V value(OptionSpec<V> option)
{
public <V> V value(OptionSpec<V> option) {
checkOwnership(option);
return set.valueOf(option);
}

@Nonnull
@Override
public <V> List<V> values(OptionSpec<V> option)
{
public <V> List<V> values(OptionSpec<V> option) {
checkOwnership(option);
return set.valuesOf(option);
}

private <V> void checkOwnership(OptionSpec<V> option)
{
if (!(option.options().stream().allMatch(opt -> opt.startsWith(serviceName + ".") || !opt.contains("."))))
{
private <V> void checkOwnership(OptionSpec<V> option) {
if (!(option.options().stream().allMatch(opt -> opt.startsWith(serviceName + ".") || !opt.contains(".")))) {
throw new IllegalArgumentException("Cannot process non-arguments");
}
}
};
}

public String[] buildArgumentList()
{
public String[] buildArgumentList() {
String[] ret = new String[this.args.length];
System.arraycopy(this.args, 0, ret, 0, this.args.length);
return ret;
Expand Down
99 changes: 25 additions & 74 deletions src/main/java/cpw/mods/modlauncher/ClassTransformer.java
Original file line number Diff line number Diff line change
@@ -1,75 +1,39 @@
/*
* Modlauncher - utility to launch Minecraft-like game environments with runtime transformation
* Copyright ©2016-2017 cpw and others
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

package cpw.mods.modlauncher;

import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.TransformerVoteResult;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import cpw.mods.modlauncher.api.*;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.security.*;
import java.util.*;
import java.util.stream.*;

/**
* Transforms classes using the supplied launcher services
*/
public class ClassTransformer
{
private final TransformStore transformers;
public class ClassTransformer {
private static final byte[] EMPTY = new byte[0];
private final TransformStore transformers;

ClassTransformer(TransformStore transformers)
{
ClassTransformer(TransformStore transformers) {
this.transformers = transformers;
}

byte[] transform(byte[] inputClass, String className)
{
byte[] transform(byte[] inputClass, String className) {
Type classDesc = Type.getObjectType(className.replaceAll("\\.", "/"));
if (!transformers.needsTransforming(className))
{
if (!transformers.needsTransforming(className)) {
return inputClass;
}

ClassNode clazz = new ClassNode(Opcodes.ASM5);
byte[] digest;
boolean empty;
if (inputClass.length > 0)
{
if (inputClass.length > 0) {
final ClassReader classReader = new ClassReader(inputClass);
classReader.accept(clazz, 0);
digest = getSha256().digest(inputClass);
empty = false;
}
else
{
} else {
clazz.name = classDesc.getInternalName();
clazz.version = 52;
clazz.superName = "java/lang/Object";
Expand All @@ -80,16 +44,14 @@ byte[] transform(byte[] inputClass, String className)

List<FieldNode> fieldList = new ArrayList<>(clazz.fields.size());
// it's probably possible to inject "dummy" fields into this list for spawning new fields without class transform
for (FieldNode field : clazz.fields)
{
for (FieldNode field : clazz.fields) {
List<ITransformer<FieldNode>> fieldTransformers = new ArrayList<>(transformers.getTransformersFor(className, field));
fieldList.add(this.performVote(fieldTransformers, field, context));
}

// it's probably possible to inject "dummy" methods into this list for spawning new methods without class transform
List<MethodNode> methodList = new ArrayList<>(clazz.methods.size());
for (MethodNode method : clazz.methods)
{
for (MethodNode method : clazz.methods) {
List<ITransformer<MethodNode>> methodTransformers = new ArrayList<>(transformers.getTransformersFor(className, method));
methodList.add(this.performVote(methodTransformers, method, context));
}
Expand All @@ -105,50 +67,39 @@ byte[] transform(byte[] inputClass, String className)
return cw.toByteArray();
}

private <T> T performVote(List<ITransformer<T>> transformers, T node, VotingContext context)
{
do
{
private <T> T performVote(List<ITransformer<T>> transformers, T node, VotingContext context) {
do {
final Stream<TransformerVote<T>> voteResultStream = transformers.stream().map(t -> gatherVote(t, context));
final Map<TransformerVoteResult, List<TransformerVote<T>>> results = voteResultStream.collect(Collectors.groupingBy(TransformerVote::getResult));
if (results.containsKey(TransformerVoteResult.REJECT))
{
if (results.containsKey(TransformerVoteResult.REJECT)) {
throw new VoteRejectedException(results.get(TransformerVoteResult.REJECT), node.getClass());
}
if (results.containsKey(TransformerVoteResult.NO))
{
if (results.containsKey(TransformerVoteResult.NO)) {
transformers.removeAll(results.get(TransformerVoteResult.NO).stream().map(TransformerVote::getTransformer).collect(Collectors.toList()));
}
if (results.containsKey(TransformerVoteResult.YES))
{
if (results.containsKey(TransformerVoteResult.YES)) {
final ITransformer<T> transformer = results.get(TransformerVoteResult.YES).get(0).getTransformer();
node = transformer.transform(node, context);
transformers.remove(transformer);
continue;
}
if (results.containsKey(TransformerVoteResult.DEFER))
{
if (results.containsKey(TransformerVoteResult.DEFER)) {
throw new VoteDeadlockException(results.get(TransformerVoteResult.DEFER), node.getClass());
}
}
while (!transformers.isEmpty());
return node;
}

private <T> TransformerVote<T> gatherVote(ITransformer<T> transformer, VotingContext context)
{
private <T> TransformerVote<T> gatherVote(ITransformer<T> transformer, VotingContext context) {
TransformerVoteResult vr = transformer.castVote(context);
return new TransformerVote<>(vr, transformer);
}

private MessageDigest getSha256()
{
try
{
private MessageDigest getSha256() {
try {
return MessageDigest.getInstance("SHA-256");
}
catch (NoSuchAlgorithmException e)
{
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("HUH");
}
}
Expand Down
56 changes: 14 additions & 42 deletions src/main/java/cpw/mods/modlauncher/DefaultLaunchHandlerService.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,40 @@
/*
* Modlauncher - utility to launch Minecraft-like game environments with runtime transformation
* Copyright ©2016-2017 cpw and others
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

package cpw.mods.modlauncher;

import cpw.mods.modlauncher.api.ILaunchHandlerService;
import cpw.mods.modlauncher.api.*;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.concurrent.Callable;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.concurrent.*;

/**
* Default launch handler service - will launch minecraft
*/
public class DefaultLaunchHandlerService implements ILaunchHandlerService
{
public class DefaultLaunchHandlerService implements ILaunchHandlerService {
@Override
public String name()
{
public String name() {
return "minecraft";
}

@Override
public File[] identifyTransformationTargets()
{
public File[] identifyTransformationTargets() {
final URL resource = getClass().getClassLoader().getResource("net/minecraft/client/main/Main.class");
try
{
JarURLConnection urlConnection = (JarURLConnection)resource.openConnection();
return new File[] { new File(urlConnection.getJarFile().getName()) };
}
catch (IOException | NullPointerException e)
{
try {
JarURLConnection urlConnection = (JarURLConnection) resource.openConnection();
return new File[]{new File(urlConnection.getJarFile().getName())};
} catch (IOException | NullPointerException e) {
e.printStackTrace();
return new File[0];
}
}

@Override
public Callable<Void> launchService(String[] arguments, ClassLoader launchClassLoader)
{
public Callable<Void> launchService(String[] arguments, ClassLoader launchClassLoader) {

return () -> {
final Class<?> mcClass = Class.forName("net.minecraft.client.main.Main", true, launchClassLoader);
final Method mcClassMethod = mcClass.getMethod("main", String[].class);
mcClassMethod.invoke(null, (Object)arguments);
mcClassMethod.invoke(null, (Object) arguments);
return null;
};
}
Expand Down
Loading

0 comments on commit f056ae3

Please sign in to comment.