mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-14 01:14:19 +00:00
Added MicroblockGenerator, micro materials can now mix traits into the microblock class itself
Improved mixin compilation a bunch
This commit is contained in:
1 parent
a621ddbe84
commit
00e6a9bb82
17 files changed
+396
-348
No files matched your search
@@ -14,7 +14,7 @@ object CornerPlacement extends PlacementProperties
|
||||
def opposite(slot:Int, side:Int) = ((slot-7)^(1<<(side>>1)))+7
|
||||
}
|
||||
|
||||
object CornerMicroClass extends MicroblockClass
|
||||
object CornerMicroClass extends CommonMicroClass
|
||||
{
|
||||
var aBounds:Array[Cuboid6] = new Array(256)
|
||||
|
||||
@@ -32,22 +32,19 @@ object CornerMicroClass extends MicroblockClass
|
||||
}
|
||||
}
|
||||
|
||||
override def itemSlot = 7
|
||||
|
||||
def getName = "mcr_cnr"
|
||||
|
||||
def baseTrait = classOf[CornerMicroblock]
|
||||
def clientTrait = classOf[CommonMicroblockClient]
|
||||
|
||||
def create(client:Boolean, material:Int) =
|
||||
if(client)
|
||||
new CornerMicroblock(material)with CommonMicroblockClient
|
||||
else
|
||||
new CornerMicroblock(material)
|
||||
override def itemSlot = 7
|
||||
|
||||
def placementProperties = CornerPlacement
|
||||
|
||||
def getResistanceFactor = 1
|
||||
}
|
||||
|
||||
class CornerMicroblock(material$:Int = 0) extends CommonMicroblock(material$)
|
||||
trait CornerMicroblock extends CommonMicroblock
|
||||
{
|
||||
override def setShape(size: Int, slot: Int) = shape = (size<<4|(slot-7)).toByte
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ object EdgePlacement extends PlacementProperties
|
||||
}
|
||||
}
|
||||
|
||||
object EdgeMicroClass extends MicroblockClass
|
||||
object EdgeMicroClass extends CommonMicroClass
|
||||
{
|
||||
var aBounds:Array[Cuboid6] = new Array(256)
|
||||
|
||||
@@ -86,19 +86,16 @@ object EdgeMicroClass extends MicroblockClass
|
||||
override def itemSlot = 15
|
||||
|
||||
def getName = "mcr_edge"
|
||||
|
||||
def create(client:Boolean, material:Int) =
|
||||
if(client)
|
||||
new EdgeMicroblock(material) with CommonMicroblockClient
|
||||
else
|
||||
new EdgeMicroblock(material)
|
||||
|
||||
|
||||
def baseTrait = classOf[EdgeMicroblock]
|
||||
def clientTrait = classOf[CommonMicroblockClient]
|
||||
|
||||
def placementProperties = EdgePlacement
|
||||
|
||||
def getResistanceFactor = 0.5F
|
||||
}
|
||||
|
||||
class EdgeMicroblock(material$:Int = 0) extends CommonMicroblock(material$) with TEdgePart
|
||||
trait EdgeMicroblock extends CommonMicroblock with TEdgePart
|
||||
{
|
||||
override def setShape(size: Int, slot: Int) = shape = (size<<4|(slot-15)).toByte
|
||||
|
||||
@@ -109,7 +106,7 @@ class EdgeMicroblock(material$:Int = 0) extends CommonMicroblock(material$) with
|
||||
override def getSlot = getShape+15
|
||||
}
|
||||
|
||||
object PostMicroClass
|
||||
object PostMicroClass extends MicroblockClass
|
||||
{
|
||||
var aBounds:Array[Cuboid6] = new Array(256)
|
||||
|
||||
@@ -125,14 +122,9 @@ object PostMicroClass
|
||||
}
|
||||
|
||||
def getName = "mcr_post"
|
||||
|
||||
def create(client:Boolean, material:Int) =
|
||||
if(client)
|
||||
new PostMicroblock(material) with PostMicroblockClient
|
||||
else
|
||||
new PostMicroblock(material)
|
||||
|
||||
def register() = MultiPartRegistry.registerParts((_, c:Boolean) => create(c, 0), getName)
|
||||
|
||||
def baseTrait = classOf[PostMicroblock]
|
||||
def clientTrait = classOf[PostMicroblockClient]
|
||||
|
||||
def getResistanceFactor = 0.5F
|
||||
}
|
||||
@@ -214,9 +206,9 @@ trait PostMicroblockClient extends PostMicroblock with MicroblockClient
|
||||
}
|
||||
}
|
||||
|
||||
class PostMicroblock(material$:Int = 0) extends Microblock(material$) with JPartialOcclusion with TNormalOcclusion
|
||||
trait PostMicroblock extends Microblock with JPartialOcclusion with TNormalOcclusion
|
||||
{
|
||||
override def getType = PostMicroClass.getName
|
||||
def microClass = PostMicroClass
|
||||
|
||||
def getBounds = PostMicroClass.aBounds(shape)
|
||||
|
||||
@@ -224,7 +216,7 @@ class PostMicroblock(material$:Int = 0) extends Microblock(material$) with JPart
|
||||
|
||||
def getPartialOcclusionBoxes = getOcclusionBoxes
|
||||
|
||||
override def itemClassID = EdgeMicroClass.classID
|
||||
override def itemClassID = EdgeMicroClass.getClassId
|
||||
|
||||
override def occlusionTest(npart:TMultiPart): Boolean =
|
||||
{
|
||||
|
||||
@@ -22,7 +22,9 @@ object FacePlacement extends PlacementProperties
|
||||
override def sneakOpposite(slot:Int, side:Int) = slot == (side^1)
|
||||
}
|
||||
|
||||
object FaceMicroClass extends MicroblockClass
|
||||
class FaceMicroClass
|
||||
|
||||
object FaceMicroClass extends CommonMicroClass
|
||||
{
|
||||
var aBounds:Array[Cuboid6] = new Array(256)
|
||||
|
||||
@@ -37,12 +39,11 @@ object FaceMicroClass extends MicroblockClass
|
||||
}
|
||||
|
||||
def getName = "mcr_face"
|
||||
|
||||
def create(client:Boolean, material:Int) =
|
||||
if(client)
|
||||
new FaceMicroblock(material) with FaceMicroblockClient
|
||||
else
|
||||
new FaceMicroblock(material)
|
||||
|
||||
def itemSlot = 3
|
||||
|
||||
def baseTrait = classOf[FaceMicroblock]
|
||||
def clientTrait = classOf[FaceMicroblockClient]
|
||||
|
||||
def placementProperties = FacePlacement
|
||||
|
||||
@@ -64,7 +65,7 @@ trait FaceMicroblockClient extends CommonMicroblockClient
|
||||
}
|
||||
}
|
||||
|
||||
class FaceMicroblock(material$:Int = 0) extends CommonMicroblock(material$) with TFacePart
|
||||
trait FaceMicroblock extends CommonMicroblock with TFacePart
|
||||
{
|
||||
def microClass = FaceMicroClass
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import codechicken.lib.lighting.LightMatrix
|
||||
|
||||
object HollowPlacement extends PlacementProperties
|
||||
{
|
||||
|
||||
object HollowPlacementGrid extends FaceEdgeGrid(3 / 8D)
|
||||
|
||||
def microClass = HollowMicroClass
|
||||
@@ -32,7 +31,7 @@ object HollowPlacement extends PlacementProperties
|
||||
override def sneakOpposite(slot: Int, side: Int) = slot == (side ^ 1)
|
||||
}
|
||||
|
||||
object HollowMicroClass extends MicroblockClass
|
||||
object HollowMicroClass extends CommonMicroClass
|
||||
{
|
||||
var pBoxes: Array[Seq[Cuboid6]] = new Array(256)
|
||||
var occBounds: Array[Cuboid6] = new Array(256)
|
||||
@@ -54,11 +53,10 @@ object HollowMicroClass extends MicroblockClass
|
||||
|
||||
def getName = "mcr_hllw"
|
||||
|
||||
def create(client:Boolean, material:Int) =
|
||||
if(client)
|
||||
new HollowMicroblock(material) with HollowMicroblockClient
|
||||
else
|
||||
new HollowMicroblock(material)
|
||||
def baseTrait = classOf[HollowMicroblock]
|
||||
def clientTrait = classOf[HollowMicroblockClient]
|
||||
|
||||
def itemSlot = 3
|
||||
|
||||
def placementProperties = HollowPlacement
|
||||
|
||||
@@ -172,7 +170,7 @@ trait HollowMicroblockClient extends HollowMicroblock with CommonMicroblockClien
|
||||
}
|
||||
}
|
||||
|
||||
class HollowMicroblock(material$: Int = 0) extends CommonMicroblock(material$) with TFacePart with TNormalOcclusion
|
||||
trait HollowMicroblock extends CommonMicroblock with TFacePart with TNormalOcclusion
|
||||
{
|
||||
def microClass = HollowMicroClass
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.lwjgl.opengl.GL11
|
||||
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial
|
||||
import java.util.List
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import codechicken.microblock.MicroblockClassRegistry._
|
||||
import codechicken.lib.render.CCRenderState
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import codechicken.microblock.handler.MicroblockProxy
|
||||
@@ -22,6 +21,7 @@ import codechicken.lib.raytracer.RayTracer
|
||||
import codechicken.lib.vec.Vector3
|
||||
import codechicken.lib.render.TextureUtils
|
||||
import net.minecraft.util.MovingObjectPosition.MovingObjectType
|
||||
import CommonMicroClass._
|
||||
|
||||
class ItemMicroPart extends Item
|
||||
{
|
||||
@@ -31,7 +31,7 @@ class ItemMicroPart extends Item
|
||||
override def getItemStackDisplayName(stack:ItemStack):String =
|
||||
{
|
||||
val material = getMaterial(stack)
|
||||
val mcrClass = MicroblockClassRegistry.getMicroClass(stack.getItemDamage)
|
||||
val mcrClass = getMicroClass(stack.getItemDamage)
|
||||
val size = stack.getItemDamage&0xFF
|
||||
if(material == null || mcrClass == null)
|
||||
return "Unnamed"
|
||||
@@ -56,7 +56,7 @@ class ItemMicroPart extends Item
|
||||
override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, s:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean =
|
||||
{
|
||||
val material = getMaterialID(item)
|
||||
val mcrClass = MicroblockClassRegistry.getMicroClass(item.getItemDamage)
|
||||
val mcrClass = getMicroClass(item.getItemDamage)
|
||||
val size = item.getItemDamage&0xFF
|
||||
if(material < 0 || mcrClass == null)
|
||||
return false
|
||||
@@ -134,7 +134,7 @@ object ItemMicroPartRenderer extends IItemRenderer
|
||||
def renderItem(t:ItemRenderType, item:ItemStack, data:Object*)
|
||||
{
|
||||
val material = getMaterial(item)
|
||||
val mcrClass = MicroblockClassRegistry.getMicroClass(item.getItemDamage)
|
||||
val mcrClass = getMicroClass(item.getItemDamage)
|
||||
val size = item.getItemDamage&0xFF
|
||||
if(material == null || mcrClass == null)
|
||||
return
|
||||
@@ -160,7 +160,7 @@ object ItemMicroPartRenderer extends IItemRenderer
|
||||
def renderHighlight(player:EntityPlayer, stack:ItemStack, hit:MovingObjectPosition):Boolean =
|
||||
{
|
||||
val material = getMaterialID(stack)
|
||||
val mcrClass = MicroblockClassRegistry.getMicroClass(stack.getItemDamage)
|
||||
val mcrClass = getMicroClass(stack.getItemDamage)
|
||||
val size = stack.getItemDamage&0xFF
|
||||
if(material < 0 || mcrClass == null)
|
||||
return false
|
||||
|
||||
@@ -107,7 +107,7 @@ object MicroMaterialRegistry
|
||||
/**
|
||||
* Return true if a custom highlight was rendered and the default should be skipped
|
||||
*/
|
||||
def renderHighlight(player: EntityPlayer, hit: MovingObjectPosition, mcrClass: MicroblockClass, size: Int, material: Int): Boolean
|
||||
def renderHighlight(player: EntityPlayer, hit: MovingObjectPosition, mcrClass: CommonMicroClass, size: Int, material: Int): Boolean
|
||||
}
|
||||
|
||||
private val typeMap = HashMap[String, IMicroMaterial]()
|
||||
@@ -229,7 +229,7 @@ object MicroMaterialRegistry
|
||||
|
||||
def getIdMap = idMap
|
||||
|
||||
def renderHighlight(player: EntityPlayer, hit: MovingObjectPosition, mcrClass: MicroblockClass, size: Int, material: Int): Boolean = {
|
||||
def renderHighlight(player: EntityPlayer, hit: MovingObjectPosition, mcrClass: CommonMicroClass, size: Int, material: Int): Boolean = {
|
||||
val overridden = highlightRenderers.find(_.renderHighlight(player, hit, mcrClass, size, material))
|
||||
if (overridden.isDefined)
|
||||
return true
|
||||
|
||||
+77
-129
@@ -31,48 +31,88 @@ import net.minecraft.init.Blocks
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import codechicken.lib.render.BlockRenderer.BlockFace
|
||||
|
||||
object MicroblockRender
|
||||
abstract class Microblock(var material:Int = 0) extends TCuboidPart
|
||||
{
|
||||
def renderHighlight(player:EntityPlayer, hit:MovingObjectPosition, mcrClass:MicroblockClass, size:Int, material:Int)
|
||||
{
|
||||
mcrClass.placementProperties.placementGrid.render(new Vector3(hit.hitVec), hit.sideHit)
|
||||
var shape:Byte = 0
|
||||
|
||||
val placement = MicroblockPlacement(player, hit, size, material, !player.capabilities.isCreativeMode, mcrClass.placementProperties)
|
||||
if(placement == null)
|
||||
return
|
||||
val pos = placement.pos
|
||||
val part = placement.part.asInstanceOf[MicroblockClient]
|
||||
def microClass:MicroblockClass
|
||||
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslated(pos.x+0.5, pos.y+0.5, pos.z+0.5)
|
||||
GL11.glScaled(1.002, 1.002, 1.002)
|
||||
GL11.glTranslated(-0.5, -0.5, -0.5)
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glDepthMask(false)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
def getType = microClass.getName
|
||||
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.alphaOverride = 80
|
||||
CCRenderState.useNormals = true
|
||||
CCRenderState.startDrawing()
|
||||
part.render(Vector3.zero, -1)
|
||||
CCRenderState.draw()
|
||||
|
||||
GL11.glDisable(GL11.GL_BLEND)
|
||||
GL11.glDepthMask(true)
|
||||
GL11.glPopMatrix()
|
||||
override def getStrength(hit:MovingObjectPosition, player:EntityPlayer) = getIMaterial match {
|
||||
case null => super.getStrength(hit, player)
|
||||
case mat => mat.getStrength(player)
|
||||
}
|
||||
|
||||
val face = new BlockFace()
|
||||
def renderCuboid(pos:Vector3, mat:IMicroMaterial, pass:Int, c:Cuboid6, faces:Int) {
|
||||
CCRenderState.setModel(face)
|
||||
for(s <- 0 until 6 if (faces & 1<<s) == 0) {
|
||||
face.loadCuboidFace(c, s)
|
||||
mat.renderMicroFace(pos, pass, c)
|
||||
override def doesTick = false
|
||||
|
||||
def getSize = shape>>4
|
||||
|
||||
def getShape = shape&0xF
|
||||
|
||||
def setShape(size:Int, slot:Int) = shape = (size<<4|slot).toByte
|
||||
|
||||
def getMaterial = material
|
||||
|
||||
def getIMaterial = MicroMaterialRegistry.getMaterial(material)
|
||||
|
||||
def itemClassID:Int
|
||||
|
||||
override def getDrops = {
|
||||
var size = getSize
|
||||
val items = ListBuffer[ItemStack]()
|
||||
for(s <- Seq(4, 2, 1))
|
||||
{
|
||||
val m = size/s
|
||||
size-=m*s
|
||||
if(m > 0)
|
||||
items+=ItemMicroPart.create(m, s|itemClassID<<8, MicroMaterialRegistry.materialName(material))
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
override def pickItem(hit:MovingObjectPosition):ItemStack = {
|
||||
val size = getSize
|
||||
for(s <- Seq(4, 2, 1))
|
||||
if(size%s == 0 && size/s >= 1)
|
||||
return ItemMicroPart.create(s|itemClassID<<8, MicroMaterialRegistry.materialName(material))
|
||||
|
||||
return null//unreachable
|
||||
}
|
||||
|
||||
override def writeDesc(packet:MCDataOutput) {
|
||||
writeMaterialID(packet, material)
|
||||
packet.writeByte(shape)
|
||||
}
|
||||
|
||||
override def readDesc(packet:MCDataInput) {
|
||||
shape = packet.readByte
|
||||
}
|
||||
|
||||
def sendShapeUpdate() {
|
||||
getWriteStream.writeByte(shape)
|
||||
}
|
||||
|
||||
override def read(packet:MCDataInput) {
|
||||
super.read(packet)
|
||||
tile.notifyPartChange(this)
|
||||
}
|
||||
|
||||
override def save(tag:NBTTagCompound) {
|
||||
tag.setByte("shape", shape)
|
||||
tag.setString("material", materialName(material))
|
||||
}
|
||||
|
||||
override def load(tag:NBTTagCompound) {
|
||||
shape = tag.getByte("shape")
|
||||
material = materialID(tag.getString("material"))
|
||||
}
|
||||
|
||||
def isTransparent = getIMaterial.isTransparent
|
||||
|
||||
override def getLightValue = getIMaterial.getLightValue
|
||||
|
||||
override def explosionResistance(entity:Entity) = getIMaterial.explosionResistance(entity) * microClass.getResistanceFactor
|
||||
}
|
||||
|
||||
trait MicroblockClient extends Microblock with TIconHitEffects with IMicroMaterialRender
|
||||
@@ -96,92 +136,6 @@ trait MicroblockClient extends Microblock with TIconHitEffects with IMicroMateri
|
||||
override def getRenderBounds = getBounds
|
||||
}
|
||||
|
||||
abstract class Microblock(var material:Int = 0) extends TCuboidPart
|
||||
{
|
||||
var shape:Byte = 0
|
||||
|
||||
override def getStrength(hit:MovingObjectPosition, player:EntityPlayer) = getIMaterial match {
|
||||
case null => super.getStrength(hit, player)
|
||||
case mat => mat.getStrength(player)
|
||||
}
|
||||
|
||||
override def doesTick = false
|
||||
|
||||
def getSize = shape>>4
|
||||
|
||||
def getShape = shape&0xF
|
||||
|
||||
def setShape(size:Int, slot:Int) = shape = (size<<4|slot).toByte
|
||||
|
||||
def getMaterial = material
|
||||
|
||||
def getIMaterial = MicroMaterialRegistry.getMaterial(material)
|
||||
|
||||
def itemClassID:Int = -1
|
||||
|
||||
override def getDrops =
|
||||
{
|
||||
var size = getSize
|
||||
val items = ListBuffer[ItemStack]()
|
||||
for(s <- Seq(4, 2, 1))
|
||||
{
|
||||
val m = size/s
|
||||
size-=m*s
|
||||
if(m > 0)
|
||||
items+=ItemMicroPart.create(m, s|itemClassID<<8, MicroMaterialRegistry.materialName(material))
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
override def pickItem(hit:MovingObjectPosition):ItemStack =
|
||||
{
|
||||
val size = getSize
|
||||
for(s <- Seq(4, 2, 1))
|
||||
if(size%s == 0 && size/s >= 1)
|
||||
return ItemMicroPart.create(s|itemClassID<<8, MicroMaterialRegistry.materialName(material))
|
||||
return null//unreachable
|
||||
}
|
||||
|
||||
override def writeDesc(packet:MCDataOutput)
|
||||
{
|
||||
packet.writeByte(shape)
|
||||
writeMaterialID(packet, material)
|
||||
}
|
||||
|
||||
override def readDesc(packet:MCDataInput)
|
||||
{
|
||||
shape = packet.readByte
|
||||
material = readMaterialID(packet)
|
||||
}
|
||||
|
||||
override def read(packet:MCDataInput)
|
||||
{
|
||||
readDesc(packet)
|
||||
tile.notifyPartChange(this)
|
||||
tile.markRender()
|
||||
}
|
||||
|
||||
override def save(tag:NBTTagCompound)
|
||||
{
|
||||
tag.setByte("shape", shape)
|
||||
tag.setString("material", materialName(material))
|
||||
}
|
||||
|
||||
override def load(tag:NBTTagCompound)
|
||||
{
|
||||
shape = tag.getByte("shape")
|
||||
material = materialID(tag.getString("material"))
|
||||
}
|
||||
|
||||
def isTransparent = getIMaterial.isTransparent
|
||||
|
||||
override def getLightValue = getIMaterial.getLightValue
|
||||
|
||||
def getResistanceFactor:Float
|
||||
|
||||
override def explosionResistance(entity:Entity) = getIMaterial.explosionResistance(entity)*getResistanceFactor
|
||||
}
|
||||
|
||||
trait CommonMicroblockClient extends CommonMicroblock with MicroblockClient with TMicroOcclusionClient
|
||||
{
|
||||
def render(pos:Vector3, pass:Int) {
|
||||
@@ -192,19 +146,13 @@ trait CommonMicroblockClient extends CommonMicroblock with MicroblockClient with
|
||||
}
|
||||
}
|
||||
|
||||
abstract class CommonMicroblock(material$:Int) extends Microblock(material$) with JPartialOcclusion with TMicroOcclusion with TSlottedPart
|
||||
trait CommonMicroblock extends Microblock with JPartialOcclusion with TMicroOcclusion with TSlottedPart
|
||||
{
|
||||
def microClass:MicroblockClass
|
||||
|
||||
def getType = microClass.getName
|
||||
def microClass:CommonMicroClass
|
||||
|
||||
def getSlot = getShape
|
||||
|
||||
def getSlotMask = 1<<getSlot
|
||||
|
||||
def getPartialOcclusionBoxes = Seq(getBounds)
|
||||
|
||||
override def itemClassID = microClass.classID
|
||||
|
||||
def getResistanceFactor = microClass.getResistanceFactor
|
||||
override def itemClassID = microClass.getClassId
|
||||
}
|
||||
@@ -1,18 +1,57 @@
|
||||
package codechicken.microblock
|
||||
|
||||
trait MicroblockClass
|
||||
{
|
||||
var classID:Int = _
|
||||
|
||||
def itemSlot = 3
|
||||
|
||||
def getName:String
|
||||
|
||||
def create(client:Boolean, material:Int):CommonMicroblock
|
||||
|
||||
def placementProperties:PlacementProperties
|
||||
|
||||
def register(id:Int) = MicroblockClassRegistry.registerMicroClass(this, id)
|
||||
import codechicken.multipart.{TMultiPart, MultiPartRegistry}
|
||||
import codechicken.multipart.MultiPartRegistry.IPartFactory2
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import codechicken.lib.data.MCDataInput
|
||||
|
||||
abstract class MicroblockClass extends IPartFactory2
|
||||
{
|
||||
def getName:String
|
||||
def baseTrait:Class[_ <: Microblock]
|
||||
def clientTrait:Class[_ <: MicroblockClient]
|
||||
def getResistanceFactor:Float
|
||||
|
||||
val baseTraitId = MicroblockGenerator.registerTrait(baseTrait)
|
||||
val clientTraitId = MicroblockGenerator.registerTrait(clientTrait)
|
||||
|
||||
def register() {
|
||||
MultiPartRegistry.registerParts(this, getName)
|
||||
}
|
||||
|
||||
def create(client:Boolean, material:Int) = MicroblockGenerator.create(this, material, client)
|
||||
override def createPart(name: String, packet: MCDataInput) = create(true, MicroMaterialRegistry.readMaterialID(packet))
|
||||
override def createPart(name: String, nbt: NBTTagCompound) = create(false, MicroMaterialRegistry.materialID(nbt.getString("material")))
|
||||
}
|
||||
|
||||
/**
|
||||
* Microblocks with corresponding items
|
||||
*/
|
||||
abstract class CommonMicroClass extends MicroblockClass
|
||||
{
|
||||
private var classId:Int = _
|
||||
|
||||
def getClassId = classId
|
||||
def itemSlot:Int
|
||||
def placementProperties:PlacementProperties
|
||||
|
||||
def register(id:Int) {
|
||||
register()
|
||||
classId = id
|
||||
CommonMicroClass.registerMicroClass(this, id)
|
||||
}
|
||||
}
|
||||
|
||||
object CommonMicroClass
|
||||
{
|
||||
val classes = new Array[CommonMicroClass](256)
|
||||
|
||||
def getMicroClass(modelId:Int) = classes(modelId>>8)
|
||||
|
||||
def registerMicroClass(mcrClass:CommonMicroClass, id:Int) {
|
||||
if(classes(id) != null)
|
||||
throw new IllegalArgumentException("Microblock class id "+id+" is already taken by "+classes(id).getName+" when adding "+mcrClass.getName)
|
||||
|
||||
classes(id) = mcrClass
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package codechicken.microblock
|
||||
|
||||
import codechicken.multipart.MultiPartRegistry
|
||||
|
||||
object MicroblockClassRegistry
|
||||
{
|
||||
val classes = new Array[MicroblockClass](256)
|
||||
|
||||
def getMicroClass(modelId:Int) = classes(modelId>>8)
|
||||
|
||||
def registerMicroClass(mcrClass:MicroblockClass, id:Int)
|
||||
{
|
||||
if(classes(id) != null)
|
||||
throw new IllegalArgumentException("Microblock class id "+id+" is already taken by "+classes(id).getName+" when adding "+mcrClass.getName)
|
||||
|
||||
classes(id) = mcrClass
|
||||
mcrClass.classID = id
|
||||
MultiPartRegistry.registerParts((_, c:Boolean) => mcrClass.create(c, 0), mcrClass.getName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package codechicken.microblock
|
||||
|
||||
import codechicken.multipart.asm.ASMMixinFactory
|
||||
import java.util.BitSet
|
||||
|
||||
object MicroblockGenerator extends ASMMixinFactory(classOf[Microblock], classOf[Int])
|
||||
{
|
||||
trait IGeneratedMaterial
|
||||
{
|
||||
def addTraits(traits:BitSet, mcrClass:MicroblockClass, client:Boolean)
|
||||
}
|
||||
|
||||
//scratch bitset
|
||||
private val bitset = new BitSet
|
||||
|
||||
def create(mcrClass: MicroblockClass, material: Int, client: Boolean) = {
|
||||
bitset.clear()
|
||||
bitset.set(mcrClass.baseTraitId)
|
||||
if(client) bitset.set(mcrClass.clientTraitId)
|
||||
|
||||
MicroMaterialRegistry.getMaterial(material) match {
|
||||
case genMat:IGeneratedMaterial => genMat.addTraits(bitset, mcrClass, client)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
construct(bitset, material:Integer)
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class ExpandingPlacement($pos:BlockCoord, $part:Microblock, opart:Microblock) ex
|
||||
{
|
||||
opart.shape = part.shape
|
||||
opart.tile.notifyPartChange(opart)
|
||||
opart.sendDescUpdate()
|
||||
opart.sendShapeUpdate()
|
||||
}
|
||||
|
||||
def consume(world:World, player:EntityPlayer, item:ItemStack)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package codechicken.microblock
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.util.MovingObjectPosition
|
||||
import codechicken.lib.vec.{Cuboid6, Vector3}
|
||||
import org.lwjgl.opengl.GL11._
|
||||
import codechicken.lib.render.{CCRenderState, TextureUtils}
|
||||
import codechicken.lib.render.BlockRenderer.BlockFace
|
||||
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial
|
||||
|
||||
object MicroblockRender
|
||||
{
|
||||
def renderHighlight(player:EntityPlayer, hit:MovingObjectPosition, mcrClass:CommonMicroClass, size:Int, material:Int)
|
||||
{
|
||||
mcrClass.placementProperties.placementGrid.render(new Vector3(hit.hitVec), hit.sideHit)
|
||||
|
||||
val placement = MicroblockPlacement(player, hit, size, material, !player.capabilities.isCreativeMode, mcrClass.placementProperties)
|
||||
if(placement == null)
|
||||
return
|
||||
val pos = placement.pos
|
||||
val part = placement.part.asInstanceOf[MicroblockClient]
|
||||
|
||||
glPushMatrix()
|
||||
glTranslated(pos.x+0.5, pos.y+0.5, pos.z+0.5)
|
||||
glScaled(1.002, 1.002, 1.002)
|
||||
glTranslated(-0.5, -0.5, -0.5)
|
||||
|
||||
glEnable(GL_BLEND)
|
||||
glDepthMask(false)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.alphaOverride = 80
|
||||
CCRenderState.useNormals = true
|
||||
CCRenderState.startDrawing()
|
||||
part.render(Vector3.zero, -1)
|
||||
CCRenderState.draw()
|
||||
|
||||
glDisable(GL_BLEND)
|
||||
glDepthMask(true)
|
||||
glPopMatrix()
|
||||
}
|
||||
|
||||
val face = new BlockFace()
|
||||
def renderCuboid(pos:Vector3, mat:IMicroMaterial, pass:Int, c:Cuboid6, faces:Int) {
|
||||
CCRenderState.setModel(face)
|
||||
for(s <- 0 until 6 if (faces & 1<<s) == 0) {
|
||||
face.loadCuboidFace(c, s)
|
||||
mat.renderMicroFace(pos, pass, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ object MultipartGenerator
|
||||
private val clientTraitId = MultipartMixinFactory.registerTrait(classOf[TileMultipartClient])
|
||||
|
||||
//scratch bitset
|
||||
private val bitset = new BitSet()
|
||||
private val bitset = new BitSet
|
||||
|
||||
private def partTraitMap(client:Boolean) = if(client) partTraitMap_c else partTraitMap_s
|
||||
private def interfaceTraitMap(client:Boolean) = if(client) interfaceTraitMap_c else interfaceTraitMap_s
|
||||
|
||||
@@ -49,9 +49,6 @@ object DebugPrinter
|
||||
|
||||
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]])
|
||||
@@ -79,7 +76,7 @@ object ASMMixinCompiler
|
||||
|
||||
def getBytes(name: String): Array[Byte] = {
|
||||
val jName = name.replace('/', '.')
|
||||
if (jName.equals("java.lang.Object"))
|
||||
if (jName == "java.lang.Object")
|
||||
return null
|
||||
|
||||
def useTransformers = f_transformerExceptions.get(cl).asInstanceOf[JSet[String]]
|
||||
@@ -108,13 +105,6 @@ object ASMMixinCompiler
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -137,6 +127,7 @@ object ASMMixinCompiler
|
||||
def owner: ClassInfo
|
||||
def name: String
|
||||
def desc: String
|
||||
def exceptions: Array[String]
|
||||
def isPrivate: Boolean
|
||||
def isAbstract: Boolean
|
||||
|
||||
@@ -147,15 +138,19 @@ object ASMMixinCompiler
|
||||
{
|
||||
def name: String
|
||||
def superClass: Option[ClassInfo]
|
||||
def interfaces: Seq[ClassInfo]
|
||||
def methods: Seq[MethodInfo]
|
||||
def interfaces: Iterable[ClassInfo]
|
||||
def methods: Iterable[MethodInfo]
|
||||
|
||||
override def toString = getClass.getSimpleName+"("+name+")"
|
||||
override def toString = getClass.getName.replaceAll(".+[\\$\\.]", "")+"("+name+")"
|
||||
|
||||
def getMethod(name:String, desc:String) = methods.find(m => m.name == name && m.desc == desc)
|
||||
def findMethod(name:String, desc:String, f:(MethodInfo)=>Boolean):Option[MethodInfo] =
|
||||
getMethod(name, desc).filter(f) orElse (superClass ++ interfaces).view.flatMap(_.findMethod(name, desc, f)).headOption
|
||||
def findPublicImpl(name:String, desc:String) = findMethod(name, desc, m => !m.isAbstract && !m.isPrivate)
|
||||
def parentMethods = (superClass ++ interfaces).view.flatMap(_.allMethods)
|
||||
def allMethods:Iterable[MethodInfo] = methods ++ parentMethods
|
||||
def findPublicImpl(name:String, desc:String) = allMethods.find(m => m.name == name && m.desc == desc && !m.isAbstract && !m.isPrivate)
|
||||
|
||||
def isScala = false
|
||||
def isTrait = false
|
||||
def isObject = false
|
||||
def moduleName = name
|
||||
}
|
||||
|
||||
private val infoCache = MMap[String, ClassInfo]()
|
||||
@@ -174,6 +169,7 @@ object ASMMixinCompiler
|
||||
def owner = ReflectionClassInfo.this
|
||||
def name = method.getName
|
||||
def desc = getType(method).getDescriptor
|
||||
def exceptions = method.getExceptionTypes.map(_.nodeName)
|
||||
def isPrivate = Modifier.isPrivate(method.getModifiers)
|
||||
def isAbstract = Modifier.isAbstract(method.getModifiers)
|
||||
}
|
||||
@@ -184,13 +180,14 @@ object ASMMixinCompiler
|
||||
def methods = clazz.getMethods.map(ReflectionMethodInfo(_))
|
||||
}
|
||||
|
||||
class ClassNodeInfo(cnode: ClassNode) extends ClassInfo
|
||||
class ClassNodeInfo(val cnode: ClassNode) extends ClassInfo
|
||||
{
|
||||
case class MethodNodeInfoSource(mnode: MethodNode) extends MethodInfo
|
||||
{
|
||||
def owner = ClassNodeInfo.this
|
||||
def name = mnode.name
|
||||
def desc = mnode.desc
|
||||
def exceptions = Array(mnode.exceptions:_*)
|
||||
def isPrivate = (mnode.access & ACC_PRIVATE) != 0
|
||||
def isAbstract = (mnode.access & ACC_ABSTRACT) != 0
|
||||
}
|
||||
@@ -201,13 +198,16 @@ object ASMMixinCompiler
|
||||
def methods = cnode.methods.map(MethodNodeInfoSource)
|
||||
}
|
||||
|
||||
class ScalaClassInfo(cnode: ClassNode) extends ClassNodeInfo(cnode)
|
||||
class ScalaClassInfo(cnode$: ClassNode) extends ClassNodeInfo(cnode$)
|
||||
{
|
||||
val sig = ScalaSigReader.read(ScalaSigReader.ann(cnode).get)
|
||||
val csym = sig.evalT(0): ClassSymbol
|
||||
|
||||
override def superClass = Some(csym.jParent(sig))
|
||||
override def interfaces = csym.jInterfaces(sig).map(getClassInfo)
|
||||
override def isScala = true
|
||||
|
||||
override def isTrait = csym.isTrait
|
||||
}
|
||||
|
||||
private[ASMMixinCompiler] def obtainInfo(name: String): ClassInfo = name match {
|
||||
@@ -217,12 +217,14 @@ object ASMMixinCompiler
|
||||
case null => null
|
||||
case c => new ReflectionClassInfo(c)
|
||||
}
|
||||
case v if isScala(v) => new ScalaClassInfo(v)
|
||||
case v if ScalaSigReader.ann(v).isDefined => new ScalaClassInfo(v)
|
||||
case v => new ClassNodeInfo(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import StackAnalyser.width
|
||||
|
||||
def finishBridgeCall(mv: MethodVisitor, mvdesc: String, opcode: Int, owner: String, name: String, desc: String) {
|
||||
val args = getArgumentTypes(mvdesc)
|
||||
val ret = getReturnType(mvdesc)
|
||||
@@ -249,20 +251,22 @@ object ASMMixinCompiler
|
||||
val startTime = System.currentTimeMillis
|
||||
|
||||
val baseTraits = traits.map(mixinMap)
|
||||
val traitInfos = baseTraits.flatMap(_.linearise).distinct
|
||||
val parentInfo = getClassInfo(superClass)
|
||||
val mixinInfos = baseTraits.flatMap(_.linearise).distinct
|
||||
val baseInfo = getClassInfo(superClass)
|
||||
val traitInfos = mixinInfos.map(i => getClassInfo(i.name))
|
||||
|
||||
val cnode = new ClassNode()
|
||||
//implements list
|
||||
cnode.visit(V1_6, ACC_PUBLIC, name, null, superClass, baseTraits.map(_.name).toArray[String])
|
||||
|
||||
val minit = cnode.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)
|
||||
minit.visitVarInsn(ALOAD, 0)
|
||||
minit.visitMethodInsn(INVOKESPECIAL, cnode.superName, "<init>", "()V", false)
|
||||
val cinit = baseInfo.methods.find(_.name == "<init>").get
|
||||
val minit = cnode.visitMethod(ACC_PUBLIC, "<init>", cinit.desc, null, null).asInstanceOf[MethodNode]
|
||||
writeBridge(minit, cinit.desc, INVOKESPECIAL, superClass, "<init>", cinit.desc)
|
||||
minit.instructions.remove(minit.instructions.getLast)//remove the RETURN from writeBridge
|
||||
|
||||
val prevInfos = MList[MixinInfo]()
|
||||
|
||||
traitInfos.foreach { t =>
|
||||
mixinInfos.foreach { t =>
|
||||
minit.visitVarInsn(ALOAD, 0)
|
||||
minit.visitMethodInsn(INVOKESTATIC, t.tname, "$init$", "(L" + t.name + ";)V", false)
|
||||
|
||||
@@ -288,10 +292,10 @@ object ASMMixinCompiler
|
||||
val (name, desc) = seperateDesc(s)
|
||||
val mv = cnode.visitMethod(ACC_PUBLIC, t.name.replace('/', '$') + "$$super$" + name, desc, null, null).asInstanceOf[MethodNode]
|
||||
|
||||
prevInfos.reverse.find(t => t.supers.contains(s)) match {
|
||||
prevInfos.reverse.find(_.methods.exists(m => m.name == name && m.desc == desc)) match {
|
||||
//each super goes to the one before
|
||||
case Some(st) => writeStaticBridge(mv, name, st)
|
||||
case None => writeBridge(mv, desc, INVOKESPECIAL, parentInfo.findPublicImpl(name, desc).get.owner.name, name, desc)
|
||||
case None => writeBridge(mv, desc, INVOKESPECIAL, baseInfo.findPublicImpl(name, desc).get.owner.name, name, desc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,10 +303,10 @@ object ASMMixinCompiler
|
||||
}
|
||||
|
||||
val methodSigs = MSet[String]()
|
||||
traitInfos.reverse.foreach { t => //last trait gets first pick on methods
|
||||
mixinInfos.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]
|
||||
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
|
||||
}
|
||||
@@ -310,11 +314,27 @@ object ASMMixinCompiler
|
||||
}
|
||||
|
||||
minit.visitInsn(RETURN)
|
||||
minit.visitMaxs(1, 1)
|
||||
|
||||
val c = define(cnode.name, createBytes(cnode, 0))
|
||||
//generate synthetic bridge methods for covariant return types
|
||||
def allParents(info:ClassInfo):Iterable[ClassInfo] = info +: (info.superClass ++ info.interfaces).toSeq.flatMap(allParents)
|
||||
val allParentInfos = (baseInfo +: traitInfos).flatMap(allParents).distinct
|
||||
val allParentMethods = allParentInfos.flatMap(_.methods)
|
||||
methodSigs.seq.foreach { nameDesc =>
|
||||
val (name, desc) = seperateDesc(nameDesc)
|
||||
val pDesc = desc.substring(0, desc.lastIndexOf(')')+1)
|
||||
|
||||
DebugPrinter.logger.debug("Generation ["+superClass+" with "+traits.mkString(", ")+"] took: "+(System.currentTimeMillis-startTime))
|
||||
allParentMethods.filter(m => m.name == name && m.desc.startsWith(pDesc)).foreach { m =>
|
||||
if(!methodSigs(m.name+m.desc)) {
|
||||
val mv = cnode.visitMethod(ACC_PUBLIC | ACC_SYNTHETIC | ACC_BRIDGE, m.name, m.desc, null, m.exceptions).asInstanceOf[MethodNode]
|
||||
writeBridge(mv, mv.desc, INVOKEVIRTUAL, cnode.name, name, desc)
|
||||
methodSigs += m.name + m.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val c = define(name, createBytes(cnode, 0))
|
||||
|
||||
DebugPrinter.logger.debug("Generation ["+superClass+" with "+traits.mkString(", ")+"] took "+(System.currentTimeMillis-startTime)+"ms")
|
||||
c
|
||||
}
|
||||
|
||||
@@ -347,7 +367,10 @@ object ASMMixinCompiler
|
||||
getClassInfo(stack.owner.getInternalName).superClass.flatMap(_.findPublicImpl(methodName, minsn.desc))
|
||||
}
|
||||
|
||||
def getAndRegisterParentTraits(cnode: ClassNode) = cnode.interfaces.map(classNode).filter(i => isScala(i) && isTrait(i)).map(registerScalaTrait)
|
||||
def getAndRegisterParentTraits(cnode: ClassNode) = cnode.interfaces.map(getClassInfo).collect{
|
||||
case i: ClassInfo.ScalaClassInfo if i.isTrait && !i.csym.isInterface =>
|
||||
registerScalaTrait(i.cnode)
|
||||
}
|
||||
|
||||
def registerJavaTrait(cnode: ClassNode) {
|
||||
if ((cnode.access & ACC_INTERFACE) != 0)
|
||||
@@ -427,7 +450,7 @@ object ASMMixinCompiler
|
||||
if (getSuper(minsn, stack).isDefined)
|
||||
replace(superInsn(minsn))
|
||||
case INVOKEVIRTUAL =>
|
||||
if (minsn.owner.equals(cnode.name)) {
|
||||
if (minsn.owner == cnode.name) {
|
||||
if (methodSigs.contains(minsn.name + minsn.desc)) {//call the interface method
|
||||
replace(new MethodInsnNode(INVOKEINTERFACE, minsn.owner, minsn.name, minsn.desc, true))
|
||||
} else {
|
||||
@@ -448,11 +471,11 @@ object ASMMixinCompiler
|
||||
}
|
||||
|
||||
def convertMethod(mnode: MethodNode) {
|
||||
if (mnode.name.equals("<clinit>"))
|
||||
if (mnode.name == "<clinit>")
|
||||
throw new IllegalArgumentException("Static initialisers are not permitted " + cnode.name + " as a mixin trait")
|
||||
|
||||
if (mnode.name.equals("<init>")) {
|
||||
if (!mnode.desc.equals("()V"))
|
||||
if (mnode.name == "<init>") {
|
||||
if (mnode.desc != "()V")
|
||||
throw new IllegalArgumentException("Constructor arguments are not permitted " + cnode.name + " as a mixin trait")
|
||||
|
||||
val mv = staticClone(mnode, "$init$", ACC_PUBLIC)
|
||||
@@ -504,30 +527,29 @@ object ASMMixinCompiler
|
||||
val methods = MList[MethodNode]()
|
||||
val supers = MList[String]()
|
||||
|
||||
val sig = ScalaSigReader.read(ScalaSigReader.ann(cnode).get)
|
||||
val csym: ClassSymbol = sig.evalT(0)
|
||||
val info = getClassInfo(cnode).asInstanceOf[ClassInfo.ScalaClassInfo]
|
||||
val sig = info.sig
|
||||
val csym = info.csym
|
||||
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)) {}
|
||||
if (sym.isParam || sym.owner != csym) {}
|
||||
else if (sym.isAccessor) {
|
||||
fieldAccessors.put(sym.name, sym)
|
||||
}
|
||||
else if (sym.isMethod) {
|
||||
val desc = sym.jDesc(sig)
|
||||
if (sym.name.contains("super$")) {
|
||||
if (sym.name.startsWith("super$"))
|
||||
supers += sym.name.substring(6) + desc
|
||||
}
|
||||
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 mixin trait: " + map + " found in scala signature but not in class file. Most likely an obfuscation issue.")
|
||||
methods += method
|
||||
}
|
||||
else if (!sym.isPrivate && !sym.isDeferred && sym.name != "$init$")
|
||||
methods += (cnode.methods.find(m => m.name == sym.name && m.desc == desc) match {
|
||||
case Some(m) => m
|
||||
case None => throw new IllegalArgumentException("Unable to add mixin trait "+cnode.name+": " +
|
||||
sym.name + desc + " found in scala signature but not in class file. Most likely an obfuscation issue.")
|
||||
})
|
||||
}
|
||||
else {
|
||||
fields += FieldMixin(sym.name.trim, getReturnType(sym.jDesc(sig)).getDescriptor,
|
||||
@@ -536,8 +558,8 @@ object ASMMixinCompiler
|
||||
}
|
||||
}
|
||||
|
||||
val info = MixinInfo(cnode.name, csym.jParent(sig), parentTraits, fields, methods, supers)
|
||||
mixinMap.put(cnode.name, info)
|
||||
info
|
||||
val mixin = MixinInfo(cnode.name, csym.jParent(sig), parentTraits, fields, methods, supers)
|
||||
mixinMap.put(cnode.name, mixin)
|
||||
mixin
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,12 @@ class ASMMixinFactory[T](val baseType:Class[T], private val paramTypes:Class[_]*
|
||||
case None =>
|
||||
}
|
||||
|
||||
def getParents(info:ClassInfo):Seq[ClassInfo] = info.superClass.toSeq.flatMap(i => i +: getParents(i))
|
||||
if(!getParents(cnode).map(_.name).contains(baseType.nodeName))
|
||||
val info = getClassInfo(cnode)
|
||||
def checkParent(info:ClassInfo):Boolean = info.superClass.exists(i => i.name == baseType.nodeName || checkParent(i))
|
||||
if(!checkParent(info))
|
||||
throw new IllegalArgumentException("Mixin trait "+s_trait+" must extend "+baseType.nodeName)
|
||||
|
||||
if(isScala(cnode) && isTrait(cnode)) {
|
||||
if(info.isTrait) {
|
||||
registerScalaTrait(cnode)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -33,8 +33,9 @@ object ScalaSignature
|
||||
def isPrivate = hasFlag(0x00000004)
|
||||
def isProtected = hasFlag(0x00000008)
|
||||
def isAbstract = hasFlag(0x00000080)
|
||||
def isInterface = hasFlag(0x00000800)
|
||||
def isDeferred = hasFlag(0x00000100)//abstract for methods
|
||||
def isMethod = hasFlag(0x00000200)
|
||||
def isInterface = hasFlag(0x00000800)
|
||||
def isParam = hasFlag(0x00002000)
|
||||
def isStatic = hasFlag(0x00800000)
|
||||
def isTrait = hasFlag(0x02000000)
|
||||
@@ -47,17 +48,25 @@ object ScalaSignature
|
||||
def flags:Int
|
||||
def hasFlag(flag:Int) = (flags&flag) != 0
|
||||
}
|
||||
|
||||
case class ClassSymbol(name:String, owner:SymbolRef, flags:Int, info:Int) extends SymbolRef
|
||||
|
||||
trait ClassSymbolRef extends SymbolRef
|
||||
{
|
||||
override def toString = "ClassSymbol("+name+","+owner+","+flags.toHexString+","+info+")"
|
||||
def name:String
|
||||
def owner:SymbolRef
|
||||
def flags:Int
|
||||
def info:Int
|
||||
|
||||
def full = owner.full+"."+name
|
||||
|
||||
override def toString = getClass.getName+"("+name+","+owner+","+flags.toHexString+","+info+")"
|
||||
|
||||
def info(sig:ScalaSignature):ClassType = sig.evalT(info)
|
||||
def jParent(sig:ScalaSignature) = info(sig).parent.jName
|
||||
def jInterfaces(sig:ScalaSignature) = info(sig).interfaces.map(_.jName)
|
||||
}
|
||||
|
||||
case class ClassSymbol(name:String, owner:SymbolRef, flags:Int, info:Int) extends ClassSymbolRef
|
||||
case class ObjectSymbol(name:String, owner:SymbolRef, flags:Int, info:Int) extends ClassSymbolRef
|
||||
|
||||
case class MethodSymbol(name:String, owner:SymbolRef, flags:Int, info:Int) extends SymbolRef
|
||||
{
|
||||
override def toString = "MethodSymbol("+name+","+owner+","+flags.toHexString+","+info+")"
|
||||
@@ -102,13 +111,15 @@ object ScalaSignature
|
||||
|
||||
trait TypeRef
|
||||
{
|
||||
def name:String
|
||||
def sym:SymbolRef
|
||||
def name = sym.full
|
||||
|
||||
def jName = name.replace('.', '/') match {
|
||||
case "scala/AnyRef" => "java/lang/Object"
|
||||
case "scala/AnyRef" | "scala/Any" => "java/lang/Object"
|
||||
case s => s
|
||||
}
|
||||
def jDesc:String = name match
|
||||
{
|
||||
|
||||
def jDesc = name match {
|
||||
case "scala.Array" => null
|
||||
case "scala.Long" => "J"
|
||||
case "scala.Int" => "I"
|
||||
@@ -128,36 +139,30 @@ object ScalaSignature
|
||||
|
||||
def returnType = this
|
||||
|
||||
def name = sym.full
|
||||
|
||||
override def jDesc = name match
|
||||
{
|
||||
override def jDesc = name match {
|
||||
case "scala.Array" => "["+typArgs(0).jDesc
|
||||
case _ => super.jDesc
|
||||
}
|
||||
}
|
||||
|
||||
case class ThisType(sym:SymbolRef) extends TypeRef
|
||||
{
|
||||
def name = sym.full
|
||||
}
|
||||
|
||||
|
||||
case class SingleType(owner:TypeRef, sym:SymbolRef) extends TypeRef
|
||||
{
|
||||
def name = sym.full
|
||||
override def jName = super.jName+"$"
|
||||
}
|
||||
|
||||
|
||||
case object NoType extends TypeRef
|
||||
{
|
||||
def name = "<no type>"
|
||||
def sym = null
|
||||
override def name = "<no type>"
|
||||
}
|
||||
|
||||
class SigEntry(val start:Int, val bytes:Bytes)
|
||||
{
|
||||
def id = bytes.bytes(start)
|
||||
|
||||
def delete()
|
||||
{
|
||||
def delete() {
|
||||
bytes.bytes(start) = 3
|
||||
}
|
||||
}
|
||||
@@ -168,8 +173,7 @@ case class ScalaSignature(major:Int, minor:Int, table:Array[SigEntry], bytes:Byt
|
||||
val e = table(i)
|
||||
val bc = e.bytes
|
||||
val bcr = bc:ByteCodeReader
|
||||
return e.id match
|
||||
{
|
||||
e.id match {
|
||||
case 1|2 => bcr.readString(bc.len)
|
||||
case 3 => NoSymbol.full
|
||||
case 9|10 =>
|
||||
@@ -182,22 +186,21 @@ case class ScalaSignature(major:Int, minor:Int, table:Array[SigEntry], bytes:Byt
|
||||
|
||||
def evalT[T](i:Int):T = eval(i).asInstanceOf[T]
|
||||
|
||||
def evalList[T](bcr:ByteCodeReader) =
|
||||
{
|
||||
def evalList[T](bcr:ByteCodeReader) = {
|
||||
var l = MList[T]()
|
||||
while(bcr.more)
|
||||
l+=evalT(bcr.readNat)
|
||||
l.toList
|
||||
}
|
||||
|
||||
def eval(i:Int):Any = {//we only parse the ones we actually care about
|
||||
def eval(i:Int):Any = {//only parse the ones that matter for this project
|
||||
val e = table(i)
|
||||
val bc = e.bytes
|
||||
val bcr = bc:ByteCodeReader
|
||||
return e.id match
|
||||
{
|
||||
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 11|12 => NoType //12 is actually NoPrefixType (no lower bound)
|
||||
@@ -206,7 +209,7 @@ case class ScalaSignature(major:Int, minor:Int, table:Array[SigEntry], bytes:Byt
|
||||
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 our purposes
|
||||
case 21|48 => ParameterlessType(evalT(bcr.readNat))//48 is actually a bounded super type, but it should work fine for this project
|
||||
case _ => NoSymbol
|
||||
}
|
||||
}
|
||||
@@ -222,37 +225,32 @@ class ByteCodeReader(val bc:Bytes)
|
||||
|
||||
def readByte = advance(1)(bc.bytes(pos))
|
||||
|
||||
def readNat:Int =
|
||||
{
|
||||
def readNat = {
|
||||
var r = 0
|
||||
var b = 0
|
||||
do
|
||||
{
|
||||
do {
|
||||
b = readByte
|
||||
r = r<<7|b&0x7F
|
||||
}
|
||||
while((b&0x80) != 0)
|
||||
return r
|
||||
r
|
||||
}
|
||||
|
||||
def advance[A](len:Int)(r:A):A =
|
||||
{
|
||||
def advance[A](len:Int)(r:A) = {
|
||||
if(pos+len > bc.pos+bc.len)
|
||||
throw new IllegalArgumentException("Ran off the end of bytecode")
|
||||
pos+=len
|
||||
return r
|
||||
r
|
||||
}
|
||||
|
||||
def readEntry =
|
||||
{
|
||||
def readEntry = {
|
||||
val p = pos
|
||||
val tpe:Int = readByte
|
||||
val tpe = readByte
|
||||
val len = readNat
|
||||
advance(len)(new SigEntry(p, new Bytes(bc.bytes, pos, len)))
|
||||
}
|
||||
|
||||
def readSig =
|
||||
{
|
||||
def readSig = {
|
||||
val major = readByte
|
||||
val minor = readByte
|
||||
val table = new Array[SigEntry](readNat)
|
||||
@@ -264,22 +262,19 @@ class ByteCodeReader(val bc:Bytes)
|
||||
|
||||
object ScalaSigReader
|
||||
{
|
||||
def decode(s:String):Array[Byte] =
|
||||
{
|
||||
def decode(s:String) = {
|
||||
val bytes = s.getBytes
|
||||
return bytes take ByteCodecs.decode(bytes)
|
||||
bytes take ByteCodecs.decode(bytes)
|
||||
}
|
||||
|
||||
def encode(b:Array[Byte]):String =
|
||||
{
|
||||
def encode(b:Array[Byte]) = {
|
||||
val bytes = ByteCodecs.encode8to7(b)
|
||||
var i = 0
|
||||
while(i < bytes.length)
|
||||
{
|
||||
while(i < bytes.length) {
|
||||
bytes(i) = ((bytes(i)+1)&0x7F).toByte
|
||||
i+=1
|
||||
}
|
||||
return new String(bytes.take(bytes.length-1), "UTF-8")
|
||||
new String(bytes.take(bytes.length-1), "UTF-8")
|
||||
}
|
||||
|
||||
def read(ann:AnnotationNode):ScalaSignature = Bytes(decode(ann.values.get(1).asInstanceOf[String])).readSig
|
||||
@@ -294,8 +289,7 @@ object ScalaSigReader
|
||||
|
||||
class ScalaSigSideTransformer
|
||||
{
|
||||
def transform(ann:AnnotationNode, cnode:ClassNode, removedFields:JList[FieldNode], removedMethods:JList[MethodNode])
|
||||
{
|
||||
def transform(ann:AnnotationNode, cnode:ClassNode, removedFields:JList[FieldNode], removedMethods:JList[MethodNode]) {
|
||||
if(removedFields.isEmpty && removedMethods.isEmpty)
|
||||
return
|
||||
|
||||
@@ -303,35 +297,28 @@ class ScalaSigSideTransformer
|
||||
val remMethods = removedMethods.asScala.map(f => (f.name, f.desc.replace('$', '/')))
|
||||
|
||||
val sig = ScalaSigReader.read(ann)
|
||||
for(i <- 0 until sig.table.length)
|
||||
{
|
||||
for(i <- 0 until sig.table.length) {
|
||||
val e = sig.table(i)
|
||||
if(e.id == 8)//check and remove
|
||||
{
|
||||
val sym:MethodSymbol = sig.evalT(i)
|
||||
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)
|
||||
{
|
||||
if (e.id == 8) {//check and remove
|
||||
val sym: MethodSymbol = sig.evalT(i)
|
||||
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)
|
||||
{
|
||||
while (it.hasNext) {
|
||||
val m = it.next
|
||||
if(m.name == sym.name && m.desc == sym.jDesc(sig))
|
||||
if (m.name == sym.name && m.desc == sym.jDesc(sig))
|
||||
it.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sym.isMethod)
|
||||
{
|
||||
if(remMethods.find(t => t._1 == sym.name && t._2 == sym.jDesc(sig)).nonEmpty)
|
||||
else if (sym.isMethod) {
|
||||
if (remMethods.find(t => t._1 == sym.name && t._2 == sym.jDesc(sig)).nonEmpty)
|
||||
e.delete()
|
||||
}
|
||||
else//field
|
||||
{
|
||||
if(remFields.find(t => t._1 == sym.name.trim).nonEmpty)
|
||||
else {//field
|
||||
if (remFields.find(t => t._1 == sym.name.trim).nonEmpty)
|
||||
e.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package codechicken.multipart.nei;
|
||||
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.microblock.MicroblockClass;
|
||||
import codechicken.microblock.MicroblockClassRegistry;
|
||||
import codechicken.microblock.CommonMicroClass;
|
||||
import codechicken.microblock.handler.MicroblockProxy;
|
||||
import codechicken.nei.ItemStackMap;
|
||||
import codechicken.nei.api.API;
|
||||
@@ -15,7 +15,7 @@ public class NEI_MicroblockConfig implements IConfigureNEI
|
||||
{
|
||||
@Override
|
||||
public void loadConfig() {
|
||||
MicroblockClass[] microClasses = MicroblockClassRegistry.classes();
|
||||
MicroblockClass[] microClasses = CommonMicroClass.classes();
|
||||
for (int c = 0; c < microClasses.length; c++) {
|
||||
MicroblockClass mcrClass = microClasses[c];
|
||||
if (mcrClass == null)
|
||||
|
||||
Reference in new issue
Block a user