From bd1a72e95861dd2d456cbfc2ec75ee3bd2bf943e Mon Sep 17 00:00:00 2001 From: Chicken-Bones Date: Mon, 28 Apr 2014 13:34:20 +1000 Subject: [PATCH] Use FML logging system. Made some of the ASM code more concise --- .../microblock/ConfigContent.scala | 20 +- .../microblock/MicroMaterialRegistry.scala | 11 +- .../microblock/handler/MicroblockMod.scala | 28 +- .../microblock/handler/proxies.scala | 6 +- src/codechicken/microblock/package.scala | 8 + .../multipart/MultiPartRegistry.scala | 2 +- .../multipart/MultipartGenerator.scala | 8 +- .../multipart/asm/ASMMixinCompiler.scala | 679 ++++++++---------- .../multipart/asm/ASMMixinFactory.scala | 2 +- .../handler/MultipartCompatiblity.scala | 2 +- .../multipart/handler/MultipartMod.scala | 26 +- .../multipart/handler/proxies.scala | 39 +- src/codechicken/multipart/package.scala | 8 + 13 files changed, 388 insertions(+), 451 deletions(-) create mode 100644 src/codechicken/microblock/package.scala create mode 100644 src/codechicken/multipart/package.scala diff --git a/src/codechicken/microblock/ConfigContent.scala b/src/codechicken/microblock/ConfigContent.scala index 4109a7a..87e24d6 100644 --- a/src/codechicken/microblock/ConfigContent.scala +++ b/src/codechicken/microblock/ConfigContent.scala @@ -109,8 +109,8 @@ object ConfigContent catch { case e:Exception => - System.err.println("Invalid line in microblocks.cfg: "+s) - System.err.println(e.getMessage) + logger.error("Invalid line in microblocks.cfg: "+s) + logger.error(e.getMessage) } } } @@ -126,7 +126,7 @@ object ConfigContent if(idMap(i) != null) { if(block == Blocks.air) - System.err.println("Warning: Unable to add micro material for block with ID "+i+" as it doesn't exist") + logger.warn("Unable to add micro material for block with ID "+i+" as it doesn't exist") else createAndRegister(block, idMap(i)) } @@ -142,10 +142,10 @@ object ConfigContent createAndRegister(block, m) } catch { - case e:IllegalStateException => System.err.println("Unable to register micro material: "+ + case e:IllegalStateException => logger.error("Unable to register micro material: "+ materialKey(block, m)+"\n\t"+e.getMessage) case e:Exception => - System.err.println("Unable to register micro material: "+materialKey(block, m)) + logger.error("Unable to register micro material: "+materialKey(block, m)) e.printStackTrace() } } @@ -153,14 +153,14 @@ object ConfigContent } } - nameMap.foreach(e => System.err.println("Warning: Unable to add micro material for block with unlocalised name "+e._1+" as it doesn't exist")) + nameMap.foreach(e => logger.warn("Unable to add micro material for block with unlocalised name "+e._1+" as it doesn't exist")) } def handleIMC(messages:Seq[IMCMessage]) { messages.filter(_.key == "microMaterial").foreach{msg => def error(s:String) { - System.err.println("Invalid microblock IMC message from "+msg.getSender+": "+s) + logger.error("Invalid microblock IMC message from "+msg.getSender+": "+s) } if(msg.getMessageType != classOf[ItemStack]) @@ -168,15 +168,15 @@ object ConfigContent else { val stack = msg.getItemStackValue if(Block.blockRegistry.containsId(Item.getIdFromItem(stack.getItem))) - System.err.println("Invalid Block: "+stack.getItem) + error("Invalid Block: "+stack.getItem) else if(stack.getItemDamage < 0 || stack.getItemDamage >= 16) - System.err.println("Invalid metadata: "+stack.getItemDamage) + error("Invalid metadata: "+stack.getItemDamage) else { try { createAndRegister(Block.getBlockFromItem(stack.getItem), stack.getItemDamage) } catch { - case e:IllegalStateException => System.err.println("Unable to register micro material: "+ + case e:IllegalStateException => error("Unable to register micro material: "+ materialKey(Block.getBlockFromItem(stack.getItem), stack.getItemDamage)+"\n\t"+e.getMessage) } } diff --git a/src/codechicken/microblock/MicroMaterialRegistry.scala b/src/codechicken/microblock/MicroMaterialRegistry.scala index 9f39687..1f5da8e 100644 --- a/src/codechicken/microblock/MicroMaterialRegistry.scala +++ b/src/codechicken/microblock/MicroMaterialRegistry.scala @@ -21,7 +21,6 @@ import net.minecraft.block.Block.SoundType object MicroMaterialRegistry { - /** * Interface for defining a micro material */ @@ -127,11 +126,11 @@ object MicroMaterialRegistry throw new IllegalStateException("You must register your materials in the init methods.") if (typeMap.contains(name)) { - System.err.println("Material with id " + name + " is already registered.") + logger.error("Material with id " + name + " is already registered.") return } - System.out.println("Registered micro material: " + name) + logger.info("Registered micro material: " + name) typeMap.put(name, material) } @@ -144,9 +143,9 @@ object MicroMaterialRegistry throw new IllegalStateException("You must register your materials in the init methods.") if (typeMap.remove(name).isEmpty) - System.err.println("Material with id " + name + " is was not registered.") + logger.error("Material with id " + name + " is was not registered.") - System.out.println("Replaced micro material: " + name) + logger.info("Replaced micro material: " + name) typeMap.put(name, material) } @@ -215,7 +214,7 @@ object MicroMaterialRegistry def materialID(name: String) = nameMap.get(name) match { case Some(v) => v case None => - System.err.println("Missing mapping for part with ID: " + name) + logger.error("Missing mapping for part with ID: " + name) 0 } diff --git a/src/codechicken/microblock/handler/MicroblockMod.scala b/src/codechicken/microblock/handler/MicroblockMod.scala index 1379b9e..3bc785c 100644 --- a/src/codechicken/microblock/handler/MicroblockMod.scala +++ b/src/codechicken/microblock/handler/MicroblockMod.scala @@ -12,41 +12,35 @@ import codechicken.microblock.ConfigContent import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent import scala.collection.JavaConversions._ -@Mod(modid = "ForgeMicroblock", acceptedMinecraftVersions = "[1.7.2]", - dependencies="required-after:ForgeMultipart;after:*", modLanguage="scala") +@Mod(modid = "ForgeMicroblock", acceptedMinecraftVersions = "[1.7.2]", dependencies = "required-after:ForgeMultipart;after:*", modLanguage = "scala") object MicroblockMod { @EventHandler - def preInit(event:FMLPreInitializationEvent) - { - MicroblockProxy.preInit() + def preInit(event: FMLPreInitializationEvent) { + MicroblockProxy.preInit(event.getModLog) DefaultContent.load() ConfigContent.parse(event.getModConfigurationDirectory) } - + @EventHandler - def init(event:FMLInitializationEvent) - { + def init(event: FMLInitializationEvent) { MicroblockProxy.init() ConfigContent.load() } - + @EventHandler - def postInit(event:FMLPostInitializationEvent) - { + def postInit(event: FMLPostInitializationEvent) { MicroMaterialRegistry.setupIDMap() MicroblockProxy.postInit() } - + @EventHandler - def beforeServerStart(event:FMLServerAboutToStartEvent) - { + def beforeServerStart(event: FMLServerAboutToStartEvent) { MicroMaterialRegistry.setupIDMap() } - + @EventHandler - def handleIMC(event:IMCEvent) - { + def handleIMC(event: IMCEvent) { ConfigContent.handleIMC(event.getMessages) } } \ No newline at end of file diff --git a/src/codechicken/microblock/handler/proxies.scala b/src/codechicken/microblock/handler/proxies.scala index 3cc4f16..413ba64 100644 --- a/src/codechicken/microblock/handler/proxies.scala +++ b/src/codechicken/microblock/handler/proxies.scala @@ -20,9 +20,12 @@ import cpw.mods.fml.common.registry.GameRegistry import cpw.mods.fml.common.network.NetworkRegistry import net.minecraft.client.renderer.RenderBlocks import net.minecraft.init.{Blocks, Items} +import org.apache.logging.log4j.Logger class MicroblockProxy_serverImpl { + var logger:Logger = _ + private var baseID = 24875-1 def nextItemID = {baseID+=1; baseID} @@ -33,8 +36,9 @@ class MicroblockProxy_serverImpl var sawDiamond:Item = _ var stoneRod:Item = _ - def preInit() + def preInit(logger:Logger) { + this.logger = logger itemMicro = new ItemMicroPart GameRegistry.registerItem(itemMicro, "microblock") sawStone = createSaw(config, "sawStone", 1) diff --git a/src/codechicken/microblock/package.scala b/src/codechicken/microblock/package.scala new file mode 100644 index 0000000..4f3a244 --- /dev/null +++ b/src/codechicken/microblock/package.scala @@ -0,0 +1,8 @@ +package codechicken + +import codechicken.microblock.handler.MicroblockProxy + +package object microblock +{ + def logger = MicroblockProxy.logger +} diff --git a/src/codechicken/multipart/MultiPartRegistry.scala b/src/codechicken/multipart/MultiPartRegistry.scala index 29244d6..35b2010 100644 --- a/src/codechicken/multipart/MultiPartRegistry.scala +++ b/src/codechicken/multipart/MultiPartRegistry.scala @@ -162,7 +162,7 @@ object MultiPartRegistry if (part.isDefined) return part.get(client) else { - System.err.println("Missing mapping for part with ID: " + name) + logger.error("Missing mapping for part with ID: " + name) return null } } diff --git a/src/codechicken/multipart/MultipartGenerator.scala b/src/codechicken/multipart/MultipartGenerator.scala index 8a7d16e..1ca6afa 100644 --- a/src/codechicken/multipart/MultipartGenerator.scala +++ b/src/codechicken/multipart/MultipartGenerator.scala @@ -159,7 +159,7 @@ object MultipartGenerator if(c_trait != null) { if(interfaceTraitMap_c.contains(s_interface)) - System.err.println("Trait already registered for "+s_interface) + logger.error("Trait already registered for "+s_interface) else { interfaceTraitMap_c = interfaceTraitMap_c+(s_interface->c_trait) @@ -169,7 +169,7 @@ object MultipartGenerator if(s_trait != null) { if(interfaceTraitMap_s.contains(s_interface)) - System.err.println("Trait already registered for "+s_interface) + logger.error("Trait already registered for "+s_interface) else { interfaceTraitMap_s = interfaceTraitMap_s+(s_interface->s_trait) @@ -198,14 +198,14 @@ object MultipartGenerator if(client) { if(interfaceTraitMap_c.contains(s_interface)) - System.err.println("Trait already registered for "+s_interface) + logger.error("Trait already registered for "+s_interface) else interfaceTraitMap_c = interfaceTraitMap_c+(s_interface->tType) } if(server) { if(interfaceTraitMap_s.contains(s_interface)) - System.err.println("Trait already registered for "+s_interface) + logger.error("Trait already registered for "+s_interface) else interfaceTraitMap_s = interfaceTraitMap_s+(s_interface->tType) } diff --git a/src/codechicken/multipart/asm/ASMMixinCompiler.scala b/src/codechicken/multipart/asm/ASMMixinCompiler.scala index 20a1e7c..2b1fad5 100644 --- a/src/codechicken/multipart/asm/ASMMixinCompiler.scala +++ b/src/codechicken/multipart/asm/ASMMixinCompiler.scala @@ -6,62 +6,53 @@ import scala.collection.JavaConversions._ import org.objectweb.asm.tree._ import org.objectweb.asm.Opcodes._ import org.objectweb.asm.ClassReader -import org.objectweb.asm.util.TraceClassVisitor -import org.objectweb.asm.util.Textifier import org.objectweb.asm.Type import org.objectweb.asm.MethodVisitor import Type._ import codechicken.lib.asm.ASMHelper._ -import codechicken.lib.asm.ObfMapping +import codechicken.lib.asm.{InsnListSection, InsnComparator, ASMHelper, ObfMapping} import java.io.File -import java.io.PrintWriter import ScalaSignature._ import java.lang.reflect.Method import java.lang.reflect.Modifier import net.minecraft.launchwrapper.LaunchClassLoader import codechicken.multipart.handler.MultipartProxy import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper +import org.apache.logging.log4j.LogManager object DebugPrinter { val debug = MultipartProxy.config.getTag("debug_asm").getBooleanValue(!ObfMapping.obfuscated) - + val logger = LogManager.getLogger("Multipart ASM") + private var permGenUsed = 0 val dir = new File("asm/multipart") - if(debug) - { - if(!dir.exists) + if (debug) { + if (!dir.exists) dir.mkdirs() - for(file <- dir.listFiles) + for (file <- dir.listFiles) file.delete } - - def dump(name:String, bytes:Array[Byte]) - { - if(!debug) return - - val fileout = new File(dir, name.replace('/', '#')+".txt") - val pout = new PrintWriter(fileout) - - new ClassReader(bytes).accept(new TraceClassVisitor(null, new Textifier(), pout), 0) - pout.close() + + def dump(name: String, bytes: Array[Byte]) { + if (debug) ASMHelper.dump(bytes, new File(dir, name.replace('/', '#') + ".txt"), false, false) } - - def defined(name:String, bytes:Array[Byte]) - { - if((permGenUsed+bytes.length)/16000 != permGenUsed/16000) - log((permGenUsed+bytes.length)+" bytes of permGen has been used by ASMMixinCompiler") - + + def defined(name: String, bytes: Array[Byte]) { + if ((permGenUsed + bytes.length) / 16000 != permGenUsed / 16000) + log((permGenUsed + bytes.length) + " bytes of permGen has been used by ASMMixinCompiler") + permGenUsed += bytes.length } - - def log(msg:String) = if(debug) println(msg) + + def log(msg: String) = if (debug) println(msg) } object ASMMixinCompiler { + import StackAnalyser.width - + val cl = getClass.getClassLoader.asInstanceOf[LaunchClassLoader] val m_defineClass = classOf[ClassLoader].getDeclaredMethod("defineClass", classOf[Array[Byte]], Integer.TYPE, Integer.TYPE) val m_runTransformers = classOf[LaunchClassLoader].getDeclaredMethod("runTransformers", classOf[String], classOf[String], classOf[Array[Byte]]) @@ -69,141 +60,141 @@ object ASMMixinCompiler m_defineClass.setAccessible(true) m_runTransformers.setAccessible(true) f_transformerExceptions.setAccessible(true) - + private val traitByteMap = MMap[String, Array[Byte]]() private val mixinMap = MMap[String, MixinInfo]() - - def define(name:String, bytes:Array[Byte]) = - { + + def define(name: String, bytes: Array[Byte]) = { internalDefine(name, bytes) DebugPrinter.defined(name, bytes) try { - m_defineClass.invoke(cl, bytes, 0:Integer, bytes.length:Integer).asInstanceOf[Class[_]] + m_defineClass.invoke(cl, bytes, 0: Integer, bytes.length: Integer).asInstanceOf[Class[_]] } catch { - case link:LinkageError if link.getMessage.contains("duplicate") => - throw new IllegalStateException("class with name: "+name+" already loaded. Do not reference your mixin classes before registering them with MultipartGenerator", link) + case link: LinkageError if link.getMessage.contains("duplicate") => + throw new IllegalStateException("class with name: " + name + " already loaded. Do not reference your mixin classes before registering them with MultipartGenerator", link) } } - + getBytes("cpw/mods/fml/common/asm/FMLSanityChecker") - - def getBytes(name:String):Array[Byte] = - { + + def getBytes(name: String): Array[Byte] = { val jName = name.replace('/', '.') - if(jName.equals("java.lang.Object")) + if (jName.equals("java.lang.Object")) return null - + def useTransformers = f_transformerExceptions.get(cl).asInstanceOf[JSet[String]] - .find(jName.startsWith).isEmpty - - val obfName = if(ObfMapping.obfuscated) FMLDeobfuscatingRemapper.INSTANCE.unmap(name).replace('/', '.') else jName + .find(jName.startsWith).isEmpty + + val obfName = if (ObfMapping.obfuscated) FMLDeobfuscatingRemapper.INSTANCE.unmap(name).replace('/', '.') else jName val bytes = cl.getClassBytes(obfName) - if(bytes != null && useTransformers) + if (bytes != null && useTransformers) return m_runTransformers.invoke(cl, jName, obfName, bytes).asInstanceOf[Array[Byte]] - + return bytes } - - def internalDefine(name:String, bytes:Array[Byte]) - { + + def internalDefine(name: String, bytes: Array[Byte]) { traitByteMap.put(name.replace('.', '/'), bytes) BaseNodeInfo.clear(name) DebugPrinter.dump(name, bytes) } - - def classNode(name:String) = traitByteMap.getOrElseUpdate(name.replace('.', '/'), getBytes(name.replace('.', '/'))) match { + + def classNode(name: String) = traitByteMap.getOrElseUpdate(name.replace('.', '/'), getBytes(name.replace('.', '/'))) match { case null => null case v => createClassNode(v, ClassReader.EXPAND_FRAMES) } - - def isScala(cnode:ClassNode) = ScalaSigReader.ann(cnode).isDefined - - def isTrait(cnode:ClassNode) = - { - val csym:ClassSymbol = ScalaSigReader.read(ScalaSigReader.ann(cnode).get).evalT(0) + + def isScala(cnode: ClassNode) = ScalaSigReader.ann(cnode).isDefined + + def isTrait(cnode: ClassNode) = { + val csym: ClassSymbol = ScalaSigReader.read(ScalaSigReader.ann(cnode).get).evalT(0) csym.isTrait && !csym.isInterface } - - def getMixinInfo(name:String) = mixinMap.get(name) - - case class FieldMixin(name:String, desc:String, access:Int) + + def getMixinInfo(name: String) = mixinMap.get(name) + + case class FieldMixin(name: String, desc: String, access: Int) { - def accessName(owner:String) = if((access & ACC_PRIVATE) != 0) - owner.replace('/', '$')+"$$"+name - else - name + def accessName(owner: String) = if ((access & ACC_PRIVATE) != 0) + owner.replace('/', '$') + "$$" + name + else + name } - - case class MixinInfo(name:String, parent:String, fields:Seq[FieldMixin], - methods:Seq[MethodNode], supers:Map[String, String]) + + case class MixinInfo(name: String, parent: String, fields: Seq[FieldMixin], + methods: Seq[MethodNode], supers: Map[String, String]) { - def tname = name+"$class" + def tname = name + "$class" } - + object BaseNodeInfo { private val baseNodeMap = MMap[String, BaseNodeInfo]() - - def clear(name:String) = baseNodeMap.remove(name) - - def getNodeInfo(name:String) = baseNodeMap.getOrElseUpdate(name, new BaseNodeInfo(name)) - - private def getNodeInfo(clazz:ClassInfoSource) = clazz match { + + def clear(name: String) = baseNodeMap.remove(name) + + def getNodeInfo(name: String) = baseNodeMap.getOrElseUpdate(name, new BaseNodeInfo(name)) + + private def getNodeInfo(clazz: ClassInfoSource) = clazz match { case null => null case v => baseNodeMap.getOrElseUpdate(v.name, new BaseNodeInfo(v)) } - - case class MethodNodeInfo(owner:String, m:MethodInfoSource) + + case class MethodNodeInfo(owner: String, m: MethodInfoSource) { def name = m.name def desc = m.desc } - + trait MethodInfoSource { - def name:String - def desc:String - def isPrivate:Boolean - def isAbstract:Boolean + def name: String + def desc: String + def isPrivate: Boolean + def isAbstract: Boolean } - + trait ClassInfoSource { - def name:String - def superClass:Option[BaseNodeInfo] - def interfaces:Seq[BaseNodeInfo] - def methods:Seq[MethodInfoSource] + def name: String + def superClass: Option[BaseNodeInfo] + def interfaces: Seq[BaseNodeInfo] + def methods: Seq[MethodInfoSource] } - - implicit def JClassInfoSource(clazz:Class[_]) = if(clazz == null) null else new JClassInfoSource(clazz) - class JClassInfoSource(clazz:Class[_]) extends ClassInfoSource + + implicit def JClassInfoSource(clazz: Class[_]) = if (clazz == null) null else new JClassInfoSource(clazz) + + class JClassInfoSource(clazz: Class[_]) extends ClassInfoSource { - case class JMethodInfoSource(method:Method) extends MethodInfoSource + + case class JMethodInfoSource(method: Method) extends MethodInfoSource { def name = method.getName def desc = getType(method).getDescriptor def isPrivate = Modifier.isPrivate(method.getModifiers) def isAbstract = Modifier.isAbstract(method.getModifiers) } - + def name = clazz.getName.replace('.', '/') def superClass = Option(getNodeInfo(clazz.getSuperclass)) def interfaces = clazz.getInterfaces.map(getNodeInfo(_)) def methods = clazz.getMethods.map(JMethodInfoSource(_)) } - - implicit def ClassNodeInfoSource(cnode:ClassNode) = if(cnode == null) null else new ClassNodeInfoSource(cnode) - class ClassNodeInfoSource(cnode:ClassNode) extends ClassInfoSource + + implicit def ClassNodeInfoSource(cnode: ClassNode) = if (cnode == null) null else new ClassNodeInfoSource(cnode) + + class ClassNodeInfoSource(cnode: ClassNode) extends ClassInfoSource { - case class MethodNodeInfoSource(mnode:MethodNode) extends MethodInfoSource + + case class MethodNodeInfoSource(mnode: MethodNode) extends MethodInfoSource { def name = mnode.name def desc = mnode.desc def isPrivate = (mnode.access & ACC_PRIVATE) != 0 def isAbstract = (mnode.access & ACC_ABSTRACT) != 0 } - + def name = cnode.name def superClass = Option(getNodeInfo(cnode.superName)) def interfaces = cnode.interfaces match { @@ -212,17 +203,17 @@ object ASMMixinCompiler } def methods = cnode.methods.map(MethodNodeInfoSource(_)) } - - class ScalaNodeInfoSource(cnode:ClassNode) extends ClassNodeInfoSource(cnode) + + class ScalaNodeInfoSource(cnode: ClassNode) extends ClassNodeInfoSource(cnode) { val sig = ScalaSigReader.read(ScalaSigReader.ann(cnode).get) - val csym = sig.evalT(0):ClassSymbol - + val csym = sig.evalT(0): ClassSymbol + override def superClass = Option(getNodeInfo(csym.jParent(sig))) override def interfaces = csym.jInterfaces(sig).map(getNodeInfo) } - - def classInfo(name:String):ClassInfoSource = name match { + + def classInfo(name: String): ClassInfoSource = name match { case null => null case s => classNode(s) match { case null => cl.findClass(s.replace('/', '.')) @@ -231,239 +222,229 @@ object ASMMixinCompiler } } } - + import BaseNodeInfo._ - class BaseNodeInfo(val clazz:ClassInfoSource) + + class BaseNodeInfo(val clazz: ClassInfoSource) { - def this(name:String) = this(classInfo(name)) - - val publicmethods = exportedMethods(clazz)//map of nameDesc to owner+method - - def exportedMethods(o:ClassInfoSource):Map[String, MethodNodeInfo] = - { - val eMethods = o.methods.filter(!_.isPrivate)//defined accessible methods - .map(m => (m.name+m.desc, MethodNodeInfo(o.name, m))).toMap - - eMethods ++ (o.superClass++o.interfaces).flatMap(_.publicmethods) + def this(name: String) = this(classInfo(name)) + + val publicmethods = exportedMethods(clazz) //map of nameDesc to owner+method + + def exportedMethods(o: ClassInfoSource): Map[String, MethodNodeInfo] = { + val eMethods = o.methods.filter(!_.isPrivate) //defined accessible methods + .map(m => (m.name + m.desc, MethodNodeInfo(o.name, m))).toMap + + eMethods ++ (o.superClass ++ o.interfaces).flatMap(_.publicmethods) } } - - def finishBridgeCall(mv:MethodVisitor, mvdesc:String, opcode:Int, owner:String, name:String, desc:String) - { + + def finishBridgeCall(mv: MethodVisitor, mvdesc: String, opcode: Int, owner: String, name: String, desc: String) { val args = getArgumentTypes(mvdesc) val ret = getReturnType(mvdesc) var localIndex = 1 - args.foreach{arg => - mv.visitVarInsn(arg.getOpcode(ILOAD), localIndex) - localIndex+=width(arg) + args.foreach { + arg => + mv.visitVarInsn(arg.getOpcode(ILOAD), localIndex) + localIndex += width(arg) } mv.visitMethodInsn(opcode, owner, name, desc) mv.visitInsn(ret.getOpcode(IRETURN)) - mv.visitMaxs(Math.max(width(args)+1, width(ret)), width(args)+1) + mv.visitMaxs(Math.max(width(args) + 1, width(ret)), width(args) + 1) } - - def writeBridge(mv:MethodVisitor, mvdesc:String, opcode:Int, owner:String, name:String, desc:String) - { + + def writeBridge(mv: MethodVisitor, mvdesc: String, opcode: Int, owner: String, name: String, desc: String) { mv.visitVarInsn(ALOAD, 0) finishBridgeCall(mv, mvdesc, opcode, owner, name, desc) } - - def writeStaticBridge(mv:MethodNode, mname:String, t:MixinInfo) = + + def writeStaticBridge(mv: MethodNode, mname: String, t: MixinInfo) = writeBridge(mv, mv.desc, INVOKESTATIC, t.tname, mname, staticDesc(t.name, mv.desc)) - - def mixinClasses(name:String, superClass:String, traits:Seq[String]) = - { + + def mixinClasses(name: String, superClass: String, traits: Seq[String]) = { val traitInfos = traits.map(t => mixinMap(t.replace('.', '/'))) - + val cnode = new ClassNode() cnode.visit(V1_6, ACC_PUBLIC, name, null, superClass.replace('.', '/'), traitInfos.map(_.name).toArray[String]) - + val minit = cnode.visitMethod(ACC_PUBLIC, "", "()V", null, null) minit.visitVarInsn(ALOAD, 0) minit.visitMethodInsn(INVOKESPECIAL, cnode.superName, "", "()V") - + val prevInfos = MList[MixinInfo]() - - traitInfos.foreach{ t => - minit.visitVarInsn(ALOAD, 0) - minit.visitMethodInsn(INVOKESTATIC, t.tname, "$init$", "(L"+t.name+";)V") - - t.fields.foreach{ f => - val fv = cnode.visitField(ACC_PRIVATE, f.accessName(t.name), f.desc, null, null).asInstanceOf[FieldNode] - - val ftype = getType(fv.desc) - var mv = cnode.visitMethod(ACC_PUBLIC, fv.name, "()"+f.desc, null, null) - mv.visitVarInsn(ALOAD, 0) - mv.visitFieldInsn(GETFIELD, name, fv.name, fv.desc) - mv.visitInsn(ftype.getOpcode(IRETURN)) - mv.visitMaxs(1, 1) - - mv = cnode.visitMethod(ACC_PUBLIC, fv.name+"_$eq", "("+f.desc+")V", null, null) - mv.visitVarInsn(ALOAD, 0) - mv.visitVarInsn(ftype.getOpcode(ILOAD), 1) - mv.visitFieldInsn(PUTFIELD, name, fv.name, fv.desc) - mv.visitInsn(RETURN) - mv.visitMaxs(width(ftype)+1, width(ftype)+1) - } - - t.supers.foreach{ s => - val (name, desc) = seperateDesc(s._1) - val mv = cnode.visitMethod(ACC_PUBLIC, t.name.replace('/', '$')+"$$super$"+name, desc, null, null).asInstanceOf[MethodNode] - - prevInfos.reverse.find(t => t.supers.contains(s._1)) match {//each super goes to the one before - case Some(st) => writeStaticBridge(mv, name, st) - case None => writeBridge(mv, desc, INVOKESPECIAL, s._2, name, desc) + + traitInfos.foreach { + t => + minit.visitVarInsn(ALOAD, 0) + minit.visitMethodInsn(INVOKESTATIC, t.tname, "$init$", "(L" + t.name + ";)V") + + t.fields.foreach { + f => + val fv = cnode.visitField(ACC_PRIVATE, f.accessName(t.name), f.desc, null, null).asInstanceOf[FieldNode] + + val ftype = getType(fv.desc) + var mv = cnode.visitMethod(ACC_PUBLIC, fv.name, "()" + f.desc, null, null) + mv.visitVarInsn(ALOAD, 0) + mv.visitFieldInsn(GETFIELD, name, fv.name, fv.desc) + mv.visitInsn(ftype.getOpcode(IRETURN)) + mv.visitMaxs(1, 1) + + mv = cnode.visitMethod(ACC_PUBLIC, fv.name + "_$eq", "(" + f.desc + ")V", null, null) + mv.visitVarInsn(ALOAD, 0) + mv.visitVarInsn(ftype.getOpcode(ILOAD), 1) + mv.visitFieldInsn(PUTFIELD, name, fv.name, fv.desc) + mv.visitInsn(RETURN) + mv.visitMaxs(width(ftype) + 1, width(ftype) + 1) } - } - - prevInfos+=t + + t.supers.foreach { + s => + val (name, desc) = seperateDesc(s._1) + val mv = cnode.visitMethod(ACC_PUBLIC, t.name.replace('/', '$') + "$$super$" + name, desc, null, null).asInstanceOf[MethodNode] + + prevInfos.reverse.find(t => t.supers.contains(s._1)) match { + //each super goes to the one before + case Some(st) => writeStaticBridge(mv, name, st) + case None => writeBridge(mv, desc, INVOKESPECIAL, s._2, name, desc) + } + } + + prevInfos += t } - + val methodSigs = MSet[String]() - traitInfos.reverse.foreach{ t => //last trait gets first pick on methods - t.methods.foreach{ m => - if(!methodSigs(m.name+m.desc)) - { - val mv = cnode.visitMethod(ACC_PUBLIC, m.name, m.desc, null, Array(m.exceptions:_*)).asInstanceOf[MethodNode] - copy(m, mv) - mv.instructions = new InsnList() - mv.tryCatchBlocks.clear() - - writeStaticBridge(mv, m.name, t) - methodSigs+=m.name+m.desc + traitInfos.reverse.foreach { + t => //last trait gets first pick on methods + t.methods.foreach { + m => + if (!methodSigs(m.name + m.desc)) { + val mv = cnode.visitMethod(ACC_PUBLIC, m.name, m.desc, null, Array(m.exceptions: _*)).asInstanceOf[MethodNode] + writeStaticBridge(mv, m.name, t) + methodSigs += m.name + m.desc + } } - } } - + minit.visitInsn(RETURN) minit.visitMaxs(1, 1) - + define(cnode.name, createBytes(cnode, 0)) } - - def seperateDesc(nameDesc:String) = { + + def seperateDesc(nameDesc: String) = { val n = nameDesc.indexOf('(') (nameDesc.substring(0, n), nameDesc.substring(n)) } - - def staticDesc(owner:String, desc:String) = - { + + def staticDesc(owner: String, desc: String) = { val descT = getMethodType(desc) - getMethodDescriptor(descT.getReturnType, getType("L"+owner+";")+:descT.getArgumentTypes : _*) + getMethodDescriptor(descT.getReturnType, getType("L" + owner + ";") +: descT.getArgumentTypes: _*) } - - def getSuper(minsn:MethodInsnNode, stack:StackAnalyser):Option[String] = - { + + def getSuper(minsn: MethodInsnNode, stack: StackAnalyser): Option[String] = { import StackAnalyser._ - - if(minsn.getOpcode != INVOKESPECIAL) return None + + if (minsn.getOpcode != INVOKESPECIAL) return None val oname = stack.owner.getInternalName - - if(minsn.owner.equals(oname)) return None//private this - + + if (minsn.owner.equals(oname)) return None //private this + stack.peek(Type.getType(minsn.desc).getArgumentTypes.length) match { case Load(This(o)) => - case _ => return None//have to be invoked on this + case _ => return None //have to be invoked on this } - - getSuper(minsn.name+minsn.desc, oname) + + getSuper(minsn.name + minsn.desc, oname) } - - def getSuper(nameDesc:String, cname:String) = + + def getSuper(nameDesc: String, cname: String) = getNodeInfo(cname).clazz.superClass match { - case None => None//no super class + case None => None //no super class case Some(o) => o.publicmethods.get(nameDesc) match { - case None => None//no method with sig in super - case Some(m) => if(m.m.isAbstract) - None //abstract can't be called for supers - else - Some(m.owner)//congrats, that's a super + case None => None //no method with sig in super + case Some(m) => if (m.m.isAbstract) + None //abstract can't be called for supers + else + Some(m.owner) //congrats, that's a super } } - - def registerJavaTrait(cnode:ClassNode) - { - if((cnode.access & ACC_INTERFACE) != 0) - throw new IllegalArgumentException("Cannot register java interface "+cnode.name+" as a multipart trait. Try register passThroughInterface") - if((cnode.access & ACC_ABSTRACT) != 0) - throw new IllegalArgumentException("Cannot register abstract class "+cnode.name+" as a multipart trait") - if(!cnode.innerClasses.isEmpty) - throw new IllegalArgumentException("Inner classes are not permitted for "+cnode.name+" as a multipart trait. Use scala") - - val inode = new ClassNode()//impl node - inode.visit(V1_6, ACC_ABSTRACT|ACC_PUBLIC, cnode.name+"$class", null, "java/lang/Object", null) + + def registerJavaTrait(cnode: ClassNode) { + if ((cnode.access & ACC_INTERFACE) != 0) + throw new IllegalArgumentException("Cannot register java interface " + cnode.name + " as a multipart trait. Try register passThroughInterface") + if ((cnode.access & ACC_ABSTRACT) != 0) + throw new IllegalArgumentException("Cannot register abstract class " + cnode.name + " as a multipart trait") + if (!cnode.innerClasses.isEmpty) + throw new IllegalArgumentException("Inner classes are not permitted for " + cnode.name + " as a multipart trait. Use scala") + + val inode = new ClassNode() //impl node + inode.visit(V1_6, ACC_ABSTRACT | ACC_PUBLIC, cnode.name + "$class", null, "java/lang/Object", null) inode.sourceFile = cnode.sourceFile - + val fields = cnode.fields.map(f => (f.name, FieldMixin(f.name, f.desc, f.access))).toMap - val supers = MMap[String, String]()//nameDesc to super owner + val supers = MMap[String, String]() //nameDesc to super owner val methods = MList[MethodNode]() - val methodSigs = cnode.methods.map(m => m.name+m.desc).toSet - - val tnode = new ClassNode()//trait node (interface) - tnode.visit(V1_6, ACC_INTERFACE|ACC_ABSTRACT|ACC_PUBLIC, cnode.name, null, "java/lang/Object", Array(cnode.interfaces:_*)) - - def fname(name:String) = fields(name).accessName(cnode.name) - - fields.values.foreach{ fnode => - tnode.visitMethod(ACC_PUBLIC|ACC_ABSTRACT, fname(fnode.name), "()"+fnode.desc, null, null) - tnode.visitMethod(ACC_PUBLIC|ACC_ABSTRACT, fname(fnode.name)+"_$eq", "("+fnode.desc+")V", null, null) + val methodSigs = cnode.methods.map(m => m.name + m.desc).toSet + + val tnode = new ClassNode() //trait node (interface) + tnode.visit(V1_6, ACC_INTERFACE | ACC_ABSTRACT | ACC_PUBLIC, cnode.name, null, "java/lang/Object", Array(cnode.interfaces: _*)) + + def fname(name: String) = fields(name).accessName(cnode.name) + + fields.values.foreach { + fnode => + tnode.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fname(fnode.name), "()" + fnode.desc, null, null) + tnode.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fname(fnode.name) + "_$eq", "(" + fnode.desc + ")V", null, null) } - - def superInsn(minsn:MethodInsnNode) = - { - val bridgeName = cnode.name.replace('/', '$')+"$$super$"+minsn.name - if(!supers.contains(minsn.name+minsn.desc)) - { - tnode.visitMethod(ACC_PUBLIC|ACC_ABSTRACT, bridgeName, minsn.desc, null, null) - supers.put(minsn.name+minsn.desc, minsn.owner) + + def superInsn(minsn: MethodInsnNode) = { + val bridgeName = cnode.name.replace('/', '$') + "$$super$" + minsn.name + if (!supers.contains(minsn.name + minsn.desc)) { + tnode.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, bridgeName, minsn.desc, null, null) + supers.put(minsn.name + minsn.desc, minsn.owner) } new MethodInsnNode(INVOKEINTERFACE, cnode.name, bridgeName, minsn.desc) } - - def staticClone(mnode:MethodNode, name:String, access:Int) = - { - val mv = inode.visitMethod(access|ACC_STATIC, name, - staticDesc(cnode.name, mnode.desc), - null, Array(mnode.exceptions:_*)).asInstanceOf[MethodNode] + + def staticClone(mnode: MethodNode, name: String, access: Int) = { + val mv = inode.visitMethod(access | ACC_STATIC, name, + staticDesc(cnode.name, mnode.desc), + null, Array(mnode.exceptions: _*)).asInstanceOf[MethodNode] copy(mnode, mv) mv } - - def staticTransform(mnode:MethodNode, base:MethodNode) - { + + def staticTransform(mnode: MethodNode, base: MethodNode) { val stack = new StackAnalyser(getType(cnode.name), base) val insnList = mnode.instructions var insn = insnList.getFirst - - def replace(newinsn:AbstractInsnNode) - { + + def replace(newinsn: AbstractInsnNode) { insnList.insert(insn, newinsn) insnList.remove(insn) insn = newinsn } //transform - while(insn != null) - { + while (insn != null) { insn match { - case finsn:FieldInsnNode => insn.getOpcode match - { - case GETFIELD => replace(new MethodInsnNode(INVOKEINTERFACE, cnode.name, - fname(finsn.name), "()"+finsn.desc)) - case PUTFIELD => replace(new MethodInsnNode(INVOKEINTERFACE, cnode.name, - fname(finsn.name)+"_$eq", "("+finsn.desc+")V")) + case finsn: FieldInsnNode => insn.getOpcode match { + case GETFIELD => replace(new MethodInsnNode(INVOKEINTERFACE, cnode.name, + fname(finsn.name), "()" + finsn.desc)) + case PUTFIELD => replace(new MethodInsnNode(INVOKEINTERFACE, cnode.name, + fname(finsn.name) + "_$eq", "(" + finsn.desc + ")V")) case _ => } - case minsn:MethodInsnNode => insn.getOpcode match - { - case INVOKESPECIAL => - if(getSuper(minsn, stack).isDefined) + case minsn: MethodInsnNode => insn.getOpcode match { + case INVOKESPECIAL => + if (getSuper(minsn, stack).isDefined) replace(superInsn(minsn)) case INVOKEVIRTUAL => - if(minsn.owner.equals(cnode.name)) { - if(methodSigs.contains(minsn.name+minsn.desc))//call the interface method + if (minsn.owner.equals(cnode.name)) { + if (methodSigs.contains(minsn.name + minsn.desc)) //call the interface method minsn.setOpcode(INVOKEINTERFACE) - else {//cast to parent class and call + else { + //cast to parent class and call val mType = Type.getMethodType(minsn.desc) val instanceEntry = stack.peek(width(mType.getArgumentTypes)) insnList.insert(instanceEntry.insn, new TypeInsnNode(CHECKCAST, cnode.superName)) @@ -478,150 +459,102 @@ object ASMMixinCompiler insn = insn.getNext } } - - def convertMethod(mnode:MethodNode) - { - if(mnode.name.equals("")) - throw new IllegalArgumentException("Static initialisers are not permitted "+cnode.name+" as a multipart trait") - - if(mnode.name.equals("")) - { - if(!mnode.desc.equals("()V")) - throw new IllegalArgumentException("Constructor arguments are not permitted "+cnode.name+" as a multipart trait") - + + def convertMethod(mnode: MethodNode) { + if (mnode.name.equals("")) + throw new IllegalArgumentException("Static initialisers are not permitted " + cnode.name + " as a multipart trait") + + if (mnode.name.equals("")) { + if (!mnode.desc.equals("()V")) + throw new IllegalArgumentException("Constructor arguments are not permitted " + cnode.name + " as a multipart trait") + val mv = staticClone(mnode, "$init$", ACC_PUBLIC) - def removeSuperConstructor() - { - def throwI = throw new IllegalArgumentException("Invalid constructor insn sequence "+cnode.name) - - val insnList = mv.instructions - var insn = insnList.getFirst - var state = 0 - while(insn != null && state < 2) - { - val next = insn.getNext - insn match { - case linsn:LabelNode => - case linsn:LineNumberNode => - case vinsn:VarInsnNode => - if(state == 0) - { - if(vinsn.getOpcode == ALOAD && vinsn.`var` == 0) - { - state = 1 - insnList.remove(insn) - } - else - throwI - } - else - throwI - case minsn:MethodInsnNode => - if(state == 1) - { - if(minsn.getOpcode == INVOKESPECIAL && minsn.name.equals("") && - minsn.owner.equals(cnode.superName)) - { - insnList.remove(insn) - state = 2 - } - else - throwI - } - else - throwI - case _ => throwI - } - insn = next - } - if(state != 2) - throwI + def removeSuperConstructor() { + val insns = new InsnListSection + insns.add(new VarInsnNode(ALOAD, 0)) + insns.add(new MethodInsnNode(INVOKESPECIAL, cnode.superName, "", "()V")) + + val minsns = new InsnListSection(mv.instructions) + val found = InsnComparator.matches(minsns, insns, Set[LabelNode]()) + if(found == null) + throw new IllegalArgumentException("Invalid constructor insn sequence " + cnode.name + "\n" + minsns) + found.trim(Set[LabelNode]()).remove() } removeSuperConstructor() staticTransform(mv, mnode) return } - - if((mnode.access & ACC_PRIVATE) == 0) - { - val mv = tnode.visitMethod(ACC_PUBLIC|ACC_ABSTRACT, mnode.name, mnode.desc, null, Array(mnode.exceptions:_*)) - methods+=mv.asInstanceOf[MethodNode] + + if ((mnode.access & ACC_PRIVATE) == 0) { + val mv = tnode.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, mnode.name, mnode.desc, null, Array(mnode.exceptions: _*)) + methods += mv.asInstanceOf[MethodNode] } - + //convert that method! - val access = if((mnode.access & ACC_PRIVATE) == 0) ACC_PUBLIC else ACC_PRIVATE + val access = if ((mnode.access & ACC_PRIVATE) == 0) ACC_PUBLIC else ACC_PRIVATE val mv = staticClone(mnode, mnode.name, access) staticTransform(mv, mnode) } - + cnode.methods.foreach(convertMethod) define(inode.name, createBytes(inode, 0)) define(tnode.name, createBytes(tnode, 0)) - - mixinMap.put(tnode.name, MixinInfo(tnode.name, cnode.superName, - fields.values.toSeq, - methods.toSeq, supers.toMap)) + + mixinMap.put(tnode.name, MixinInfo(tnode.name, cnode.superName, + fields.values.toSeq, + methods.toSeq, supers.toMap)) } - - def registerScalaTrait(cnode:ClassNode) - { - for(i <- cnode.interfaces) - { + + def registerScalaTrait(cnode: ClassNode) { + for (i <- cnode.interfaces) { val inode = classNode(i) - if(isScala(inode) && isTrait(inode)) - throw new IllegalArgumentException("Multipart trait "+cnode.name+" cannot extend other traits") + if (isScala(inode) && isTrait(inode)) + throw new IllegalArgumentException("Multipart trait " + cnode.name + " cannot extend other traits") } - + val fieldAccessors = MMap[String, MethodSymbol]() val fields = MList[MethodSymbol]() val methods = MList[MethodNode]() val supers = MMap[String, String]() - + val sig = ScalaSigReader.read(ScalaSigReader.ann(cnode).get) - val csym:ClassSymbol = sig.evalT(0) - for(i <- 0 until sig.table.length) - { + val csym: ClassSymbol = sig.evalT(0) + for (i <- 0 until sig.table.length) { import ScalaSignature._ - + val e = sig.table(i) - if(e.id == 8)//method - { - val sym:MethodSymbol = sig.evalT(i) - if(sym.isParam || !sym.owner.equals(csym)){} - else if(sym.isAccessor) - { + if (e.id == 8) {//method + val sym: MethodSymbol = sig.evalT(i) + if (sym.isParam || !sym.owner.equals(csym)) {} + else if (sym.isAccessor) { fieldAccessors.put(sym.name, sym) } - else if(sym.isMethod) - { + else if (sym.isMethod) { val desc = sym.jDesc(sig) - if(sym.name.contains("super$")) - { + if (sym.name.contains("super$")) { val name = sym.name.substring(6) - supers.put(name+desc, getSuper(name+desc, cnode.name).get) + supers.put(name + desc, getSuper(name + desc, cnode.name).get) } - else if(!sym.name.equals("$init$") && !sym.isPrivate) - { + else if (!sym.name.equals("$init$") && !sym.isPrivate) { val map = new ObfMapping(cnode.name, sym.name, desc) val method = findMethod(map, cnode) - if(method == null) - throw new RuntimeException("Unable to add multipart trait: "+map+" found in scala signature but not in class file. Most likely an obfuscation issue.") - methods+=method + if (method == null) + throw new RuntimeException("Unable to add multipart trait: " + map + " found in scala signature but not in class file. Most likely an obfuscation issue.") + methods += method } } - else - { - fields+=sym + else { + fields += sym } } } - mixinMap.put(cnode.name, MixinInfo(cnode.name, csym.jParent(sig), - fields.map(sym => FieldMixin(sym.name.trim, getReturnType(sym.jDesc(sig)).getDescriptor, - if(fieldAccessors(sym.name.trim).isPrivate) ACC_PRIVATE else ACC_PUBLIC)), - methods, supers.toMap)) + mixinMap.put(cnode.name, MixinInfo(cnode.name, csym.jParent(sig), + fields.map(sym => FieldMixin(sym.name.trim, getReturnType(sym.jDesc(sig)).getDescriptor, + if (fieldAccessors(sym.name.trim).isPrivate) ACC_PRIVATE else ACC_PUBLIC)), + methods, supers.toMap)) } - - + + } \ No newline at end of file diff --git a/src/codechicken/multipart/asm/ASMMixinFactory.scala b/src/codechicken/multipart/asm/ASMMixinFactory.scala index 8f6c3a6..4e87b50 100644 --- a/src/codechicken/multipart/asm/ASMMixinFactory.scala +++ b/src/codechicken/multipart/asm/ASMMixinFactory.scala @@ -189,7 +189,7 @@ object ASMMixinFactory extends IMultipartFactory val inode = classNode(s_interface) if(inode == null) { - System.out.println("Unable to generate pass through trait for: "+s_interface+" class not found.") + logger.error("Unable to generate pass through trait for: "+s_interface+" class not found.") return null } if((inode.access&ACC_INTERFACE) == 0) throw new IllegalArgumentException(s_interface+" is not an interface.") diff --git a/src/codechicken/multipart/handler/MultipartCompatiblity.scala b/src/codechicken/multipart/handler/MultipartCompatiblity.scala index fbb83c5..9cf35ed 100644 --- a/src/codechicken/multipart/handler/MultipartCompatiblity.scala +++ b/src/codechicken/multipart/handler/MultipartCompatiblity.scala @@ -24,7 +24,7 @@ object MCPCCompatModule } } catch { case e:Exception => - System.err.println("Failed to integrate MCPC placement hooks") + MultipartProxy.logger.error("Failed to integrate MCPC placement hooks") e.printStackTrace() } } diff --git a/src/codechicken/multipart/handler/MultipartMod.scala b/src/codechicken/multipart/handler/MultipartMod.scala index 06e368a..1aee1d7 100644 --- a/src/codechicken/multipart/handler/MultipartMod.scala +++ b/src/codechicken/multipart/handler/MultipartMod.scala @@ -8,35 +8,29 @@ import cpw.mods.fml.common.Mod.EventHandler import cpw.mods.fml.common.event.FMLServerAboutToStartEvent import codechicken.multipart.MultiPartRegistry -@Mod(modid = "ForgeMultipart", acceptedMinecraftVersions = "[1.7.2]", - modLanguage="scala") +@Mod(modid = "ForgeMultipart", acceptedMinecraftVersions = "[1.7.2]", modLanguage = "scala") object MultipartMod { @EventHandler - def preInit(event:FMLPreInitializationEvent) - { - MultipartProxy.preInit(event.getModConfigurationDirectory) + def preInit(event: FMLPreInitializationEvent) { + MultipartProxy.preInit(event.getModConfigurationDirectory, event.getModLog) } - + @EventHandler - def init(event:FMLInitializationEvent) - { + def init(event: FMLInitializationEvent) { MultipartProxy.init() } - + @EventHandler - def postInit(event:FMLPostInitializationEvent) - { - if(MultiPartRegistry.required) - { + def postInit(event: FMLPostInitializationEvent) { + if (MultiPartRegistry.required) { MultiPartRegistry.postInit() MultipartProxy.postInit() } } - + @EventHandler - def beforeServerStart(event:FMLServerAboutToStartEvent) - { + def beforeServerStart(event: FMLServerAboutToStartEvent) { MultiPartRegistry.beforeServerStart() } } \ No newline at end of file diff --git a/src/codechicken/multipart/handler/proxies.scala b/src/codechicken/multipart/handler/proxies.scala index edf6c3c..fa9bd64 100644 --- a/src/codechicken/multipart/handler/proxies.scala +++ b/src/codechicken/multipart/handler/proxies.scala @@ -6,7 +6,6 @@ import cpw.mods.fml.client.registry.ClientRegistry import net.minecraft.tileentity.TileEntity import codechicken.lib.config.ConfigFile import java.io.File -import codechicken.multipart.handler.MultipartProxy._ import net.minecraftforge.common.MinecraftForge import cpw.mods.fml.relauncher.SideOnly import cpw.mods.fml.relauncher.Side @@ -17,11 +16,16 @@ import codechicken.lib.world.WorldExtensionManager import cpw.mods.fml.common.FMLCommonHandler import cpw.mods.fml.common.registry.GameRegistry import net.minecraft.block.Block +import org.apache.logging.log4j.Logger class MultipartProxy_serverImpl { - def preInit(cfgdir:File) - { + var block:BlockMultipart = _ + var config:ConfigFile = _ + var logger:Logger = _ + + def preInit(cfgdir: File, logger:Logger) { + this.logger = logger config = new ConfigFile(new File(cfgdir, "multipart.cfg")) .setComment("Multipart API config file") @@ -36,14 +40,13 @@ class MultipartProxy_serverImpl MultipartGenerator.registerTrait("codechicken.multipart.IRedstonePart", "codechicken.multipart.scalatraits.TRedstoneTile") MultipartGenerator.registerTrait("codechicken.multipart.IRandomDisplayTick", "codechicken.multipart.scalatraits.TRandomDisplayTickTile", null) MultipartGenerator.registerTrait("codechicken.multipart.INeighborTileChange", null, "codechicken.multipart.scalatraits.TTileChangeTile") - + MultipartSaveLoad.hookLoader() } - def init(){} + def init() {} - def postInit() - { + def postInit() { FMLCommonHandler.instance().bus().register(MultipartEventHandler) MinecraftForge.EVENT_BUS.register(MultipartEventHandler) PacketCustom.assignHandler(MultipartSPH.channel, MultipartSPH) @@ -53,18 +56,16 @@ class MultipartProxy_serverImpl MultipartCompatiblity.load() } - - def onTileClassBuilt(t:Class[_ <: TileEntity]) - { - MultipartSaveLoad.registerTileClass(t) + + def onTileClassBuilt(t: Class[_ <: TileEntity]) { + MultipartSaveLoad.registerTileClass(t) } } class MultipartProxy_clientImpl extends MultipartProxy_serverImpl { @SideOnly(Side.CLIENT) - override def postInit() - { + override def postInit() { super.postInit() RenderingRegistry.registerBlockHandler(MultipartRenderer) PacketCustom.assignHandler(MultipartCPH.channel, MultipartCPH) @@ -73,10 +74,9 @@ class MultipartProxy_clientImpl extends MultipartProxy_serverImpl FMLCommonHandler.instance().bus().register(ControlKeyHandler) ClientRegistry.registerKeyBinding(ControlKeyHandler) } - + @SideOnly(Side.CLIENT) - override def onTileClassBuilt(t:Class[_ <: TileEntity]) - { + override def onTileClassBuilt(t: Class[_ <: TileEntity]) { super.onTileClassBuilt(t) ClientRegistry.bindTileEntitySpecialRenderer(t, MultipartRenderer) } @@ -84,9 +84,6 @@ class MultipartProxy_clientImpl extends MultipartProxy_serverImpl object MultipartProxy extends MultipartProxy_clientImpl { - var block:BlockMultipart = _ - var config:ConfigFile = _ - - def indexInChunk(cc:ChunkCoordIntPair, i:Int) = new BlockCoord(cc.chunkXPos<<4|i&0xF, (i>>8)&0xFF, cc.chunkZPos<<4|(i&0xF0)>>4) - def indexInChunk(pos:BlockCoord) = pos.x&0xF|pos.y<<8|(pos.z&0xF)<<4 + def indexInChunk(cc: ChunkCoordIntPair, i: Int) = new BlockCoord(cc.chunkXPos << 4 | i & 0xF, (i >> 8) & 0xFF, cc.chunkZPos << 4 | (i & 0xF0) >> 4) + def indexInChunk(pos: BlockCoord) = pos.x & 0xF | pos.y << 8 | (pos.z & 0xF) << 4 } \ No newline at end of file diff --git a/src/codechicken/multipart/package.scala b/src/codechicken/multipart/package.scala new file mode 100644 index 0000000..9350821 --- /dev/null +++ b/src/codechicken/multipart/package.scala @@ -0,0 +1,8 @@ +package codechicken + +import codechicken.multipart.handler.MultipartProxy + +package object multipart +{ + def logger = MultipartProxy.logger +}