Update to 0.10 modlauncher API with performance improvements..
Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
237f9dec5a
commit
bbdf52e038
9 changed files with 103 additions and 52 deletions
10
build.gradle
10
build.gradle
|
@ -288,11 +288,11 @@ project(':forge') {
|
|||
installer 'org.ow2.asm:asm:6.2'
|
||||
installer 'org.ow2.asm:asm-commons:6.2'
|
||||
installer 'org.ow2.asm:asm-tree:6.2'
|
||||
installer 'cpw.mods:modlauncher:0.9.+'
|
||||
installer 'net.minecraftforge:accesstransformers:0.14.+:shadowed'
|
||||
installer 'net.minecraftforge:eventbus:0.7.+:service'
|
||||
installer 'net.minecraftforge:forgespi:0.6.+'
|
||||
installer 'net.minecraftforge:coremods:0.3.+'
|
||||
installer 'cpw.mods:modlauncher:0.10.+'
|
||||
installer 'net.minecraftforge:accesstransformers:0.15.+:shadowed'
|
||||
installer 'net.minecraftforge:eventbus:0.8.+:service'
|
||||
installer 'net.minecraftforge:forgespi:0.8.+'
|
||||
installer 'net.minecraftforge:coremods:0.4.+'
|
||||
installer 'net.minecraftforge:unsafe:0.2.+'
|
||||
installer 'com.electronwill.night-config:core:3.4.2'
|
||||
installer 'com.electronwill.night-config:toml:3.4.2'
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
package net.minecraftforge.common.asm;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
@ -41,14 +43,13 @@ public class CapabilityInjectDefinalize implements ILaunchPluginService {
|
|||
return "capability_inject_definalize";
|
||||
}
|
||||
|
||||
@Override public void addResource(Path resource, String name) { }
|
||||
|
||||
@Override public <T> T getExtension() { return null; } // ?
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public boolean handlesClass(Type classType, boolean isEmpty)
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
|
||||
{
|
||||
return !isEmpty; //Check for annotations?
|
||||
return isEmpty ? NAY : YAY;
|
||||
}
|
||||
|
||||
private boolean hasHolder(List<AnnotationNode> lst)
|
||||
|
@ -57,17 +58,19 @@ public class CapabilityInjectDefinalize implements ILaunchPluginService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ClassNode processClass(ClassNode classNode, Type classType)
|
||||
public boolean processClass(Phase phase, ClassNode classNode, Type classType)
|
||||
{
|
||||
final int flags = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
|
||||
|
||||
AtomicBoolean changed = new AtomicBoolean();
|
||||
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.equals(CAP) && hasHolder(f.visibleAnnotations)).forEach(f ->
|
||||
{
|
||||
f.access &= ~Opcodes.ACC_FINAL; //Strip final
|
||||
f.access |= Opcodes.ACC_SYNTHETIC; //Add Synthetic so we can check in runtime.
|
||||
int prev = f.access;
|
||||
f.access &= ~Opcodes.ACC_FINAL; //Strip final
|
||||
f.access |= Opcodes.ACC_SYNTHETIC; //Add Synthetic so we can check in runtime.
|
||||
changed.compareAndSet(false, prev != f.access);
|
||||
});
|
||||
|
||||
return classNode;
|
||||
return changed.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
package net.minecraftforge.common.asm;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
@ -41,14 +43,14 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
|
|||
return "object_holder_definalize";
|
||||
}
|
||||
|
||||
@Override public void addResource(Path resource, String name) { }
|
||||
|
||||
@Override public <T> T getExtension() { return null; } // ?
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public boolean handlesClass(Type classType, boolean isEmpty)
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
|
||||
{
|
||||
return !isEmpty; //Check for annotations?
|
||||
return isEmpty ? NAY : YAY;
|
||||
}
|
||||
|
||||
private boolean hasHolder(List<AnnotationNode> lst)
|
||||
|
@ -71,16 +73,19 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ClassNode processClass(ClassNode classNode, Type classType)
|
||||
public boolean processClass(Phase phase, ClassNode classNode, Type classType)
|
||||
{
|
||||
AtomicBoolean changes = new AtomicBoolean();
|
||||
//Must be public static finals, and non-array objects
|
||||
final int flags = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
|
||||
|
||||
//Fix Annotated Fields before injecting from class level
|
||||
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L") && hasHolder(f.visibleAnnotations)).forEach(f ->
|
||||
{
|
||||
f.access &= ~Opcodes.ACC_FINAL; //Strip final
|
||||
f.access |= Opcodes.ACC_SYNTHETIC; //Add Synthetic so we can check in runtime. ? Good idea?
|
||||
int prev = f.access;
|
||||
f.access &= ~Opcodes.ACC_FINAL; //Strip final
|
||||
f.access |= Opcodes.ACC_SYNTHETIC; //Add Synthetic so we can check in runtime. ? Good idea?
|
||||
changes.compareAndSet(false, prev != f.access);
|
||||
});
|
||||
|
||||
if (hasHolder(classNode.visibleAnnotations)) //Class level, de-finalize all fields and add @ObjectHolder to them!
|
||||
|
@ -89,18 +94,20 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
|
|||
String value = getValue(classNode.visibleAnnotations);
|
||||
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L")).forEach(f ->
|
||||
{
|
||||
f.access &= ~Opcodes.ACC_FINAL;
|
||||
f.access |= Opcodes.ACC_SYNTHETIC;
|
||||
/*if (!hasHolder(f.visibleAnnotations)) //Add field level annotation, doesn't do anything until after we figure out how ASMDataTable is gatherered
|
||||
{
|
||||
int prev = f.access;
|
||||
f.access &= ~Opcodes.ACC_FINAL;
|
||||
f.access |= Opcodes.ACC_SYNTHETIC;
|
||||
/*if (!hasHolder(f.visibleAnnotations)) //Add field level annotation, doesn't do anything until after we figure out how ASMDataTable is gatherered
|
||||
{
|
||||
if (value == null)
|
||||
f.visitAnnotation(OBJECT_HOLDER, true);
|
||||
else
|
||||
f.visitAnnotation(OBJECT_HOLDER, true).visit("value", value + ":" + f.name.toLowerCase());
|
||||
}*/
|
||||
}*/
|
||||
changes.compareAndSet(false, prev != f.access);
|
||||
});
|
||||
}
|
||||
return classNode;
|
||||
return changes.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package net.minecraftforge.common.asm;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -58,21 +59,20 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
|
|||
return "runtime_enum_extender";
|
||||
}
|
||||
|
||||
@Override public void addResource(Path resource, String name) { }
|
||||
|
||||
@Override public <T> T getExtension() { return null; } // ?
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public boolean handlesClass(Type classType, boolean isEmpty)
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
|
||||
{
|
||||
return !isEmpty; //Any way to determine if its a enum at this level?
|
||||
return isEmpty ? NAY : YAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassNode processClass(ClassNode classNode, Type classType)
|
||||
public boolean processClass(Phase phase, ClassNode classNode, Type classType)
|
||||
{
|
||||
if ((classNode.access & Opcodes.ACC_ENUM) == 0)
|
||||
return classNode;
|
||||
return false;
|
||||
|
||||
Type array = Type.getType("[" + classType.getDescriptor());
|
||||
final int flags = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
|
||||
|
@ -80,7 +80,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
|
|||
FieldNode values = classNode.fields.stream().filter(f -> f.desc.contentEquals(array.getDescriptor()) && ((f.access & flags) == flags)).findFirst().orElse(null);
|
||||
|
||||
if (!classNode.interfaces.contains(MARKER_IFACE.getInternalName())) {
|
||||
return classNode;
|
||||
return false;
|
||||
}
|
||||
|
||||
//Static methods named "create", with first argument as a string, and returning this type
|
||||
|
@ -205,7 +205,7 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
|
|||
ins.areturn(classType);
|
||||
}
|
||||
});
|
||||
return classNode;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
|
@ -57,17 +58,12 @@ public class RuntimeDistCleaner implements ILaunchPluginService
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addResource(Path resource, String name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassNode processClass(ClassNode classNode, Type classType)
|
||||
public boolean processClass(Phase phase, ClassNode classNode, Type classType)
|
||||
{
|
||||
AtomicBoolean changes = new AtomicBoolean();
|
||||
if (remove(classNode.visibleAnnotations, DIST))
|
||||
{
|
||||
LOGGER.debug(DISTXFORM, "Attempted to load class {} for invalid dist {}", classNode.name, DIST);
|
||||
LOGGER.fatal(DISTXFORM, "Attempted to load class {} for invalid dist {}", classNode.name, DIST);
|
||||
throw new RuntimeException("Attempted to load class "+ classNode.name + " for invalid dist "+ DIST);
|
||||
}
|
||||
|
||||
|
@ -79,6 +75,7 @@ public class RuntimeDistCleaner implements ILaunchPluginService
|
|||
{
|
||||
LOGGER.debug(DISTXFORM,"Removing field: {}.{}", classNode.name, field.name);
|
||||
fields.remove();
|
||||
changes.compareAndSet(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +89,7 @@ public class RuntimeDistCleaner implements ILaunchPluginService
|
|||
LOGGER.debug(DISTXFORM,"Removing method: {}.{}{}", classNode.name, method.name, method.desc);
|
||||
methods.remove();
|
||||
lambdaGatherer.accept(method);
|
||||
changes.compareAndSet(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,11 +107,12 @@ public class RuntimeDistCleaner implements ILaunchPluginService
|
|||
{
|
||||
LOGGER.debug(DISTXFORM,"Removing lambda method: {}.{}{}", classNode.name, method.name, method.desc);
|
||||
methods.remove();
|
||||
changes.compareAndSet(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return classNode;
|
||||
return changes.get();
|
||||
}
|
||||
|
||||
private boolean remove(final List<AnnotationNode> anns, final String side)
|
||||
|
@ -133,10 +132,13 @@ public class RuntimeDistCleaner implements ILaunchPluginService
|
|||
};
|
||||
}
|
||||
|
||||
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
|
||||
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
|
||||
|
||||
@Override
|
||||
public boolean handlesClass(Type classType, boolean isEmpty)
|
||||
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
|
||||
{
|
||||
return !isEmpty;
|
||||
return isEmpty ? NAY : YAY;
|
||||
}
|
||||
|
||||
private static class LambdaGatherer extends MethodVisitor {
|
||||
|
|
|
@ -98,4 +98,9 @@ public class ModFileInfo implements IModFileInfo
|
|||
public Optional<Manifest> getManifest() {
|
||||
return modFile.getLocator().findManifest(modFile.getFilePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showAsResourcePack() {
|
||||
return false; // noop right now
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import net.minecraft.util.text.TextComponentString;
|
|||
import net.minecraftforge.fml.config.ConfigTracker;
|
||||
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
||||
import net.minecraftforge.fml.util.ThreeConsumer;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -35,10 +36,14 @@ import org.apache.logging.log4j.Marker;
|
|||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
|
||||
|
||||
/**
|
||||
* Instance responsible for handling the overall FML network handshake.
|
||||
*
|
||||
|
@ -176,6 +181,9 @@ public class FMLHandshakeHandler {
|
|||
private final NetworkDirection direction;
|
||||
private final NetworkManager manager;
|
||||
private int packetPosition;
|
||||
private ForgeRegistry.Snapshot registrySnapshot;
|
||||
private Set<String> registriesToReceive;
|
||||
|
||||
private FMLHandshakeHandler(NetworkManager networkManager, NetworkDirection side)
|
||||
{
|
||||
this.direction = side;
|
||||
|
@ -199,6 +207,8 @@ public class FMLHandshakeHandler {
|
|||
LOGGER.debug(FMLHSMARKER, "Accepted server connection");
|
||||
// Set the modded marker on the channel so we know we got packets
|
||||
c.get().getNetworkManager().channel().attr(FMLNetworking.FML_MARKER).set(NetworkHooks.NETVERSION);
|
||||
this.registriesToReceive = new HashSet<>(serverModList.getRegistries());
|
||||
LOGGER.debug(REGISTRIES, "Expecting {} registries: {}", ()->this.registriesToReceive.size(), ()->this.registriesToReceive);
|
||||
}
|
||||
|
||||
private <MSG extends FMLHandshakeMessages.LoginIndexedMessage> void handleIndexedMessage(MSG message, Supplier<NetworkEvent.Context> c)
|
||||
|
@ -223,10 +233,12 @@ public class FMLHandshakeHandler {
|
|||
LOGGER.debug(FMLHSMARKER, "Accepted client connection mod list");
|
||||
}
|
||||
private void handleRegistryMessage(final FMLHandshakeMessages.S2CRegistry registryPacket, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
this.registriesToReceive.remove(registryPacket.getRegistryName());
|
||||
RegistryManager.acceptRegistry(registryPacket, contextSupplier);
|
||||
contextSupplier.get().setPacketHandled(true);
|
||||
final FMLHandshakeMessages.C2SAcknowledge reply = new FMLHandshakeMessages.C2SAcknowledge();
|
||||
channel.reply(reply, contextSupplier.get());
|
||||
if (this.registriesToReceive.isEmpty()) {}//injectSnapshot
|
||||
}
|
||||
|
||||
private void handleClientAck(final FMLHandshakeMessages.C2SAcknowledge msg, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import net.minecraftforge.fml.ModList;
|
|||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -51,6 +52,7 @@ public class FMLHandshakeMessages
|
|||
*/
|
||||
public static class S2CModList extends LoginIndexedMessage
|
||||
{
|
||||
private List<String> registries;
|
||||
private NBTTagList channels;
|
||||
private List<String> modList;
|
||||
|
||||
|
@ -62,6 +64,7 @@ public class FMLHandshakeMessages
|
|||
{
|
||||
this.modList = nbtTagCompound.getList("modlist", 8).stream().map(INBTBase::getString).collect(Collectors.toList());
|
||||
this.channels = nbtTagCompound.getList("channels", 10);
|
||||
this.registries = nbtTagCompound.getList("registries", 8).stream().map(INBTBase::getString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static S2CModList decode(PacketBuffer packetBuffer)
|
||||
|
@ -75,6 +78,7 @@ public class FMLHandshakeMessages
|
|||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.setTag("modlist",modList.stream().map(NBTTagString::new).collect(Collectors.toCollection(NBTTagList::new)));
|
||||
tag.setTag("channels", NetworkRegistry.buildChannelVersions());
|
||||
tag.setTag("registries", RegistryManager.registryNames().stream().map(NBTTagString::new).collect(Collectors.toCollection(NBTTagList::new)));
|
||||
packetBuffer.writeCompoundTag(tag);
|
||||
}
|
||||
|
||||
|
@ -82,6 +86,9 @@ public class FMLHandshakeMessages
|
|||
return String.join(",", modList);
|
||||
}
|
||||
|
||||
List<String> getRegistries() {
|
||||
return this.registries;
|
||||
}
|
||||
NBTTagList getChannels() {
|
||||
return this.channels;
|
||||
}
|
||||
|
@ -119,17 +126,26 @@ public class FMLHandshakeMessages
|
|||
}
|
||||
|
||||
public static class S2CRegistry extends LoginIndexedMessage {
|
||||
private String registryName;
|
||||
|
||||
public S2CRegistry(final ResourceLocation key, final ForgeRegistry<? extends IForgeRegistryEntry<?>> registry) {
|
||||
registryName = key.toString();
|
||||
}
|
||||
|
||||
S2CRegistry() {
|
||||
private S2CRegistry(final String registryName) {
|
||||
this.registryName = registryName;
|
||||
}
|
||||
|
||||
void encode(final PacketBuffer buffer) {
|
||||
buffer.writeString(registryName, 128);
|
||||
}
|
||||
|
||||
public static S2CRegistry decode(final PacketBuffer buffer) {
|
||||
return new S2CRegistry();
|
||||
return new S2CRegistry(buffer.readString(128));
|
||||
}
|
||||
|
||||
public String getRegistryName() {
|
||||
return registryName;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
|
||||
|
||||
public class RegistryManager
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
@ -154,7 +156,11 @@ public class RegistryManager
|
|||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<String> registryNames() {
|
||||
return ACTIVE.registries.entrySet().stream().map(Map.Entry::getKey).map(Object::toString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static void acceptRegistry(final FMLHandshakeMessages.S2CRegistry registryUpdate, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
LOGGER.debug("Received registry packet");
|
||||
LOGGER.debug(REGISTRIES,"Received registry packet for {}", registryUpdate.getRegistryName());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue