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,21 +45,23 @@ 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 ->
val drawIcon = icon(this, quadIdx, quad) if (quadFilter(quadIdx, quad)) {
if (drawIcon != null) { val drawIcon = icon(this, quadIdx, quad)
quad.verts.forEachIndexed { vertIdx, vert -> if (drawIcon != null) {
temp.init(vert).rotate(rotation).translate(trans) quad.verts.forEachIndexed { vertIdx, vert ->
val shader = if (aoEnabled && !forceFlat) vert.aoShader else vert.flatShader temp.init(vert).rotate(rotation).translate(trans)
shader.shade(this, temp) val shader = if (aoEnabled && !forceFlat) vert.aoShader else vert.flatShader
temp.postProcess(this, quadIdx, quad, vertIdx, vert) shader.shade(this, temp)
temp.setIcon(drawIcon) temp.postProcess(this, quadIdx, quad, vertIdx, vert)
temp.setIcon(drawIcon)
worldRenderer worldRenderer
.pos(temp.x, temp.y, temp.z) .pos(temp.x, temp.y, temp.z)
.color(temp.red, temp.green, temp.blue, 1.0f) .color(temp.red, temp.green, temp.blue, 1.0f)
.tex(temp.u, temp.v) .tex(temp.u, temp.v)
.lightmap(temp.brightness shr 16 and 65535, temp.brightness and 65535) .lightmap(temp.brightness shr 16 and 65535, temp.brightness and 65535)
.endVertex() .endVertex()
}
} }
} }
} }
@@ -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) {
transformations.filter { it.second != null }.forEach { MCP -> log.info("Found method ${targetMethod.parentClass.name}.${targetMethod.name(MCP)} ${targetMethod.asmDescriptor(MCP)}")
synchronized(it.second!!) { SRG -> log.info("Found method ${targetMethod.parentClass.name}.${targetMethod.name(namespace)} ${targetMethod.asmDescriptor(namespace)} (matching ${targetMethod.name(MCP)})")
try { }
val trans = it.first MethodTransformContext(method, namespace).transform()
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