parent
a688f775b8
commit
3ead1c998d
@ -360,9 +360,15 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
|
||||
fun onHurt(event: LivingHurtEvent) {
|
||||
if (isAndroid) {
|
||||
for (feature in featureMap.values) {
|
||||
feature.onHurt(event)
|
||||
}
|
||||
|
||||
if (!event.isCanceled) {
|
||||
sendNetwork(GlitchPacket((event.amount * 300).toLong().coerceAtLeast(200L).coerceAtMost(800L)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> computeIfAbsent(feature: AndroidFeatureType<T>): T {
|
||||
|
@ -1,5 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.client
|
||||
|
||||
import com.mojang.blaze3d.pipeline.MainTarget
|
||||
import com.mojang.blaze3d.platform.GlConst.GL_COLOR_BUFFER_BIT
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.BufferUploader
|
||||
@ -7,6 +10,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import com.mojang.math.Matrix4f
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
@ -16,6 +20,7 @@ import net.minecraftforge.client.event.ScreenEvent
|
||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
|
||||
import ru.dbotthepony.mc.otm.android.feature.JumpBoostFeature
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.render.GlitchRenderer
|
||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.render.tesselator
|
||||
@ -27,6 +32,7 @@ import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorScreen
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.identityFast
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import kotlin.math.min
|
||||
|
||||
fun onMovementInputUpdate(event: MovementInputUpdateEvent) {
|
||||
val ply = event.entity
|
||||
@ -111,11 +117,3 @@ fun onScreenOpen(event: ScreenEvent.Opening) {
|
||||
event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu)
|
||||
}
|
||||
}
|
||||
|
||||
fun postLevelDrawHook(poseStack: PoseStack) {
|
||||
|
||||
}
|
||||
|
||||
fun lastLevelDrawHook(poseStack: PoseStack) {
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,505 @@
|
||||
package ru.dbotthepony.mc.otm.client.render
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.blaze3d.pipeline.MainTarget
|
||||
import com.mojang.blaze3d.platform.GlConst
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder
|
||||
import com.mojang.blaze3d.vertex.BufferUploader
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import com.mojang.math.Matrix4f
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.component1
|
||||
import ru.dbotthepony.mc.otm.core.component2
|
||||
import ru.dbotthepony.mc.otm.core.component3
|
||||
import ru.dbotthepony.mc.otm.core.linearInterpolation
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.pow
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
object GlitchRenderer {
|
||||
private abstract class VideoGlitchType {
|
||||
abstract fun upload(builder: BufferBuilder, x: Double, y: Double, width: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float)
|
||||
|
||||
protected fun uploadVertices(faces: Int, builder: BufferBuilder, x: Double, y: Double, width: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float, red: Int, green: Int, blue: Int, alpha: Int) {
|
||||
if (faces and BOTTOM_LEFT != 0) {
|
||||
builder.vertex(x, y + height, 0.0).uv(u0, v1).color(red, green, blue, alpha).endVertex()
|
||||
}
|
||||
|
||||
if (faces and BOTTOM_RIGHT != 0) {
|
||||
builder.vertex(x + width, y + height, 0.0).uv(u1, v1).color(red, green, blue, alpha).endVertex()
|
||||
}
|
||||
|
||||
if (faces and TOP_RIGHT != 0) {
|
||||
builder.vertex(x + width, y, 0.0).uv(u1, v0).color(red, green, blue, alpha).endVertex()
|
||||
}
|
||||
|
||||
if (faces and TOP_LEFT != 0) {
|
||||
builder.vertex(x, y, 0.0).uv(u0, v0).color(red, green, blue, alpha).endVertex()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun uploadQuad(builder: BufferBuilder, x: Double, y: Double, width: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float, red: Int, green: Int, blue: Int, alpha: Int) {
|
||||
uploadVertices(TOP_LEFT or TOP_RIGHT or BOTTOM_RIGHT, builder, x, y, width, height, u0, v0, u1, v1, red, green, blue, alpha)
|
||||
uploadVertices(TOP_LEFT or BOTTOM_RIGHT or BOTTOM_LEFT, builder, x, y, width, height, u0, v0, u1, v1, red, green, blue, alpha)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TOP_LEFT = 1
|
||||
const val TOP_RIGHT = 2
|
||||
const val BOTTOM_LEFT = 4
|
||||
const val BOTTOM_RIGHT = 8
|
||||
|
||||
val vertices = intArrayOf(
|
||||
TOP_LEFT,
|
||||
TOP_RIGHT,
|
||||
BOTTOM_LEFT,
|
||||
BOTTOM_RIGHT,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val glitchesSorted: List<List<VideoGlitchType>>
|
||||
private val glitchesTrisSorted: List<List<VideoGlitchType>>
|
||||
private val glitchesQuadsSorted: List<List<VideoGlitchType>>
|
||||
|
||||
private fun selectGlitch(): List<VideoGlitchType> {
|
||||
for (list in glitchesSorted) {
|
||||
if (random.nextFloat() < 0.35f) {
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
return glitchesSorted[glitchesSorted.size - 1]
|
||||
}
|
||||
|
||||
private fun selectGlitchQuad(): List<VideoGlitchType> {
|
||||
for (list in glitchesQuadsSorted) {
|
||||
if (random.nextFloat() < 0.35f) {
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
return glitchesQuadsSorted[glitchesQuadsSorted.size - 1]
|
||||
}
|
||||
|
||||
private fun selectGlitchTriangle(): List<VideoGlitchType> {
|
||||
for (list in glitchesTrisSorted) {
|
||||
if (random.nextFloat() < 0.35f) {
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
return glitchesTrisSorted[glitchesTrisSorted.size - 1]
|
||||
}
|
||||
|
||||
init {
|
||||
val glitchesMapQuads = Int2ObjectArrayMap<ArrayList<VideoGlitchType>>()
|
||||
val glitchesMapTris = Int2ObjectArrayMap<ArrayList<VideoGlitchType>>()
|
||||
val glitchesMap = Int2ObjectArrayMap<ArrayList<VideoGlitchType>>()
|
||||
|
||||
val colorVariants = ArrayList<Vec3i>()
|
||||
|
||||
val flippersFloppers = listOf(
|
||||
{ u0: Float, v0: Float, u1: Float, v1: Float -> UVCoords(u0, v0, u1, v1) },
|
||||
{ u0: Float, v0: Float, u1: Float, v1: Float -> UVCoords(1f - u0, v0, 1f - u1, v1) },
|
||||
{ u0: Float, v0: Float, u1: Float, v1: Float -> UVCoords(u0, 1f - v0, u1, 1f - v1) },
|
||||
{ u0: Float, v0: Float, u1: Float, v1: Float -> UVCoords(1f - u0, 1f - v0, 1f - u1, 1f - v1) },
|
||||
)
|
||||
|
||||
val colors = intArrayOf(0, 10, 30, 50, 80, 100, 120, 150, 180, 220, 230, 235, 245, 249, 255)
|
||||
|
||||
for (red in colors)
|
||||
for (green in colors)
|
||||
for (blue in colors)
|
||||
if (red != 255 || green != 255 || blue != 255)
|
||||
colorVariants.add(Vec3i(red, green, blue))
|
||||
|
||||
for ((r, g, b) in colorVariants) {
|
||||
for (winding in UVWindingOrder.distinct) {
|
||||
for ((i, flipflop) in flippersFloppers.withIndex()) {
|
||||
object : VideoGlitchType() {
|
||||
@Suppress("name_shadowing")
|
||||
override fun upload(builder: BufferBuilder, x: Double, y: Double, width: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float) {
|
||||
val (u0_, v0_, u1_, v1_) = winding.translate(u0, v0, u1, v1)
|
||||
val (u0, v0, u1, v1) = flipflop.invoke(u0_, v0_, u1_, v1_)
|
||||
uploadQuad(builder, x, y, width, height, u0, v0, u1, v1, r, g, b, 255)
|
||||
}
|
||||
}.also {
|
||||
if (i == 0) {
|
||||
glitchesMapQuads
|
||||
.computeIfAbsent(255 - r + 255 - g + 255 - b, Int2ObjectFunction { ArrayList() })
|
||||
.add(it)
|
||||
}
|
||||
|
||||
glitchesMap
|
||||
.computeIfAbsent(255 - r + 255 - g + 255 - b, Int2ObjectFunction { ArrayList() })
|
||||
.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (va in VideoGlitchType.vertices) {
|
||||
for (vb in VideoGlitchType.vertices) {
|
||||
if (va == vb) continue
|
||||
|
||||
for (cb in VideoGlitchType.vertices) {
|
||||
if (cb == va || cb == vb) continue
|
||||
|
||||
for ((r, g, b) in colorVariants) {
|
||||
for (winding in UVWindingOrder.distinct) {
|
||||
for ((i, flipflop) in flippersFloppers.withIndex()) {
|
||||
@Suppress("name_shadowing")
|
||||
object : VideoGlitchType() {
|
||||
val vertices = va or vb or cb
|
||||
|
||||
override fun upload(builder: BufferBuilder, x: Double, y: Double, width: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float) {
|
||||
val (u0_, v0_, u1_, v1_) = winding.translate(u0, v0, u1, v1)
|
||||
val (u0, v0, u1, v1) = flipflop.invoke(u0_, v0_, u1_, v1_)
|
||||
uploadVertices(vertices, builder, x, y, width, height, u0, v0, u1, v1, r, g, b, 255)
|
||||
}
|
||||
}.also {
|
||||
if (i == 0) {
|
||||
glitchesMapTris
|
||||
.computeIfAbsent(255 - r + 255 - g + 255 - b, Int2ObjectFunction { ArrayList() })
|
||||
.add(it)
|
||||
}
|
||||
|
||||
glitchesMap
|
||||
.computeIfAbsent(255 - r + 255 - g + 255 - b, Int2ObjectFunction { ArrayList() })
|
||||
.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val toSort = glitchesMapQuads.entries.stream().collect(Collectors.toList())
|
||||
toSort.sortBy { it.key }
|
||||
glitchesQuadsSorted = toSort.stream().map { ImmutableList.copyOf(it.value) }.collect(ImmutableList.toImmutableList())
|
||||
|
||||
val toSort2 = glitchesMapTris.entries.stream().collect(Collectors.toList())
|
||||
toSort2.sortBy { it.key }
|
||||
glitchesTrisSorted = toSort2.stream().map { ImmutableList.copyOf(it.value) }.collect(ImmutableList.toImmutableList())
|
||||
|
||||
val toSort3 = glitchesMap.entries.stream().collect(Collectors.toList())
|
||||
toSort3.sortBy { it.key }
|
||||
glitchesSorted = toSort3.stream().map { ImmutableList.copyOf(it.value) }.collect(ImmutableList.toImmutableList())
|
||||
}
|
||||
|
||||
private val random = XoroshiroRandomSource(System.nanoTime(), System.currentTimeMillis())
|
||||
|
||||
var redShiftX = 0.0
|
||||
private set
|
||||
var redShiftY = 0.0
|
||||
private set
|
||||
var greenShiftX = 0.0
|
||||
private set
|
||||
var greenShiftY = 0.0
|
||||
private set
|
||||
var blueShiftX = 0.0
|
||||
private set
|
||||
var blueShiftY = 0.0
|
||||
private set
|
||||
|
||||
var lastGlitch = System.nanoTime()
|
||||
private set
|
||||
|
||||
var nextGlitch = 0L
|
||||
private set
|
||||
|
||||
var lastEncodingGlitch = System.nanoTime()
|
||||
private set
|
||||
|
||||
var nextEncodingGlitch = 0L
|
||||
private set
|
||||
|
||||
|
||||
|
||||
private val glitchBuffer by lazy(LazyThreadSafetyMode.NONE) {
|
||||
MainTarget(minecraft.window.width, minecraft.window.height)
|
||||
}
|
||||
|
||||
private fun upload(builder: BufferBuilder, offsetX: Double, offsetY: Double, u0: Float, v0: Float, u1: Float, v1: Float) {
|
||||
builder.vertex(offsetX - 1.0, offsetY + 1.0, 0.0).uv(u0, v1).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY + 1.0, 0.0).uv(u1, v1).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY - 1.0, 0.0).uv(u1, v0).endVertex()
|
||||
builder.vertex(offsetX - 1.0, offsetY - 1.0, 0.0).uv(u0, v0).endVertex()
|
||||
}
|
||||
|
||||
private fun uploadEmpty(builder: BufferBuilder, offsetX: Double, offsetY: Double) {
|
||||
builder.vertex(offsetX - 1.0, offsetY + 1.0, 0.0).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY + 1.0, 0.0).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY - 1.0, 0.0).endVertex()
|
||||
builder.vertex(offsetX - 1.0, offsetY - 1.0, 0.0).endVertex()
|
||||
}
|
||||
|
||||
private fun uploadLine(builder: BufferBuilder, offsetX: Double, offsetY: Double, height: Double, u0: Float, v0: Float, u1: Float, v1: Float) {
|
||||
builder.vertex(offsetX - 1.0, offsetY - height, 0.0).uv(u0, v1).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY - height, 0.0).uv(u1, v1).endVertex()
|
||||
builder.vertex(offsetX + 1.0, offsetY, 0.0).uv(u1, v0).endVertex()
|
||||
builder.vertex(offsetX - 1.0, offsetY, 0.0).uv(u0, v0).endVertex()
|
||||
}
|
||||
|
||||
private inline fun makeMirrors(handler: (x: Double, y: Double, u0: Float, v0: Float, u1: Float, v1: Float) -> Unit) {
|
||||
handler(0.0 - 2f, 0.0, 1f, 0f, 0f, 1f)
|
||||
handler(0.0 + 2f, 0.0, 1f, 0f, 0f, 1f)
|
||||
|
||||
handler(0.0, 2.0, 0f, 1f, 1f, 0f)
|
||||
handler(0.0, -2.0, 0f, 1f, 1f, 0f)
|
||||
|
||||
handler(0.0 - 2f, -2.0, 1f, 1f, 0f, 0f)
|
||||
handler(0.0 + 2f, -2.0, 1f, 1f, 0f, 0f)
|
||||
|
||||
handler(0.0 - 2f, +2.0, 1f, 1f, 0f, 0f)
|
||||
handler(0.0 + 2f, +2.0, 1f, 1f, 0f, 0f)
|
||||
}
|
||||
|
||||
private fun draw(offsetX: Double, offsetY: Double) {
|
||||
val builder = tesselator.builder
|
||||
|
||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
|
||||
|
||||
upload(builder, offsetX, offsetY, 0f, 0f, 1f, 1f)
|
||||
|
||||
if (offsetX != 0.0 || offsetY != 0.0) {
|
||||
makeMirrors { x: Double, y: Double, u0: Float, v0: Float, u1: Float, v1: Float ->
|
||||
upload(builder, offsetX + x, offsetY + y, u0, v0, u1, v1)
|
||||
}
|
||||
}
|
||||
|
||||
BufferUploader.drawWithShader(builder.end())
|
||||
}
|
||||
|
||||
private fun pixel2ViewX(value: Double) = linearInterpolation(value / glitchBuffer.width, 1.0, -1.0)
|
||||
private fun pixel2ViewY(value: Double) = linearInterpolation(value / glitchBuffer.height, 1.0, -1.0)
|
||||
private fun pixel2TextureX(value: Double) = (value / glitchBuffer.width).toFloat()
|
||||
private fun pixel2TextureY(value: Double) = 1f - (value / glitchBuffer.height).toFloat()
|
||||
|
||||
private fun drawVHSLineGap(y: Double, height: Double) {
|
||||
val builder = tesselator.builder
|
||||
|
||||
val v = pixel2TextureY(y)
|
||||
|
||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
|
||||
uploadLine(builder, 0.0, pixel2ViewY(y), (height / glitchBuffer.height) * 2.0, 0f, v, 1f, v)
|
||||
BufferUploader.drawWithShader(builder.end())
|
||||
}
|
||||
|
||||
private var colorGlitchBuff = arrayOfNulls<VideoGlitchType>(0)
|
||||
private var colorGlitchWidth = 0
|
||||
private var colorGlitchHeight = 0
|
||||
|
||||
private fun putMacroGlitch(x: Int, y: Int, width: Int, height: Int, value: VideoGlitchType?) {
|
||||
for (offsetX in 0 until width) {
|
||||
for (offsetY in 0 until height) {
|
||||
val index = (x + offsetX) + (y + offsetY) * colorGlitchWidth
|
||||
|
||||
if (colorGlitchBuff.size > index) {
|
||||
colorGlitchBuff[index] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun colorGlitchChanceMultiplier(x: Int, y: Int): Float {
|
||||
return (1f - ((x.toDouble() - colorGlitchWidth.toDouble() / 2.0).pow(2.0) / colorGlitchWidth.toDouble().pow(2.0) +
|
||||
(y.toDouble() - colorGlitchHeight.toDouble() / 2.0).pow(2.0) / colorGlitchHeight.toDouble().pow(2.0))
|
||||
.toFloat()
|
||||
.coerceAtLeast(0f)
|
||||
.coerceAtMost(1f))
|
||||
.pow(1f / 8f)
|
||||
}
|
||||
|
||||
private fun makeColorGlitch() {
|
||||
lastEncodingGlitch = System.nanoTime()
|
||||
nextEncodingGlitch = random.nextIntBetweenInclusive(10_000_000, 40_000_000).toLong()
|
||||
colorGlitchWidth = ceil(glitchBuffer.width / GLITCH_BLOCK_SIZE).toInt()
|
||||
colorGlitchHeight = ceil(glitchBuffer.height / GLITCH_BLOCK_SIZE).toInt()
|
||||
|
||||
colorGlitchBuff = arrayOfNulls((colorGlitchWidth + 1) * (colorGlitchHeight + 1))
|
||||
|
||||
for (xBlock in 0 .. colorGlitchWidth)
|
||||
for (yBlock in 0 .. colorGlitchHeight)
|
||||
if (colorGlitchChanceMultiplier(xBlock, yBlock) < 0.99f && random.nextFloat() > colorGlitchChanceMultiplier(xBlock, yBlock) * 0.999f)
|
||||
colorGlitchBuff[xBlock + yBlock * colorGlitchWidth] = selectGlitch().let { it[random.nextInt(0, it.size)] }
|
||||
|
||||
for (xBlock in 0 .. colorGlitchWidth)
|
||||
for (yBlock in 0 .. colorGlitchHeight)
|
||||
if (colorGlitchChanceMultiplier(xBlock, yBlock) < 0.99f && random.nextFloat() > colorGlitchChanceMultiplier(xBlock, yBlock) * 0.9999f)
|
||||
putMacroGlitch(xBlock, yBlock, random.nextInt(1, 5), random.nextInt(1, 5), selectGlitchQuad().let { it[random.nextInt(0, it.size)] })
|
||||
|
||||
for (xBlock in 0 .. colorGlitchWidth)
|
||||
for (yBlock in 0 .. colorGlitchHeight)
|
||||
if (colorGlitchChanceMultiplier(xBlock, yBlock) < 0.99f && random.nextFloat() > colorGlitchChanceMultiplier(xBlock, yBlock) * 0.99999f)
|
||||
putMacroGlitch(xBlock, yBlock, random.nextInt(1, 9), random.nextInt(1, 9), selectGlitchQuad().let { it[random.nextInt(0, it.size)] })
|
||||
|
||||
for (xBlock in 0 .. colorGlitchWidth)
|
||||
for (yBlock in 0 .. colorGlitchHeight)
|
||||
if (colorGlitchChanceMultiplier(xBlock, yBlock) < 0.99f && random.nextFloat() > colorGlitchChanceMultiplier(xBlock, yBlock) * 0.999999f)
|
||||
putMacroGlitch(xBlock, yBlock, random.nextInt(1, 14), random.nextInt(1, 14), selectGlitchQuad().let { it[random.nextInt(0, it.size)] })
|
||||
}
|
||||
|
||||
private fun makeGlitch() {
|
||||
redShiftX = random.nextDouble() * 0.05 - 0.025
|
||||
redShiftY = random.nextDouble() * 0.05 - 0.025
|
||||
greenShiftX = random.nextDouble() * 0.05 - 0.025
|
||||
greenShiftY = random.nextDouble() * 0.05 - 0.025
|
||||
blueShiftX = random.nextDouble() * 0.05 - 0.025
|
||||
blueShiftY = random.nextDouble() * 0.05 - 0.025
|
||||
lastGlitch = System.nanoTime()
|
||||
nextGlitch = random.nextIntBetweenInclusive(75_000_000, 400_000_000).toLong()
|
||||
}
|
||||
|
||||
var glitchUntil = 0L
|
||||
private set
|
||||
var glitchSince = System.nanoTime()
|
||||
private set
|
||||
|
||||
fun glitchFor(millis: Long) {
|
||||
if (glitchUntil - (System.nanoTime() - glitchSince) < millis) {
|
||||
glitchSince = System.nanoTime()
|
||||
glitchUntil = millis * 1_000_000L
|
||||
}
|
||||
}
|
||||
|
||||
private const val GLITCH_BLOCK_SIZE = 8f
|
||||
|
||||
@JvmStatic
|
||||
fun render() {
|
||||
if (System.nanoTime() - glitchSince >= glitchUntil) {
|
||||
return
|
||||
}
|
||||
|
||||
if (System.nanoTime() - lastGlitch >= nextGlitch) {
|
||||
makeGlitch()
|
||||
}
|
||||
|
||||
if (System.nanoTime() - lastEncodingGlitch >= nextEncodingGlitch) {
|
||||
makeColorGlitch()
|
||||
}
|
||||
|
||||
val glitchBuffer = glitchBuffer
|
||||
val projection = RenderSystem.getProjectionMatrix()
|
||||
RenderSystem.setProjectionMatrix(Matrix4f().also { it.setIdentity() })
|
||||
|
||||
RenderSystem.getModelViewStack().also {
|
||||
it.pushPose()
|
||||
it.setIdentity()
|
||||
}
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
|
||||
RenderSystem.disableCull()
|
||||
RenderSystem.disableDepthTest()
|
||||
RenderSystem.enableBlend()
|
||||
RenderSystem.enableTexture()
|
||||
RenderSystem.clearColor(0f, 0f, 0f, 1f)
|
||||
|
||||
if (glitchBuffer.width != minecraft.window.width || glitchBuffer.height != minecraft.window.height) {
|
||||
glitchBuffer.resize(minecraft.window.width, minecraft.window.height, Minecraft.ON_OSX)
|
||||
glitchBuffer.bindWrite(true)
|
||||
} else {
|
||||
glitchBuffer.bindWrite(true)
|
||||
RenderSystem.clear(GlConst.GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX)
|
||||
}
|
||||
|
||||
// distort colors by sampling main frame buffer (raw stage)
|
||||
RenderSystem.setShaderTexture(0, minecraft.mainRenderTarget.colorTextureId)
|
||||
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_DST_ALPHA)
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||
|
||||
RenderSystem.setShaderColor(1f, 0.1f, 0f, 1f)
|
||||
draw(redShiftX, redShiftY)
|
||||
|
||||
RenderSystem.setShaderColor(0f, 1f, 0f, 1f)
|
||||
draw(greenShiftX, greenShiftY)
|
||||
|
||||
RenderSystem.setShaderColor(0f, 0f, 1f, 1f)
|
||||
draw(blueShiftX, blueShiftY)
|
||||
|
||||
minecraft.mainRenderTarget.bindWrite(true)
|
||||
|
||||
// draw back to main frame buffer (prepare for post process)
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO)
|
||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
||||
RenderSystem.setShaderTexture(0, glitchBuffer.colorTextureId)
|
||||
draw(0.0, 0.0)
|
||||
|
||||
// return to our frame buffer (post process stage)
|
||||
glitchBuffer.bindWrite(true)
|
||||
RenderSystem.setShaderTexture(0, minecraft.mainRenderTarget.colorTextureId)
|
||||
|
||||
// color perception errors (eye-camera glitch)
|
||||
drawVHSLineGap((System.currentTimeMillis() % glitchBuffer.height).toDouble(), glitchBuffer.height * 0.025)
|
||||
drawVHSLineGap(((System.currentTimeMillis() + glitchBuffer.height / 2) % glitchBuffer.height).toDouble(), glitchBuffer.height * 0.075)
|
||||
drawVHSLineGap(((System.currentTimeMillis() + glitchBuffer.height / 3) % glitchBuffer.height).toDouble(), glitchBuffer.height * 0.04)
|
||||
drawVHSLineGap(((-System.currentTimeMillis() - glitchBuffer.height / 3) % glitchBuffer.height).toDouble().absoluteValue, glitchBuffer.height * 0.07)
|
||||
|
||||
// color encoding errors (encoder/transmission glitch)
|
||||
val blocksWidth = ceil(glitchBuffer.width / GLITCH_BLOCK_SIZE).toInt()
|
||||
val blocksHeight = ceil(glitchBuffer.height / GLITCH_BLOCK_SIZE).toInt()
|
||||
|
||||
if (colorGlitchWidth != blocksWidth || colorGlitchHeight != blocksHeight) {
|
||||
makeColorGlitch()
|
||||
}
|
||||
|
||||
val blockStepWidth = (GLITCH_BLOCK_SIZE / glitchBuffer.width) * 2.0
|
||||
val blockStepHeight = (GLITCH_BLOCK_SIZE / glitchBuffer.height) * 2.0
|
||||
|
||||
val blockStepWidthUV = GLITCH_BLOCK_SIZE / glitchBuffer.width
|
||||
val blockStepHeightUV = GLITCH_BLOCK_SIZE / glitchBuffer.height
|
||||
|
||||
val builder = tesselator.builder
|
||||
|
||||
builder.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_TEX_COLOR)
|
||||
|
||||
for (xBlock in 0 .. blocksWidth) {
|
||||
for (yBlock in 0 .. blocksHeight) {
|
||||
colorGlitchBuff[xBlock + yBlock * blocksWidth]?.upload(
|
||||
builder = builder,
|
||||
x = -1.0 + xBlock * blockStepWidth,
|
||||
y = -1.0 + yBlock * blockStepHeight,
|
||||
width = blockStepWidth,
|
||||
height = blockStepHeight,
|
||||
u0 = xBlock * blockStepWidthUV,
|
||||
v0 = yBlock * blockStepHeightUV,
|
||||
u1 = (xBlock + 1) * blockStepWidthUV,
|
||||
v1 = (yBlock + 1) * blockStepHeightUV,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexColorShader)
|
||||
BufferUploader.drawWithShader(builder.end())
|
||||
|
||||
// upload final result to main frame buffer
|
||||
minecraft.mainRenderTarget.bindWrite(true)
|
||||
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||
|
||||
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO)
|
||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
||||
RenderSystem.setShaderTexture(0, glitchBuffer.colorTextureId)
|
||||
draw(0.0, 0.0)
|
||||
|
||||
RenderSystem.setProjectionMatrix(projection)
|
||||
RenderSystem.getModelViewStack().popPose()
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.client.render
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
|
||||
sealed interface IUVCoords {
|
||||
val u0: Float
|
||||
val v0: Float
|
||||
@ -80,6 +82,10 @@ enum class UVWindingOrder(
|
||||
U1_V1_U0_V0(2, 3, 0, 1), // mirror both
|
||||
FLIP_FLOP(2, 3, 0, 1); // mirror both
|
||||
|
||||
companion object {
|
||||
val distinct: List<UVWindingOrder> = ImmutableList.of(NORMAL, FLIP, FLOP, FLIP_FLOP)
|
||||
}
|
||||
|
||||
val isIdentity: Boolean = u0 == 0 && v0 == 1 && u1 == 2 && v1 == 3
|
||||
|
||||
operator fun component1() = u0
|
||||
|
@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.android.feature.TriggerShockwavePacket
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.MatteryGUI
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.GlitchRenderer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.set
|
||||
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
||||
@ -430,6 +431,23 @@ class PickItemFromInventoryPacket(
|
||||
}
|
||||
}
|
||||
|
||||
class GlitchPacket(val millis: Long) : MatteryPacket {
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeVarLong(millis)
|
||||
}
|
||||
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.packetHandled = true
|
||||
GlitchRenderer.glitchFor(millis)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun read(buff: FriendlyByteBuf): GlitchPacket {
|
||||
return GlitchPacket(buff.readVarLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object MatteryPlayerNetworkChannel : MatteryNetworkChannel(
|
||||
version = "1",
|
||||
name = "player"
|
||||
@ -457,5 +475,7 @@ object MatteryPlayerNetworkChannel : MatteryNetworkChannel(
|
||||
add(TriggerJumpBoostPacket::class, { TriggerJumpBoostPacket }, PLAY_TO_SERVER)
|
||||
|
||||
add(PickItemFromInventoryPacket::class, PickItemFromInventoryPacket.Companion::read, PLAY_TO_SERVER)
|
||||
|
||||
add(GlitchPacket::class, GlitchPacket.Companion::read, PLAY_TO_CLIENT)
|
||||
}
|
||||
}
|
||||
|
@ -890,33 +890,6 @@ function initializeCoreMod() {
|
||||
}
|
||||
},
|
||||
|
||||
'big GameRenderer#renderItemInHand fuck off':
|
||||
method('net.minecraft.client.renderer.GameRenderer.m_109120_(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/Camera;F)V', function(node) {
|
||||
putInstructions(node, undefined, [
|
||||
new VarInsnNode(opcodesRemapped.aload, 1),
|
||||
new MethodInsnNode(
|
||||
opcodesRemapped.invokevirtual,
|
||||
'com/mojang/blaze3d/vertex/PoseStack',
|
||||
ASMAPI.mapMethod('m_85836_'), // pushPose
|
||||
'()V',
|
||||
false
|
||||
)
|
||||
])
|
||||
|
||||
injectInstructionsAtTail(node, [
|
||||
new VarInsnNode(opcodesRemapped.aload, 1),
|
||||
new MethodInsnNode(
|
||||
opcodesRemapped.invokevirtual,
|
||||
'com/mojang/blaze3d/vertex/PoseStack',
|
||||
ASMAPI.mapMethod('m_85849_'), // popPose
|
||||
'()V',
|
||||
false
|
||||
)
|
||||
])
|
||||
|
||||
return node
|
||||
}),
|
||||
|
||||
'GameRenderer#render hook': {
|
||||
'target': {
|
||||
'type': 'METHOD',
|
||||
@ -934,137 +907,35 @@ function initializeCoreMod() {
|
||||
false
|
||||
))
|
||||
|
||||
// 233: new #26 // class com/mojang/blaze3d/vertex/PoseStack
|
||||
// 236: dup
|
||||
// 237: invokespecial #1425 // Method com/mojang/blaze3d/vertex/PoseStack."<init>":()V
|
||||
// <-- our target for local variable
|
||||
// 240: invokevirtual #3398 // Method renderLevel:(FJLcom/mojang/blaze3d/vertex/PoseStack;)V
|
||||
// 243: aload_0
|
||||
// 244: invokevirtual #3540 // Method tryTakeScreenshotIfNeeded:()V
|
||||
// 247: aload_0
|
||||
// 248: getfield #2773 // Field minecraft:Lnet/minecraft/client/Minecraft;
|
||||
// 251: getfield #3207 // Field net/minecraft/client/Minecraft.levelRenderer:Lnet/minecraft/client/renderer/LevelRenderer;
|
||||
// 254: invokevirtual #3543 // Method net/minecraft/client/renderer/LevelRenderer.doEntityOutline:()V
|
||||
// <-- our target for post
|
||||
// 257: aload_0
|
||||
// 258: getfield #2788 // Field postEffect:Lnet/minecraft/client/renderer/PostChain;
|
||||
// 261: ifnull 291
|
||||
// 264: aload_0
|
||||
// 265: getfield #2805 // Field effectActive:Z
|
||||
// 268: ifeq 291
|
||||
// 271: invokestatic #3546 // Method com/mojang/blaze3d/systems/RenderSystem.disableBlend:()V
|
||||
// 274: invokestatic #3549 // Method com/mojang/blaze3d/systems/RenderSystem.disableDepthTest:()V
|
||||
// 277: invokestatic #3552 // Method com/mojang/blaze3d/systems/RenderSystem.enableTexture:()V
|
||||
// 280: invokestatic #3555 // Method com/mojang/blaze3d/systems/RenderSystem.resetTextureMatrix:()V
|
||||
// 283: aload_0
|
||||
// 284: getfield #2788 // Field postEffect:Lnet/minecraft/client/renderer/PostChain;
|
||||
// 287: fload_1
|
||||
// 288: invokevirtual #3558 // Method net/minecraft/client/renderer/PostChain.process:(F)V
|
||||
// 291: aload_0
|
||||
// 292: getfield #2773 // Field minecraft:Lnet/minecraft/client/Minecraft;
|
||||
// 295: invokevirtual #2818 // Method net/minecraft/client/Minecraft.getMainRenderTarget:()Lcom/mojang/blaze3d/pipeline/RenderTarget;
|
||||
// 298: iconst_1
|
||||
// 299: invokevirtual #3561 // Method com/mojang/blaze3d/pipeline/RenderTarget.bindWrite:(Z)V
|
||||
// <-- our target for last
|
||||
// <-- our target
|
||||
// 302: aload_0
|
||||
// 303: getfield #2773 // Field minecraft:Lnet/minecraft/client/Minecraft;
|
||||
// 306: invokevirtual #2821 // Method net/minecraft/client/Minecraft.getWindow:()Lcom/mojang/blaze3d/platform/Window;
|
||||
// 309: astore 7
|
||||
|
||||
var ourmethod = ASMAPI.mapMethod('m_83947_')
|
||||
var lastLabel = undefined
|
||||
var beforeInvoke = undefined
|
||||
var slot = undefined
|
||||
var ourmethod = ASMAPI.mapMethod('m_83947_') // bindWrite
|
||||
|
||||
for (var i = 0; i < node.instructions.size(); i++) {
|
||||
var instruction = node.instructions.get(i)
|
||||
|
||||
if (instruction.getOpcode() == opcodesRemapped.invokevirtual && instruction.name == ourmethod && instruction.desc == '(Z)V') {
|
||||
beforeInvoke = instruction
|
||||
|
||||
var invoke = new MethodInsnNode(
|
||||
node.instructions.insert(instruction, new MethodInsnNode(
|
||||
opcodesRemapped.invokestatic,
|
||||
'ru/dbotthepony/mc/otm/client/ClientEventHandlerKt',
|
||||
'lastLevelDrawHook',
|
||||
'(Lcom/mojang/blaze3d/vertex/PoseStack;)V',
|
||||
false
|
||||
)
|
||||
|
||||
node.instructions.insert(instruction, invoke)
|
||||
|
||||
lastLabel = new LabelNode(new Label())
|
||||
node.instructions.insert(invoke, lastLabel)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (lastLabel !== undefined && beforeInvoke !== undefined) {
|
||||
var renderLevel = ASMAPI.mapMethod('m_109089_')
|
||||
|
||||
node.maxLocals++
|
||||
|
||||
for (var i = 0; i < node.instructions.size(); i++) {
|
||||
var instruction = node.instructions.get(i)
|
||||
|
||||
if (instruction.getOpcode() == opcodesRemapped.invokevirtual && instruction.name == renderLevel && instruction.desc == '(FJLcom/mojang/blaze3d/vertex/PoseStack;)V') {
|
||||
var startLabel = new Label()
|
||||
var prev = node.instructions.get(i - 1)
|
||||
|
||||
var labelNode = new LabelNode(startLabel)
|
||||
node.instructions.insert(prev, labelNode)
|
||||
prev = labelNode
|
||||
|
||||
var slot = node.localVariables.size() + 1
|
||||
|
||||
var local = new LocalVariableNode(
|
||||
'otm_capturePoseStack',
|
||||
'Lcom/mojang/blaze3d/vertex/PoseStack;',
|
||||
null,
|
||||
labelNode,
|
||||
lastLabel,
|
||||
slot
|
||||
)
|
||||
|
||||
node.localVariables.add(local)
|
||||
|
||||
var next = new InsnNode(opcodesRemapped.dup)
|
||||
node.instructions.insert(prev, next)
|
||||
prev = next
|
||||
next = new VarInsnNode(opcodesRemapped.astore, slot)
|
||||
node.instructions.insert(prev, next)
|
||||
|
||||
node.instructions.insert(beforeInvoke, new VarInsnNode(opcodesRemapped.aload, slot))
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slot !== undefined) {
|
||||
var doEntityOutline = ASMAPI.mapMethod('m_109769_')
|
||||
|
||||
for (var i = 0; i < node.instructions.size(); i++) {
|
||||
var instruction = node.instructions.get(i)
|
||||
|
||||
if (instruction.getOpcode() == opcodesRemapped.invokevirtual && instruction.name == doEntityOutline && instruction.desc == '()V') {
|
||||
var prev = instruction
|
||||
var next = new VarInsnNode(opcodesRemapped.aload, slot)
|
||||
node.instructions.insert(prev, next)
|
||||
prev = next
|
||||
|
||||
node.instructions.insert(prev, new MethodInsnNode(
|
||||
opcodesRemapped.invokestatic,
|
||||
'ru/dbotthepony/mc/otm/client/ClientEventHandlerKt',
|
||||
'postLevelDrawHook',
|
||||
'(Lcom/mojang/blaze3d/vertex/PoseStack;)V',
|
||||
'ru/dbotthepony/mc/otm/client/render/GlitchRenderer',
|
||||
'render',
|
||||
'()V',
|
||||
false
|
||||
))
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user