Compare commits

..
Author SHA1 Message Date
Landon Wills c921496b50 some shader stuff 2025-08-31 11:37:55 -04:00
Landon Wills a9d1000384 testing 2025-08-28 01:11:03 -04:00
Landon Wills 225721aec4 Add tropius 2025-08-26 16:58:05 -04:00
Landon Wills ae9475959d Add sound scraping 2025-08-26 16:57:52 -04:00
14 changed files with 275 additions and 66 deletions

No files matched your search

@@ -8,17 +8,26 @@
package com.cobblemon.mod.common.client.render.models.blockbench
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel.Companion.getOrMakeShard
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.shader.CobblemonShaders
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.util.cobblemonResource
import com.google.common.collect.ImmutableList
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.client.renderer.RenderType
import com.mojang.blaze3d.vertex.VertexConsumer
import net.minecraft.client.renderer.entity.LivingEntityRenderer
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexFormat
import net.minecraft.client.model.EntityModel
import net.minecraft.client.renderer.RenderStateShard
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity
import net.minecraft.resources.ResourceLocation
import org.apache.commons.lang3.tuple.Triple
/**
* A wrapping around a [PosableModel] that presents as an [EntityModel]. This is used to continue using
@@ -29,13 +38,46 @@ import net.minecraft.resources.ResourceLocation
* @since January 5th, 2024
*/
abstract class PosableEntityModel<T : Entity>(
renderTypeFunc: (ResourceLocation) -> RenderType = RenderType::entityCutout
renderTypeFunc: (ResourceLocation) -> RenderType = {
val textures = ImmutableList.of(
Triple.of(it, false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
)
makeLayer(RenderStateShard.MultiTextureStateShard(textures), false, false, false)
}
) : EntityModel<T>(renderTypeFunc) {
val context: RenderContext = RenderContext().also {
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.WORLD)
}
lateinit var posableModel: PosableModel
companion object {
fun makeLayer(texture: RenderStateShard.EmptyTextureStateShard, emissive: Boolean, translucent: Boolean, translucentCull: Boolean): RenderType {
val multiPhaseParameters: RenderType.CompositeState = RenderType.CompositeState.builder()
.setShaderState(getOrMakeShard() as RenderStateShard.ShaderStateShard)
.setTextureState(texture)
.setTransparencyState(if (translucent) RenderStateShard.TRANSLUCENT_TRANSPARENCY else RenderStateShard.NO_TRANSPARENCY)
.setLightmapState(if (!emissive) RenderStateShard.LIGHTMAP else RenderStateShard.LightmapStateShard(false))
.setCullState(RenderStateShard.CULL)
.setWriteMaskState(RenderStateShard.COLOR_DEPTH_WRITE)
.setOverlayState(RenderStateShard.OVERLAY)
.createCompositeState(false)
return RenderType.create(
"cobblemon_entity_layer",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.QUADS,
256,
true,
translucent,
multiPhaseParameters
)
}
}
override fun renderToBuffer(
stack: PoseStack,
buffer: VertexConsumer,
@@ -49,6 +91,7 @@ abstract class PosableEntityModel<T : Entity>(
// We're using the living entity renderer, ergo we need to apply a Y offset of 24 model units (1.5 blocks) for reasons only God can tell us.
stack.translate(0.0, 1.5, 0.0)
}
// RenderSystem.setShader { CobblemonShaders.OVERLAY }
posableModel.render(context, stack, buffer, packedLight, overlay, color)
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.client.ClientMoLangFunctions.animationFunctions
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.client.render.AnimatedModelTextureSupplier
import com.cobblemon.mod.common.client.render.ModelLayer
@@ -33,6 +34,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.SimpleQuirk
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
import com.cobblemon.mod.common.client.render.shader.CobblemonShaders
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
@@ -40,26 +42,33 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.plus
import com.cobblemon.mod.common.util.toRGBA
import com.google.common.collect.ImmutableList
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.blaze3d.vertex.VertexFormat
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderStateShard
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.ShaderInstance
import net.minecraft.client.renderer.texture.DynamicTexture
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.ItemDisplayContext
import net.minecraft.world.phys.Vec3
import org.apache.commons.lang3.tuple.Triple
import org.joml.Matrix4f
import org.joml.Vector3f
import java.lang.reflect.Constructor
/**
* A model that can be posed and animated using [PoseAnimation]s and [ActiveAnimation]s. This
@@ -414,6 +423,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
/** Needed a custom one, so I can make it take in a dynamic texture instead of resource location */
class DynamicStateShard(texture: DynamicTexture) : RenderStateShard.EmptyTextureStateShard(Runnable {
RenderSystem.setShaderTexture(0, texture.id)
RenderSystem.setShaderTexture(1, cobblemonResource("textures/tera_layer.png"))
}, Runnable {
texture.close() // Cleanup
})
@@ -453,13 +463,14 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
if (provider != null) {
for (layer in currentLayers) {
var renderLayer : RenderType
var texture: ResourceLocation? = null
if (layer.texture is AnimatedModelTextureSupplier && layer.texture.interpolation) {
//Handle Interpolation
val texture = layer.texture.interpolatedTexture(currentState ?: FloatingState()) ?: continue
renderLayer = makeLayer(DynamicStateShard(texture), layer.emissive, layer.translucent, layer.translucent_cull)
}
else {
val texture = layer.texture?.invoke(currentState ?: FloatingState()) ?: continue
texture = layer.texture?.invoke(currentState ?: FloatingState()) ?: continue
renderLayer = getLayer(texture, layer.emissive, layer.translucent, layer.translucent_cull)
}
val consumer = provider.getBuffer(renderLayer)
@@ -490,18 +501,21 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
return ItemDisplayContext.valueOf(displayContextString)
}
companion object {
var test: Any? = null
fun getOrMakeShard(): Any {
if (test == null) {
test = RenderStateShard.ShaderStateShard({ CobblemonShaders.OVERLAY })
}
return test!!
}
}
/** Generates a [RenderType] by the power of god and anime. Only possible thanks to 100 access wideners. */
fun makeLayer(texture: RenderStateShard.EmptyTextureStateShard, emissive: Boolean, translucent: Boolean, translucentCull: Boolean): RenderType {
val multiPhaseParameters: RenderType.CompositeState = RenderType.CompositeState.builder()
.setShaderState(
when {
emissive && translucent -> RenderStateShard.RENDERTYPE_ENTITY_TRANSLUCENT_EMISSIVE_SHADER
!emissive && translucent && translucentCull -> RenderStateShard.RENDERTYPE_ENTITY_TRANSLUCENT_CULL_SHADER
!emissive && translucent -> RenderStateShard.RENDERTYPE_ENTITY_TRANSLUCENT_SHADER
!emissive && !translucent -> RenderStateShard.RENDERTYPE_ENTITY_CUTOUT_SHADER
else -> RenderStateShard.RENDERTYPE_ENTITY_TRANSLUCENT_EMISSIVE_SHADER // This one should be changed to maybe a custom shader? Translucent stuffs with things
}
)
.setShaderState(getOrMakeShard() as RenderStateShard.ShaderStateShard)
.setTextureState(texture)
.setTransparencyState(if (translucent) RenderStateShard.TRANSLUCENT_TRANSPARENCY else RenderStateShard.NO_TRANSPARENCY)
.setLightmapState(if (!emissive) RenderStateShard.LIGHTMAP else RenderStateShard.LightmapStateShard(false))
@@ -528,7 +542,14 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
} else if (!emissive && !translucentCull) {
RenderType.entityTranslucent(texture)
} else {
makeLayer(RenderStateShard.TextureStateShard(texture, false, false), emissive = emissive, translucent = translucent, translucentCull = translucentCull)
val texture = RenderStateShard.MultiTextureStateShard(ImmutableList.of(
Triple.of(texture, false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
Triple.of(cobblemonResource("textures/tera_layer.png"), false, false),
))
makeLayer(texture, emissive = emissive, translucent = translucent, translucentCull = translucentCull)
}
}
@@ -20,6 +20,7 @@ object CobblemonShaders {
lateinit var PARTICLE_BLEND: ShaderInstance
// This is Material.ALPHA. Weird internal name for "alphatest" shader.
lateinit var PARTICLE_CUTOUT: ShaderInstance
lateinit var OVERLAY: ShaderInstance
private fun registerShader(shader: (ResourceProvider) -> ShaderRegistryData, callback: Consumer<ShaderInstance>){
SHADERS_TO_REGISTER.add(Pair(shader, callback))
@@ -31,5 +32,8 @@ object CobblemonShaders {
registerShader({rm: ResourceProvider -> ShaderRegistryData(rm, cobblemonResource("particle_cutout"), DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) }) {
PARTICLE_CUTOUT = it
}
registerShader({rm: ResourceProvider -> ShaderRegistryData(rm, cobblemonResource("overlay"), DefaultVertexFormat.NEW_ENTITY) }) {
OVERLAY = it
}
}
}
@@ -0,0 +1,36 @@
#version 150
#moj_import <fog.glsl>
uniform sampler2D Sampler0;
uniform sampler2D Sampler3;
uniform vec4 ColorModulator;
uniform float FogStart;
uniform float FogEnd;
uniform vec4 FogColor;
uniform float u_evo_progress;
in float vertexDistance;
in vec4 vertexColor;
in vec4 lightMapColor;
in vec4 overlayColor;
in vec2 texCoord0;
in vec4 normal;
out vec4 fragColor;
void main() {
vec4 color = texture(Sampler0, texCoord0);
vec4 teraColor = texture(Sampler3, texCoord0);
if (color.a < 0.1) {
discard;
}
vec4 mixed = mix(color, teraColor, teraColor.a);
color = mixed * vertexColor * ColorModulator;
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
color *= lightMapColor;
color = mix(color, vec4(1.0, 1.0, 1.0, 1.0), u_evo_progress);
fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor);
}
@@ -0,0 +1,37 @@
#version 150
#moj_import <light.glsl>
#moj_import <fog.glsl>
in vec3 Position;
in vec4 Color;
in vec2 UV0;
in ivec2 UV1;
in ivec2 UV2;
in vec3 Normal;
uniform sampler2D Sampler1;
uniform sampler2D Sampler2;
uniform mat4 ModelViewMat;
uniform mat4 ProjMat;
uniform int FogShape;
uniform vec3 Light0_Direction;
uniform vec3 Light1_Direction;
out float vertexDistance;
out vec4 vertexColor;
out vec4 lightMapColor;
out vec4 overlayColor;
out vec2 texCoord0;
void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
vertexDistance = fog_distance(Position, FogShape);
vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, Normal, Color);
lightMapColor = texelFetch(Sampler2, UV2 / 16, 0);
overlayColor = texelFetch(Sampler1, UV1, 0);
texCoord0 = UV0;
}
@@ -0,0 +1,36 @@
{
"blend": {
"func": "add",
"srcrgb": "srcalpha",
"dstrgb": "1-srcalpha"
},
"vertex": "cobblemon:foo",
"fragment": "cobblemon:bar",
"attributes": [
"Position",
"Color",
"UV0",
"UV1",
"UV2",
"Normal"
],
"samplers": [
{ "name": "Sampler0" },
{ "name": "Sampler1" },
{ "name": "Sampler2" },
{ "name": "Sampler3" }
],
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] },
{ "name": "Light0_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] },
{ "name": "Light1_Direction", "type": "float", "count": 3, "values": [0.0, 0.0, 0.0] },
{ "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] },
{ "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] },
{ "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] },
{ "name": "u_evo_progress", "type": "float", "count": 1, "values": [ 0 ]}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

@@ -79,6 +79,9 @@ transitive-accessible field net/minecraft/client/renderer/RenderStateShard ADDIT
#transitive-accessible field net/minecraft/recipe/BrewingRecipeRegistry POTION_RECIPES Ljava/util/List;
#transitive-accessible field net/minecraft/recipe/BrewingRecipeRegistry POTION_TYPES Ljava/util/List;
transitive-accessible class net/minecraft/world/item/alchemy/PotionBrewing$Mix
transitive-accessible class net/minecraft/client/renderer/RenderStateShard$ShaderStateShard
transitive-accessible class net/minecraft/client/renderer/RenderStateShard$MultiTextureStateShard
transitive-accessible method net/minecraft/client/renderer/RenderStateShard$MultiTextureStateShard <init> (Lcom/google/common/collect/ImmutableList;)V
transitive-accessible class net/minecraft/util/datafix/fixes/ItemStackComponentizationFix$ItemStackData
@@ -490,6 +490,65 @@
"speed": 100
},
"baseExperienceYield": 317,
"riding": {
"behaviour": {
"alternateBehaviour": {
"speed": "Math.clamp(q.entity.velocity.horizontal_magnitude + 0.33, 0, 1)",
"gravity": "q.gravity * (0.1 + (q.passenger_count - 1) * 0.1)",
"jumpVector": [
0,
"0.3*q.jump_strength/50",
0
],
"key": "cobblemon:air/bird"
},
"defaultBehaviour": {
"speed": "Math.clamp(q.entity.velocity.horizontal_magnitude + 0.33, 0, 1)",
"gravity": "q.gravity * (0.1 + (q.passenger_count - 1) * 0.1)",
"jumpVector": [
0,
"0.3*q.jump_strength/50",
"-1 * 0.5*q.jump_strength/50"
],
"key": "cobblemon:land/horse"
},
"key": "cobblemon:composite",
"transitionStrategy": "cobblemon:strategy/jump"
},
"seats": [],
"stats": {
"ACCELERATION": {
"ranges": {
"AIR": "20-50",
"LAND": "90-100"
}
},
"JUMP": {
"ranges": {
"AIR": "25-50",
"LAND": "10-20"
}
},
"SKILL": {
"ranges": {
"AIR": "50-100",
"LAND": "15-30"
}
},
"SPEED": {
"ranges": {
"AIR": "25-60",
"LAND": "10-20"
}
},
"STAMINA": {
"ranges": {
"AIR": "35-70",
"LAND": "15-30"
}
}
}
},
"evolutions": [],
"battleOnly": true,
"dynamaxBlocked": true
@@ -53,24 +53,22 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/hover",
"ridingSounds": [],
"stats": {
"ACCELERATION": "41-60",
"JUMP": "41-60",
"SKILL": "41-60",
"ACCELERATION": "21-40",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "21-40"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "41-60",
"JUMP": "21-40",
"SKILL": "21-40",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "21-40"
}
}
},
@@ -52,7 +52,7 @@
"riding": {
"behaviours": {
"LIQUID": {
"key": "cobblemon:liquid/boat",
"key": "cobblemon:liquid/submarine",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
@@ -53,35 +53,22 @@
"behaviours": {
"AIR": {
"key": "cobblemon:air/rocket",
"ridingSounds": [
{
"muffleEnabled": true,
"pitchExpr": "math.max(1.0 ,0.2 + math.pow(math.min(q.driver_input() / 1.5, 1.0),2))",
"playForNonPassengers": true,
"soundLocation": "cobblemon:ride.loop.rocket",
"volumeExpr": "math.pow(math.min((q.driver_input() / 1.5) + (q.ride_velocity() / 1.5), 1.0),2)"
},
{
"soundLocation": "cobblemon:ride.loop.wind"
}
],
"stats": {
"ACCELERATION": "21-40",
"JUMP": "41-60",
"SKILL": "0-20",
"ACCELERATION": "0-20",
"JUMP": "61-80",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "61-80"
"STAMINA": "41-60"
}
},
"LAND": {
"key": "cobblemon:land/horse",
"ridingSounds": [],
"stats": {
"ACCELERATION": "21-40",
"ACCELERATION": "0-20",
"JUMP": "41-60",
"SKILL": "0-20",
"SKILL": "41-60",
"SPEED": "21-40",
"STAMINA": "41-60"
"STAMINA": "61-80"
}
}
},
@@ -41,7 +41,9 @@ public class GameRendererMixin {
} catch (IOException e) {
throw new RuntimeException(e);
}
FabricShaderProgram finalProgram = program;
list2.removeIf(x -> x.getFirst().getName().equals(finalProgram.getName()));
list2.add(Pair.of(program, pair.getSecond()));
});
}
}
}
+7 -24
View File
@@ -409,30 +409,11 @@
Returns the sanitized JSON map."
[json-data]
(-> json-data
(dissoc-in [:riding :behaviours])
(dissoc-in [:riding :behaviour])
(dissoc-in [:riding :stats])
(dissoc-in [:riding :seats])))
(defn reconcile-riding-sounds [a b]
(update b :behaviours
(fn [b-behaviours]
(reduce-kv
(fn [acc k b-entry]
(let [a-sounds (get-in a [:behaviours k :ridingSounds])
b-sounds (:ridingSounds b-entry)]
(if (seq b-sounds)
(let [a-by-loc (into {} (map (juxt :soundLocation identity) a-sounds))
b-by-loc (into {} (map (juxt :soundLocation identity) b-sounds))
;; keep sounds that exist in both (from A) + sounds only in B
merged (concat
(vals (select-keys a-by-loc (keys b-by-loc))) ; from A
(vals (apply dissoc b-by-loc (keys a-by-loc))))] ; only B
(assoc-in acc [k :ridingSounds] (vec merged)))
;; if B has no sounds, just skip
(assoc acc k b-entry))))
{}
b-behaviours))))
(defn apply-riding-data
"Apply computed `riding-data` to an existing species JSON structure.
- First sanitizes old/legacy riding fields.
@@ -444,14 +425,14 @@
(if form
(assoc sanitized-json-data :forms (map #(if (= (:name %) form) (apply-riding-data % riding-data nil) %) (:forms sanitized-json-data)))
(let [old-riding-json-data (:riding sanitized-json-data)
new-riding-json-data (reconcile-riding-sounds old-riding-json-data (get-in riding-data [:riding]))]
(assoc sanitized-json-data :riding (deep-merge old-riding-json-data new-riding-json-data))))))
new-riding-json-data (get-in riding-data [:riding])]
(assoc sanitized-json-data :riding (merge old-riding-json-data new-riding-json-data))))))
(def sort-order
[:implemented :nationalPokedexNumber :name :primaryType :secondaryType :maleRatio :height :weight
:pokedex :labels :aspects :abilities :eggGroups :baseStats :evYield :baseExperienceYield :experienceGroup :catchRate
:eggCycles :baseFriendship :baseScale :hitbox :riding :behaviour :drops :moves :preEvolution :evolutions
:forms :hp :attack :defence :special_attack :special_defence :speed :key :ridingSounds])
:forms :hp :attack :defence :special_attack :special_defence :speed])
(defn key-comparator
"Create a comparator for map keys using a preferred order.
@@ -567,4 +548,6 @@
(run-script)
(.setRunnable PokemonRenderer/Companion nil)))))
(-main)
(-main)
(.setRunnable PokemonRenderer/Companion nil)