Merge branch 'kotlin-1.10' into kotlin-1.11.2

This commit is contained in:
octarine-noise
2017-04-09 12:07:25 +02:00
24 changed files with 150 additions and 163 deletions

View File

@@ -2,11 +2,11 @@ apply plugin: "net.minecraftforge.gradle.forge"
apply plugin: 'kotlin' apply plugin: 'kotlin'
group = 'com.github.octarine-noise' group = 'com.github.octarine-noise'
version = "2.1.3" version = "2.1.4"
archivesBaseName = rootProject.name + '-MC1.11.2' archivesBaseName = rootProject.name + '-MC1.11.2'
buildscript { buildscript {
ext.kotlin_version = '1.0.3' ext.kotlin_version = '1.1.1'
repositories { repositories {
mavenCentral() mavenCentral()
maven { maven {

View File

@@ -20,9 +20,9 @@ import net.minecraftforge.fml.relauncher.SideOnly
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
interface IColumnTextureInfo { interface IColumnTextureInfo {
val axis: Axis? val axis: Axis?
val top: (ShadingContext, Int, Quad)->TextureAtlasSprite? val top: QuadIconResolver
val bottom: (ShadingContext, Int, Quad)->TextureAtlasSprite? val bottom: QuadIconResolver
val side: (ShadingContext, Int, Quad)->TextureAtlasSprite? val side: QuadIconResolver
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@@ -35,13 +35,13 @@ data class StaticColumnInfo(override val axis: Axis?,
val topTexture: TextureAtlasSprite, val topTexture: TextureAtlasSprite,
val bottomTexture: TextureAtlasSprite, val bottomTexture: TextureAtlasSprite,
val sideTexture: TextureAtlasSprite) : IColumnTextureInfo { val sideTexture: TextureAtlasSprite) : IColumnTextureInfo {
override val top = { ctx: ShadingContext, idx: Int, quad: Quad -> override val top: QuadIconResolver = { ctx, _, _ ->
OptifineCTM.override(topTexture, blockContext, UP.rotate(ctx.rotation)) OptifineCTM.override(topTexture, blockContext, UP.rotate(ctx.rotation))
} }
override val bottom = { ctx: ShadingContext, idx: Int, quad: Quad -> override val bottom: QuadIconResolver = { ctx, _, _ ->
OptifineCTM.override(bottomTexture, blockContext, DOWN.rotate(ctx.rotation)) OptifineCTM.override(bottomTexture, blockContext, DOWN.rotate(ctx.rotation))
} }
override val side = { ctx: ShadingContext, idx: Int, quad: Quad -> override val side: QuadIconResolver = { ctx, idx, _ ->
OptifineCTM.override(sideTexture, blockContext, (if ((idx and 1) == 0) SOUTH else EAST).rotate(ctx.rotation)) OptifineCTM.override(sideTexture, blockContext, (if ((idx and 1) == 0) SOUTH else EAST).rotate(ctx.rotation))
} }
} }
@@ -129,7 +129,7 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
val transitionTop = model { mix(sideRoundLarge.model, sideRoundSmall.model) { it > 1 } } val transitionTop = model { mix(sideRoundLarge.model, sideRoundSmall.model) { it > 1 } }
val transitionBottom = model { mix(sideRoundSmall.model, sideRoundLarge.model) { it > 1 } } val transitionBottom = model { mix(sideRoundSmall.model, sideRoundLarge.model) { it > 1 } }
inline fun continous(q1: QuadrantType, q2: QuadrantType) = inline fun continuous(q1: QuadrantType, q2: QuadrantType) =
q1 == q2 || ((q1 == SQUARE || q1 == INVISIBLE) && (q2 == SQUARE || q2 == INVISIBLE)) q1 == q2 || ((q1 == SQUARE || q1 == INVISIBLE) && (q2 == SQUARE || q2 == INVISIBLE))
abstract val blockPredicate: (IBlockState)->Boolean abstract val blockPredicate: (IBlockState)->Boolean
@@ -185,7 +185,6 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
renderer, renderer,
sideModel, sideModel,
rotation, rotation,
blockContext.blockCenter,
icon = columnTextures.side, icon = columnTextures.side,
postProcess = noPost postProcess = noPost
) )
@@ -210,7 +209,7 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
} }
} }
PARALLEL -> { PARALLEL -> {
if (!continous(quadrants[idx], quadrantsTop[idx])) { if (!continuous(quadrants[idx], quadrantsTop[idx])) {
if (quadrants[idx] == SQUARE || quadrants[idx] == INVISIBLE) { if (quadrants[idx] == SQUARE || quadrants[idx] == INVISIBLE) {
upModel = topSquare.model upModel = topSquare.model
} }
@@ -229,7 +228,7 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
} }
} }
PARALLEL -> { PARALLEL -> {
if (!continous(quadrants[idx], quadrantsBottom[idx]) && if (!continuous(quadrants[idx], quadrantsBottom[idx]) &&
(quadrants[idx] == SQUARE || quadrants[idx] == INVISIBLE)) { (quadrants[idx] == SQUARE || quadrants[idx] == INVISIBLE)) {
downModel = bottomSquare.model downModel = bottomSquare.model
} }
@@ -240,9 +239,8 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
renderer, renderer,
upModel, upModel,
rotation, rotation,
blockContext.blockCenter,
icon = upIcon, icon = upIcon,
postProcess = { ctx, qi, q, vi, v -> postProcess = { _, _, _, _, _ ->
if (isLidUp) { if (isLidUp) {
rotateUV(idx + if (logAxis == Axis.X) 1 else 0) rotateUV(idx + if (logAxis == Axis.X) 1 else 0)
if (logAxis == Axis.X) mirrorUV(true, true) if (logAxis == Axis.X) mirrorUV(true, true)
@@ -253,9 +251,8 @@ abstract class AbstractRenderColumn(modId: String) : AbstractBlockRenderingHandl
renderer, renderer,
downModel, downModel,
rotation, rotation,
blockContext.blockCenter,
icon = downIcon, icon = downIcon,
postProcess = { ctx, qi, q, vi, v -> postProcess = { _, _, _, _, _ ->
if (isLidDown) { if (isLidDown) {
rotateUV((if (logAxis == Axis.X) 0 else 3) - idx) rotateUV((if (logAxis == Axis.X) 0 else 3) - idx)
if (logAxis != Axis.Y) mirrorUV(true, true) if (logAxis != Axis.Y) mirrorUV(true, true)

View File

@@ -47,7 +47,7 @@ class RenderAlgae : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
renderer, renderer,
algaeModels[rand[2]], algaeModels[rand[2]],
Rotation.identity, Rotation.identity,
icon = { ctx, qi, q -> algaeIcons[rand[qi and 1]]!! }, icon = { _, qi, _ -> algaeIcons[rand[qi and 1]]!! },
postProcess = noPost postProcess = noPost
) )
} }

View File

@@ -110,14 +110,14 @@ class RenderCactus : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
renderer, renderer,
modelCross[ctx.random(0)], modelCross[ctx.random(0)],
Rotation.identity, Rotation.identity,
icon = { ctx, qi, q -> iconCross.icon!!}, icon = { _, _, _ -> iconCross.icon!!},
postProcess = noPost postProcess = noPost
) )
modelRenderer.render( modelRenderer.render(
renderer, renderer,
modelArm[ctx.random(1)], modelArm[ctx.random(1)],
cactusArmRotation[ctx.random(2) % 4], cactusArmRotation[ctx.random(2) % 4],
icon = { ctx2, qi, q -> iconArm[ctx.random(3)]!!}, icon = { _, _, _ -> iconArm[ctx.random(3)]!!},
postProcess = noPost postProcess = noPost
) )
return true return true

View File

@@ -6,6 +6,8 @@ import mods.octarinecore.client.render.AbstractBlockRenderingHandler
import mods.octarinecore.client.render.BlockContext import mods.octarinecore.client.render.BlockContext
import mods.octarinecore.client.render.withOffset import mods.octarinecore.client.render.withOffset
import mods.octarinecore.common.Int3 import mods.octarinecore.common.Int3
import mods.octarinecore.common.forgeDirsHorizontal
import mods.octarinecore.common.offset
import net.minecraft.client.renderer.BlockRendererDispatcher import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.VertexBuffer import net.minecraft.client.renderer.VertexBuffer
import net.minecraft.util.BlockRenderLayer import net.minecraft.util.BlockRenderLayer
@@ -21,6 +23,10 @@ class RenderConnectedGrass : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_
(Config.connectedGrass.snowEnabled || !ctx.blockState(up2).isSnow) (Config.connectedGrass.snowEnabled || !ctx.blockState(up2).isSnow)
override fun render(ctx: BlockContext, dispatcher: BlockRendererDispatcher, renderer: VertexBuffer, layer: BlockRenderLayer): Boolean { override fun render(ctx: BlockContext, dispatcher: BlockRendererDispatcher, renderer: VertexBuffer, layer: BlockRenderLayer): Boolean {
// if the block sides are not visible anyway, render normally
if (forgeDirsHorizontal.all { ctx.blockState(it.offset).isOpaqueCube }) return renderWorldBlockBase(ctx, dispatcher, renderer, null)
if (ctx.isSurroundedBy { it.isOpaqueCube } ) return false
return ctx.withOffset(Int3.zero, up1) { return ctx.withOffset(Int3.zero, up1) {
ctx.withOffset(up1, up2) { ctx.withOffset(up1, up2) {
renderWorldBlockBase(ctx, dispatcher, renderer, null) renderWorldBlockBase(ctx, dispatcher, renderer, null)

View File

@@ -65,7 +65,7 @@ class RenderCoral : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
renderer, renderer,
coralModels[variation++], coralModels[variation++],
rotationFromUp[idx], rotationFromUp[idx],
icon = { ctx, qi, q -> if (qi == 4) crustIcons[variation]!! else coralIcons[variation + (qi and 1)]!!}, icon = { _, qi, _ -> if (qi == 4) crustIcons[variation]!! else coralIcons[variation + (qi and 1)]!!},
postProcess = noPost postProcess = noPost
) )
} }

View File

@@ -6,9 +6,7 @@ import mods.betterfoliage.client.config.Config
import mods.betterfoliage.client.integration.ShadersModIntegration import mods.betterfoliage.client.integration.ShadersModIntegration
import mods.betterfoliage.client.texture.GrassRegistry import mods.betterfoliage.client.texture.GrassRegistry
import mods.octarinecore.client.render.* import mods.octarinecore.client.render.*
import mods.octarinecore.common.Double3 import mods.octarinecore.common.*
import mods.octarinecore.common.Int3
import mods.octarinecore.common.Rotation
import mods.octarinecore.random import mods.octarinecore.random
import net.minecraft.client.renderer.BlockRendererDispatcher import net.minecraft.client.renderer.BlockRendererDispatcher
import net.minecraft.client.renderer.VertexBuffer import net.minecraft.client.renderer.VertexBuffer
@@ -66,15 +64,17 @@ class RenderGrass : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
// get full AO data // get full AO data
modelRenderer.updateShading(Int3.zero, allFaces) modelRenderer.updateShading(Int3.zero, allFaces)
// check occlusion
val isHidden = forgeDirs.map { ctx.blockState(it.offset).isOpaqueCube }
// render full grass block // render full grass block
ShadersModIntegration.renderAs(ctx.blockState(Int3.zero), renderer) { ShadersModIntegration.renderAs(ctx.blockState(Int3.zero), renderer) {
modelRenderer.render( modelRenderer.render(
renderer, renderer,
fullCube, fullCube,
Rotation.identity, quadFilter = { qi, _ -> !isHidden[qi] },
ctx.blockCenter, icon = { _, _, _ -> grassInfo.grassTopTexture },
icon = { ctx, qi, q -> grassInfo.grassTopTexture }, postProcess = { ctx, _, _, _, _ ->
postProcess = { ctx, qi, q, vi, v ->
rotateUV(2) rotateUV(2)
if (isSnowed) { if (isSnowed) {
if (!ctx.aoEnabled) setGrey(1.4f) if (!ctx.aoEnabled) setGrey(1.4f)
@@ -104,10 +104,8 @@ class RenderGrass : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
grassModels[rand[0]], grassModels[rand[0]],
Rotation.identity, Rotation.identity,
ctx.blockCenter + (if (isSnowed) snowOffset else Double3.zero), ctx.blockCenter + (if (isSnowed) snowOffset else Double3.zero),
icon = { ctx: ShadingContext, qi: Int, q: Quad -> icon = { _, qi, _ -> if (Config.shortGrass.useGenerated) iconGen.icon!! else iconset[rand[qi and 1]]!! },
if (Config.shortGrass.useGenerated) iconGen.icon!! else iconset[rand[qi and 1]]!! postProcess = { _, _, _, _, _ -> if (isSnowed) setGrey(1.0f) else multiplyColor(grassInfo.overrideColor ?: blockColor) }
},
postProcess = { ctx, qi, q, vi, v -> if (isSnowed) setGrey(1.0f) else multiplyColor(grassInfo.overrideColor ?: blockColor) }
) )
} }

View File

@@ -64,8 +64,8 @@ class RenderLeaves : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
leavesModel.model, leavesModel.model,
rotation, rotation,
ctx.blockCenter + perturbs[rand[0]], ctx.blockCenter + perturbs[rand[0]],
icon = { ctx, qi, q -> leafInfo.roundLeafTexture }, icon = { _, _, _ -> leafInfo.roundLeafTexture },
postProcess = { ctx, qi, q, vi, v -> postProcess = { _, _, _, _, _ ->
rotateUV(rand[1]) rotateUV(rand[1])
multiplyColor(blockColor) multiplyColor(blockColor)
} }
@@ -76,7 +76,7 @@ class RenderLeaves : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
leavesModel.model, leavesModel.model,
Rotation.identity, Rotation.identity,
ctx.blockCenter + perturbs[rand[0]], ctx.blockCenter + perturbs[rand[0]],
icon = { ctx, qi, q -> snowedIcon[rand[1]]!! }, icon = { _, _, _ -> snowedIcon[rand[1]]!! },
postProcess = whitewash postProcess = whitewash
) )
} }

View File

@@ -68,7 +68,7 @@ class RenderLilypad : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
Rotation.identity, Rotation.identity,
ctx.blockCenter.add(perturbs[rand[4]]), ctx.blockCenter.add(perturbs[rand[4]]),
forceFlat = true, forceFlat = true,
icon = { ctx, qi, q -> flowerIcon[rand[0]]!! }, icon = { _, _, _ -> flowerIcon[rand[0]]!! },
postProcess = noPost postProcess = noPost
) )

View File

@@ -73,7 +73,7 @@ object StandardLogSupport : TextureListModelProcessor<IColumnTextureInfo>, IColu
fun getAxis(state: IBlockState): Axis? { fun getAxis(state: IBlockState): Axis? {
val axis = tryDefault(null) { state.getValue(BlockLog.LOG_AXIS).toString() } ?: val axis = tryDefault(null) { state.getValue(BlockLog.LOG_AXIS).toString() } ?:
state.properties.entries.find { it.key.getName().toLowerCase() == "axis" }?.let { it.value.toString() } state.properties.entries.find { it.key.getName().toLowerCase() == "axis" }?.value?.toString()
return when (axis) { return when (axis) {
"x" -> Axis.X "x" -> Axis.X
"y" -> Axis.Y "y" -> Axis.Y

View File

@@ -47,7 +47,7 @@ class RenderMycelium : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
myceliumModel[rand[0]], myceliumModel[rand[0]],
Rotation.identity, Rotation.identity,
ctx.blockCenter + (if (isSnowed) snowOffset else Double3.zero), ctx.blockCenter + (if (isSnowed) snowOffset else Double3.zero),
icon = { ctx, qi, q -> myceliumIcon[rand[qi and 1]]!! }, icon = { _, qi, _ -> myceliumIcon[rand[qi and 1]]!! },
postProcess = if (isSnowed) whitewash else noPost postProcess = if (isSnowed) whitewash else noPost
) )

View File

@@ -49,7 +49,7 @@ class RenderNetherrack : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID)
renderer, renderer,
netherrackModel[rand[0]], netherrackModel[rand[0]],
Rotation.identity, Rotation.identity,
icon = { ctx, qi, q -> netherrackIcon[rand[qi and 1]]!! }, icon = { _, qi, _ -> netherrackIcon[rand[qi and 1]]!! },
postProcess = noPost postProcess = noPost
) )

View File

@@ -64,7 +64,7 @@ class RenderReeds : AbstractBlockRenderingHandler(BetterFoliageMod.MOD_ID) {
reedModels[ctx.random(0)], reedModels[ctx.random(0)],
Rotation.identity, Rotation.identity,
forceFlat = true, forceFlat = true,
icon = { ctx, qi, q -> reedIcons[iconVar]!! }, icon = { _, _, _ -> reedIcons[iconVar]!! },
postProcess = noPost postProcess = noPost
) )
} }

View File

@@ -21,8 +21,8 @@ val snowOffset = UP * 0.0625
val normalLeavesRot = arrayOf(Rotation.identity) val normalLeavesRot = arrayOf(Rotation.identity)
val denseLeavesRot = arrayOf(Rotation.identity, Rotation.rot90[EAST.ordinal], Rotation.rot90[SOUTH.ordinal]) val denseLeavesRot = arrayOf(Rotation.identity, Rotation.rot90[EAST.ordinal], Rotation.rot90[SOUTH.ordinal])
val whitewash: RenderVertex.(ShadingContext, Int, Quad, Int, Vertex)->Unit = { ctx, qi, q, vi, v -> setGrey(1.4f) } val whitewash: PostProcessLambda = { _, _, _, _, _ -> setGrey(1.4f) }
val greywash: RenderVertex.(ShadingContext, Int, Quad, Int, Vertex)->Unit = { ctx, qi, q, vi, v -> setGrey(1.0f) } val greywash: PostProcessLambda = { _, _, _, _, _ -> setGrey(1.0f) }
val IBlockState.isSnow: Boolean get() = material.let { it == Material.SNOW || it == Material.CRAFTED_SNOW } val IBlockState.isSnow: Boolean get() = material.let { it == Material.SNOW || it == Material.CRAFTED_SNOW }

View File

@@ -14,6 +14,7 @@ import org.objectweb.asm.Opcodes.*
"mods.octarinecore.kotlin" "mods.octarinecore.kotlin"
) )
@IFMLLoadingPlugin.MCVersion("1.11.2") @IFMLLoadingPlugin.MCVersion("1.11.2")
@IFMLLoadingPlugin.SortingIndex(1400)
class BetterFoliageLoader : ASMPlugin(BetterFoliageTransformer::class.java) class BetterFoliageLoader : ASMPlugin(BetterFoliageTransformer::class.java)
class BetterFoliageTransformer : Transformer() { class BetterFoliageTransformer : Transformer() {

View File

@@ -16,53 +16,50 @@ object Refs {
val Random = ClassRef("java.util.Random") val Random = ClassRef("java.util.Random")
// Minecraft // Minecraft
val IBlockAccess = ClassRef("net.minecraft.world.IBlockAccess", "ajw") val IBlockAccess = ClassRef("net.minecraft.world.IBlockAccess")
val IBlockState = ClassRef("net.minecraft.block.state.IBlockState", "atl") val IBlockState = ClassRef("net.minecraft.block.state.IBlockState")
val BlockStateBase = ClassRef("net.minecraft.block.state.BlockStateBase", "ati") val BlockStateBase = ClassRef("net.minecraft.block.state.BlockStateBase")
val BlockPos = ClassRef("net.minecraft.util.math.BlockPos", "co") val BlockPos = ClassRef("net.minecraft.util.math.BlockPos")
val MutableBlockPos = ClassRef("net.minecraft.util.math.BlockPos\$MutableBlockPos", "co\$a") val MutableBlockPos = ClassRef("net.minecraft.util.math.BlockPos\$MutableBlockPos")
val BlockRenderLayer = ClassRef("net.minecraft.util.BlockRenderLayer", "ajk") val BlockRenderLayer = ClassRef("net.minecraft.util.BlockRenderLayer")
val EnumFacing = ClassRef("net.minecraft.util.EnumFacing", "cv") val EnumFacing = ClassRef("net.minecraft.util.EnumFacing")
val World = ClassRef("net.minecraft.world.World", "ajs") val World = ClassRef("net.minecraft.world.World")
val WorldClient = ClassRef("net.minecraft.client.multiplayer.WorldClient", "bnq") val WorldClient = ClassRef("net.minecraft.client.multiplayer.WorldClient")
val showBarrierParticles = MethodRef(WorldClient, "showBarrierParticles", "func_184153_a", "a", ClassRef.void, ClassRef.int, ClassRef.int, ClassRef.int, ClassRef.int, Random, ClassRef.boolean, MutableBlockPos) val showBarrierParticles = MethodRef(WorldClient, "showBarrierParticles", "func_184153_a", ClassRef.void, ClassRef.int, ClassRef.int, ClassRef.int, ClassRef.int, Random, ClassRef.boolean, MutableBlockPos)
val Block = ClassRef("net.minecraft.block.Block", "alu") val Block = ClassRef("net.minecraft.block.Block")
val StateImplementation = ClassRef("net.minecraft.block.state.BlockStateContainer\$StateImplementation", "atm\$a") val StateImplementation = ClassRef("net.minecraft.block.state.BlockStateContainer\$StateImplementation")
val canRenderInLayer = MethodRef(Block, "canRenderInLayer", ClassRef.boolean, IBlockState, BlockRenderLayer) val canRenderInLayer = MethodRef(Block, "canRenderInLayer", ClassRef.boolean, IBlockState, BlockRenderLayer)
val getAmbientOcclusionLightValue = MethodRef(StateImplementation, "getAmbientOcclusionLightValue", "func_185892_j", "k", ClassRef.float) val getAmbientOcclusionLightValue = MethodRef(StateImplementation, "getAmbientOcclusionLightValue", "func_185892_j", ClassRef.float)
val useNeighborBrightness = MethodRef(StateImplementation, "useNeighborBrightness", "func_185916_f", "f", ClassRef.boolean) val useNeighborBrightness = MethodRef(StateImplementation, "useNeighborBrightness", "func_185916_f", ClassRef.boolean)
val doesSideBlockRendering = MethodRef(StateImplementation, "doesSideBlockRendering", ClassRef.boolean, IBlockAccess, BlockPos, EnumFacing) val doesSideBlockRendering = MethodRef(StateImplementation, "doesSideBlockRendering", ClassRef.boolean, IBlockAccess, BlockPos, EnumFacing)
val isOpaqueCube = MethodRef(StateImplementation, "isOpaqueCube", "func_185914_p", "q", ClassRef.boolean) val isOpaqueCube = MethodRef(StateImplementation, "isOpaqueCube", "func_185914_p", ClassRef.boolean)
val randomDisplayTick = MethodRef(Block, "randomDisplayTick", "func_180655_c", "a", ClassRef.void, IBlockState, World, BlockPos, Random) val randomDisplayTick = MethodRef(Block, "randomDisplayTick", "func_180655_c", ClassRef.void, IBlockState, World, BlockPos, Random)
val BlockModelRenderer = ClassRef("net.minecraft.client.renderer.BlockModelRenderer", "brc") val BlockModelRenderer = ClassRef("net.minecraft.client.renderer.BlockModelRenderer")
val AmbientOcclusionFace = ClassRef("net.minecraft.client.renderer.BlockModelRenderer\$AmbientOcclusionFace", "brc\$b") val AmbientOcclusionFace = ClassRef("net.minecraft.client.renderer.BlockModelRenderer\$AmbientOcclusionFace")
val ChunkCompileTaskGenerator = ClassRef("net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator", "bsy") val ChunkCompileTaskGenerator = ClassRef("net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator")
val VertexBuffer = ClassRef("net.minecraft.client.renderer.VertexBuffer", "bpy") val VertexBuffer = ClassRef("net.minecraft.client.renderer.VertexBuffer")
val AOF_constructor = MethodRef(AmbientOcclusionFace, "<init>", ClassRef.void, BlockModelRenderer) val AOF_constructor = MethodRef(AmbientOcclusionFace, "<init>", ClassRef.void, BlockModelRenderer)
val RenderChunk = ClassRef("net.minecraft.client.renderer.chunk.RenderChunk", "bte") val RenderChunk = ClassRef("net.minecraft.client.renderer.chunk.RenderChunk")
val rebuildChunk = MethodRef(RenderChunk, "rebuildChunk", "func_178581_b", "b", ClassRef.void, ClassRef.float, ClassRef.float, ClassRef.float, ChunkCompileTaskGenerator) val rebuildChunk = MethodRef(RenderChunk, "rebuildChunk", "func_178581_b", ClassRef.void, ClassRef.float, ClassRef.float, ClassRef.float, ChunkCompileTaskGenerator)
val BlockRendererDispatcher = ClassRef("net.minecraft.client.renderer.BlockRendererDispatcher", "bra") val BlockRendererDispatcher = ClassRef("net.minecraft.client.renderer.BlockRendererDispatcher")
val renderBlock = MethodRef(BlockRendererDispatcher, "renderBlock", "func_175018_a", "a", ClassRef.boolean, IBlockState, BlockPos, IBlockAccess, VertexBuffer) val renderBlock = MethodRef(BlockRendererDispatcher, "renderBlock", "func_175018_a", ClassRef.boolean, IBlockState, BlockPos, IBlockAccess, VertexBuffer)
val TextureAtlasSprite = ClassRef("net.minecraft.client.renderer.texture.TextureAtlasSprite", "byz") val TextureAtlasSprite = ClassRef("net.minecraft.client.renderer.texture.TextureAtlasSprite")
val TextureMap = ClassRef("net.minecraft.client.renderer.texture.TextureMap", "byy")
val IResourceManager = ClassRef("net.minecraft.client.resources.IResourceManager", "bzy")
val loadTextureAtlas = MethodRef(TextureMap, "loadTextureAtlas", "func_110571_b", "b", ClassRef.void, IResourceManager)
val IRegistry = ClassRef("net.minecraft.util.registry.IRegistry", "dh") val IRegistry = ClassRef("net.minecraft.util.registry.IRegistry")
val ModelLoader = ClassRef("net.minecraftforge.client.model.ModelLoader") val ModelLoader = ClassRef("net.minecraftforge.client.model.ModelLoader")
val stateModels = FieldRef(ModelLoader, "stateModels", Map) val stateModels = FieldRef(ModelLoader, "stateModels", Map)
val setupModelRegistry = MethodRef(ModelLoader, "setupModelRegistry", "func_177570_a", "a", IRegistry) val setupModelRegistry = MethodRef(ModelLoader, "setupModelRegistry", "func_177570_a", IRegistry)
val IModel = ClassRef("net.minecraftforge.client.model.IModel") val IModel = ClassRef("net.minecraftforge.client.model.IModel")
val ModelBlock = ClassRef("net.minecraft.client.renderer.block.model.ModelBlock", "bri") val ModelBlock = ClassRef("net.minecraft.client.renderer.block.model.ModelBlock")
val ResourceLocation = ClassRef("net.minecraft.util.ResourceLocation", "kq") val ResourceLocation = ClassRef("net.minecraft.util.ResourceLocation")
val ModelResourceLocation = ClassRef("net.minecraft.client.renderer.block.model.ModelResourceLocation", "cbm") val ModelResourceLocation = ClassRef("net.minecraft.client.renderer.block.model.ModelResourceLocation")
val VanillaModelWrapper = ClassRef("net.minecraftforge.client.model.ModelLoader\$VanillaModelWrapper") val VanillaModelWrapper = ClassRef("net.minecraftforge.client.model.ModelLoader\$VanillaModelWrapper")
val model_VMW = FieldRef(VanillaModelWrapper, "model", ModelBlock) val model_VMW = FieldRef(VanillaModelWrapper, "model", ModelBlock)
val location_VMW = FieldRef(VanillaModelWrapper, "location", ModelBlock) val location_VMW = FieldRef(VanillaModelWrapper, "location", ModelBlock)
@@ -88,7 +85,6 @@ object Refs {
val onAfterBakeModels = MethodRef(BetterFoliageHooks, "onAfterBakeModels", ClassRef.void, Map) val onAfterBakeModels = MethodRef(BetterFoliageHooks, "onAfterBakeModels", ClassRef.void, Map)
val renderWorldBlock = MethodRef(BetterFoliageHooks, "renderWorldBlock", ClassRef.boolean, BlockRendererDispatcher, IBlockState, BlockPos, IBlockAccess, VertexBuffer, BlockRenderLayer) val renderWorldBlock = MethodRef(BetterFoliageHooks, "renderWorldBlock", ClassRef.boolean, BlockRendererDispatcher, IBlockState, BlockPos, IBlockAccess, VertexBuffer, BlockRenderLayer)
val canRenderBlockInLayer = MethodRef(BetterFoliageHooks, "canRenderBlockInLayer", ClassRef.boolean, Block, IBlockState, BlockRenderLayer) val canRenderBlockInLayer = MethodRef(BetterFoliageHooks, "canRenderBlockInLayer", ClassRef.boolean, Block, IBlockState, BlockRenderLayer)
val onLoadAtlasPre = MethodRef(BetterFoliageHooks, "onLoadAtlasPre", ClassRef.void, TextureMap)
// Optifine // Optifine
val OptifineClassTransformer = ClassRef("optifine.OptiFineClassTransformer") val OptifineClassTransformer = ClassRef("optifine.OptiFineClassTransformer")

View File

@@ -70,13 +70,13 @@ data class Quad(val v1: Vertex, val v2: Vertex, val v3: Vertex, val v4: Vertex)
fun clampUV(minU: Double = -0.5, maxU: Double = 0.5, minV: Double = -0.5, maxV: Double = 0.5) = fun clampUV(minU: Double = -0.5, maxU: Double = 0.5, minV: Double = -0.5, maxV: Double = 0.5) =
transformV { it.copy(uv = it.uv.clamp(minU, maxU, minV, maxV)) } transformV { it.copy(uv = it.uv.clamp(minU, maxU, minV, maxV)) }
fun mirrorUV(mirrorU: Boolean, mirrorV: Boolean) = transformV { it.copy(uv = it.uv.mirror(mirrorU, mirrorV)) } fun mirrorUV(mirrorU: Boolean, mirrorV: Boolean) = transformV { it.copy(uv = it.uv.mirror(mirrorU, mirrorV)) }
fun setAoShader(resolver: (Quad, Vertex)->Shader, predicate: (Vertex, Int)->Boolean = { v, vi -> true }) = fun setAoShader(factory: ShaderFactory, predicate: (Vertex, Int)->Boolean = { v, vi -> true }) =
transformVI { vertex, idx -> transformVI { vertex, idx ->
if (!predicate(vertex, idx)) vertex else vertex.copy(aoShader = resolver(this@Quad, vertex)) if (!predicate(vertex, idx)) vertex else vertex.copy(aoShader = factory(this@Quad, vertex))
} }
fun setFlatShader(resolver: (Quad, Vertex)->Shader, predicate: (Vertex, Int)->Boolean = { v, vi -> true }) = fun setFlatShader(factory: ShaderFactory, predicate: (Vertex, Int)->Boolean = { v, vi -> true }) =
transformVI { vertex, idx -> transformVI { vertex, idx ->
if (!predicate(vertex, idx)) vertex else vertex.copy(flatShader = resolver(this@Quad, vertex)) if (!predicate(vertex, idx)) vertex else vertex.copy(flatShader = factory(this@Quad, vertex))
} }
fun setFlatShader(shader: Shader) = transformVI { vertex, idx -> vertex.copy(flatShader = shader) } fun setFlatShader(shader: Shader) = transformVI { vertex, idx -> vertex.copy(flatShader = shader) }
val flipped: Quad get() = Quad(v4, v3, v2, v1) val flipped: Quad get() = Quad(v4, v3, v2, v1)

View File

@@ -7,7 +7,10 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.EnumFacing import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumFacing.* import net.minecraft.util.EnumFacing.*
class ModelRenderer() : ShadingContext() { typealias QuadIconResolver = (ShadingContext, Int, Quad) -> TextureAtlasSprite?
typealias PostProcessLambda = RenderVertex.(ShadingContext, Int, Quad, Int, Vertex) -> Unit
class ModelRenderer : ShadingContext() {
/** Holds final vertex data before it goes to the [Tessellator]. */ /** Holds final vertex data before it goes to the [Tessellator]. */
val temp = RenderVertex() val temp = RenderVertex()
@@ -25,14 +28,15 @@ class ModelRenderer() : ShadingContext() {
* @param[rotateUV] lambda to get amount of UV rotation for each quad * @param[rotateUV] lambda to get amount of UV rotation for each quad
* @param[postProcess] lambda to perform arbitrary modifications on the [RenderVertex] just before it goes to the [Tessellator] * @param[postProcess] lambda to perform arbitrary modifications on the [RenderVertex] just before it goes to the [Tessellator]
*/ */
inline fun render( fun render(
worldRenderer: VertexBuffer, worldRenderer: VertexBuffer,
model: Model, model: Model,
rot: Rotation, rot: Rotation = Rotation.identity,
trans: Double3 = blockContext.blockCenter, trans: Double3 = blockContext.blockCenter,
forceFlat: Boolean = false, forceFlat: Boolean = false,
icon: (ShadingContext, Int, Quad) -> TextureAtlasSprite?, quadFilter: (Int, Quad) -> Boolean = { _, _ -> true },
postProcess: RenderVertex.(ShadingContext, Int, Quad, Int, Vertex) -> Unit icon: QuadIconResolver,
postProcess: PostProcessLambda
) { ) {
rotation = rot rotation = rot
aoEnabled = Minecraft.isAmbientOcclusionEnabled() aoEnabled = Minecraft.isAmbientOcclusionEnabled()
@@ -41,6 +45,7 @@ class ModelRenderer() : ShadingContext() {
worldRenderer.ensureSpaceForQuads(model.quads.size + 1) worldRenderer.ensureSpaceForQuads(model.quads.size + 1)
model.quads.forEachIndexed { quadIdx, quad -> model.quads.forEachIndexed { quadIdx, quad ->
if (quadFilter(quadIdx, quad)) {
val drawIcon = icon(this, quadIdx, quad) val drawIcon = icon(this, quadIdx, quad)
if (drawIcon != null) { if (drawIcon != null) {
quad.verts.forEachIndexed { vertIdx, vert -> quad.verts.forEachIndexed { vertIdx, vert ->
@@ -60,6 +65,7 @@ class ModelRenderer() : ShadingContext() {
} }
} }
} }
}
} }
/** /**
@@ -167,4 +173,4 @@ val allFaces: (EnumFacing) -> Boolean = { true }
val topOnly: (EnumFacing) -> Boolean = { it == UP } val topOnly: (EnumFacing) -> Boolean = { it == UP }
/** Perform no post-processing */ /** Perform no post-processing */
val noPost: RenderVertex.(ShadingContext, Int, Quad, Int, Vertex) -> Unit = { ctx, qi, q, vi, v -> } val noPost: PostProcessLambda = { _, _, _, _, _ -> }

View File

@@ -10,7 +10,7 @@ const val defaultEdgeDimming = 0.8f
// ================================ // ================================
// Shader instantiation lambdas // Shader instantiation lambdas
// ================================ // ================================
fun cornerAo(fallbackAxis: EnumFacing.Axis): (EnumFacing, EnumFacing, EnumFacing)->Shader = { face, dir1, dir2 -> fun cornerAo(fallbackAxis: EnumFacing.Axis): CornerShaderFactory = { face, dir1, dir2 ->
val fallbackDir = listOf(face, dir1, dir2).find { it.axis == fallbackAxis }!! val fallbackDir = listOf(face, dir1, dir2).find { it.axis == fallbackAxis }!!
CornerSingleFallback(face, dir1, dir2, fallbackDir) CornerSingleFallback(face, dir1, dir2, fallbackDir)
} }
@@ -20,7 +20,7 @@ fun cornerAoTri(func: (AoData, AoData)-> AoData) = { face: EnumFacing, dir1: Enu
} }
val cornerAoMaxGreen = cornerAoTri { s1, s2 -> if (s1.green > s2.green) s1 else s2 } val cornerAoMaxGreen = cornerAoTri { s1, s2 -> if (s1.green > s2.green) s1 else s2 }
fun cornerInterpolate(edgeAxis: EnumFacing.Axis, weight: Float, dimming: Float): (EnumFacing, EnumFacing, EnumFacing)->Shader = { dir1, dir2, dir3 -> fun cornerInterpolate(edgeAxis: EnumFacing.Axis, weight: Float, dimming: Float): CornerShaderFactory = { dir1, dir2, dir3 ->
val edgeDir = listOf(dir1, dir2, dir3).find { it.axis == edgeAxis }!! val edgeDir = listOf(dir1, dir2, dir3).find { it.axis == edgeAxis }!!
val faceDirs = listOf(dir1, dir2, dir3).filter { it.axis != edgeAxis } val faceDirs = listOf(dir1, dir2, dir3).filter { it.axis != edgeAxis }
CornerInterpolateDimming(faceDirs[0], faceDirs[1], edgeDir, weight, dimming) CornerInterpolateDimming(faceDirs[0], faceDirs[1], edgeDir, weight, dimming)

View File

@@ -10,6 +10,10 @@ import net.minecraft.util.EnumFacing.*
import java.lang.Math.min import java.lang.Math.min
import java.util.* import java.util.*
typealias EdgeShaderFactory = (EnumFacing, EnumFacing) -> Shader
typealias CornerShaderFactory = (EnumFacing, EnumFacing, EnumFacing) -> Shader
typealias ShaderFactory = (Quad, Vertex) -> Shader
/** Holds shading values for block corners as calculated by vanilla Minecraft rendering. */ /** Holds shading values for block corners as calculated by vanilla Minecraft rendering. */
class AoData() { class AoData() {
var valid = false var valid = false
@@ -140,8 +144,8 @@ interface Shader {
* @param[edge] shader instantiation lambda for edge midpoint vertices * @param[edge] shader instantiation lambda for edge midpoint vertices
*/ */
fun faceOrientedAuto(overrideFace: EnumFacing? = null, fun faceOrientedAuto(overrideFace: EnumFacing? = null,
corner: ((EnumFacing, EnumFacing, EnumFacing)->Shader)? = null, corner: CornerShaderFactory? = null,
edge: ((EnumFacing, EnumFacing)->Shader)? = null) = edge: EdgeShaderFactory? = null) =
fun(quad: Quad, vertex: Vertex): Shader { fun(quad: Quad, vertex: Vertex): Shader {
val quadFace = overrideFace ?: quad.normal.nearestCardinal val quadFace = overrideFace ?: quad.normal.nearestCardinal
val nearestCorner = nearestPosition(vertex.xyz, faceCorners[quadFace.ordinal].asList) { val nearestCorner = nearestPosition(vertex.xyz, faceCorners[quadFace.ordinal].asList) {
@@ -167,7 +171,7 @@ fun faceOrientedAuto(overrideFace: EnumFacing? = null,
* @param[corner] shader instantiation lambda * @param[corner] shader instantiation lambda
*/ */
fun edgeOrientedAuto(overrideEdge: Pair<EnumFacing, EnumFacing>? = null, fun edgeOrientedAuto(overrideEdge: Pair<EnumFacing, EnumFacing>? = null,
corner: (EnumFacing, EnumFacing, EnumFacing)->Shader) = corner: CornerShaderFactory) =
fun(quad: Quad, vertex: Vertex): Shader { fun(quad: Quad, vertex: Vertex): Shader {
val edgeDir = overrideEdge ?: nearestAngle(quad.normal, boxEdges) { it.first.vec + it.second.vec }.first val edgeDir = overrideEdge ?: nearestAngle(quad.normal, boxEdges) { it.first.vec + it.second.vec }.first
val nearestFace = nearestPosition(vertex.xyz, edgeDir.toList()) { it.vec }.first val nearestFace = nearestPosition(vertex.xyz, edgeDir.toList()) { it.vec }.first

View File

@@ -16,6 +16,7 @@ val axisDirs = listOf(POSITIVE, NEGATIVE)
val EnumFacing.dir: AxisDirection get() = axisDirection val EnumFacing.dir: AxisDirection get() = axisDirection
val AxisDirection.sign: String get() = when(this) { POSITIVE -> "+"; NEGATIVE -> "-" } val AxisDirection.sign: String get() = when(this) { POSITIVE -> "+"; NEGATIVE -> "-" }
val forgeDirs = EnumFacing.values() val forgeDirs = EnumFacing.values()
val forgeDirsHorizontal = listOf(NORTH, SOUTH, EAST, WEST)
val forgeDirOffsets = forgeDirs.map { Int3(it) } val forgeDirOffsets = forgeDirs.map { Int3(it) }
val Pair<Axis, AxisDirection>.face: EnumFacing get() = when(this) { val Pair<Axis, AxisDirection>.face: EnumFacing get() = when(this) {
X to POSITIVE -> EAST; X to NEGATIVE -> WEST; X to POSITIVE -> EAST; X to NEGATIVE -> WEST;

View File

@@ -43,7 +43,7 @@ fun Any.reflectFieldsOfType(vararg types: Class<*>) = this.javaClass.declaredFie
.map { field -> field.name to field.let { it.isAccessible = true; it.get(this) } } .map { field -> field.name to field.let { it.isAccessible = true; it.get(this) } }
.filterNotNull() .filterNotNull()
enum class Namespace { OBF, SRG, MCP } enum class Namespace { MCP, SRG }
abstract class Resolvable<T> { abstract class Resolvable<T> {
abstract fun resolve(): T? abstract fun resolve(): T?
@@ -56,11 +56,9 @@ fun allAvailable(vararg codeElement: Resolvable<*>) = codeElement.all { it.eleme
/** /**
* Reference to a class. * Reference to a class.
* *
* @param[mcpName] MCP name of the class * @param[name] MCP name of the class
* @param[obfName] obfuscated name of the class
*/ */
open class ClassRef(val mcpName: String, val obfName: String) : Resolvable<Class<*>>() { open class ClassRef(val name: String) : Resolvable<Class<*>>() {
constructor(mcpName: String) : this(mcpName, mcpName)
companion object { companion object {
val int = ClassRefPrimitive("I", Int::class.java) val int = ClassRefPrimitive("I", Int::class.java)
@@ -70,10 +68,9 @@ open class ClassRef(val mcpName: String, val obfName: String) : Resolvable<Class
val void = ClassRefPrimitive("V", null) val void = ClassRefPrimitive("V", null)
} }
fun name(namespace: Namespace) = if (namespace == Namespace.OBF) obfName else mcpName open fun asmDescriptor(namespace: Namespace) = "L${name.replace(".", "/")};"
open fun asmDescriptor(namespace: Namespace) = "L${name(namespace).replace(".", "/")};"
override fun resolve() = listOf(mcpName, obfName).map { getJavaClass(it) }.filterNotNull().firstOrNull() override fun resolve() = getJavaClass(name)
fun isInstance(obj: Any) = element?.isInstance(obj) ?: false fun isInstance(obj: Any) = element?.isInstance(obj) ?: false
} }
@@ -85,17 +82,16 @@ open class ClassRef(val mcpName: String, val obfName: String) : Resolvable<Class
* @param[clazz] class of this primitive type * @param[clazz] class of this primitive type
*/ */
class ClassRefPrimitive(name: String, val clazz: Class<*>?) : ClassRef(name) { class ClassRefPrimitive(name: String, val clazz: Class<*>?) : ClassRef(name) {
override fun asmDescriptor(namespace: Namespace) = mcpName override fun asmDescriptor(namespace: Namespace) = name
override fun resolve() = clazz override fun resolve() = clazz
} }
class ClassRefArray(mcpName: String, obfName: String) : ClassRef(mcpName, obfName) { class ClassRefArray(name: String) : ClassRef(name) {
constructor(mcpName: String) : this(mcpName, mcpName)
override fun asmDescriptor(namespace: Namespace) = "[" + super.asmDescriptor(namespace) override fun asmDescriptor(namespace: Namespace) = "[" + super.asmDescriptor(namespace)
override fun resolve() = listOf(mcpName, obfName).map { getJavaClass("[L$it;") }.filterNotNull().firstOrNull() override fun resolve() = getJavaClass("[L$name;")
} }
fun ClassRef.array() = ClassRefArray(mcpName, obfName) fun ClassRef.array() = ClassRefArray(name)
/** /**
* Reference to a method. * Reference to a method.
@@ -103,30 +99,26 @@ fun ClassRef.array() = ClassRefArray(mcpName, obfName)
* @param[parentClass] reference to the class containing the method * @param[parentClass] reference to the class containing the method
* @param[mcpName] MCP name of the method * @param[mcpName] MCP name of the method
* @param[srgName] SRG name of the method * @param[srgName] SRG name of the method
* @param[obfName] obfuscated name of the method
* @param[returnType] reference to the return type * @param[returnType] reference to the return type
* @param[returnType] references to the argument types * @param[returnType] references to the argument types
*/ */
class MethodRef(val parentClass: ClassRef, class MethodRef(val parentClass: ClassRef,
val mcpName: String, val mcpName: String,
val srgName: String?, val srgName: String,
val obfName: String?,
val returnType: ClassRef, val returnType: ClassRef,
vararg argTypes: ClassRef vararg val argTypes: ClassRef
) : Resolvable<Method>() { ) : Resolvable<Method>() {
constructor(parentClass: ClassRef, mcpName: String, returnType: ClassRef, vararg argTypes: ClassRef) : constructor(parentClass: ClassRef, mcpName: String, returnType: ClassRef, vararg argTypes: ClassRef) :
this(parentClass, mcpName, mcpName, mcpName, returnType, *argTypes) this(parentClass, mcpName, mcpName, returnType, *argTypes)
val argTypes = argTypes fun name(namespace: Namespace) = when(namespace) { SRG -> srgName; MCP -> mcpName }
fun name(namespace: Namespace) = when(namespace) { OBF -> obfName!!; SRG -> srgName!!; MCP -> mcpName }
fun asmDescriptor(namespace: Namespace) = "(${argTypes.map { it.asmDescriptor(namespace) }.fold(""){ s1, s2 -> s1 + s2 } })${returnType.asmDescriptor(namespace)}" fun asmDescriptor(namespace: Namespace) = "(${argTypes.map { it.asmDescriptor(namespace) }.fold(""){ s1, s2 -> s1 + s2 } })${returnType.asmDescriptor(namespace)}"
override fun resolve(): Method? = override fun resolve(): Method? =
if (parentClass.element == null || argTypes.any { it.element == null }) null if (parentClass.element == null || argTypes.any { it.element == null }) null
else { else {
val args = argTypes.map { it.element!! }.toTypedArray() val args = argTypes.map { it.element!! }.toTypedArray()
listOf(srgName!!, mcpName).map { tryDefault(null) { listOf(srgName, mcpName).map { tryDefault(null) {
parentClass.element!!.getDeclaredMethod(it, *args) parentClass.element!!.getDeclaredMethod(it, *args)
}}.filterNotNull().firstOrNull() }}.filterNotNull().firstOrNull()
?.apply { isAccessible = true } ?.apply { isAccessible = true }
@@ -146,24 +138,22 @@ class MethodRef(val parentClass: ClassRef,
* @param[parentClass] reference to the class containing the field * @param[parentClass] reference to the class containing the field
* @param[mcpName] MCP name of the field * @param[mcpName] MCP name of the field
* @param[srgName] SRG name of the field * @param[srgName] SRG name of the field
* @param[obfName] obfuscated name of the field
* @param[type] reference to the field type * @param[type] reference to the field type
*/ */
class FieldRef(val parentClass: ClassRef, class FieldRef(val parentClass: ClassRef,
val mcpName: String, val mcpName: String,
val srgName: String?, val srgName: String,
val obfName: String?,
val type: ClassRef? val type: ClassRef?
) : Resolvable<Field>() { ) : Resolvable<Field>() {
constructor(parentClass: ClassRef, mcpName: String, type: ClassRef?) : this(parentClass, mcpName, mcpName, mcpName, type) constructor(parentClass: ClassRef, mcpName: String, type: ClassRef?) : this(parentClass, mcpName, mcpName, type)
fun name(namespace: Namespace) = when(namespace) { OBF -> obfName!!; SRG -> srgName!!; MCP -> mcpName } fun name(namespace: Namespace) = when(namespace) { SRG -> srgName; MCP -> mcpName }
fun asmDescriptor(namespace: Namespace) = type!!.asmDescriptor(namespace) fun asmDescriptor(namespace: Namespace) = type!!.asmDescriptor(namespace)
override fun resolve(): Field? = override fun resolve(): Field? =
if (parentClass.element == null) null if (parentClass.element == null) null
else { else {
listOf(srgName!!, mcpName).map { tryDefault(null) { listOf(srgName, mcpName).map { tryDefault(null) {
parentClass.element!!.getDeclaredField(it) parentClass.element!!.getDeclaredField(it)
}}.filterNotNull().firstOrNull() }}.filterNotNull().firstOrNull()
?.apply{ isAccessible = true } ?.apply{ isAccessible = true }

View File

@@ -1,7 +1,6 @@
package mods.octarinecore.metaprog package mods.octarinecore.metaprog
import mods.octarinecore.metaprog.Namespace.MCP import mods.octarinecore.metaprog.Namespace.*
import mods.octarinecore.metaprog.Namespace.OBF
import net.minecraft.launchwrapper.IClassTransformer import net.minecraft.launchwrapper.IClassTransformer
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
@@ -29,9 +28,6 @@ open class Transformer : IClassTransformer {
val log = LogManager.getLogger(this) val log = LogManager.getLogger(this)
/** The type of environment we are in. Assume MCP until proven otherwise. */
var environment: Namespace = MCP
/** The list of transformers and targets. */ /** The list of transformers and targets. */
var methodTransformers: MutableList<Pair<MethodRef, MethodTransformContext.()->Unit>> = arrayListOf() var methodTransformers: MutableList<Pair<MethodRef, MethodTransformContext.()->Unit>> = arrayListOf()
@@ -44,36 +40,28 @@ open class Transformer : IClassTransformer {
override fun transform(name: String?, transformedName: String?, classData: ByteArray?): ByteArray? { override fun transform(name: String?, transformedName: String?, classData: ByteArray?): ByteArray? {
if (classData == null) return null if (classData == null) return null
if (name != transformedName) environment = OBF
val classNode = ClassNode().apply { val reader = ClassReader(classData); reader.accept(this, 0) } val classNode = ClassNode().apply { val reader = ClassReader(classData); reader.accept(this, 0) }
var workDone = false var workDone = false
val transformations: List<Pair<MethodTransformContext.()->Unit, MethodNode?>> = methodTransformers.map { transformer -> synchronized(this) {
if (transformedName != transformer.first.parentClass.mcpName) return@map transformer.second to null methodTransformers.forEach { (targetMethod, transform) ->
log.debug("Found class: $name -> $transformedName") if (transformedName != targetMethod.parentClass.name) return@forEach
log.debug(" searching: ${transformer.first.name(OBF)} ${transformer.first.asmDescriptor(OBF)} -> ${transformer.first.name(MCP)} ${transformer.first.asmDescriptor(MCP)}")
transformer.second to classNode.methods.find {
log.debug(" ${it.name} ${it.desc}")
it.name == transformer.first.name(MCP) && it.desc == transformer.first.asmDescriptor(MCP) || for (method in classNode.methods) {
it.name == transformer.first.name(OBF) && it.desc == transformer.first.asmDescriptor(OBF) val namespace = Namespace.values().find {
method.name == targetMethod.name(it) && method.desc == targetMethod.asmDescriptor(it)
} ?: continue
when (namespace) {
MCP -> log.info("Found method ${targetMethod.parentClass.name}.${targetMethod.name(MCP)} ${targetMethod.asmDescriptor(MCP)}")
SRG -> log.info("Found method ${targetMethod.parentClass.name}.${targetMethod.name(namespace)} ${targetMethod.asmDescriptor(namespace)} (matching ${targetMethod.name(MCP)})")
} }
} MethodTransformContext(method, namespace).transform()
transformations.filter { it.second != null }.forEach {
synchronized(it.second!!) {
try {
val trans = it.first
MethodTransformContext(it.second!!, environment).trans()
workDone = true workDone = true
} catch (e: Throwable) {
log.warn("Error transforming method ${it.second!!.name} ${it.second!!.desc}")
} }
} }
} }
return if (!workDone) classData else ClassWriter(3).apply { classNode.accept(this) }.toByteArray() return if (!workDone) classData else ClassWriter(0).apply { classNode.accept(this) }.toByteArray()
} }
} }
@@ -169,7 +157,7 @@ class MethodTransformContext(val method: MethodNode, val environment: Namespace)
fun invokeRef(ref: MethodRef): (AbstractInsnNode)->Boolean = { insn -> fun invokeRef(ref: MethodRef): (AbstractInsnNode)->Boolean = { insn ->
(insn as? MethodInsnNode)?.let { (insn as? MethodInsnNode)?.let {
it.name == ref.name(environment) && it.owner == ref.parentClass.name(environment).replace(".", "/") it.name == ref.name(environment) && it.owner == ref.parentClass.name.replace(".", "/")
} ?: false } ?: false
} }
} }
@@ -202,7 +190,7 @@ class InstructionList(val environment: Namespace) {
*/ */
fun invokeStatic(target: MethodRef, isInterface: Boolean = false) = list.add(MethodInsnNode( fun invokeStatic(target: MethodRef, isInterface: Boolean = false) = list.add(MethodInsnNode(
Opcodes.INVOKESTATIC, Opcodes.INVOKESTATIC,
target.parentClass.name(environment).replace(".", "/"), target.parentClass.name.replace(".", "/"),
target.name(environment), target.name(environment),
target.asmDescriptor(environment), target.asmDescriptor(environment),
isInterface isInterface
@@ -215,7 +203,7 @@ class InstructionList(val environment: Namespace) {
*/ */
fun getField(target: FieldRef) = list.add(FieldInsnNode( fun getField(target: FieldRef) = list.add(FieldInsnNode(
Opcodes.GETFIELD, Opcodes.GETFIELD,
target.parentClass.name(environment).replace(".", "/"), target.parentClass.name.replace(".", "/"),
target.name(environment), target.name(environment),
target.asmDescriptor(environment) target.asmDescriptor(environment)
)) ))

View File

@@ -1,8 +1,8 @@
// Vanilla // Vanilla
net.minecraft.block.BlockTallGrass net.minecraft.block.BlockTallGrass
net.minecraft.block.BlockCrops net.minecraft.block.BlockCrops
net.minecraft.block.BlockReed -net.minecraft.block.BlockReed
net.minecraft.block.BlockDoublePlant -net.minecraft.block.BlockDoublePlant
-net.minecraft.block.BlockCarrot -net.minecraft.block.BlockCarrot
-net.minecraft.block.BlockPotato -net.minecraft.block.BlockPotato