mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-14 01:14:19 +00:00
Added SideOnly support to scala mixins
This commit is contained in:
1 parent
9c3a4ea0e8
commit
82174e96fb
3 files changed
+85
-62
No files matched your search
@@ -4,10 +4,8 @@ import codechicken.lib.vec.Cuboid6
|
||||
import codechicken.multipart.TFacePart
|
||||
import codechicken.lib.vec.Vector3
|
||||
import codechicken.lib.vec.Rotation
|
||||
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial
|
||||
import Rotation._
|
||||
import Vector3._
|
||||
import codechicken.lib.lighting.LightMatrix
|
||||
|
||||
object FacePlacement extends PlacementProperties
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ import codechicken.multipart.handler.MultipartProxy
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ASMImplicits._
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler
|
||||
|
||||
object DebugPrinter
|
||||
{
|
||||
@@ -535,6 +536,14 @@ object ASMMixinCompiler
|
||||
fields.values.toSeq, methods, supers))
|
||||
}
|
||||
|
||||
def listSideOnly(sig:ScalaSignature) = {
|
||||
val side = "cpw.mods.fml.relauncher.Side."+FMLLaunchHandler.side.name
|
||||
sig.collect[sig.AnnotationInfo](40).filter{ a =>
|
||||
a.annType.name == "cpw.mods.fml.relauncher.SideOnly" &&
|
||||
a.getValue[sig.EnumLiteral]("value").value.full != side
|
||||
}.map(_.owner.full).toSet
|
||||
}
|
||||
|
||||
def registerScalaTrait(cnode: ClassNode):MixinInfo = {
|
||||
getMixinInfo(cnode.name) match {
|
||||
case Some(info) => return info
|
||||
@@ -543,6 +552,7 @@ object ASMMixinCompiler
|
||||
|
||||
val info = getClassInfo(cnode).asInstanceOf[ClassInfo.ScalaClassInfo]
|
||||
val sig = info.sig
|
||||
val sideOnly = listSideOnly(sig)
|
||||
|
||||
val parentTraits = getAndRegisterParentTraits(cnode)
|
||||
val fieldAccessors = MMap[String, sig.MethodSymbol]()
|
||||
@@ -553,6 +563,7 @@ object ASMMixinCompiler
|
||||
val csym = info.csym
|
||||
for (sym <- sig.collect[sig.MethodSymbol](8)) {
|
||||
if (sym.isParam || sym.owner != csym) {}
|
||||
else if (sideOnly(sym.full)) {}
|
||||
else if (sym.isAccessor) {
|
||||
fieldAccessors.put(sym.name, sym)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.objectweb.asm.tree.AnnotationNode
|
||||
import org.objectweb.asm.tree.FieldNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
import java.util.{List => JList}
|
||||
import scala.collection.mutable.{ListBuffer => MList}
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
@@ -18,10 +17,10 @@ object ScalaSignature
|
||||
def apply(arr: Array[Byte]):Bytes = Bytes(arr, 0, arr.length)
|
||||
}
|
||||
|
||||
case class Bytes(val arr: Array[Byte], val pos: Int, val len: Int)
|
||||
case class Bytes(arr: Array[Byte], pos: Int, len: Int)
|
||||
{
|
||||
def reader = new ByteCodeReader(this)
|
||||
def section = arr.take(pos).drop(len)
|
||||
def section = arr.drop(pos).take(len)
|
||||
}
|
||||
|
||||
trait Flags
|
||||
@@ -185,6 +184,33 @@ class ScalaSignature(val bytes: Bytes)
|
||||
{
|
||||
def id = bytes.arr(start)
|
||||
def delete() = bytes.arr(start) = 3
|
||||
override def toString = "SigEntry("+index+","+id+","+bytes.len+" bytes)"
|
||||
}
|
||||
|
||||
trait Literal
|
||||
{
|
||||
def value:Any
|
||||
}
|
||||
case class BooleanLiteral(value:Boolean) extends Literal
|
||||
case class ByteLiteral(value:Byte) extends Literal
|
||||
case class ShortLiteral(value:Short) extends Literal
|
||||
case class CharLiteral(value:Char) extends Literal
|
||||
case class IntLiteral(value:Int) extends Literal
|
||||
case class LongLiteral(value:Long) extends Literal
|
||||
case class FloatLiteral(value:Float) extends Literal
|
||||
case class DoubleLiteral(value:Double) extends Literal
|
||||
case object NullLiteral extends Literal
|
||||
{
|
||||
override def value = null
|
||||
}
|
||||
case class StringLiteral(value:String) extends Literal
|
||||
case class TypeLiteral(value:TypeRef) extends Literal
|
||||
case class EnumLiteral(value:ExternalSymbol) extends Literal
|
||||
case class ArrayLiteral(value:List[_]) extends Literal
|
||||
|
||||
case class AnnotationInfo(owner:SymbolRef, annType:TypeRef, values:Map[String, Literal])
|
||||
{
|
||||
def getValue[T](name:String) = values(name).asInstanceOf[T]
|
||||
}
|
||||
|
||||
def evalS(i: Int): String = {
|
||||
@@ -202,33 +228,54 @@ class ScalaSignature(val bytes: Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
def evalT[T](i: Int): T = eval(i).asInstanceOf[T]
|
||||
def evalT[T](i: Int) = eval(i).asInstanceOf[T]
|
||||
|
||||
def evalList[T](bcr: ByteCodeReader) = {
|
||||
var l = MList[T]()
|
||||
val l = List.newBuilder
|
||||
while (bcr.more)
|
||||
l += evalT(bcr.readNat)
|
||||
l.toList
|
||||
l.result()
|
||||
}
|
||||
|
||||
def eval(i: Int): Any = {
|
||||
//only parse the ones that matter for this project
|
||||
val e = table(i)
|
||||
val bcr = e.bytes.reader
|
||||
|
||||
def nat = bcr.readNat
|
||||
def evalS = this.evalS(nat)
|
||||
def evalT[T] = this.evalT[T](nat)
|
||||
def evalList[T] = this.evalList[T](bcr)
|
||||
|
||||
e.id match {
|
||||
case 1 | 2 => evalS(i)
|
||||
case 6 => ClassSymbol(evalS(bcr.readNat), evalT(bcr.readNat), bcr.readNat, bcr.readNat)
|
||||
case 7 => ObjectSymbol(evalS(bcr.readNat), evalT(bcr.readNat), bcr.readNat, bcr.readNat)
|
||||
case 8 => MethodSymbol(evalS(bcr.readNat), evalT(bcr.readNat), bcr.readNat, bcr.readNat)
|
||||
case 9 | 10 => ExternalSymbol(evalS(i))
|
||||
case 1 | 2 => this.evalS(i)
|
||||
case 3 => NoSymbol
|
||||
case 6 => ClassSymbol(evalS, evalT, nat, nat)
|
||||
case 7 => ObjectSymbol(evalS, evalT, nat, nat)
|
||||
case 8 => MethodSymbol(evalS, evalT, nat, nat)
|
||||
case 9 | 10 => ExternalSymbol(this.evalS(i))
|
||||
case 11 | 12 => NoType //12 is actually NoPrefixType (no lower bound)
|
||||
case 13 => ThisType(evalT(bcr.readNat))
|
||||
case 14 => SingleType(evalT(bcr.readNat), evalT(bcr.readNat))
|
||||
case 16 => TypeRefType(evalT(bcr.readNat), evalT(bcr.readNat), evalList(bcr))
|
||||
case 19 => ClassType(evalT(bcr.readNat), evalList(bcr))
|
||||
case 20 => MethodType(evalT(bcr.readNat), evalList(bcr))
|
||||
case 21 | 48 => ParameterlessType(evalT(bcr.readNat)) //48 is actually a bounded super type, but it should work fine for this project
|
||||
case _ => NoSymbol
|
||||
case 13 => ThisType(evalT)
|
||||
case 14 => SingleType(evalT, evalT)
|
||||
case 16 => TypeRefType(evalT, evalT, evalList)
|
||||
case 19 => ClassType(evalT, evalList)
|
||||
case 20 => MethodType(evalT, evalList)
|
||||
case 21 | 48 => ParameterlessType(evalT) //48 is actually a bounded super type, but it should work fine for this project
|
||||
case 25 => BooleanLiteral(bcr.readLong != 0)
|
||||
case 26 => ByteLiteral(bcr.readLong.toByte)
|
||||
case 27 => ShortLiteral(bcr.readLong.toShort)
|
||||
case 28 => CharLiteral(bcr.readLong.toChar)
|
||||
case 29 => IntLiteral(bcr.readLong.toInt)
|
||||
case 30 => LongLiteral(bcr.readLong)
|
||||
case 31 => FloatLiteral(java.lang.Float.intBitsToFloat(bcr.readLong.toInt))
|
||||
case 32 => DoubleLiteral(java.lang.Double.longBitsToDouble(bcr.readLong))
|
||||
case 33 => StringLiteral(evalS)
|
||||
case 34 => NullLiteral
|
||||
case 35 => TypeLiteral(evalT)
|
||||
case 36 => EnumLiteral(evalT)
|
||||
case 40 => AnnotationInfo(evalT, evalT, evalList.grouped(2).map(g => (g(0), g(1))).toMap)
|
||||
case 44 => ArrayLiteral(evalList)
|
||||
case _ => e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +308,15 @@ class ByteCodeReader(val bc: Bytes)
|
||||
r
|
||||
}
|
||||
|
||||
def readLong = {
|
||||
var l = 0L
|
||||
while(more) {
|
||||
l <<= 8
|
||||
l |= readByte & 0xFF
|
||||
}
|
||||
l
|
||||
}
|
||||
|
||||
def advance[A](len: Int)(r: A) = {
|
||||
if (pos + len > bc.pos + bc.len)
|
||||
throw new IllegalArgumentException("Ran off the end of bytecode")
|
||||
@@ -294,46 +350,4 @@ object ScalaSigReader
|
||||
case null => None
|
||||
case a => a.find(ann => ann.desc.equals("Lscala/reflect/ScalaSignature;"))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Was an idea for a transformer in FML
|
||||
*/
|
||||
class ScalaSigSideTransformer
|
||||
{
|
||||
def transform(ann: AnnotationNode, cnode: ClassNode, removedFields: JList[FieldNode], removedMethods: JList[MethodNode]) {
|
||||
if (removedFields.isEmpty && removedMethods.isEmpty)
|
||||
return
|
||||
|
||||
val remFields = removedFields.asScala.map(f => (f.name, f.desc.replace('$', '/')))
|
||||
val remMethods = removedMethods.asScala.map(f => (f.name, f.desc.replace('$', '/')))
|
||||
|
||||
val sig = ScalaSigReader.read(ann)
|
||||
for (e <- sig.table if e.id == 8) {
|
||||
//check and remove
|
||||
val sym: sig.MethodSymbol = sig.evalT(e.index)
|
||||
if (sym.isAccessor) {
|
||||
val fName = if (sym.name.endsWith("_$eq")) sym.name.substring(0, sym.name.length - 4) else sym.name
|
||||
if (remFields.find(t => t._1 == sym.name.trim).nonEmpty) {
|
||||
e.delete()
|
||||
val it = cnode.methods.iterator
|
||||
while (it.hasNext) {
|
||||
val m = it.next
|
||||
if (m.name == sym.name && m.desc == sym.jDesc)
|
||||
it.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sym.isMethod) {
|
||||
if (remMethods.find(t => t._1 == sym.name && t._2 == sym.jDesc).nonEmpty)
|
||||
e.delete()
|
||||
}
|
||||
else {
|
||||
//field
|
||||
if (remFields.find(t => t._1 == sym.name.trim).nonEmpty)
|
||||
e.delete()
|
||||
}
|
||||
}
|
||||
ScalaSigReader.write(sig, ann)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user