Merge branch 'kotlin-1.11.2' into kotlin-1.12

This commit is contained in:
octarine-noise
2017-08-12 19:12:46 +02:00
26 changed files with 277 additions and 130 deletions

View File

@@ -73,6 +73,11 @@ fun <T> tryDefault(default: T, work: ()->T) = try { work() } catch (e: Throwable
/** Return a random [Double] value between the given two limits (inclusive min, exclusive max). */
fun random(min: Double, max: Double) = Math.random().let { min + (max - min) * it }
fun semiRandom(x: Int, y: Int, z: Int, seed: Int): Int {
var value = (x * x + y * y + z * z + x * y + y * z + z * x + (seed * seed)) and 63
value = (3 * x * value + 5 * y * value + 7 * z * value + (11 * seed)) and 63
return value
}
/**
* Return this [Double] value if it lies between the two limits. If outside, return the
* minimum/maximum value correspondingly.

View File

@@ -10,6 +10,7 @@ import mods.octarinecore.common.Double3
import mods.octarinecore.common.Int3
import mods.octarinecore.common.forgeDirOffsets
import mods.octarinecore.common.plus
import mods.octarinecore.semiRandom
import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
import net.minecraft.client.Minecraft
@@ -105,11 +106,7 @@ class BlockContext {
fun isSurroundedBy(predicate: (IBlockState)->Boolean) = forgeDirOffsets.all { predicate(blockState(it)) }
/** Get a semi-random value based on the block coordinate and the given seed. */
fun random(seed: Int): Int {
var value = (pos.x * pos.x + pos.y * pos.y + pos.z * pos.z + pos.x * pos.y + pos.y * pos.z + pos.z * pos.x + (seed * seed)) and 63
value = (3 * pos.x * value + 5 * pos.y * value + 7 * pos.z * value + (11 * seed)) and 63
return value
}
fun random(seed: Int) = semiRandom(pos.x, pos.y, pos.z, seed)
/** Get an array of semi-random values based on the block coordinate. */
fun semiRandomArray(num: Int): Array<Int> = Array(num) { random(it) }

View File

@@ -2,7 +2,6 @@ package mods.octarinecore.client.resource
import com.google.common.base.Joiner
import mods.betterfoliage.loader.Refs
import mods.octarinecore.common.config.ConfigurableBlockMatcher
import mods.octarinecore.common.config.IBlockMatcher
import mods.octarinecore.common.config.ModelTextureList
import mods.octarinecore.filterValuesNotNull
@@ -13,6 +12,7 @@ import net.minecraft.client.renderer.block.statemap.DefaultStateMapper
import net.minecraft.client.renderer.block.statemap.IStateMapper
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.util.ResourceLocation
import net.minecraftforge.client.event.TextureStitchEvent
import net.minecraftforge.client.model.IModel
import net.minecraftforge.client.model.ModelLoader
@@ -24,20 +24,36 @@ import org.apache.logging.log4j.Logger
class LoadModelDataEvent(val loader: ModelLoader) : Event()
data class ModelVariant(
val state: IBlockState,
val modelLocation: ResourceLocation?,
val weight: Int
)
interface ModelProcessor<T1, T2> {
val logger: Logger?
var stateToKey: MutableMap<IBlockState, T1>
var stateToValue: Map<IBlockState, T2>
var variants: MutableMap<IBlockState, MutableList<ModelVariant>>
var variantToKey: MutableMap<ModelVariant, T1>
var variantToValue: Map<ModelVariant, T2>
fun addVariant(state: IBlockState, variant: ModelVariant) { variants.getOrPut(state) { mutableListOf() }.add(variant) }
fun getVariant(state: IBlockState, rand: Int) = variants[state]?.let { it[rand % it.size] }
fun putKeySingle(state: IBlockState, key: T1) {
val variant = ModelVariant(state, null, 1)
variants[state] = mutableListOf(variant)
variantToKey[variant] = key
}
fun onPostLoad() { }
fun onPreStitch() { }
fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): T1?
fun processStitch(state: IBlockState, key: T1, atlas: TextureMap): T2?
fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel)
fun processStitch(variant: ModelVariant, key: T1, atlas: TextureMap): T2?
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun clearBeforeLoadModelData(event: LoadModelDataEvent) {
stateToKey.clear()
variants.clear()
variantToKey.clear()
}
@SubscribeEvent
@@ -52,7 +68,7 @@ interface ModelProcessor<T1, T2> {
stateMappings.forEach { mapping ->
if (mapping.key.block != null) stateModels[mapping.value]?.let { model ->
processModelLoad(mapping.key, mapping.value, model)?.let { key -> stateToKey.put(mapping.key, key) }
processModelLoad(mapping.key, mapping.value, model)
}
}
}
@@ -61,7 +77,7 @@ interface ModelProcessor<T1, T2> {
@SubscribeEvent(priority = EventPriority.LOW)
fun handlePreStitch(event: TextureStitchEvent.Pre) {
onPreStitch()
stateToValue = stateToKey.mapValues { processStitch(it.key, it.value, event.map) }.filterValuesNotNull()
variantToValue = variantToKey.mapValues { processStitch(it.key, it.value, event.map) }.filterValuesNotNull()
}
}
@@ -70,30 +86,60 @@ interface TextureListModelProcessor<T2> : ModelProcessor<List<String>, T2> {
val matchClasses: IBlockMatcher
val modelTextures: List<ModelTextureList>
override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List<String>? {
val matchClass = matchClasses.matchingClass(state.block) ?: return null
override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel) {
val matchClass = matchClasses.matchingClass(state.block) ?: return
logger?.log(Level.DEBUG, "$logName: block state ${state.toString()}")
logger?.log(Level.DEBUG, "$logName: class ${state.block.javaClass.name} matches ${matchClass.name}")
val allModels = model.modelBlockAndLoc
val allModels = model.modelBlockAndLoc.distinctBy { it.second }
if (allModels.isEmpty()) {
logger?.log(Level.DEBUG, "$logName: no models found")
return null
return
}
allModels.forEach { blockLoc ->
modelTextures.firstOrNull { blockLoc.derivesFrom(it.modelLocation) }?.let{ modelMatch ->
logger?.log(Level.DEBUG, "$logName: model ${blockLoc.second} matches ${modelMatch.modelLocation.toString()}")
val modelMatch = modelTextures.firstOrNull { blockLoc.derivesFrom(it.modelLocation) }
if (modelMatch != null) {
logger?.log(Level.DEBUG, "$logName: model ${blockLoc.second} matches ${modelMatch.modelLocation}")
val textures = modelMatch.textureNames.map { it to blockLoc.first.resolveTextureName(it) }
val texMapString = Joiner.on(", ").join(textures.map { "${it.first}=${it.second}" })
logger?.log(Level.DEBUG, "$logName: textures [$texMapString]")
return if (textures.all { it.second != "missingno" }) textures.map { it.second } else null
if (textures.all { it.second != "missingno" }) {
// found a valid variant (all required textures exist)
val variant = ModelVariant(state, blockLoc.second, 1)
addVariant(state, variant)
variantToKey[variant] = textures.map { it.second }
}
}
}
logger?.log(Level.DEBUG, "$logName: no matching models found")
return null
}
// override fun processModelLoad(state: IBlockState, modelLoc: ModelResourceLocation, model: IModel): List<String>? {
// val matchClass = matchClasses.matchingClass(state.block) ?: return null
// logger?.log(Level.DEBUG, "$logName: block state ${state.toString()}")
// logger?.log(Level.DEBUG, "$logName: class ${state.block.javaClass.name} matches ${matchClass.name}")
//
// val allModels = model.modelBlockAndLoc
// if (allModels.isEmpty()) {
// logger?.log(Level.DEBUG, "$logName: no models found")
// return null
// }
// allModels.forEach { blockLoc ->
// modelTextures.firstOrNull { blockLoc.derivesFrom(it.modelLocation) }?.let{ modelMatch ->
// logger?.log(Level.DEBUG, "$logName: model ${blockLoc.second} matches ${modelMatch.modelLocation.toString()}")
//
// val textures = modelMatch.textureNames.map { it to blockLoc.first.resolveTextureName(it) }
// val texMapString = Joiner.on(", ").join(textures.map { "${it.first}=${it.second}" })
// logger?.log(Level.DEBUG, "$logName: textures [$texMapString]")
//
// return if (textures.all { it.second != "missingno" }) textures.map { it.second } else null
// }
// }
// logger?.log(Level.DEBUG, "$logName: no matching models found")
// return null
// }
}
interface TextureMediatedRegistry<T1, T3> : ModelProcessor<T1, TextureAtlasSprite> {
@@ -105,9 +151,9 @@ interface TextureMediatedRegistry<T1, T3> : ModelProcessor<T1, TextureAtlasSprit
textureToValue.clear()
super.handlePreStitch(event)
val textureToStates = stateToValue.entries.groupBy(keySelector = { it.value }, valueTransform = { it.key })
stateToValue.values.toSet().forEach { processTexture(textureToStates[it]!!, it, event.map) }
val textureToVariants = variantToValue.entries.groupBy(keySelector = { it.value }, valueTransform = { it.key })
variantToValue.values.toSet().forEach { processTexture(textureToVariants[it]!!, it, event.map) }
}
fun processTexture(states: List<IBlockState>, texture: TextureAtlasSprite, atlas: TextureMap)
fun processTexture(states: List<ModelVariant>, texture: TextureAtlasSprite, atlas: TextureMap)
}