Release 2.6.16
This commit is contained in:
BIN
.gitignore
vendored
BIN
.gitignore
vendored
Binary file not shown.
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -5,3 +5,6 @@
|
||||
[submodule "src/main/resources/assets/replaymod/lang"]
|
||||
path = src/main/resources/assets/replaymod/lang
|
||||
url = https://github.com/ReplayMod/Translations
|
||||
[submodule "ReplayStudio"]
|
||||
path = libs/ReplayStudio
|
||||
url = ../ReplayStudio
|
||||
|
||||
735
build.gradle
735
build.gradle
@@ -1,735 +0,0 @@
|
||||
import com.replaymod.gradle.preprocess.PreprocessTask
|
||||
import static gg.essential.gradle.util.PrebundleKt.prebundle
|
||||
|
||||
buildscript {
|
||||
def mcVersion
|
||||
def (major, minor, patch) = project.name.tokenize('-')[0].tokenize('.')
|
||||
mcVersion = "${major}${minor.padLeft(2, '0')}${(patch ?: '').padLeft(2, '0')}" as int
|
||||
def fabric = mcVersion >= 11400 && !project.name.endsWith("-forge")
|
||||
project.ext.mcVersion = mcVersion
|
||||
project.ext.fabric = fabric
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
url = "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "fabric"
|
||||
url = "https://maven.fabricmc.net/"
|
||||
}
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://maven.minecraftforge.net"
|
||||
}
|
||||
maven {
|
||||
name = "sonatype"
|
||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url "https://maven.architectury.dev" }
|
||||
maven { url "https://repo.essential.gg/repository/maven-public" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
|
||||
if (fabric) {
|
||||
classpath 'fabric-loom:fabric-loom.gradle.plugin:0.11-SNAPSHOT'
|
||||
} else if (mcVersion >= 11400) {
|
||||
classpath('net.minecraftforge.gradle:ForgeGradle:5.0.5') { // the FG people still haven't learned to not do breaking changes
|
||||
exclude group: 'trove', module: 'trove' // preprocessor/idea requires more recent one
|
||||
}
|
||||
} else if (mcVersion >= 10800) {
|
||||
classpath('com.github.ReplayMod:ForgeGradle:' + (
|
||||
mcVersion >= 11200 ? '34ab703' : // FG 2.3
|
||||
mcVersion >= 10904 ? '5d1e8d8' : // FG 2.2
|
||||
'ceb83c0' // FG 2.1
|
||||
) + ':all')
|
||||
} else {
|
||||
classpath 'com.github.ReplayMod:ForgeGradle:a8a9e0ca:all' // FG 1.2
|
||||
}
|
||||
classpath 'gg.essential:essential-gradle-toolkit:0.1.10'
|
||||
}
|
||||
}
|
||||
|
||||
def FG3 = !fabric && mcVersion >= 11400
|
||||
def FABRIC = fabric
|
||||
|
||||
def jGuiVersion = project.name
|
||||
if (['1.10.2', '1.11', '1.11.2'].contains(jGuiVersion)) jGuiVersion = '1.9.4'
|
||||
if (['1.12.1', '1.12.2'].contains(jGuiVersion)) jGuiVersion = '1.12'
|
||||
def jGui = project.evaluationDependsOn(":jGui:$jGuiVersion")
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
if (mcVersion >= 10800) {
|
||||
if (FABRIC) {
|
||||
apply plugin: 'fabric-loom'
|
||||
} else if (FG3) {
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
} else {
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
}
|
||||
} else {
|
||||
apply plugin: 'forge'
|
||||
}
|
||||
|
||||
if (!FABRIC) {
|
||||
ext {
|
||||
mixinSrg = new File(project.buildDir, 'tmp/mixins/mixins.srg')
|
||||
mixinRefMap = new File(project.buildDir, 'tmp/mixins/mixins.replaymod.refmap.json')
|
||||
}
|
||||
|
||||
compileJava {
|
||||
options.compilerArgs += [
|
||||
"-AoutSrgFile=${project.mixinSrg.canonicalPath}",
|
||||
"-AoutRefMapFile=${project.mixinRefMap.canonicalPath}",
|
||||
"-AreobfSrgFile=${project.file('build/mcp-srg.srg').canonicalPath}"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.replaymod.preprocess'
|
||||
|
||||
preprocess {
|
||||
vars.put("MC", project.mcVersion)
|
||||
vars.put("FABRIC", project.fabric ? 1 : 0)
|
||||
|
||||
keywords.set([
|
||||
".java": PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".json": PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".mcmeta": PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".cfg": PreprocessTask.CFG_KEYWORDS,
|
||||
".vert": PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".frag": PreprocessTask.DEFAULT_KEYWORDS,
|
||||
])
|
||||
|
||||
patternAnnotation.set("com.replaymod.gradle.remap.Pattern")
|
||||
}
|
||||
|
||||
def mcVersionStr = "${(int)(mcVersion/10000)}.${(int)(mcVersion/100)%100}" + (mcVersion%100==0 ? '' : ".${mcVersion%100}")
|
||||
|
||||
sourceCompatibility = targetCompatibility = mcVersion >= 11800 ? 17 : mcVersion >= 11700 ? 16 : 1.8
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.release = mcVersion >= 11800 ? 17 : mcVersion >= 11700 ? 16 : 8
|
||||
}
|
||||
|
||||
if (mcVersion >= 11400) {
|
||||
sourceSets {
|
||||
api
|
||||
}
|
||||
}
|
||||
|
||||
version = project.name + '-' + rootProject.version
|
||||
group= "com.replaymod"
|
||||
archivesBaseName = "replaymod"
|
||||
|
||||
if (FABRIC) {
|
||||
loom {
|
||||
mixin.defaultRefmapName.set('mixins.replaymod.refmap.json')
|
||||
runConfigs.all {
|
||||
ideConfigGenerated = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
minecraft {
|
||||
if (FG3) {
|
||||
runs {
|
||||
client {
|
||||
workingDirectory rootProject.file('run')
|
||||
property 'forge.logging.console.level', 'info'
|
||||
mods {
|
||||
replaymod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mcVersion >= 10800) {
|
||||
coreMod = 'com.replaymod.core.LoadingPlugin'
|
||||
}
|
||||
runDir = "../../run"
|
||||
}
|
||||
|
||||
if (!FG3) {
|
||||
version = [
|
||||
11202: '1.12.2-14.23.0.2486',
|
||||
11201: '1.12.1-14.22.0.2444',
|
||||
11200: '1.12-14.21.1.2387',
|
||||
11102: '1.11.2-13.20.0.2216',
|
||||
11100: '1.11-13.19.1.2188',
|
||||
11002: '1.10.2-12.18.2.2099',
|
||||
10904: '1.9.4-12.17.0.1976',
|
||||
10809: '1.8.9-11.15.1.1722',
|
||||
10800: '1.8-11.14.4.1563',
|
||||
10710: '1.7.10-10.13.4.1558-1.7.10',
|
||||
][mcVersion]
|
||||
}
|
||||
mappings = [
|
||||
11404: "snapshot_20190719-1.14.3",
|
||||
11202: "snapshot_20170615",
|
||||
11201: "snapshot_20170615",
|
||||
11200: "snapshot_20170615",
|
||||
11102: "snapshot_20161220",
|
||||
11100: "snapshot_20161111",
|
||||
11002: "snapshot_20160518",
|
||||
10904: "snapshot_20160518",
|
||||
10809: "stable_22",
|
||||
10800: "snapshot_nodoc_20141130",
|
||||
10710: "stable_12",
|
||||
][mcVersion]
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if (mcVersion >= 11400) {
|
||||
// No longer required in 1.13+ because all version info is in the toml file
|
||||
} else {
|
||||
// Note cannot use minecraft.replace because that has already been forwarded to the task by FG by now
|
||||
tasks.sourceMainJava.replace '@MOD_VERSION@', project.version
|
||||
// Includes intentional whitespace to stop Forge from declaring the mod to be compatible with
|
||||
// a newer srg-compatible MC version (that may be using a different protocol version)
|
||||
tasks.sourceMainJava.replace '@MC_VERSION@', "[ $mcVersionStr ]"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
name = "SpongePowered Repo"
|
||||
url = "https://repo.spongepowered.org/maven/"
|
||||
}
|
||||
maven {
|
||||
name = "fabric"
|
||||
url = "https://maven.fabricmc.net/"
|
||||
}
|
||||
maven {
|
||||
url 'https://maven.terraformersmc.com/releases/'
|
||||
content {
|
||||
includeGroup 'com.terraformersmc'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
content {
|
||||
includeGroupByRegex 'com\\.github\\..*'
|
||||
}
|
||||
}
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name = "Modrinth"
|
||||
url = "https://api.modrinth.com/maven"
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup "maven.modrinth"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
// Include dep in fat jar without relocation and, when forge supports it, without exploding (TODO)
|
||||
shade
|
||||
implementation.extendsFrom shade
|
||||
// Include dep in fat jar with relocation and minimization
|
||||
shadow
|
||||
implementation.extendsFrom shadow
|
||||
}
|
||||
|
||||
def shadeExclusions = {
|
||||
// Cannot just add these to the shade configuration because they'd be inherited by the compile configuration then
|
||||
exclude group: 'com.google.guava', module: 'guava-jdk5'
|
||||
exclude group: 'com.google.guava', module: 'guava' // provided by MC
|
||||
exclude group: 'com.google.code.gson', module: 'gson' // provided by MC (or manually bundled for 1.11.2 and below)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if (FABRIC) {
|
||||
minecraft 'com.mojang:minecraft:' + [
|
||||
11404: '1.14.4',
|
||||
11502: '1.15.2',
|
||||
11601: '1.16.1',
|
||||
11603: '1.16.3',
|
||||
11604: '1.16.4',
|
||||
11701: '1.17.1',
|
||||
11800: '1.18',
|
||||
11801: '1.18.1',
|
||||
11802: '1.18.2',
|
||||
11900: '1.19',
|
||||
11901: '1.19.1',
|
||||
11902: '1.19.2',
|
||||
11903: '1.19.3-rc3',
|
||||
11904: '1.19.4',
|
||||
12001: '1.20.1',
|
||||
12002: '1.20.2',
|
||||
12004: '1.20.4',
|
||||
][mcVersion]
|
||||
mappings 'net.fabricmc:yarn:' + [
|
||||
11404: '1.14.4+build.16',
|
||||
11502: '1.15.2+build.14',
|
||||
11601: '1.16.1+build.17:v2',
|
||||
11603: '1.16.3+build.1:v2',
|
||||
11604: '1.16.4+build.6:v2',
|
||||
11701: '1.17.1+build.29:v2',
|
||||
11800: '1.18+build.1:v2',
|
||||
11801: '1.18.1+build.1:v2',
|
||||
11802: '1.18.2+build.1:v2',
|
||||
11900: '1.19+build.2:v2',
|
||||
11901: '1.19.1+build.5:v2',
|
||||
11902: '1.19.2+build.28:v2',
|
||||
11903: '1.19.3-rc3+build.1:v2',
|
||||
11904: '1.19.4+build.1:v2',
|
||||
12001: '1.20.1+build.2:v2',
|
||||
12002: '1.20.2+build.4:v2',
|
||||
12004: '1.20.4+build.1:v2',
|
||||
][mcVersion]
|
||||
modImplementation 'net.fabricmc:fabric-loader:0.15.1'
|
||||
def fabricApiVersion = [
|
||||
11404: '0.4.3+build.247-1.14',
|
||||
11502: '0.5.1+build.294-1.15',
|
||||
11601: '0.14.0+build.371-1.16',
|
||||
11603: '0.17.1+build.394-1.16',
|
||||
11604: '0.42.0+1.16',
|
||||
11701: '0.46.1+1.17',
|
||||
11800: '0.43.1+1.18',
|
||||
11801: '0.43.1+1.18',
|
||||
11802: '0.47.9+1.18.2',
|
||||
11900: '0.55.3+1.19',
|
||||
11901: '0.58.5+1.19.1',
|
||||
11902: '0.68.0+1.19.2',
|
||||
11903: '0.68.1+1.19.3',
|
||||
11904: '0.76.0+1.19.4',
|
||||
12001: '0.83.1+1.20.1',
|
||||
12002: '0.91.2+1.20.2',
|
||||
12004: '0.91.2+1.20.4',
|
||||
][mcVersion]
|
||||
def fabricApiModules = [
|
||||
"api-base",
|
||||
"networking-v0",
|
||||
"keybindings-v0",
|
||||
"resource-loader-v0",
|
||||
]
|
||||
if (mcVersion >= 11600) {
|
||||
fabricApiModules.remove("keybindings-v0")
|
||||
fabricApiModules.add("key-binding-api-v1")
|
||||
}
|
||||
if (mcVersion >= 11604) {
|
||||
fabricApiModules.add("screen-api-v1")
|
||||
fabricApiModules.add("networking-api-v1")
|
||||
}
|
||||
if (mcVersion >= 11700) {
|
||||
fabricApiModules.remove("networking-v0")
|
||||
}
|
||||
fabricApiModules.each { module ->
|
||||
modImplementation fabricApi.module("fabric-$module", fabricApiVersion)
|
||||
include fabricApi.module("fabric-$module", fabricApiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
if (FG3) {
|
||||
minecraft 'net.minecraftforge:forge:' + [
|
||||
11404: '1.14.4-28.1.113',
|
||||
][mcVersion]
|
||||
}
|
||||
|
||||
if (!FABRIC) {
|
||||
// Mixin 0.8 is no longer compatible with MC 1.11.2 or older
|
||||
def mixinVersion = mcVersion >= 11200 ? '0.8.2' : '0.7.11-SNAPSHOT'
|
||||
annotationProcessor "org.spongepowered:mixin:$mixinVersion"
|
||||
compileOnly "org.spongepowered:mixin:$mixinVersion"
|
||||
shade("org.spongepowered:mixin:$mixinVersion") {
|
||||
transitive = false // deps should all be bundled with MC
|
||||
}
|
||||
|
||||
// Mixin needs these (and depends on them but for some reason that's not enough. FG, did you do that?)
|
||||
annotationProcessor 'com.google.code.gson:gson:2.2.4'
|
||||
annotationProcessor 'com.google.guava:guava:21.0'
|
||||
annotationProcessor 'org.ow2.asm:asm-tree:6.2'
|
||||
annotationProcessor 'org.apache.logging.log4j:log4j-core:2.0-beta9'
|
||||
}
|
||||
|
||||
if (mcVersion >= 11604) {
|
||||
shadow(annotationProcessor('com.github.LlamaLad7:MixinExtras:0.1.1'))
|
||||
}
|
||||
|
||||
shadow 'com.googlecode.mp4parser:isoparser:1.1.7'
|
||||
shadow 'org.apache.commons:commons-exec:1.3'
|
||||
shadow 'com.google.apis:google-api-services-youtube:v3-rev178-1.22.0', shadeExclusions
|
||||
shadow 'com.google.api-client:google-api-client-gson:1.20.0', shadeExclusions
|
||||
shadow 'com.google.api-client:google-api-client-java6:1.20.0', shadeExclusions
|
||||
shadow 'com.google.oauth-client:google-oauth-client-jetty:1.20.0'
|
||||
|
||||
def lwjgl = configurations.create("lwjgl")
|
||||
for (suffix in ['', ':natives-linux', ':natives-windows', ':natives-macos', ':natives-macos-arm64']) {
|
||||
add(lwjgl.name, 'org.lwjgl:lwjgl:3.3.1' + suffix)
|
||||
add(lwjgl.name, 'org.lwjgl:lwjgl-tinyexr:3.3.1' + suffix)
|
||||
}
|
||||
compileOnly('org.lwjgl:lwjgl-tinyexr:3.3.1')
|
||||
shadow(prebundle(project, lwjgl, "com/replaymod/render/utils/lwjgl.jar", {}))
|
||||
|
||||
if (mcVersion < 11200) {
|
||||
// The version which MC ships is too old, we'll need to ship our own
|
||||
shadow 'com.google.code.gson:gson:2.8.7'
|
||||
}
|
||||
|
||||
shadow 'com.github.javagl.JglTF:jgltf-model:3af6de4'
|
||||
|
||||
if (FABRIC) {
|
||||
shadow 'org.apache.maven:maven-artifact:3.6.1'
|
||||
}
|
||||
|
||||
shadow 'org.aspectj:aspectjrt:1.8.2'
|
||||
|
||||
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
|
||||
|
||||
shadow "com.github.ReplayMod:ReplayStudio:d9f7c11", shadeExclusions
|
||||
|
||||
// FIXME this should be pulled in by ReplayStudio, and IntelliJ sees it, but javac for some reason does not
|
||||
implementation 'com.github.viaversion:opennbt:0a02214' // 2.0-SNAPSHOT (ViaVersion Edition)
|
||||
|
||||
implementation(FABRIC ? dependencies.project(path: jGui.path, configuration: "namedElements") : jGui) {
|
||||
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
||||
}
|
||||
shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66'
|
||||
|
||||
if (FABRIC) {
|
||||
if (mcVersion >= 12003) {
|
||||
modImplementation 'com.terraformersmc:modmenu:9.0.0-pre.1'
|
||||
} else if (mcVersion >= 12002) {
|
||||
modImplementation 'com.terraformersmc:modmenu:8.0.0'
|
||||
} else if (mcVersion >= 12000) {
|
||||
modImplementation 'com.terraformersmc:modmenu:7.0.1'
|
||||
} else if (mcVersion >= 11904) {
|
||||
modImplementation 'com.terraformersmc:modmenu:6.1.0-rc.4'
|
||||
} else if (mcVersion >= 11903) {
|
||||
modImplementation 'com.terraformersmc:modmenu:5.0.0-alpha.4'
|
||||
} else if (mcVersion >= 11901) {
|
||||
modImplementation 'com.terraformersmc:modmenu:4.0.5'
|
||||
} else if (mcVersion >= 11900) {
|
||||
modImplementation 'com.terraformersmc:modmenu:4.0.4'
|
||||
} else if (mcVersion >= 11802) {
|
||||
modImplementation 'com.terraformersmc:modmenu:3.1.0'
|
||||
} else if (mcVersion >= 11800) {
|
||||
modImplementation 'com.terraformersmc:modmenu:3.0.0'
|
||||
} else if (mcVersion >= 11700) {
|
||||
modImplementation 'com.terraformersmc:modmenu:2.0.0-beta.7'
|
||||
} else if (mcVersion >= 11602) {
|
||||
modImplementation 'com.terraformersmc:modmenu:1.16.8'
|
||||
} else if (mcVersion >= 11600) {
|
||||
modImplementation('com.terraformersmc:modmenu:1.14.15') {
|
||||
exclude module: 'fabric-resource-loader-v0' // inappropriate version for 1.16.1
|
||||
}
|
||||
} else if (mcVersion >= 11500) {
|
||||
modImplementation 'com.terraformersmc:modmenu:1.10.6'
|
||||
} else {
|
||||
modCompileOnly 'com.terraformersmc:modmenu:1.10.6'
|
||||
}
|
||||
}
|
||||
|
||||
if (mcVersion >= 11600) {
|
||||
modCompileOnly("maven.modrinth:iris:1.18.x-v1.2.0") {
|
||||
transitive = false // we do not want to upgrade our libs, we only need this to compile our mixins
|
||||
}
|
||||
}
|
||||
|
||||
testImplementation 'junit:junit:4.11'
|
||||
}
|
||||
|
||||
if (mcVersion <= 10710) {
|
||||
// FG 1.2 adds all MC deps to the compile configuration which we don't want
|
||||
afterEvaluate {
|
||||
// Remove them from the compile and runtime configurations
|
||||
configurations.compile.extendsFrom -= [configurations.minecraft, configurations.minecraftDeps]
|
||||
configurations.runtime.extendsFrom -= [configurations.forgeGradleStartClass]
|
||||
// And add them to the source sets instead
|
||||
sourceSets.main.with {
|
||||
compileClasspath += configurations.minecraft + configurations.minecraftDeps
|
||||
runtimeClasspath += configurations.minecraft + configurations.minecraftDeps + configurations.forgeGradleStartClass
|
||||
}
|
||||
// Also need to reconfigure the reobf task, so it can properly re-obfuscates inherited members
|
||||
tasks.reobf.obfOutput.all { artifact ->
|
||||
artifact.getFile() // force resolve
|
||||
artifact.classpath += configurations.minecraft + configurations.minecraftDeps
|
||||
}
|
||||
}
|
||||
|
||||
// Test sources aren't preprocessed and I can't be bothered to fix that
|
||||
tasks.compileTestJava.onlyIf { false }
|
||||
}
|
||||
|
||||
if (FABRIC) {
|
||||
tasks.remapJar {
|
||||
addNestedDependencies.set(true)
|
||||
afterEvaluate { // FIXME why does loom overwrite this if we set it immediately?
|
||||
archiveClassifier.set('obf')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File configureRelocationOutput = new File(project.buildDir, 'configureRelocation')
|
||||
task configureRelocation() {
|
||||
dependsOn tasks.jar
|
||||
dependsOn configurations.shadow
|
||||
outputs.file(configureRelocationOutput)
|
||||
doLast {
|
||||
def pkgs = files(configurations.shadow).filter { it.exists() }.collect {
|
||||
def tree = it.isDirectory() ? fileTree(it) : zipTree(it)
|
||||
def pkgs = [].toSet()
|
||||
tree.visit { file ->
|
||||
if (!file.directory && file.name.endsWith('.class') && file.path.contains('/')) {
|
||||
def pkg = file.path.substring(0, file.path.lastIndexOf('/')) + '/'
|
||||
if (pkg.startsWith('com/')) {
|
||||
if (pkg.startsWith('com/google/')) {
|
||||
if (!pkg.startsWith('com/google/common')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 'com/google/'.length()))
|
||||
}
|
||||
} else if (!pkg.startsWith('com/replaymod')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 4))
|
||||
}
|
||||
} else if (pkg.startsWith('net/')) {
|
||||
if (!pkg.startsWith('net/minecraft')
|
||||
&& !pkg.startsWith('net/fabric')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 'net/'.length()))
|
||||
}
|
||||
} else if (pkg.startsWith('org/')) {
|
||||
if (pkg.startsWith('org/apache/')) {
|
||||
if (pkg.startsWith('org/apache/commons/')) {
|
||||
if (!pkg.startsWith('org/apache/commons/io')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 'org/apache/commons/'.length()))
|
||||
}
|
||||
} else if (!pkg.startsWith('org/apache/logging')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 'org/apache/'.length()))
|
||||
}
|
||||
} else if (pkg.startsWith('org/lwjgl')) {
|
||||
return // either bundled with MC or uses natives which we can't relocate
|
||||
} else if (!pkg.startsWith('org/spongepowered')) {
|
||||
pkgs << pkg.substring(0, pkg.indexOf('/', 4))
|
||||
}
|
||||
} else if (pkg.startsWith('it/unimi/dsi/fastutil') && mcVersion >= 11400) {
|
||||
return // MC uses this as well
|
||||
} else if (!pkg.startsWith('javax/')) {
|
||||
// Note: we cannot just use top level packages as those will be too generic and we'll run
|
||||
// into this long standing bug: https://github.com/johnrengelman/shadow/issues/232
|
||||
def i = pkg.indexOf('/')
|
||||
def i2 = pkg.indexOf('/', i + 1)
|
||||
if (i2 > 0) {
|
||||
pkgs << pkg.substring(0, i2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pkgs
|
||||
}.flatten().unique()
|
||||
configureRelocationOutput.write(pkgs.join('\n'))
|
||||
}
|
||||
}
|
||||
|
||||
// we want to base our shadowed jar on the reobfJar output, not the sourceSet output
|
||||
// Tried tasks.replace but that does not actually seem to replace everything.
|
||||
tasks.shadowJar.doFirst {
|
||||
throw new GradleException("Wrong task! You want to run 'bundleJar' instead.")
|
||||
}
|
||||
tasks.register('bundleJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar).configure {
|
||||
from { (FABRIC ? tasks.remapJar : tasks.jar).archiveFile.get() }
|
||||
dependsOn { FABRIC ? tasks.remapJar : (mcVersion >= 10800 ? tasks.reobfJar : tasks.reobf) }
|
||||
|
||||
from({ zipTree((FABRIC ? jGui.tasks.remapJar : jGui.tasks.jar).archiveFile.get()) }) {
|
||||
filesMatching('mixins.jgui.json') {
|
||||
filter { it.replace('de.johni0702', 'com.replaymod.lib.de.johni0702') }
|
||||
}
|
||||
filesMatching('mixins.jgui.refmap.json') {
|
||||
filter { it.replace('de/johni0702', 'com/replaymod/lib/de/johni0702') }
|
||||
}
|
||||
}
|
||||
dependsOn { FABRIC ? jGui.tasks.remapJar : (mcVersion >= 10800 ? jGui.tasks.reobfJar : jGui.tasks.reobf) }
|
||||
relocate 'de.johni0702', 'com.replaymod.lib.de.johni0702'
|
||||
|
||||
manifest.inheritFrom tasks.jar.manifest
|
||||
|
||||
from project.configurations.shade
|
||||
configurations = [project.configurations.shadow]
|
||||
exclude 'META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class'
|
||||
|
||||
dependsOn tasks.configureRelocation
|
||||
inputs.file(configureRelocationOutput)
|
||||
doFirst {
|
||||
configureRelocationOutput.readLines().each { pkg ->
|
||||
def pkgName = pkg.replace('/', '.')
|
||||
relocate pkgName, 'com.replaymod.lib.' + pkgName
|
||||
}
|
||||
}
|
||||
|
||||
// No need to shadow netty, MC provides it
|
||||
// (actually, pre-1.12 ships a netty which is too old, so we need to shade it there anyway)
|
||||
if (mcVersion >= 11200) {
|
||||
relocate 'com.github.steveice10.netty', 'io.netty'
|
||||
exclude 'com/github/steveice10/netty/**'
|
||||
}
|
||||
|
||||
if (mcVersion >= 11400) {
|
||||
// MC ships this
|
||||
exclude 'it/unimi/dsi/fastutil/**'
|
||||
}
|
||||
|
||||
minimize {
|
||||
exclude(dependency('.*spongepowered:mixin:.*'))
|
||||
}
|
||||
}
|
||||
tasks.assemble.dependsOn tasks.bundleJar
|
||||
|
||||
jar {
|
||||
classifier = 'raw'
|
||||
|
||||
if (!FABRIC) {
|
||||
from files(project.mixinRefMap.canonicalPath)
|
||||
manifest {
|
||||
attributes 'TweakClass': 'com.replaymod.core.tweaker.ReplayModTweaker',
|
||||
'TweakOrder': '0',
|
||||
'FMLCorePluginContainsFMLMod': 'true',
|
||||
'FMLCorePlugin': 'com.replaymod.core.LoadingPlugin',
|
||||
'FMLAT': 'replaymod_at.cfg'
|
||||
}
|
||||
}
|
||||
|
||||
if (mcVersion >= 11700) {
|
||||
// Workaround a mixin bug which generates invalid refmaps for the `addDrawableChild` invoker
|
||||
filesMatching("mixins.replaymod.refmap.json") {
|
||||
it.filter {
|
||||
it.replace("addDrawableChild(L/;)L/;", "method_37063(Lnet/minecraft/class_364;)Lnet/minecraft/class_364;")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property 'version', { project.version }
|
||||
inputs.property 'mcversion', { mcVersionStr }
|
||||
|
||||
// replace stuff in mcmod.info (forge) and fabric.mod.json, nothing else
|
||||
filesMatching(['mcmod.info', 'fabric.mod.json']) {
|
||||
// replace version and mcversion
|
||||
expand 'version': project.version, 'mcversion': mcVersionStr
|
||||
}
|
||||
|
||||
// strip comments from (strict) JSON files
|
||||
filesMatching('pack.mcmeta') {
|
||||
filter { line -> line.trim().startsWith('//') ? '' : line}
|
||||
}
|
||||
|
||||
// exclude mod meta for non-applicable loader
|
||||
if (FABRIC) {
|
||||
exclude 'mcmod.info'
|
||||
} else {
|
||||
exclude 'fabric.mod.json'
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
integrationTest {
|
||||
compileClasspath += main.runtimeClasspath + main.output
|
||||
java {
|
||||
srcDir file('src/integration-test/java')
|
||||
}
|
||||
resources.srcDir file('src/integration-test/resources')
|
||||
}
|
||||
}
|
||||
|
||||
if (FABRIC) {
|
||||
// not required, fabric manages those by itself just fine
|
||||
} else if (FG3) {
|
||||
task copySrg(dependsOn: 'createMcpToSrg') {
|
||||
doLast {
|
||||
def tsrg = file(project.tasks.createMcpToSrg.output).readLines()
|
||||
def srg = []
|
||||
def cls = ''
|
||||
for (def line : tsrg) {
|
||||
if (line[0] != '\t') {
|
||||
srg.add('CL: ' + line)
|
||||
cls = line.split(' ')[0]
|
||||
} else {
|
||||
def parts = line.substring(1).split(' ')
|
||||
if (line.contains('(')) {
|
||||
srg.add('MD: ' + cls + '/' + parts[0] + ' ' + parts[1] + ' ' + cls + '/' + parts[2] + ' ' + parts[1])
|
||||
} else {
|
||||
srg.add('FD: ' + cls + '/' + parts[0] + ' ' + cls + '/' + parts[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
new File(project.buildDir, 'mcp-srg.srg').write(srg.join('\n'))
|
||||
}
|
||||
}
|
||||
compileJava.dependsOn copySrg
|
||||
} else {
|
||||
task copySrg(type: Copy, dependsOn: 'genSrgs') {
|
||||
from {project.tasks.genSrgs.mcpToSrg}
|
||||
into 'build'
|
||||
}
|
||||
compileJava.dependsOn copySrg
|
||||
}
|
||||
|
||||
if (!FABRIC && !FG3) {
|
||||
if (mcVersion <= 10710) {
|
||||
reobf.addExtraSrgFile project.mixinSrg
|
||||
} else {
|
||||
reobfJar.addSecondarySrgFile project.mixinSrg
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME
|
||||
// Mixin uses multiple HashMaps to generate the refmap.
|
||||
// HashMaps are unordered collections and as such do not produce deterministic output.
|
||||
// To fix that, we simply sort the refmap json file.
|
||||
import groovy.json.JsonSlurper
|
||||
import groovy.json.JsonOutput
|
||||
compileJava.doLast {
|
||||
File refmapFile = mcVersion >= 10800 ? compileJava.ext.refMapFile : project.mixinRefMap
|
||||
if (refmapFile.exists()) {
|
||||
def ordered
|
||||
ordered = {
|
||||
if (it instanceof Map) {
|
||||
def sorted = new TreeMap(it)
|
||||
sorted.replaceAll { k, v -> ordered(v) }
|
||||
sorted
|
||||
} else if (it instanceof List) {
|
||||
it.replaceAll { v -> ordered(v) }
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
def json = JsonOutput.toJson(ordered(new JsonSlurper().parse(refmapFile)))
|
||||
refmapFile.withWriter { it.write json }
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!FG3 && !FABRIC) { // FIXME
|
||||
task runIntegrationTest(type: JavaExec, dependsOn: ["makeStart", "jar"]) {
|
||||
main = 'GradleStart'
|
||||
standardOutput = System.out
|
||||
errorOutput = System.err
|
||||
workingDir file(minecraft.runDir)
|
||||
|
||||
def testDir = new File(minecraft.runDir, "integration-test")
|
||||
doFirst {
|
||||
testDir.deleteDir()
|
||||
testDir.mkdirs()
|
||||
}
|
||||
|
||||
doLast {
|
||||
testDir.deleteDir()
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
def runClient = tasks.getByName("runClient")
|
||||
runIntegrationTest.jvmArgs = runClient.jvmArgs + "-Dfml.noGrab=true"
|
||||
runIntegrationTest.args = runClient.args + "--gameDir" + testDir.canonicalPath
|
||||
runIntegrationTest.classpath runClient.classpath + sourceSets.integrationTest.output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultTasks 'build'
|
||||
348
build.gradle.kts
Normal file
348
build.gradle.kts
Normal file
@@ -0,0 +1,348 @@
|
||||
import com.replaymod.gradle.preprocess.PreprocessTask
|
||||
import gg.essential.gradle.util.*
|
||||
|
||||
plugins {
|
||||
java
|
||||
id("io.github.goooler.shadow") apply false
|
||||
id("gg.essential.multi-version")
|
||||
id("gg.essential.defaults.repo")
|
||||
id("gg.essential.defaults.java")
|
||||
id("gg.essential.defaults.loom")
|
||||
}
|
||||
|
||||
val mcVersion = platform.mcVersion
|
||||
|
||||
var jGuiVersion = project.name
|
||||
if (jGuiVersion in listOf("1.10.2", "1.11", "1.11.2")) jGuiVersion = "1.9.4"
|
||||
if (jGuiVersion in listOf("1.12.1", "1.12.2")) jGuiVersion = "1.12"
|
||||
val jGui = project.evaluationDependsOn(":jGui:$jGuiVersion")
|
||||
|
||||
version = "${project.name}-${rootProject.version}"
|
||||
base.archivesName.set("replaymod")
|
||||
java.withSourcesJar()
|
||||
|
||||
loom {
|
||||
mixin.defaultRefmapName.set("mixins.replaymod.refmap.json")
|
||||
noServerRunConfigs()
|
||||
}
|
||||
|
||||
if (platform.isLegacyForge) {
|
||||
loom.runs.named("client") {
|
||||
property("fml.coreMods.load", "com.replaymod.core.LoadingPlugin")
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven("https://repo.spongepowered.org/maven/")
|
||||
maven("https://maven.terraformersmc.com/releases/") {
|
||||
content {
|
||||
includeGroup("com.terraformersmc")
|
||||
}
|
||||
}
|
||||
maven("https://jitpack.io") {
|
||||
content {
|
||||
includeGroupByRegex("com\\.github\\..*")
|
||||
}
|
||||
}
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://api.modrinth.com/maven")
|
||||
}
|
||||
filter {
|
||||
includeGroup("maven.modrinth")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include dep in fat jar without relocation and, when forge supports it, without exploding (TODO)
|
||||
val shade by configurations.creating
|
||||
// Include dep in fat jar with relocation and minimization
|
||||
val shadow by configurations.creating {
|
||||
exclude(group = "net.fabricmc", module = "fabric-loader")
|
||||
exclude(group = "com.google.guava", module = "guava-jdk5")
|
||||
exclude(group = "com.google.guava", module = "guava") // provided by MC
|
||||
exclude(group = "com.google.code.gson", module = "gson") // provided by MC (or manually bundled for 1.11.2 and below)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if (platform.isFabric) {
|
||||
val fabricApiVersion = when (mcVersion) {
|
||||
11404 -> "0.4.3+build.247-1.14"
|
||||
11502 -> "0.5.1+build.294-1.15"
|
||||
11601 -> "0.14.0+build.371-1.16"
|
||||
11603 -> "0.17.1+build.394-1.16"
|
||||
11604 -> "0.42.0+1.16"
|
||||
11701 -> "0.46.1+1.17"
|
||||
11800 -> "0.43.1+1.18"
|
||||
11801 -> "0.43.1+1.18"
|
||||
11802 -> "0.47.9+1.18.2"
|
||||
11900 -> "0.55.3+1.19"
|
||||
11901 -> "0.58.5+1.19.1"
|
||||
11902 -> "0.68.0+1.19.2"
|
||||
11903 -> "0.68.1+1.19.3"
|
||||
11904 -> "0.76.0+1.19.4"
|
||||
12001 -> "0.83.1+1.20.1"
|
||||
12002 -> "0.91.2+1.20.2"
|
||||
12004 -> "0.91.2+1.20.4"
|
||||
12006 -> "0.98.0+1.20.6"
|
||||
12100 -> "0.100.3+1.21"
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
val fabricApiModules = mutableListOf(
|
||||
"api-base",
|
||||
"networking-v0",
|
||||
"keybindings-v0",
|
||||
"resource-loader-v0",
|
||||
)
|
||||
if (mcVersion >= 11600) {
|
||||
fabricApiModules.remove("keybindings-v0")
|
||||
fabricApiModules.add("key-binding-api-v1")
|
||||
}
|
||||
if (mcVersion >= 11604) {
|
||||
fabricApiModules.add("screen-api-v1")
|
||||
fabricApiModules.add("networking-api-v1")
|
||||
}
|
||||
if (mcVersion >= 11700) {
|
||||
fabricApiModules.remove("networking-v0")
|
||||
}
|
||||
for (module in fabricApiModules) {
|
||||
val dep = fabricApi.module("fabric-$module", fabricApiVersion)
|
||||
modImplementation(dep)
|
||||
"include"(dep)
|
||||
}
|
||||
}
|
||||
|
||||
if (!platform.isFabric) {
|
||||
// Mixin 0.8 is no longer compatible with MC 1.11.2 or older
|
||||
val mixinVersion = if (mcVersion >= 11200) "0.8.2" else "0.7.11-SNAPSHOT"
|
||||
compileOnly("org.spongepowered:mixin:$mixinVersion")
|
||||
implementation(shade("org.spongepowered:mixin:$mixinVersion") {
|
||||
isTransitive = false // deps should all be bundled with MC
|
||||
})
|
||||
}
|
||||
|
||||
if (platform.isFabric) {
|
||||
"include"(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:0.3.6")!!)!!)
|
||||
}
|
||||
|
||||
implementation(shadow("com.googlecode.mp4parser:isoparser:1.1.7")!!)
|
||||
implementation(shadow("org.apache.commons:commons-exec:1.3")!!)
|
||||
implementation(shadow("com.google.apis:google-api-services-youtube:v3-rev178-1.22.0")!!)
|
||||
implementation(shadow("com.google.api-client:google-api-client-gson:1.20.0")!!)
|
||||
implementation(shadow("com.google.api-client:google-api-client-java6:1.20.0")!!)
|
||||
implementation(shadow("com.google.oauth-client:google-oauth-client-jetty:1.20.0")!!)
|
||||
|
||||
val lwjgl by configurations.creating
|
||||
for (suffix in listOf("", ":natives-linux", ":natives-windows", ":natives-macos", ":natives-macos-arm64")) {
|
||||
lwjgl("org.lwjgl:lwjgl:3.3.1$suffix")
|
||||
lwjgl("org.lwjgl:lwjgl-tinyexr:3.3.1$suffix")
|
||||
}
|
||||
compileOnly("org.lwjgl:lwjgl-tinyexr:3.3.1")
|
||||
shadow(prebundle(lwjgl, "com/replaymod/render/utils/lwjgl.jar"))
|
||||
|
||||
if (mcVersion < 11200) {
|
||||
// The version which MC ships is too old, we'll need to ship our own
|
||||
implementation(shadow("com.google.code.gson:gson:2.8.7")!!)
|
||||
}
|
||||
|
||||
implementation(shadow("com.github.javagl.JglTF:jgltf-model:3af6de4")!!)
|
||||
|
||||
if (platform.isFabric) {
|
||||
implementation(shadow("org.apache.maven:maven-artifact:3.6.1")!!)
|
||||
}
|
||||
|
||||
implementation(shadow("org.aspectj:aspectjrt:1.8.2")!!)
|
||||
|
||||
implementation(shadow("com.github.ReplayMod.JavaBlend:2.79.0:a0696f8")!!)
|
||||
|
||||
implementation(shadow("com.github.ReplayMod:ReplayStudio")!!)
|
||||
// FIXME hack because I don't know how to get this to be inherited properly
|
||||
implementation(rootProject.files("libs/ReplayStudio/.gradle/prebundled-jars/viaVersion.jar"))
|
||||
|
||||
implementation(project(path = jGui.path, configuration = "namedElements"))
|
||||
implementation(shadow("com.github.ReplayMod:lwjgl-utils:27dcd66")!!)
|
||||
|
||||
if (platform.isFabric) {
|
||||
val modMenuVersion = when {
|
||||
mcVersion >= 12100 -> "11.0.0-rc.4"
|
||||
mcVersion >= 12006 -> "10.0.0-beta.1"
|
||||
mcVersion >= 12003 -> "9.0.0-pre.1"
|
||||
mcVersion >= 12002 -> "8.0.0"
|
||||
mcVersion >= 12000 -> "7.0.1"
|
||||
mcVersion >= 11904 -> "6.1.0-rc.4"
|
||||
mcVersion >= 11903 -> "5.0.0-alpha.4"
|
||||
mcVersion >= 11901 -> "4.0.5"
|
||||
mcVersion >= 11900 -> "4.0.4"
|
||||
mcVersion >= 11802 -> "3.1.0"
|
||||
mcVersion >= 11800 -> "3.0.0"
|
||||
mcVersion >= 11700 -> "2.0.0-beta.7"
|
||||
mcVersion >= 11602 -> "1.16.8"
|
||||
mcVersion >= 11600 -> null // maven doesn't have one for this version (only 1.16.5)
|
||||
mcVersion >= 11500 -> "1.10.6"
|
||||
else -> null
|
||||
}
|
||||
if (modMenuVersion != null) {
|
||||
modCompileOnly("com.terraformersmc:modmenu:$modMenuVersion")
|
||||
} else {
|
||||
// Oldest modmenu on their maven is 1.10.5 for MC 1.15.2; for older versions we won't run it in dev
|
||||
modCompileOnly("com.terraformersmc:modmenu:1.10.6")
|
||||
}
|
||||
// Lacks maven dependencies
|
||||
if (mcVersion == 12006) {
|
||||
//modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:0.98.0+1.20.6")
|
||||
}
|
||||
}
|
||||
|
||||
val irisVersion = when {
|
||||
mcVersion >= 12000 -> "1.7.2+1.20.1"
|
||||
mcVersion >= 11600 -> "1.18.x-v1.2.0"
|
||||
else -> null
|
||||
}
|
||||
if (irisVersion != null) {
|
||||
modCompileOnly("maven.modrinth:iris:$irisVersion")
|
||||
}
|
||||
|
||||
testImplementation("junit:junit:4.11")
|
||||
}
|
||||
|
||||
preprocess {
|
||||
keywords.set(mapOf(
|
||||
".java" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".kt" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".json" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".mcmeta" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".cfg" to PreprocessTask.CFG_KEYWORDS,
|
||||
".vert" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
".frag" to PreprocessTask.DEFAULT_KEYWORDS,
|
||||
))
|
||||
|
||||
patternAnnotation.set("com.replaymod.gradle.remap.Pattern")
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
archiveClassifier.set("raw")
|
||||
|
||||
if (!platform.isFabric) {
|
||||
manifest {
|
||||
attributes(
|
||||
"TweakClass" to "com.replaymod.core.tweaker.ReplayModTweaker",
|
||||
"TweakOrder" to "0",
|
||||
"FMLCorePluginContainsFMLMod" to "true",
|
||||
"FMLCorePlugin" to "com.replaymod.core.LoadingPlugin",
|
||||
"FMLAT" to "replaymod_at.cfg",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.remapJar {
|
||||
if (platform.isFabric) {
|
||||
addNestedDependencies.set(true)
|
||||
}
|
||||
archiveClassifier.set("obf")
|
||||
}
|
||||
|
||||
val configureRelocationOutput = project.layout.buildDirectory.file("configureRelocation")
|
||||
val configureRelocation by tasks.registering {
|
||||
dependsOn(tasks.jar)
|
||||
dependsOn(shadow)
|
||||
outputs.file(configureRelocationOutput)
|
||||
doLast {
|
||||
val pkgs = files(shadow).filter { it.exists() }.map {
|
||||
val tree = if (it.isDirectory) fileTree(it) else zipTree(it)
|
||||
val pkgs = mutableSetOf<String>()
|
||||
tree.visit {
|
||||
val file = this
|
||||
if (!file.isDirectory && file.name.endsWith(".class") && file.path.contains("/")) {
|
||||
val pkg = file.path.substring(0, file.path.lastIndexOf("/")) + "/"
|
||||
if (pkg.startsWith("com/")) {
|
||||
if (pkg.startsWith("com/google/")) {
|
||||
if (!pkg.startsWith("com/google/common")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", "com/google/".length))
|
||||
}
|
||||
} else if (!pkg.startsWith("com/replaymod")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", 4))
|
||||
}
|
||||
} else if (pkg.startsWith("net/")) {
|
||||
if (!pkg.startsWith("net/minecraft")
|
||||
&& !pkg.startsWith("net/fabric")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", "net/".length))
|
||||
}
|
||||
} else if (pkg.startsWith("org/")) {
|
||||
if (pkg.startsWith("org/apache/")) {
|
||||
if (pkg.startsWith("org/apache/commons/")) {
|
||||
if (!pkg.startsWith("org/apache/commons/io")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", "org/apache/commons/".length))
|
||||
}
|
||||
} else if (!pkg.startsWith("org/apache/logging")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", "org/apache/".length))
|
||||
}
|
||||
} else if (pkg.startsWith("org/lwjgl")) {
|
||||
return@visit // either bundled with MC or uses natives which we can't relocate
|
||||
} else if (!pkg.startsWith("org/spongepowered")) {
|
||||
pkgs += pkg.substring(0, pkg.indexOf("/", 4))
|
||||
}
|
||||
} else if (pkg.startsWith("it/unimi/dsi/fastutil") && mcVersion >= 11400) {
|
||||
return@visit // MC uses this as well
|
||||
} else if (!pkg.startsWith("javax/")) {
|
||||
// Note: we cannot just use top level packages as those will be too generic and we'll run
|
||||
// into this long standing bug: https://github.com/johnrengelman/shadow/issues/232
|
||||
val i = pkg.indexOf("/")
|
||||
val i2 = pkg.indexOf("/", i + 1)
|
||||
if (i2 > 0) {
|
||||
pkgs += pkg.substring(0, i2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pkgs
|
||||
}.flatten().toSortedSet()
|
||||
configureRelocationOutput.get().asFile.writeText(pkgs.joinToString("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
val bundleJar by tasks.registering(com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar::class) {
|
||||
from(tasks.remapJar.flatMap { it.archiveFile }.map { zipTree(it) })
|
||||
|
||||
from(jGui.tasks.remapJar.flatMap { it.archiveFile }.map { zipTree(it) }) {
|
||||
filesMatching("mixins.jgui.json") {
|
||||
filter { it.replace("de.johni0702", "com.replaymod.lib.de.johni0702") }
|
||||
}
|
||||
filesMatching("mixins.jgui.refmap.json") {
|
||||
filter { it.replace("de/johni0702", "com/replaymod/lib/de/johni0702") }
|
||||
}
|
||||
}
|
||||
relocate("de.johni0702", "com.replaymod.lib.de.johni0702")
|
||||
|
||||
manifest.inheritFrom(tasks.jar.get().manifest)
|
||||
from(shade)
|
||||
configurations = listOf(shadow)
|
||||
exclude("META-INF/INDEX.LIST", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", "module-info.class")
|
||||
|
||||
dependsOn(configureRelocation)
|
||||
inputs.file(configureRelocationOutput)
|
||||
doFirst {
|
||||
configureRelocationOutput.get().asFile.forEachLine { pkg ->
|
||||
val pkgName = pkg.replace("/", ".")
|
||||
relocate(pkgName, "com.replaymod.lib.$pkgName")
|
||||
}
|
||||
}
|
||||
|
||||
// No need to shadow netty, MC provides it
|
||||
// (actually, pre-1.12 ships a netty which is too old, so we need to shade it there anyway)
|
||||
if (mcVersion >= 11200) {
|
||||
relocate("com.github.steveice10.netty", "io.netty")
|
||||
exclude("com/github/steveice10/netty/**")
|
||||
}
|
||||
|
||||
if (mcVersion >= 11400) {
|
||||
// MC ships this
|
||||
exclude("it/unimi/dsi/fastutil/**")
|
||||
}
|
||||
|
||||
minimize {
|
||||
exclude(dependency(".*spongepowered:mixin:.*"))
|
||||
}
|
||||
}
|
||||
tasks.assemble { dependsOn(bundleJar) }
|
||||
@@ -1,6 +1,8 @@
|
||||
essential.defaults.loom=0
|
||||
essential.defaults.loom.fabric-loader=net.fabricmc:fabric-loader:0.15.11
|
||||
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
org.gradle.jvmargs=-Xmx8G
|
||||
org.gradle.parallel=true
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
2
jGui
2
jGui
Submodule jGui updated: bd41e57af0...d2626659b0
1
libs/ReplayStudio
Submodule
1
libs/ReplayStudio
Submodule
Submodule libs/ReplayStudio added at 1e96fda605
@@ -2,8 +2,7 @@ import groovy.json.JsonOutput
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
plugins {
|
||||
id("fabric-loom") version "0.11-SNAPSHOT" apply false
|
||||
id("com.replaymod.preprocess") version "48e02ad"
|
||||
id("gg.essential.multi-version.root")
|
||||
id("com.github.hierynomus.license") version "0.15.0"
|
||||
}
|
||||
|
||||
@@ -35,6 +34,12 @@ subprojects {
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
}
|
||||
if (name == "jGui" || name == "ReplayStudio") {
|
||||
return@subprojects
|
||||
}
|
||||
val (_, minor) = name.split("-")[0].split(".")
|
||||
val fabric = minor.toInt() >= 14 && !name.endsWith("-forge")
|
||||
extra.set("loom.platform", if (fabric) "fabric" else "forge")
|
||||
|
||||
afterEvaluate {
|
||||
val projectBundleJar = project.tasks.findByName("bundleJar")
|
||||
@@ -91,8 +96,11 @@ fun generateVersionsJson(): Map<String, Any> {
|
||||
.filter { it != "core" }
|
||||
// Internal project used to automatically remap from Forge 1.12.2 to Fabric 1.14.4
|
||||
.filter { it != "1.14.4-forge" }
|
||||
// We dropped 1.8 with the switch to archloom but still kept its source in case someone
|
||||
// volunteers to make it build again
|
||||
.filterNot { it == "1.8" && versionComparator.compare(version, "2.6.16") >= 0 }
|
||||
// We dropped 1.7.10 with the Gradle 7 update but still kept its source in case someone
|
||||
// volunteers to update FG 1.2 to Gradle 7.
|
||||
// volunteers to ~~update FG 1.2 to Gradle 7~~ make it work with archloom.
|
||||
.filterNot { it == "1.7.10" && versionComparator.compare(version, "2.6.0") >= 0 }
|
||||
val versions = mcVersions.map { "$it-$version" }.toMutableList()
|
||||
when (version) {
|
||||
@@ -193,6 +201,8 @@ val doRelease by tasks.registering {
|
||||
defaultTasks("bundleJar")
|
||||
|
||||
preprocess {
|
||||
val mc12100 = createNode("1.21", 12100, "yarn")
|
||||
val mc12006 = createNode("1.20.6", 12006, "yarn")
|
||||
val mc12004 = createNode("1.20.4", 12004, "yarn")
|
||||
val mc12002 = createNode("1.20.2", 12002, "yarn")
|
||||
val mc12001 = createNode("1.20.1", 12001, "yarn")
|
||||
@@ -220,9 +230,11 @@ preprocess {
|
||||
val mc10800 = createNode("1.8", 10800, "srg")
|
||||
val mc10710 = createNode("1.7.10", 10710, "srg")
|
||||
|
||||
mc12100.link(mc12006)
|
||||
mc12006.link(mc12004)
|
||||
mc12004.link(mc12002, file("versions/mapping-fabric-1.20.4-1.20.2.txt"))
|
||||
mc12002.link(mc12001)
|
||||
mc12001.link(mc11904)
|
||||
mc12001.link(mc11904, file("versions/mapping-fabric-1.20.1-1.19.4.txt"))
|
||||
mc11904.link(mc11903)
|
||||
mc11903.link(mc11902, file("versions/mapping-fabric-1.19.3-1.19.2.txt"))
|
||||
mc11902.link(mc11901)
|
||||
@@ -235,14 +247,14 @@ preprocess {
|
||||
mc11601.link(mc11502, file("versions/mapping-fabric-1.16.1-1.15.2.txt"))
|
||||
mc11502.link(mc11404, file("versions/mapping-fabric-1.15.2-1.14.4.txt"))
|
||||
mc11404.link(mc11404Forge, file("versions/mapping-1.14.4-fabric-forge.txt"))
|
||||
mc11404Forge.link(mc11202, file("versions/1.14.4-forge/mapping.txt"))
|
||||
mc11404Forge.link(mc11202, file("versions/mapping-forge-1.14.4-1.12.2.txt"))
|
||||
mc11202.link(mc11201)
|
||||
mc11201.link(mc11200)
|
||||
mc11200.link(mc11102, file("versions/1.12/mapping.txt"))
|
||||
mc11102.link(mc11100, file("versions/1.11.2/mapping.txt"))
|
||||
mc11100.link(mc11002, file("versions/1.11/mapping.txt"))
|
||||
mc11200.link(mc11102, file("versions/mapping-forge-1.12-1.11.2.txt"))
|
||||
mc11102.link(mc11100, file("versions/mapping-forge-1.11.2-1.11.txt"))
|
||||
mc11100.link(mc11002, file("versions/mapping-forge-1.11-1.10.2.txt"))
|
||||
mc11002.link(mc10904)
|
||||
mc10904.link(mc10809, file("versions/1.9.4/mapping.txt"))
|
||||
mc10809.link(mc10800, file("versions/1.8.9/mapping.txt"))
|
||||
mc10800.link(mc10710, file("versions/1.8/mapping.txt"))
|
||||
mc10904.link(mc10809, file("versions/mapping-forge-1.9.4-1.8.9.txt"))
|
||||
mc10809.link(mc10800, file("versions/mapping-forge-1.8.9-1.8.txt"))
|
||||
mc10800.link(mc10710, file("versions/mapping-forge-1.8-1.7.10.txt"))
|
||||
}
|
||||
|
||||
@@ -6,21 +6,19 @@ pluginManagement {
|
||||
google()
|
||||
maven("https://jitpack.io")
|
||||
maven("https://maven.fabricmc.net")
|
||||
maven("https://maven.architectury.dev/")
|
||||
maven("https://maven.minecraftforge.net")
|
||||
maven("https://repo.essential.gg/repository/maven-public")
|
||||
}
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
when (requested.id.id) {
|
||||
"com.replaymod.preprocess" -> {
|
||||
useModule("com.github.replaymod:preprocessor:${requested.version}")
|
||||
}
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id("gg.essential.multi-version.root") version "0.6.1"
|
||||
id("io.github.goooler.shadow") version "8.1.7"
|
||||
}
|
||||
}
|
||||
|
||||
val jGuiVersions = listOf(
|
||||
// "1.7.10",
|
||||
"1.8",
|
||||
// "1.8",
|
||||
"1.8.9",
|
||||
"1.9.4",
|
||||
"1.12",
|
||||
@@ -40,10 +38,12 @@ val jGuiVersions = listOf(
|
||||
"1.20.1",
|
||||
"1.20.2",
|
||||
"1.20.4",
|
||||
"1.20.6",
|
||||
"1.21",
|
||||
)
|
||||
val replayModVersions = listOf(
|
||||
// "1.7.10",
|
||||
"1.8",
|
||||
// "1.8",
|
||||
"1.8.9",
|
||||
"1.9.4",
|
||||
"1.10.2",
|
||||
@@ -68,20 +68,24 @@ val replayModVersions = listOf(
|
||||
"1.20.1",
|
||||
"1.20.2",
|
||||
"1.20.4",
|
||||
"1.20.6",
|
||||
"1.21",
|
||||
)
|
||||
|
||||
rootProject.buildFileName = "root.gradle.kts"
|
||||
|
||||
includeBuild("libs/ReplayStudio")
|
||||
|
||||
include(":jGui")
|
||||
project(":jGui").apply {
|
||||
projectDir = file("jGui")
|
||||
buildFileName = "preprocess.gradle.kts"
|
||||
buildFileName = "root.gradle.kts"
|
||||
}
|
||||
jGuiVersions.forEach { version ->
|
||||
include(":jGui:$version")
|
||||
project(":jGui:$version").apply {
|
||||
projectDir = file("jGui/versions/$version")
|
||||
buildFileName = "../../build.gradle"
|
||||
buildFileName = "../../build.gradle.kts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +93,6 @@ replayModVersions.forEach { version ->
|
||||
include(":$version")
|
||||
project(":$version").apply {
|
||||
projectDir = file("versions/$version")
|
||||
buildFileName = "../../build.gradle"
|
||||
buildFileName = "../../build.gradle.kts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.util.Identifier;
|
||||
import static com.replaymod.core.ReplayMod.MOD_ID;
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
//#else
|
||||
//$$ import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
//#endif
|
||||
@@ -66,7 +67,7 @@ public class KeyBindingRegistry extends EventRegistrations {
|
||||
if (keyCode == 0) {
|
||||
keyCode = -1;
|
||||
}
|
||||
Identifier id = new Identifier(MOD_ID, name.substring(LangResourcePack.LEGACY_KEY_PREFIX.length()));
|
||||
Identifier id = identifier(MOD_ID, name.substring(LangResourcePack.LEGACY_KEY_PREFIX.length()));
|
||||
//#if MC>=11600
|
||||
String key = String.format("key.%s.%s", id.getNamespace(), id.getPath());
|
||||
KeyBinding keyBinding = new KeyBinding(key, InputUtil.Type.KEYSYM, keyCode, CATEGORY);
|
||||
|
||||
@@ -36,6 +36,15 @@ import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ import net.minecraft.resource.ResourcePackInfo;
|
||||
//$$ import net.minecraft.resource.ResourcePackSource;
|
||||
//$$ import net.minecraft.text.Text;
|
||||
//$$ import java.util.Optional;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11900
|
||||
//#else
|
||||
import net.minecraft.client.options.Option;
|
||||
@@ -45,9 +54,9 @@ public class ReplayMod implements Module, Scheduler {
|
||||
|
||||
public static final String MOD_ID = "replaymod";
|
||||
|
||||
public static final Identifier TEXTURE = new Identifier("replaymod", "replay_gui.png");
|
||||
public static final Identifier TEXTURE = identifier("replaymod", "replay_gui.png");
|
||||
public static final int TEXTURE_SIZE = 256;
|
||||
public static final Identifier LOGO_FAVICON = new Identifier("replaymod", "favicon_logo.png");
|
||||
public static final Identifier LOGO_FAVICON = identifier("replaymod", "favicon_logo.png");
|
||||
|
||||
private static final MinecraftClient mc = MCVer.getMinecraft();
|
||||
|
||||
@@ -120,7 +129,9 @@ public class ReplayMod implements Module, Scheduler {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//#if MC>=11903
|
||||
//#if MC>=12006
|
||||
//$$ return new DirectoryResourcePack(new ResourcePackInfo(JGUI_RESOURCE_PACK_NAME, Text.literal("jGui"), ResourcePackSource.NONE, Optional.empty()), folder.toPath()) {
|
||||
//#elseif MC>=11903
|
||||
//$$ return new DirectoryResourcePack(JGUI_RESOURCE_PACK_NAME, folder.toPath(), true) {
|
||||
//#else
|
||||
return new DirectoryResourcePack(folder) {
|
||||
|
||||
@@ -6,8 +6,10 @@ import de.johni0702.minecraft.gui.element.GuiButton;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
public class GuiReplayButton extends GuiButton {
|
||||
public static final Identifier ICON = new Identifier("replaymod", "logo_button.png");
|
||||
public static final Identifier ICON = identifier("replaymod", "logo_button.png");
|
||||
|
||||
@Override
|
||||
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
|
||||
|
||||
@@ -29,6 +29,13 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public interface MinecraftAccessor {
|
||||
//#if MC>=12100
|
||||
//$$ @Accessor("renderTickCounter")
|
||||
//$$ RenderTickCounter.Dynamic getTimer();
|
||||
//$$ @Accessor("renderTickCounter")
|
||||
//$$ @Mutable
|
||||
//$$ void setTimer(RenderTickCounter.Dynamic value);
|
||||
//#else
|
||||
@Accessor("renderTickCounter")
|
||||
RenderTickCounter getTimer();
|
||||
@Accessor("renderTickCounter")
|
||||
@@ -36,6 +43,7 @@ public interface MinecraftAccessor {
|
||||
@Mutable
|
||||
//#endif
|
||||
void setTimer(RenderTickCounter value);
|
||||
//#endif
|
||||
|
||||
//#if MC>=11400
|
||||
@Accessor
|
||||
|
||||
@@ -48,16 +48,22 @@ public abstract class MixinMinecraft
|
||||
}
|
||||
//#endif
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ private static final String GAME_RENDERER_RENDER = "Lnet/minecraft/client/render/GameRenderer;render(Lnet/minecraft/client/render/RenderTickCounter;Z)V";
|
||||
//#else
|
||||
private static final String GAME_RENDERER_RENDER = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V";
|
||||
//#endif
|
||||
|
||||
@Inject(method = "render",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V"))
|
||||
target = GAME_RENDERER_RENDER))
|
||||
private void preRender(boolean unused, CallbackInfo ci) {
|
||||
PreRenderCallback.EVENT.invoker().preRender();
|
||||
}
|
||||
|
||||
@Inject(method = "render",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V",
|
||||
target = GAME_RENDERER_RENDER,
|
||||
shift = At.Shift.AFTER))
|
||||
private void postRender(boolean unused, CallbackInfo ci) {
|
||||
PostRenderCallback.EVENT.invoker().postRender();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//#if MC>=11400
|
||||
package com.replaymod.core.mixin;
|
||||
|
||||
import com.replaymod.core.events.PostRenderWorldCallback;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=11500
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
//#endif
|
||||
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class Mixin_PostRenderWorldCalback {
|
||||
//#if MC>=12005
|
||||
//$$ @Inject(method = "render", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4fStack;popMatrix()Lorg/joml/Matrix4fStack;"))
|
||||
//$$ private void postRenderWorld(CallbackInfo ci) {
|
||||
//$$ MatrixStack matrixStack = new MatrixStack();
|
||||
//#else
|
||||
@Inject(method = "render", at = @At("RETURN"))
|
||||
//#if MC>=11500
|
||||
private void postRenderWorld(CallbackInfo ci, @Local(argsOnly = true) MatrixStack matrixStack) {
|
||||
//#else
|
||||
//$$ private void postRenderWorld(CallbackInfo ci) {
|
||||
//$$ MatrixStack matrixStack = new MatrixStack();
|
||||
//#endif
|
||||
//#endif
|
||||
PostRenderWorldCallback.EVENT.invoker().postRenderWorld(matrixStack);
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
//#if MC>=11400
|
||||
package com.replaymod.core.mixin;
|
||||
|
||||
import com.replaymod.core.events.PostRenderWorldCallback;
|
||||
import com.replaymod.core.events.PreRenderHandCallback;
|
||||
import net.minecraft.client.render.Camera;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
@@ -11,35 +10,23 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class MixinGameRenderer {
|
||||
@Inject(
|
||||
method = "renderWorld",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"
|
||||
)
|
||||
)
|
||||
private void postRenderWorld(
|
||||
float partialTicks,
|
||||
long nanoTime,
|
||||
//#if MC>=11500
|
||||
MatrixStack matrixStack,
|
||||
//#if MC>=12005
|
||||
//$$ import org.joml.Matrix4f;
|
||||
//#else
|
||||
//#endif
|
||||
CallbackInfo ci) {
|
||||
//#if MC<11500
|
||||
//$$ MatrixStack matrixStack = new MatrixStack();
|
||||
//#endif
|
||||
PostRenderWorldCallback.EVENT.invoker().postRenderWorld(matrixStack);
|
||||
}
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class Mixin_PreRenderHandCallback {
|
||||
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
|
||||
private void preRenderHand(
|
||||
//#if MC>=11500
|
||||
//#if MC>=11500 && MC<12005
|
||||
MatrixStack matrixStack,
|
||||
//#endif
|
||||
Camera camera,
|
||||
float partialTicks,
|
||||
//#if MC>=12005
|
||||
//$$ Matrix4f matrixStack,
|
||||
//#endif
|
||||
CallbackInfo ci) {
|
||||
if (PreRenderHandCallback.EVENT.invoker().preRenderHand()) {
|
||||
ci.cancel();
|
||||
@@ -5,13 +5,12 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ @Mixin(RenderTickCounter.Dynamic.class)
|
||||
//#else
|
||||
@Mixin(RenderTickCounter.class)
|
||||
//#endif
|
||||
public interface TimerAccessor {
|
||||
@Accessor("prevTimeMillis")
|
||||
long getLastSyncSysClock();
|
||||
@Accessor("prevTimeMillis")
|
||||
void setLastSyncSysClock(long value);
|
||||
|
||||
//#if MC>=11200
|
||||
@Accessor("tickTime")
|
||||
float getTickLength();
|
||||
@@ -23,25 +22,5 @@ public interface TimerAccessor {
|
||||
//$$ float getTimerSpeed();
|
||||
//$$ @Accessor
|
||||
//$$ void setTimerSpeed(float value);
|
||||
//$$ @Accessor
|
||||
//$$ float getTicksPerSecond();
|
||||
//$$ @Accessor
|
||||
//$$ void setTicksPerSecond(float value);
|
||||
//$$ @Accessor
|
||||
//$$ double getLastHRTime();
|
||||
//$$ @Accessor
|
||||
//$$ void setLastHRTime(double value);
|
||||
//$$ @Accessor
|
||||
//$$ long getLastSyncHRClock();
|
||||
//$$ @Accessor
|
||||
//$$ void setLastSyncHRClock(long value);
|
||||
//$$ @Accessor
|
||||
//$$ double getTimeSyncAdjustment();
|
||||
//$$ @Accessor
|
||||
//$$ void setTimeSyncAdjustment(double value);
|
||||
//$$ @Accessor
|
||||
//$$ long getCounter();
|
||||
//$$ @Accessor
|
||||
//$$ void setCounter(long value);
|
||||
//#endif
|
||||
}
|
||||
|
||||
@@ -2,8 +2,15 @@ package com.replaymod.core.utils;
|
||||
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ import net.minecraft.network.codec.PacketCodec;
|
||||
//$$ import net.minecraft.network.packet.CustomPayload;
|
||||
//#endif
|
||||
|
||||
//#if MC>=10904
|
||||
import net.minecraft.util.Identifier;
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
//#endif
|
||||
|
||||
//#if MC<=10710 || MC>=12002
|
||||
@@ -16,7 +23,7 @@ import net.minecraft.util.Identifier;
|
||||
*/
|
||||
public class Restrictions {
|
||||
//#if MC>=11400
|
||||
public static final Identifier PLUGIN_CHANNEL = new Identifier("replaymod", "restrict");
|
||||
public static final Identifier PLUGIN_CHANNEL = identifier("replaymod", "restrict");
|
||||
//#else
|
||||
//$$ public static final String PLUGIN_CHANNEL = "Replay|Restrict";
|
||||
//#endif
|
||||
@@ -26,7 +33,9 @@ public class Restrictions {
|
||||
private boolean onlyRecordingPlayer;
|
||||
|
||||
public String handle(CustomPayloadS2CPacket packet) {
|
||||
//#if MC>=12002
|
||||
//#if MC>=12006
|
||||
//$$ PacketByteBuf buffer = new PacketByteBuf(Unpooled.wrappedBuffer(((Payload) packet.payload()).bytes()));
|
||||
//#elseif MC>=12002
|
||||
//$$ PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer());
|
||||
//$$ packet.write(buffer);
|
||||
//#elseif MC>=10800
|
||||
@@ -67,4 +76,22 @@ public class Restrictions {
|
||||
public boolean isOnlyRecordingPlayer() {
|
||||
return onlyRecordingPlayer;
|
||||
}
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ public static final CustomPayload.Id<Payload> ID = new CustomPayload.Id<>(PLUGIN_CHANNEL);
|
||||
//$$ public static final PacketCodec<? super PacketByteBuf, Payload> CODEC = PacketCodec.ofStatic(
|
||||
//$$ (buf, payload) -> buf.writeBytes(payload.bytes()),
|
||||
//$$ buf -> {
|
||||
//$$ byte[] bytes = new byte[buf.readableBytes()];
|
||||
//$$ buf.readBytes(bytes);
|
||||
//$$ return new Payload(bytes);
|
||||
//$$ }
|
||||
//$$ );
|
||||
//$$ public record Payload(byte[] bytes) implements CustomPayload {
|
||||
//$$ @Override
|
||||
//$$ public Id<? extends CustomPayload> getId() {
|
||||
//$$ return ID;
|
||||
//$$ }
|
||||
//$$ }
|
||||
//#endif
|
||||
}
|
||||
|
||||
@@ -68,9 +68,15 @@ import java.util.function.Consumer;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.getMinecraft;
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ import net.minecraft.util.crash.ReportType;
|
||||
//#endif
|
||||
|
||||
public class Utils {
|
||||
private static Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static final float DEFAULT_MS_PER_TICK = 1000 / 20;
|
||||
|
||||
private static InputStream getResourceAsStream(String path) {
|
||||
return Utils.class.getResourceAsStream(path);
|
||||
}
|
||||
@@ -246,7 +252,11 @@ public class Utils {
|
||||
|
||||
public static GuiInfoPopup error(Logger logger, GuiContainer container, CrashReport crashReport, Runnable onClose) {
|
||||
// Convert crash report to string
|
||||
String crashReportStr = crashReport.asString();
|
||||
String crashReportStr = crashReport.asString(
|
||||
//#if MC>=12100
|
||||
//$$ ReportType.MINECRAFT_CRASH_REPORT
|
||||
//#endif
|
||||
);
|
||||
|
||||
// Log via logger
|
||||
logger.error(crashReportStr);
|
||||
@@ -257,7 +267,11 @@ public class Utils {
|
||||
File folder = new File(getMinecraft().runDirectory, "crash-reports");
|
||||
File file = new File(folder, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-client.txt");
|
||||
logger.debug("Saving crash report to file: {}", file);
|
||||
//#if MC>=12100
|
||||
//$$ crashReport.writeToFile(file.toPath(), ReportType.MINECRAFT_CRASH_REPORT);
|
||||
//#else
|
||||
crashReport.writeToFile(file);
|
||||
//#endif
|
||||
} catch (Throwable t) {
|
||||
logger.error("Saving crash report file:", t);
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.replaymod.core.utils;
|
||||
|
||||
import com.replaymod.core.mixin.TimerAccessor;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
|
||||
public class WrappedTimer extends RenderTickCounter {
|
||||
public static final float DEFAULT_MS_PER_TICK = 1000 / 20;
|
||||
|
||||
protected final RenderTickCounter wrapped;
|
||||
|
||||
public WrappedTimer(RenderTickCounter wrapped) {
|
||||
//#if MC>=12003
|
||||
//$$ super(0, 0, f -> f);
|
||||
//#elseif MC>=11400
|
||||
super(0, 0);
|
||||
//#else
|
||||
//$$ super(0);
|
||||
//#endif
|
||||
this.wrapped = wrapped;
|
||||
copy(wrapped, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
//#if MC>=11600
|
||||
int
|
||||
//#else
|
||||
//$$ void
|
||||
//#endif
|
||||
beginRenderTick(
|
||||
//#if MC>=11400
|
||||
long sysClock
|
||||
//#endif
|
||||
) {
|
||||
copy(this, wrapped);
|
||||
try {
|
||||
//#if MC>=11600
|
||||
return
|
||||
//#endif
|
||||
wrapped.beginRenderTick(
|
||||
//#if MC>=11400
|
||||
sysClock
|
||||
//#endif
|
||||
);
|
||||
} finally {
|
||||
copy(wrapped, this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copy(RenderTickCounter from, RenderTickCounter to) {
|
||||
TimerAccessor fromA = (TimerAccessor) from;
|
||||
TimerAccessor toA = (TimerAccessor) to;
|
||||
|
||||
//#if MC<11600
|
||||
//$$ to.ticksThisFrame = from.ticksThisFrame;
|
||||
//#endif
|
||||
to.tickDelta = from.tickDelta;
|
||||
toA.setLastSyncSysClock(fromA.getLastSyncSysClock());
|
||||
to.lastFrameDuration = from.lastFrameDuration;
|
||||
//#if MC>=11200
|
||||
toA.setTickLength(fromA.getTickLength());
|
||||
//#else
|
||||
//$$ toA.setTicksPerSecond(fromA.getTicksPerSecond());
|
||||
//$$ toA.setLastHRTime(fromA.getLastHRTime());
|
||||
//$$ toA.setTimerSpeed(fromA.getTimerSpeed());
|
||||
//$$ toA.setLastSyncHRClock(fromA.getLastSyncHRClock());
|
||||
//$$ toA.setCounter(fromA.getCounter());
|
||||
//$$ toA.setTimeSyncAdjustment(fromA.getTimeSyncAdjustment());
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
@@ -28,12 +28,21 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
//#if FABRIC>=1
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
//#else
|
||||
//#endif
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ import net.minecraft.resource.ResourcePackInfo;
|
||||
//$$ import net.minecraft.resource.ResourcePackSource;
|
||||
//$$ import net.minecraft.text.Text;
|
||||
//$$ import java.util.Optional;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11903
|
||||
//$$ import java.util.Objects;
|
||||
//$$ import net.minecraft.resource.InputSupplier;
|
||||
@@ -64,7 +73,9 @@ public class LangResourcePack extends AbstractFileResourcePack {
|
||||
|
||||
private final Path basePath;
|
||||
public LangResourcePack() {
|
||||
//#if MC>=11903
|
||||
//#if MC>=12006
|
||||
//$$ super(new ResourcePackInfo(NAME, Text.literal("ReplayMod Translations"), ResourcePackSource.NONE, Optional.empty()));
|
||||
//#elseif MC>=11903
|
||||
//$$ super(NAME, true);
|
||||
//#else
|
||||
super(new File(NAME));
|
||||
@@ -244,7 +255,7 @@ public class LangResourcePack extends AbstractFileResourcePack {
|
||||
.map(LANG_FILE_NAME_PATTERN::matcher)
|
||||
.filter(Matcher::matches)
|
||||
.map(matcher -> String.format("%s_%s.json", matcher.group(1), matcher.group(1)))
|
||||
.map(name -> new Identifier(ReplayMod.MOD_ID, "lang/" + name))
|
||||
.map(name -> identifier(ReplayMod.MOD_ID, "lang/" + name))
|
||||
.forEach(consumer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -10,6 +10,7 @@ import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector3f;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
@@ -397,7 +398,9 @@ public class MCVer {
|
||||
}
|
||||
|
||||
public static void pushMatrix() {
|
||||
//#if MC>=11700
|
||||
//#if MC>=12006
|
||||
//$$ RenderSystem.getModelViewStack().pushMatrix();
|
||||
//#elseif MC>=11700
|
||||
//$$ RenderSystem.getModelViewStack().push();
|
||||
//#else
|
||||
GlStateManager.pushMatrix();
|
||||
@@ -406,7 +409,11 @@ public class MCVer {
|
||||
|
||||
public static void popMatrix() {
|
||||
//#if MC>=11700
|
||||
//#if MC>=12006
|
||||
//$$ RenderSystem.getModelViewStack().popMatrix();
|
||||
//#else
|
||||
//$$ RenderSystem.getModelViewStack().pop();
|
||||
//#endif
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//#else
|
||||
GlStateManager.popMatrix();
|
||||
@@ -431,11 +438,11 @@ public class MCVer {
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
public static void emitLine(BufferBuilder buffer, Vector2f p1, Vector2f p2, int color) {
|
||||
emitLine(buffer, new Vector3f(p1.x, p1.y, 0), new Vector3f(p2.x, p2.y, 0), color);
|
||||
public static void emitLine(MatrixStack matrixStack, BufferBuilder buffer, Vector2f p1, Vector2f p2, int color) {
|
||||
emitLine(matrixStack, buffer, new Vector3f(p1.x, p1.y, 0), new Vector3f(p2.x, p2.y, 0), color);
|
||||
}
|
||||
|
||||
public static void emitLine(BufferBuilder buffer, Vector3f p1, Vector3f p2, int color) {
|
||||
public static void emitLine(MatrixStack matrixStack, BufferBuilder buffer, Vector3f p1, Vector3f p2, int color) {
|
||||
int r = color >> 24 & 0xff;
|
||||
int g = color >> 16 & 0xff;
|
||||
int b = color >> 8 & 0xff;
|
||||
@@ -443,18 +450,28 @@ public class MCVer {
|
||||
//#if MC>=11700
|
||||
//$$ Vector3f n = Vector3f.sub(p2, p1, null);
|
||||
//#endif
|
||||
buffer.vertex(p1.x, p1.y, p1.z)
|
||||
//#if MC>=11600
|
||||
buffer.vertex(matrixStack.peek().getModel(), p1.x, p1.y, p1.z)
|
||||
//#else
|
||||
//$$ buffer.vertex(p1.x, p1.y, p1.z)
|
||||
//#endif
|
||||
.color(r, g, b, a)
|
||||
//#if MC>=11700
|
||||
//$$ .normal(n.x, n.y, n.z)
|
||||
//#endif
|
||||
.next();
|
||||
buffer.vertex(p2.x, p2.y, p2.z)
|
||||
;
|
||||
buffer.next();
|
||||
//#if MC>=11600
|
||||
buffer.vertex(matrixStack.peek().getModel(), p2.x, p2.y, p2.z)
|
||||
//#else
|
||||
//$$ buffer.vertex(p2.x, p2.y, p2.z)
|
||||
//#endif
|
||||
.color(r, g, b, a)
|
||||
//#if MC>=11700
|
||||
//$$ .normal(n.x, n.y, n.z)
|
||||
//#endif
|
||||
.next();
|
||||
;
|
||||
buffer.next();
|
||||
}
|
||||
|
||||
public static void bindTexture(Identifier id) {
|
||||
|
||||
@@ -21,6 +21,8 @@ import net.minecraft.network.NetworkSide;
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
@@ -44,6 +46,7 @@ import org.lwjgl.opengl.GL11;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11600
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
@@ -85,6 +88,7 @@ import net.minecraft.client.render.BufferBuilder;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
class Patterns {
|
||||
//#if MC>=10904
|
||||
@@ -364,6 +368,9 @@ class Patterns {
|
||||
//#endif
|
||||
}
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ @Pattern private static void Tessellator_getBuffer() {}
|
||||
//#else
|
||||
@Pattern
|
||||
private static BufferBuilder Tessellator_getBuffer(Tessellator tessellator) {
|
||||
//#if MC>=10800
|
||||
@@ -372,6 +379,20 @@ class Patterns {
|
||||
//$$ return new BufferBuilder(tessellator);
|
||||
//#endif
|
||||
}
|
||||
//#endif
|
||||
|
||||
//#if MC>=11600
|
||||
@Pattern
|
||||
private static void VertexConsumer_next(VertexConsumer buffer) {
|
||||
//#if MC>=12100
|
||||
//$$ buffer./*next()*/getClass();
|
||||
//#else
|
||||
buffer.next();
|
||||
//#endif
|
||||
}
|
||||
//#else
|
||||
//$$ private static void VertexConsumer_next() {}
|
||||
//#endif
|
||||
|
||||
//#if MC<11700
|
||||
@Pattern
|
||||
@@ -474,7 +495,9 @@ class Patterns {
|
||||
|
||||
@Pattern
|
||||
private static float getRenderPartialTicks(MinecraftClient mc) {
|
||||
//#if MC>=10900
|
||||
//#if MC>=12100
|
||||
//$$ return mc.getRenderTickCounter().getTickDelta(true);
|
||||
//#elseif MC>=10900
|
||||
return mc.getTickDelta();
|
||||
//#else
|
||||
//$$ return ((com.replaymod.core.mixin.MinecraftAccessor) mc).getTimer().renderPartialTicks;
|
||||
@@ -521,7 +544,7 @@ class Patterns {
|
||||
//#endif
|
||||
}
|
||||
|
||||
//#if MC>=11600
|
||||
//#if MC>=11600 && MC<12100
|
||||
@Pattern
|
||||
private static void BufferBuilder_beginLineStrip(BufferBuilder buffer, VertexFormat vertexFormat) {
|
||||
//#if MC>=11700
|
||||
@@ -574,7 +597,9 @@ class Patterns {
|
||||
|
||||
@Pattern
|
||||
private static void GL11_glRotatef(float angle, float x, float y, float z) {
|
||||
//#if MC>=11700
|
||||
//#if MC>=12006
|
||||
//$$ com.mojang.blaze3d.systems.RenderSystem.getModelViewStack().rotate(com.replaymod.core.versions.MCVer.quaternion(angle, new org.joml.Vector3f(x, y, z)));
|
||||
//#elseif MC>=11700
|
||||
//$$ com.mojang.blaze3d.systems.RenderSystem.getModelViewStack().multiply(com.replaymod.core.versions.MCVer.quaternion(angle, new net.minecraft.util.math.Vec3f(x, y, z)));
|
||||
//#else
|
||||
GL11.glRotatef(angle, x, y, z);
|
||||
@@ -915,7 +940,9 @@ class Patterns {
|
||||
|
||||
@Pattern
|
||||
public Object channel(CustomPayloadS2CPacket packet) {
|
||||
//#if MC>=12002
|
||||
//#if MC>=12006
|
||||
//$$ return packet.payload().getId().id();
|
||||
//#elseif MC>=12002
|
||||
//$$ return packet.payload().id();
|
||||
//#else
|
||||
return packet.getChannel();
|
||||
@@ -923,6 +950,9 @@ class Patterns {
|
||||
}
|
||||
|
||||
//#if MC>=10904
|
||||
//#if MC>=12006
|
||||
//$$ @Pattern public void getPacketId() {}
|
||||
//#else
|
||||
@Pattern
|
||||
public Integer getPacketId(NetworkState state, NetworkSide side, Packet<?> packet) throws Exception {
|
||||
//#if MC>=12002
|
||||
@@ -931,6 +961,7 @@ class Patterns {
|
||||
return state.getPacketId(side, packet);
|
||||
//#endif
|
||||
}
|
||||
//#endif
|
||||
|
||||
@Pattern
|
||||
public int UnloadChunkPacket_getX(UnloadChunkS2CPacket packet) {
|
||||
@@ -955,6 +986,15 @@ class Patterns {
|
||||
//$$ @Pattern public void UnloadChunkPacket_getX() {}
|
||||
//#endif
|
||||
|
||||
@Pattern
|
||||
public UUID getId(PlayerListS2CPacket.Entry entry) {
|
||||
//#if MC>=11903
|
||||
//$$ return entry.profileId();
|
||||
//#else
|
||||
return entry.getProfile().getId();
|
||||
//#endif
|
||||
}
|
||||
|
||||
@Pattern
|
||||
public Identifier getSkinTexture(AbstractClientPlayerEntity player) {
|
||||
//#if MC>=12002
|
||||
@@ -972,4 +1012,13 @@ class Patterns {
|
||||
return mc.options.debugEnabled;
|
||||
//#endif
|
||||
}
|
||||
|
||||
@Pattern
|
||||
public Text getMessage(DisconnectS2CPacket packet) {
|
||||
//#if MC>=12006
|
||||
//$$ return packet.reason();
|
||||
//#else
|
||||
return packet.getReason();
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ import net.minecraft.util.crash.ReportType;
|
||||
//#endif
|
||||
|
||||
public class SchedulerImpl implements Scheduler {
|
||||
private static final MinecraftClient mc = MinecraftClient.getInstance();
|
||||
|
||||
@@ -113,7 +117,11 @@ public class SchedulerImpl implements Scheduler {
|
||||
runnable.run();
|
||||
} catch (CrashException e) {
|
||||
e.printStackTrace();
|
||||
//#if MC>=12100
|
||||
//$$ System.err.println(e.getReport().asString(ReportType.MINECRAFT_CRASH_REPORT));
|
||||
//#else
|
||||
System.err.println(e.getReport().asString());
|
||||
//#endif
|
||||
mc.setCrashReport(e.getReport());
|
||||
} finally {
|
||||
inRunLater = false;
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.replaymod.render.gui.GuiRenderSettings;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||
import de.johni0702.minecraft.gui.container.GuiScreen;
|
||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.function.Loadable;
|
||||
import de.johni0702.minecraft.gui.layout.GridLayout;
|
||||
@@ -58,8 +59,9 @@ public class GuiCreateScreenshot extends GuiRenderSettings implements Loadable {
|
||||
|
||||
boolean success = new ScreenshotRenderer(settings).renderScreenshot();
|
||||
if (success) {
|
||||
new GuiUploadScreenshot(ReplayModReplay.instance.getReplayHandler().getOverlay(), mod,
|
||||
settings).open();
|
||||
GuiScreen screen = createBaseScreen();
|
||||
new GuiUploadScreenshot(screen, mod, settings).open();
|
||||
screen.display();
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import com.replaymod.core.mixin.MinecraftAccessor;
|
||||
import com.replaymod.core.mixin.TimerAccessor;
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
||||
import com.replaymod.replaystudio.pathing.path.Path;
|
||||
@@ -20,6 +19,7 @@ import net.minecraft.client.render.RenderTickCounter;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static com.replaymod.core.utils.Utils.DEFAULT_MS_PER_TICK;
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
|
||||
/**
|
||||
@@ -31,6 +31,11 @@ public abstract class AbstractTimelinePlayer extends EventRegistrations {
|
||||
private Timeline timeline;
|
||||
protected long startOffset;
|
||||
private boolean wasAsyncMode;
|
||||
//#if MC>=12100
|
||||
//$$ private RenderTickCounter.Dynamic orgTimer;
|
||||
//#else
|
||||
private RenderTickCounter orgTimer;
|
||||
//#endif
|
||||
private long lastTime;
|
||||
private long lastTimestamp;
|
||||
private ListenableFuture<Void> future;
|
||||
@@ -76,13 +81,14 @@ public abstract class AbstractTimelinePlayer extends EventRegistrations {
|
||||
lastTime = 0;
|
||||
|
||||
MinecraftAccessor mcA = (MinecraftAccessor) mc;
|
||||
ReplayTimer timer = new ReplayTimer(mcA.getTimer());
|
||||
orgTimer = mcA.getTimer();
|
||||
ReplayTimer timer = new ReplayTimer();
|
||||
mcA.setTimer(timer);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
TimerAccessor timerA = (TimerAccessor) timer;
|
||||
//#if MC>=11200
|
||||
timerA.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK);
|
||||
timerA.setTickLength(DEFAULT_MS_PER_TICK);
|
||||
timer.tickDelta = timer.ticksThisFrame = 0;
|
||||
//#else
|
||||
//$$ timer.timerSpeed = 1;
|
||||
@@ -103,7 +109,7 @@ public abstract class AbstractTimelinePlayer extends EventRegistrations {
|
||||
public void onTick() {
|
||||
if (future.isDone()) {
|
||||
MinecraftAccessor mcA = (MinecraftAccessor) mc;
|
||||
mcA.setTimer(((ReplayTimer) mcA.getTimer()).getWrapped());
|
||||
mcA.setTimer(orgTimer);
|
||||
replayHandler.getReplaySender().setReplaySpeed(0);
|
||||
if (wasAsyncMode) {
|
||||
replayHandler.getReplaySender().setAsyncMode(true);
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
package com.replaymod.pathing.player;
|
||||
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import de.johni0702.minecraft.gui.utils.Event;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
|
||||
/**
|
||||
* Wrapper around the current timer that prevents the timer from advancing by itself.
|
||||
* A timer that does not advance by itself.
|
||||
*/
|
||||
public class ReplayTimer extends WrappedTimer {
|
||||
//#if MC>=12003
|
||||
//$$ private final RenderTickCounter state = new RenderTickCounter(0, 0, f -> f);
|
||||
//#elseif MC>=11400
|
||||
private final RenderTickCounter state = new RenderTickCounter(0, 0);
|
||||
//#if MC>=12100
|
||||
//$$ public class ReplayTimer extends RenderTickCounter.Dynamic {
|
||||
//#else
|
||||
//$$ private final Timer state = new Timer(0);
|
||||
public class ReplayTimer extends RenderTickCounter {
|
||||
//#endif
|
||||
|
||||
//#if MC>=11600
|
||||
public int ticksThisFrame;
|
||||
//#endif
|
||||
|
||||
public ReplayTimer(RenderTickCounter wrapped) {
|
||||
super(wrapped);
|
||||
public ReplayTimer() {
|
||||
//#if MC>=12003
|
||||
//$$ super(0, 0, f -> f);
|
||||
//#elseif MC>=11400
|
||||
super(0, 0);
|
||||
//#else
|
||||
//$$ super(0);
|
||||
//#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,29 +41,27 @@ public class ReplayTimer extends WrappedTimer {
|
||||
//#if MC>=11400
|
||||
long sysClock
|
||||
//#endif
|
||||
//#if MC>=12100
|
||||
//$$ , boolean tick
|
||||
//#endif
|
||||
) {
|
||||
copy(this, state); // Save our current state
|
||||
try {
|
||||
//#if MC>=11600
|
||||
ticksThisFrame =
|
||||
//#if MC>=12100
|
||||
//$$ if (!tick) return 0;
|
||||
//#endif
|
||||
wrapped.beginRenderTick(
|
||||
//#if MC>=11400
|
||||
sysClock
|
||||
//#endif
|
||||
); // Update current state
|
||||
} finally {
|
||||
copy(state, this); // Restore our old state
|
||||
UpdatedCallback.EVENT.invoker().onUpdate();
|
||||
}
|
||||
//#if MC>=11600
|
||||
return ticksThisFrame;
|
||||
//#endif
|
||||
}
|
||||
|
||||
public RenderTickCounter getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
//#if MC>=12100
|
||||
//$$ public float tickDelta;
|
||||
//$$
|
||||
//$$ @Override
|
||||
//$$ public float getTickDelta(boolean bl) {
|
||||
//$$ return tickDelta;
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
public interface UpdatedCallback {
|
||||
Event<UpdatedCallback> EVENT = Event.create((listeners) ->
|
||||
|
||||
@@ -9,12 +9,17 @@ import com.replaymod.recording.handler.ConnectionEventHandler;
|
||||
import com.replaymod.recording.handler.GuiHandler;
|
||||
import com.replaymod.recording.mixin.NetworkManagerAccessor;
|
||||
import com.replaymod.recording.packet.PacketListener;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.util.AttributeKey;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
//#endif
|
||||
|
||||
//#if FABRIC>=1
|
||||
//#if MC>=11700
|
||||
//$$ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
@@ -72,7 +77,11 @@ public class ReplayModRecording implements Module {
|
||||
new GuiHandler(core).register();
|
||||
|
||||
//#if FABRIC>=1
|
||||
//#if MC>=11700
|
||||
//#if MC>=12006
|
||||
//$$ PayloadTypeRegistry.configurationS2C().register(Restrictions.ID, Restrictions.CODEC);
|
||||
//$$ PayloadTypeRegistry.playS2C().register(Restrictions.ID, Restrictions.CODEC);
|
||||
//$$ ClientPlayNetworking.registerGlobalReceiver(Restrictions.ID, (payload, context) -> {});
|
||||
//#elseif MC>=11700
|
||||
//$$ ClientPlayNetworking.registerGlobalReceiver(Restrictions.PLUGIN_CHANNEL, (client, handler, buf, resp) -> {});
|
||||
//#else
|
||||
ClientSidePacketRegistry.INSTANCE.register(Restrictions.PLUGIN_CHANNEL, (packetContext, packetByteBuf) -> {});
|
||||
@@ -93,7 +102,7 @@ public class ReplayModRecording implements Module {
|
||||
|
||||
public void initiateRecording(ClientConnection networkManager) {
|
||||
Channel channel = ((NetworkManagerAccessor) networkManager).getChannel();
|
||||
if (channel.pipeline().get("ReplayModReplay_replaySender") != null) return;
|
||||
if (channel.pipeline().get(ReplayHandler.PACKET_HANDLER_NAME) != null) return;
|
||||
//#if MC>=11400
|
||||
if (channel.hasAttr(ATTR_CHECKED)) return;
|
||||
channel.attr(ATTR_CHECKED).set(null);
|
||||
|
||||
@@ -153,15 +153,25 @@ public class ConnectionEventHandler {
|
||||
metaData.setGenerator("ReplayMod v" + ReplayMod.instance.getVersion());
|
||||
metaData.setDate(System.currentTimeMillis());
|
||||
metaData.setMcVersion(ReplayMod.instance.getMinecraftVersion());
|
||||
packetListener = new PacketListener(core, outputPath, replayFile, metaData);
|
||||
|
||||
Channel channel = ((NetworkManagerAccessor) networkManager).getChannel();
|
||||
packetListener = new PacketListener(core, channel, outputPath, replayFile, metaData);
|
||||
|
||||
//#if MC>=12005
|
||||
//$$ String target = channel.pipeline().get("inbound_config") != null ? "inbound_config" : PacketListener.DECODER_KEY;
|
||||
//$$ channel.pipeline().addBefore(target, PacketListener.RAW_RECORDER_KEY, packetListener);
|
||||
//$$ channel.pipeline().addAfter(target, PacketListener.DECODED_RECORDER_KEY, packetListener.new DecodedPacketListener());
|
||||
//#else
|
||||
if (channel.pipeline().get(PacketListener.DECODER_KEY) != null) {
|
||||
// Regular channel, we'll inject our recorder directly before the decoder
|
||||
channel.pipeline().addBefore(PacketListener.DECODER_KEY, PacketListener.RAW_RECORDER_KEY, packetListener);
|
||||
channel.pipeline().addAfter(PacketListener.DECODER_KEY, PacketListener.DECODED_RECORDER_KEY, packetListener.new DecodedPacketListener());
|
||||
} else {
|
||||
// Integrated server passes packets directly, there's no splitting, decompression or decoding
|
||||
channel.pipeline().addFirst(PacketListener.RAW_RECORDER_KEY, packetListener);
|
||||
channel.pipeline().addAfter(PacketListener.RAW_RECORDER_KEY, PacketListener.DECODED_RECORDER_KEY, packetListener.new DecodedPacketListener());
|
||||
}
|
||||
//#endif
|
||||
|
||||
recordingEventHandler = new RecordingEventHandler(packetListener);
|
||||
recordingEventHandler.register();
|
||||
|
||||
@@ -73,7 +73,12 @@ public class RecordingEventHandler extends EventRegistrations {
|
||||
private final PacketListener packetListener;
|
||||
|
||||
private Double lastX, lastY, lastZ;
|
||||
private final List<ItemStack> playerItems = DefaultedList.ofSize(6, ItemStack.EMPTY);
|
||||
//#if MC>=10904
|
||||
private static final int EQUIPMENT_SLOTS = EquipmentSlot.values().length;
|
||||
//#else
|
||||
//$$ private static final int EQUIPMENT_SLOTS = 5;
|
||||
//#endif
|
||||
private final List<ItemStack> playerItems = DefaultedList.ofSize(EQUIPMENT_SLOTS, ItemStack.EMPTY);
|
||||
private int ticksSinceLastCorrection;
|
||||
private boolean wasSleeping;
|
||||
private int lastRiding = -1;
|
||||
@@ -108,7 +113,21 @@ public class RecordingEventHandler extends EventRegistrations {
|
||||
try {
|
||||
ClientPlayerEntity player = mc.player;
|
||||
assert player != null;
|
||||
//#if MC>=12002
|
||||
//#if MC>=12100
|
||||
//$$ packetListener.save(new EntitySpawnS2CPacket(
|
||||
//$$ player.getId(),
|
||||
//$$ player.getUuid(),
|
||||
//$$ player.getX(),
|
||||
//$$ player.getY(),
|
||||
//$$ player.getZ(),
|
||||
//$$ player.getPitch(),
|
||||
//$$ player.getYaw(),
|
||||
//$$ player.getType(),
|
||||
//$$ 0,
|
||||
//$$ player.getVelocity(),
|
||||
//$$ player.getHeadYaw()
|
||||
//$$ ));
|
||||
//#elseif MC>=12002
|
||||
//$$ packetListener.save(new EntitySpawnS2CPacket(player));
|
||||
//#else
|
||||
packetListener.save(new PlayerSpawnS2CPacket(player));
|
||||
@@ -279,7 +298,7 @@ public class RecordingEventHandler extends EventRegistrations {
|
||||
ItemStack stack = player.getEquippedStack(slot);
|
||||
int index = slot.ordinal();
|
||||
//#else
|
||||
//$$ for (int slot = 0; slot < 5; slot++) {
|
||||
//$$ for (int slot = 0; slot < EQUIPMENT_SLOTS; slot++) {
|
||||
//$$ ItemStack stack = player.getEquipmentInSlot(slot);
|
||||
//$$ int index = slot;
|
||||
//#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
// 1.20.6 and above
|
||||
@@ -0,0 +1 @@
|
||||
// 1.20.6 and above
|
||||
@@ -2,7 +2,6 @@ package com.replaymod.recording.mixin;
|
||||
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.recording.handler.RecordingEventHandler;
|
||||
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
|
||||
@@ -13,16 +12,9 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=10800
|
||||
import com.replaymod.replaystudio.protocol.Packet;
|
||||
import com.replaymod.replaystudio.protocol.PacketType;
|
||||
import com.replaymod.replaystudio.protocol.packets.PacketPlayerListEntry;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
|
||||
import net.minecraft.client.network.PlayerListEntry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
//#else
|
||||
@@ -67,33 +59,13 @@ public abstract class MixinNetHandlerPlayClient {
|
||||
//#else
|
||||
if (handler != null && packet.getAction() == PlayerListS2CPacket.Action.ADD_PLAYER) {
|
||||
//#endif
|
||||
// We cannot reference SPacketPlayerListItem.AddPlayerData directly for complicated (and yet to be
|
||||
// resolved) reasons (see https://github.com/MinecraftForge/ForgeGradle/issues/472), so we use ReplayStudio
|
||||
// to parse it instead.
|
||||
ByteBuf byteBuf = Unpooled.buffer();
|
||||
try {
|
||||
packet.write(new PacketByteBuf(byteBuf));
|
||||
|
||||
byteBuf.readerIndex(0);
|
||||
byte[] array = new byte[byteBuf.readableBytes()];
|
||||
byteBuf.readBytes(array);
|
||||
|
||||
for (PacketPlayerListEntry data : PacketPlayerListEntry.read(new Packet(
|
||||
MCVer.getPacketTypeRegistry(State.PLAY), 0, PacketType.PlayerListEntry,
|
||||
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(array)
|
||||
))) {
|
||||
if (data.getUuid() == null) continue;
|
||||
for (PlayerListS2CPacket.Entry entry : packet.getEntries()) {
|
||||
UUID uuid = entry.getProfile().getId();
|
||||
// Only add spawn packet for our own player and only if he isn't known yet
|
||||
if (data.getUuid().equals(mcStatic.player.getGameProfile().getId())
|
||||
&& !this.playerListEntries.containsKey(data.getUuid())) {
|
||||
if (uuid.equals(mcStatic.player.getGameProfile().getId()) && !this.playerListEntries.containsKey(uuid)) {
|
||||
handler.spawnRecordingPlayer();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e); // we just parsed this?
|
||||
} finally {
|
||||
byteBuf.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
//#else
|
||||
|
||||
@@ -22,9 +22,12 @@ import com.replaymod.replaystudio.replay.ReplayMetaData;
|
||||
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.util.AttributeKey;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
@@ -40,6 +43,15 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ import com.replaymod.recording.mixin.DecoderHandlerAccessor;
|
||||
//$$ import net.minecraft.network.NetworkState;
|
||||
//$$ import net.minecraft.network.handler.DecoderHandler;
|
||||
//$$ import net.minecraft.network.handler.NetworkStateTransitions;
|
||||
//$$ import net.minecraft.network.packet.s2c.config.ReadyS2CPacket;
|
||||
//$$ import net.minecraft.network.state.LoginStates;
|
||||
//#endif
|
||||
|
||||
//#if MC>=12002
|
||||
//$$ import net.minecraft.entity.EntityType;
|
||||
//$$ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
||||
@@ -73,7 +85,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
import static com.replaymod.replaystudio.util.Utils.writeInt;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
//#if MC>=11904
|
||||
//$$ import net.minecraft.network.PacketBundleHandler;
|
||||
@@ -92,28 +103,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
private static final MinecraftClient mc = getMinecraft();
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
|
||||
private static final ResourcePackSendS2CPacket RESOURCE_PACK_SEND_PACKET =
|
||||
//#if MC>=12003
|
||||
//$$ new ResourcePackSendS2CPacket(null, "", "", false, null)
|
||||
//#elseif MC>=11700
|
||||
//$$ new ResourcePackSendS2CPacket("", "", false, null)
|
||||
//#else
|
||||
new ResourcePackSendS2CPacket()
|
||||
//#endif
|
||||
;
|
||||
private static final int PACKET_ID_RESOURCE_PACK_SEND = getPacketId(NetworkState.PLAY, RESOURCE_PACK_SEND_PACKET);
|
||||
//#if MC>=12002
|
||||
//$$ private static final int PACKET_ID_CONFIG_RESOURCE_PACK_SEND = getPacketId(NetworkState.CONFIGURATION, RESOURCE_PACK_SEND_PACKET);
|
||||
//#endif
|
||||
//#if MC>=11700
|
||||
//$$ private static final int PACKET_ID_LOGIN_COMPRESSION = getPacketId(NetworkState.LOGIN, new LoginCompressionS2CPacket(0));
|
||||
//#else
|
||||
private static final int PACKET_ID_LOGIN_COMPRESSION = getPacketId(NetworkState.LOGIN, new LoginCompressionS2CPacket());
|
||||
//#endif
|
||||
//#if MC<10904
|
||||
//$$ private static final int PACKET_ID_PLAY_COMPRESSION = getPacketId(EnumConnectionState.PLAY, new S46PacketSetCompressionLevel());
|
||||
//#endif
|
||||
|
||||
private final ReplayMod core;
|
||||
private final Path outputPath;
|
||||
private final ReplayFile replayFile;
|
||||
@@ -125,7 +114,8 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private ReplayMetaData metaData;
|
||||
|
||||
private ChannelHandlerContext context = null;
|
||||
private final Channel channel;
|
||||
private Packet currentRawPacket;
|
||||
|
||||
private final long startTime;
|
||||
private long lastSentPacket;
|
||||
@@ -138,8 +128,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
*/
|
||||
private final AtomicInteger lastSaveMetaDataId = new AtomicInteger();
|
||||
|
||||
public PacketListener(ReplayMod core, Path outputPath, ReplayFile replayFile, ReplayMetaData metaData) throws IOException {
|
||||
public PacketListener(ReplayMod core, Channel channel, Path outputPath, ReplayFile replayFile, ReplayMetaData metaData) throws IOException {
|
||||
this.core = core;
|
||||
this.channel = channel;
|
||||
this.outputPath = outputPath;
|
||||
this.replayFile = replayFile;
|
||||
this.metaData = metaData;
|
||||
@@ -199,17 +190,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
//#if MC>=11800
|
||||
if (packet.getRegistry().getState() == State.LOGIN && packet.getId() == PACKET_ID_LOGIN_COMPRESSION) {
|
||||
return; // Replay data is never compressed on the packet level
|
||||
}
|
||||
//#if MC<10904
|
||||
//$$ if (packet.getRegistry().getState() == State.PLAY && packet.getId() == PACKET_ID_PLAY_COMPRESSION) {
|
||||
//$$ return; // Replay data is never compressed on the packet level
|
||||
//$$ }
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (serverWasPaused) {
|
||||
timePassedWhilePaused = now - startTime - lastSentPacket;
|
||||
@@ -249,22 +229,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||
super.handlerAdded(ctx);
|
||||
|
||||
if (ctx.pipeline().get(DECODED_RECORDER_KEY) == null) {
|
||||
if (ctx.pipeline().get(PacketListener.DECODER_KEY) != null) {
|
||||
// Regular channel, we'll inject our decoded recorder directly after the decoder
|
||||
ctx.pipeline().addAfter(DECODER_KEY, DECODED_RECORDER_KEY, new DecodedPacketListener());
|
||||
} else {
|
||||
// Integrated server passes packets directly, there's no splitting, decompression or decoding
|
||||
// The decoded packet handler can just go directly behind this hand
|
||||
ctx.pipeline().addAfter(RAW_RECORDER_KEY, DECODED_RECORDER_KEY, new DecodedPacketListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
metaData.setDuration((int) lastSentPacket);
|
||||
@@ -342,15 +306,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
if(ctx == null) {
|
||||
if(context == null) {
|
||||
return;
|
||||
} else {
|
||||
ctx = context;
|
||||
}
|
||||
}
|
||||
this.context = ctx;
|
||||
|
||||
NetworkState connectionState = getConnectionState();
|
||||
|
||||
Packet packet = null;
|
||||
@@ -363,6 +318,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
} else if (msg instanceof net.minecraft.network.Packet) {
|
||||
// for integrated server connections MC is passing the packet objects directly, so we need to encode them
|
||||
// ourselves to be able to store them
|
||||
//#if MC>=12006
|
||||
//$$ // No longer applies. MC now encodes packets even for the integrated server connection.
|
||||
//#else
|
||||
//#if MC>=11904
|
||||
//#if MC>=12002
|
||||
//$$ PacketBundleHandler bundleHandler = ctx.channel().attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY).get().getBundler();
|
||||
@@ -386,43 +344,55 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
//#else
|
||||
packet = encodeMcPacket(connectionState, (net.minecraft.network.Packet) msg);
|
||||
//#endif
|
||||
}
|
||||
|
||||
if (packet != null) {
|
||||
if (connectionState == NetworkState.PLAY && packet.getId() == PACKET_ID_RESOURCE_PACK_SEND
|
||||
//#if MC>=12002
|
||||
//$$ || connectionState == NetworkState.CONFIGURATION && packet.getId() == PACKET_ID_CONFIG_RESOURCE_PACK_SEND
|
||||
//#endif
|
||||
) {
|
||||
ClientConnection connection = ctx.pipeline().get(ClientConnection.class);
|
||||
save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) decodeMcPacket(packet)));
|
||||
//#if MC>=12003
|
||||
//$$ super.channelRead(ctx, msg);
|
||||
//#endif
|
||||
return;
|
||||
}
|
||||
|
||||
save(packet);
|
||||
}
|
||||
|
||||
currentRawPacket = packet;
|
||||
try {
|
||||
super.channelRead(ctx, msg);
|
||||
} finally {
|
||||
if (currentRawPacket != null) {
|
||||
currentRawPacket.release();
|
||||
currentRawPacket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkState getConnectionState() {
|
||||
ChannelHandlerContext ctx = context;
|
||||
if (ctx == null) {
|
||||
return NetworkState.LOGIN;
|
||||
}
|
||||
//#if MC>=12002
|
||||
//#if MC>=12006
|
||||
//$$ var decoderHandler = (DecoderHandlerAccessor<?>) channel.pipeline().get(DecoderHandler.class);
|
||||
//$$ if (decoderHandler == null) {
|
||||
//$$ return NetworkPhase.LOGIN;
|
||||
//$$ }
|
||||
//$$ return decoderHandler.getState().id();
|
||||
//#elseif MC>=12002
|
||||
//$$ AttributeKey<NetworkState.PacketHandler<?>> key = ClientConnection.CLIENTBOUND_PROTOCOL_KEY;
|
||||
//$$ return ctx.channel().attr(key).get().getState();
|
||||
//$$ return channel.attr(key).get().getState();
|
||||
//#else
|
||||
AttributeKey<NetworkState> key = ClientConnection.ATTR_KEY_PROTOCOL;
|
||||
return ctx.channel().attr(key).get();
|
||||
return channel.attr(key).get();
|
||||
//#endif
|
||||
}
|
||||
|
||||
private static Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception {
|
||||
private Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception {
|
||||
//#if MC>=12006
|
||||
//$$ var byteBuf = Unpooled.buffer();
|
||||
//$$ try {
|
||||
//$$ NetworkState<?> state;
|
||||
//$$ if (connectionState == NetworkPhase.LOGIN) {
|
||||
//$$ // Special case for our initial LoginSuccess packet which we only save after the pipeline has already
|
||||
//$$ // started to transition to the next phase, so we can't just use its DecoderHandler (and luckily we
|
||||
//$$ // also don't need it).
|
||||
//$$ state = LoginStates.S2C;
|
||||
//$$ } else {
|
||||
//$$ state = ((DecoderHandlerAccessor<?>) channel.pipeline().get(DecoderHandler.class)).getState();
|
||||
//$$ }
|
||||
//$$ state.codec().encode(byteBuf, packet);
|
||||
//$$ return decodePacket(state.id(), byteBuf);
|
||||
//$$ } finally {
|
||||
//$$ byteBuf.release();
|
||||
//$$ }
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
Integer packetId = connectionState.getPacketId(NetworkSide.CLIENTBOUND, packet);
|
||||
//#else
|
||||
@@ -446,25 +416,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
} finally {
|
||||
byteBuf.release();
|
||||
}
|
||||
}
|
||||
|
||||
private static net.minecraft.network.Packet decodeMcPacket(Packet packet) throws IOException, IllegalAccessException, InstantiationException {
|
||||
NetworkState connectionState = asMc(packet.getRegistry().getState());
|
||||
int packetId = packet.getId();
|
||||
PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.wrappedBuffer(packet.getBuf().nioBuffer()));
|
||||
|
||||
//#if MC>=12002
|
||||
//$$ return connectionState.getHandler(NetworkSide.CLIENTBOUND).createPacket(packetId, packetBuf);
|
||||
//#elseif MC>=11700
|
||||
//$$ return connectionState.getPacketHandler(NetworkSide.CLIENTBOUND, packetId, packetBuf);
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
net.minecraft.network.Packet p = connectionState.getPacketHandler(NetworkSide.CLIENTBOUND, packetId);
|
||||
//#else
|
||||
//$$ net.minecraft.network.Packet p = net.minecraft.network.Packet.generatePacket(connectionState.func_150755_b(), packetId);
|
||||
//#endif
|
||||
p.read(packetBuf);
|
||||
return p;
|
||||
//#endif
|
||||
}
|
||||
|
||||
@@ -480,14 +431,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
);
|
||||
}
|
||||
|
||||
private static int getPacketId(NetworkState networkState, net.minecraft.network.Packet packet) {
|
||||
try {
|
||||
return requireNonNull(networkState.getPacketId(NetworkSide.CLIENTBOUND, packet));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to determine packet id for " + packet.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addMarker(String name) {
|
||||
addMarker(name, (int) getCurrentDuration());
|
||||
}
|
||||
@@ -531,10 +474,21 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
return resourcePackRecorder;
|
||||
}
|
||||
|
||||
private class DecodedPacketListener extends ChannelInboundHandlerAdapter {
|
||||
public class DecodedPacketListener extends ChannelDuplexHandler {
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
|
||||
if (msg instanceof LoginCompressionS2CPacket) {
|
||||
super.channelRead(ctx, msg);
|
||||
return;
|
||||
}
|
||||
//#if MC<10904
|
||||
//$$ if (msg instanceof S46PacketSetCompressionLevel) {
|
||||
//$$ super.channelRead(ctx, msg);
|
||||
//$$ return;
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
if (msg instanceof CustomPayloadS2CPacket) {
|
||||
CustomPayloadS2CPacket packet = (CustomPayloadS2CPacket) msg;
|
||||
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannel())) {
|
||||
@@ -559,7 +513,48 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||
saveMetaData();
|
||||
}
|
||||
|
||||
if (msg instanceof ResourcePackSendS2CPacket) {
|
||||
ClientConnection connection = ctx.pipeline().get(ClientConnection.class);
|
||||
save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) msg));
|
||||
//#if MC>=12003
|
||||
//$$ super.channelRead(ctx, msg);
|
||||
//#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ // Special case: We need to inject another packet before this one, and we can only construct that
|
||||
//$$ // packet on the main thread, so we'll skip saving this packet here and then manually re-add it after
|
||||
//$$ // that other packet has been injected.
|
||||
//$$ // See MixinNetHandlerConfigClient.
|
||||
//$$ if (msg instanceof ReadyS2CPacket) {
|
||||
//$$ super.channelRead(ctx, msg);
|
||||
//$$ return;
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
if (currentRawPacket != null) {
|
||||
save(currentRawPacket);
|
||||
currentRawPacket = null;
|
||||
}
|
||||
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
//#if MC>=12006
|
||||
//$$ if (msg instanceof NetworkStateTransitions.DecoderTransitioner) {
|
||||
//$$ // We need our DecodedPacketListener to stay right behind the decoder, however MC will on network state
|
||||
//$$ // transitions insert the bundler in the middle, so we need to re-position our handler in that case.
|
||||
//$$ msg = ((NetworkStateTransitions.DecoderTransitioner) msg).andThen(context -> {
|
||||
//$$ context.pipeline().remove(this);
|
||||
//$$ context.pipeline().addAfter(DECODER_KEY, DECODED_RECORDER_KEY, new DecodedPacketListener());
|
||||
//$$ });
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
||||
for (int i = 0; i < numChannels; i++) {
|
||||
FloatBuffer channel = images.slice();
|
||||
channel.position(width * height * i);
|
||||
imagePointers.put(i, channel.slice());
|
||||
imagePointers.put(i, memAddress(channel));
|
||||
if (i == 4) {
|
||||
depthChannel = channel;
|
||||
} else {
|
||||
@@ -125,8 +125,8 @@ public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
||||
|
||||
int ret = SaveEXRImageToFile(image, header, path.toString(), err);
|
||||
if (ret != TINYEXR_SUCCESS) {
|
||||
String message = err.getStringASCII(0);
|
||||
FreeEXRErrorMessage(err.getByteBuffer(0));
|
||||
String message = memASCII(err.get(0));
|
||||
nFreeEXRErrorMessage(err.get(0));
|
||||
throw new IOException(message);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.replaymod.render.blend.data.DMaterial;
|
||||
import com.replaymod.render.blend.data.DPackedFile;
|
||||
import com.replaymod.render.blend.data.DTexture;
|
||||
import de.johni0702.minecraft.gui.versions.Image;
|
||||
import net.minecraft.client.util.GlAllocationUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -25,7 +25,7 @@ public class BlendMaterials {
|
||||
// Read raw image data from GL
|
||||
int width = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
|
||||
int height = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT);
|
||||
ByteBuffer buffer = GlAllocationUtils.allocateByteBuffer(width * height * 4);
|
||||
ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 4);
|
||||
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
// Convert to Image
|
||||
|
||||
@@ -5,13 +5,13 @@ import de.johni0702.minecraft.gui.utils.lwjgl.vector.Matrix4f;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.vector.Quaternion;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector3f;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.util.GlAllocationUtils;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import org.blender.dna.Link;
|
||||
import org.blender.dna.ListBase;
|
||||
import org.blender.utils.BlenderFactory;
|
||||
import org.cakelab.blender.nio.CPointer;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -39,7 +39,7 @@ public class Util {
|
||||
}
|
||||
}
|
||||
|
||||
private static FloatBuffer floatBuffer = GlAllocationUtils.allocateByteBuffer(16 * 4).asFloatBuffer();
|
||||
private static FloatBuffer floatBuffer = BufferUtils.createByteBuffer(16 * 4).asFloatBuffer();
|
||||
public static Matrix4f getGlMatrix(int matrix) {
|
||||
floatBuffer.clear();
|
||||
//#if MC>=11400
|
||||
@@ -183,6 +183,9 @@ public class Util {
|
||||
}
|
||||
|
||||
public static String getTileEntityId(BlockEntity tileEntity) {
|
||||
//#if MC>=12006
|
||||
//$$ return net.minecraft.block.entity.BlockEntityType.getId(tileEntity.getType()).toString();
|
||||
//#else
|
||||
//#if MC>=11800
|
||||
//$$ NbtCompound nbt = tileEntity.createNbt();
|
||||
//#else
|
||||
@@ -194,6 +197,7 @@ public class Util {
|
||||
//#endif
|
||||
//#endif
|
||||
return nbt.getString("id");
|
||||
//#endif
|
||||
}
|
||||
|
||||
public interface IOCallable<R> {
|
||||
|
||||
@@ -19,9 +19,11 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
|
||||
private static final Identifier vertexResource = new Identifier("replaymod", "shader/ods.vert");
|
||||
private static final Identifier fragmentResource = new Identifier("replaymod", "shader/ods.frag");
|
||||
private static final Identifier vertexResource = identifier("replaymod", "shader/ods.vert");
|
||||
private static final Identifier fragmentResource = identifier("replaymod", "shader/ods.frag");
|
||||
|
||||
private final CubicPboOpenGlFrameCapturer left, right;
|
||||
private final Program shaderProgram;
|
||||
|
||||
@@ -27,8 +27,10 @@ import net.minecraft.client.texture.NativeImage;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
public class GuiVideoRenderer extends GuiScreen implements Tickable {
|
||||
private static final Identifier NO_PREVIEW_TEXTURE = new Identifier("replaymod", "logo.png");
|
||||
private static final Identifier NO_PREVIEW_TEXTURE = identifier("replaymod", "logo.png");
|
||||
|
||||
private final VideoRenderer renderer;
|
||||
|
||||
@@ -112,7 +114,13 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable {
|
||||
size(contentPanel, width - 10, height - 10);
|
||||
}
|
||||
});
|
||||
// FIXME default background doesn't work during rendering because the blur effect relies on the framebuffer
|
||||
//#if MC>=12006
|
||||
//$$ setBackground(Background.NONE);
|
||||
//$$ setBackgroundColor(new de.johni0702.minecraft.gui.utils.lwjgl.Color(32, 32, 32));
|
||||
//#else
|
||||
setBackground(Background.DIRT);
|
||||
//#endif
|
||||
}
|
||||
|
||||
public GuiVideoRenderer(VideoRenderer renderer) {
|
||||
|
||||
@@ -41,6 +41,8 @@ public class EntityRendererHandler extends EventRegistrations implements WorldRe
|
||||
|
||||
private final long startTime;
|
||||
|
||||
private long fakeFinishTimeNano;
|
||||
|
||||
public EntityRendererHandler(RenderSettings settings, RenderInfo renderInfo) {
|
||||
this.settings = settings;
|
||||
this.renderInfo = renderInfo;
|
||||
@@ -71,6 +73,7 @@ public class EntityRendererHandler extends EventRegistrations implements WorldRe
|
||||
}
|
||||
|
||||
public void renderWorld(float partialTicks, long finishTimeNano) {
|
||||
fakeFinishTimeNano = finishTimeNano;
|
||||
//#if MC>=11400
|
||||
PreRenderCallback.EVENT.invoker().preRender();
|
||||
//#else
|
||||
@@ -93,7 +96,9 @@ public class EntityRendererHandler extends EventRegistrations implements WorldRe
|
||||
gameRenderer.setRenderHand(false); // makes no sense, we wouldn't even know where to put it
|
||||
}
|
||||
|
||||
//#if MC>=11400
|
||||
//#if MC>=12100
|
||||
//$$ mc.gameRenderer.render(mc.getRenderTickCounter(), true);
|
||||
//#elseif MC>=11400
|
||||
mc.gameRenderer.render(partialTicks, finishTimeNano, true);
|
||||
//#else
|
||||
//$$ mc.setIngameNotInFocus(); // this should already be the case but it somehow still sometimes is not
|
||||
@@ -140,6 +145,10 @@ public class EntityRendererHandler extends EventRegistrations implements WorldRe
|
||||
return this.renderInfo;
|
||||
}
|
||||
|
||||
public long getFakeFinishTimeNano() {
|
||||
return fakeFinishTimeNano;
|
||||
}
|
||||
|
||||
public interface IEntityRenderer {
|
||||
void replayModRender_setHandler(EntityRendererHandler handler);
|
||||
EntityRendererHandler replayModRender_getHandler();
|
||||
|
||||
@@ -22,7 +22,9 @@ public abstract class Mixin_ChromaKeyColorSky {
|
||||
|
||||
//#if MC>=11800
|
||||
//$$ @Inject(
|
||||
//#if MC>=11802
|
||||
//#if MC>=12005
|
||||
//$$ method = "renderSky(Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;FLnet/minecraft/client/render/Camera;ZLjava/lang/Runnable;)V",
|
||||
//#elseif MC>=11802
|
||||
//$$ method = "renderSky(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/math/Matrix4f;FLnet/minecraft/client/render/Camera;ZLjava/lang/Runnable;)V",
|
||||
//#else
|
||||
//$$ method = "renderSky(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/math/Matrix4f;FLjava/lang/Runnable;)V",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
// 1.21+
|
||||
@@ -11,7 +11,11 @@ import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
public abstract class Mixin_Omnidirectional_Camera implements EntityRendererHandler.IEntityRenderer {
|
||||
private static final String METHOD = "getBasicProjectionMatrix";
|
||||
//#if MC>=11903
|
||||
//#if MC>=12005
|
||||
//$$ private static final String TARGET = "Lorg/joml/Matrix4f;perspective(FFFF)Lorg/joml/Matrix4f;";
|
||||
//#else
|
||||
//$$ private static final String TARGET = "Lorg/joml/Matrix4f;setPerspective(FFFF)Lorg/joml/Matrix4f;";
|
||||
//#endif
|
||||
//$$ private static final boolean TARGET_REMAP = false;
|
||||
//$$ private static final float OMNIDIRECTIONAL_FOV = (float) Math.PI / 2;
|
||||
//#else
|
||||
|
||||
@@ -7,6 +7,11 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=12005
|
||||
//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
//$$ import org.joml.Matrix4f;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11500
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
@@ -30,6 +35,14 @@ public abstract class Mixin_Omnidirectional_Rotation {
|
||||
return ((EntityRendererHandler.IEntityRenderer) getMinecraft().gameRenderer).replayModRender_getHandler();
|
||||
}
|
||||
|
||||
//#if MC>=12005
|
||||
//#if MC>=12100
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotation(Lorg/joml/Quaternionfc;)Lorg/joml/Matrix4f;"))
|
||||
//#else
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;"))
|
||||
//#endif
|
||||
//$$ private Matrix4f replayModRender_setupCubicFrameRotation(Matrix4f matrix) {
|
||||
//#else
|
||||
//#if MC>=11500
|
||||
@Inject(method = "renderWorld", at = @At("HEAD"))
|
||||
//#else
|
||||
@@ -47,6 +60,7 @@ public abstract class Mixin_Omnidirectional_Rotation {
|
||||
//#endif
|
||||
CallbackInfo ci
|
||||
) {
|
||||
//#endif
|
||||
if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) {
|
||||
CubicOpenGlFrameCapturer.Data data = (CubicOpenGlFrameCapturer.Data) getHandler().data;
|
||||
float angle = 0;
|
||||
@@ -78,7 +92,9 @@ public abstract class Mixin_Omnidirectional_Rotation {
|
||||
x = 1;
|
||||
break;
|
||||
}
|
||||
//#if MC>=11500
|
||||
//#if MC>=12005
|
||||
//$$ matrix.rotateLocal(angle * (float) Math.PI / 180f, x, y, 0);
|
||||
//#elseif MC>=11500
|
||||
matrixStack.multiply(new Vector3f(x, y, 0).getDegreesQuaternion(angle));
|
||||
//#else
|
||||
//$$ GL11.glRotatef(angle, x, y, 0);
|
||||
@@ -96,5 +112,8 @@ public abstract class Mixin_Omnidirectional_Rotation {
|
||||
//#endif
|
||||
//$$ }
|
||||
//#endif
|
||||
//#if MC>=12005
|
||||
//$$ return matrix;
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,11 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
//#if MC>=12005
|
||||
//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
//$$ import org.joml.Matrix4f;
|
||||
//#endif
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public abstract class Mixin_Stereoscopic_Camera implements EntityRendererHandler.IEntityRenderer {
|
||||
@Inject(method = "getBasicProjectionMatrix", at = @At("RETURN"), cancellable = true)
|
||||
@@ -29,14 +34,34 @@ public abstract class Mixin_Stereoscopic_Camera implements EntityRendererHandler
|
||||
}
|
||||
}
|
||||
|
||||
//#if MC>=12005
|
||||
//#if MC>=12100
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotation(Lorg/joml/Quaternionfc;)Lorg/joml/Matrix4f;"))
|
||||
//#else
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;"))
|
||||
//#endif
|
||||
//$$ private Matrix4f replayModRender_setupStereoscopicProjection(Matrix4f matrix) {
|
||||
//#else
|
||||
@Inject(method = "renderWorld", at = @At("HEAD"))
|
||||
private void replayModRender_setupStereoscopicProjection(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) {
|
||||
//#endif
|
||||
if (replayModRender_getHandler() != null) {
|
||||
if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) {
|
||||
matrixStack.translate(0.1, 0, 0);
|
||||
//#if MC>=12005
|
||||
//$$ matrix.translateLocal(0.1f, 0, 0);
|
||||
//#else
|
||||
matrixStack.translate(0.1f, 0, 0);
|
||||
//#endif
|
||||
} else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) {
|
||||
matrixStack.translate(-0.1, 0, 0);
|
||||
//#if MC>=12005
|
||||
//$$ matrix.translateLocal(-0.1f, 0, 0);
|
||||
//#else
|
||||
matrixStack.translate(-0.1f, 0, 0);
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
//#if MC>=12005
|
||||
//$$ return matrix;
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.replaymod.render.rendering;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.replaymod.core.mixin.MinecraftAccessor;
|
||||
import com.replaymod.core.mixin.TimerAccessor;
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.pathing.player.AbstractTimelinePlayer;
|
||||
import com.replaymod.pathing.player.ReplayTimer;
|
||||
import com.replaymod.pathing.properties.TimestampProperty;
|
||||
import com.replaymod.render.CameraPathExporter;
|
||||
import com.replaymod.render.EXRWriter;
|
||||
@@ -38,7 +38,6 @@ import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.crash.CrashException;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
//#if MC>=12000
|
||||
@@ -85,13 +84,15 @@ import java.util.concurrent.FutureTask;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.google.common.collect.Iterables.getLast;
|
||||
import static com.replaymod.core.utils.Utils.DEFAULT_MS_PER_TICK;
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
public class VideoRenderer implements RenderInfo {
|
||||
private static final Identifier SOUND_RENDER_SUCCESS = new Identifier("replaymod", "render_success");
|
||||
private static final Identifier SOUND_RENDER_SUCCESS = identifier("replaymod", "render_success");
|
||||
private final MinecraftClient mc = MCVer.getMinecraft();
|
||||
private final RenderSettings settings;
|
||||
private final ReplayHandler replayHandler;
|
||||
@@ -191,7 +192,7 @@ public class VideoRenderer implements RenderInfo {
|
||||
// Because this might take some time to prepare we'll render the GUI at least once to not confuse the user
|
||||
drawGui();
|
||||
|
||||
RenderTickCounter timer = ((MinecraftAccessor) mc).getTimer();
|
||||
ReplayTimer timer = (ReplayTimer) ((MinecraftAccessor) mc).getTimer();
|
||||
|
||||
// Play up to one second before starting to render
|
||||
// This is necessary in order to ensure that all entities have at least two position packets
|
||||
@@ -207,7 +208,7 @@ public class VideoRenderer implements RenderInfo {
|
||||
int replayTime = videoStart - 1000;
|
||||
//#if MC>=11200
|
||||
timer.tickDelta = 0;
|
||||
((TimerAccessor) timer).setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK);
|
||||
((TimerAccessor) timer).setTickLength(DEFAULT_MS_PER_TICK);
|
||||
//#else
|
||||
//$$ timer.elapsedPartialTicks = timer.renderPartialTicks = 0;
|
||||
//$$ timer.timerSpeed = 1;
|
||||
@@ -268,7 +269,7 @@ public class VideoRenderer implements RenderInfo {
|
||||
}
|
||||
|
||||
// Updating the timer will cause the timeline player to update the game state
|
||||
RenderTickCounter timer = ((MinecraftAccessor) mc).getTimer();
|
||||
ReplayTimer timer = (ReplayTimer) ((MinecraftAccessor) mc).getTimer();
|
||||
//#if MC>=11600
|
||||
int elapsedTicks =
|
||||
//#endif
|
||||
@@ -276,6 +277,9 @@ public class VideoRenderer implements RenderInfo {
|
||||
//#if MC>=11400
|
||||
MCVer.milliTime()
|
||||
//#endif
|
||||
//#if MC>=12100
|
||||
//$$ , true
|
||||
//#endif
|
||||
);
|
||||
//#if MC<11600
|
||||
//$$ int elapsedTicks = timer.ticksThisFrame;
|
||||
@@ -512,9 +516,14 @@ public class VideoRenderer implements RenderInfo {
|
||||
//$$ , VertexSorter.BY_Z
|
||||
//#endif
|
||||
//$$ );
|
||||
//#if MC>=12006
|
||||
//$$ org.joml.Matrix4fStack matrixStack = RenderSystem.getModelViewStack();
|
||||
//$$ matrixStack.translation(0, 0, -2000);
|
||||
//#else
|
||||
//$$ MatrixStack matrixStack = RenderSystem.getModelViewStack();
|
||||
//$$ matrixStack.loadIdentity();
|
||||
//$$ matrixStack.translate(0, 0, -2000);
|
||||
//#endif
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//$$ DiffuseLighting.enableGuiDepthLighting();
|
||||
//#else
|
||||
@@ -558,13 +567,17 @@ public class VideoRenderer implements RenderInfo {
|
||||
int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / Math.max(window.getWidth(), 1);
|
||||
int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / Math.max(window.getHeight(), 1);
|
||||
|
||||
//#if MC>=12000
|
||||
//$$ DrawContext drawContext = new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers());
|
||||
//#endif
|
||||
|
||||
if (mc.getOverlay() != null) {
|
||||
Screen orgScreen = mc.currentScreen;
|
||||
try {
|
||||
mc.currentScreen = gui.toMinecraft();
|
||||
mc.getOverlay().render(
|
||||
//#if MC>=12000
|
||||
//$$ new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()),
|
||||
//$$ drawContext,
|
||||
//#elseif MC>=11600
|
||||
new MatrixStack(),
|
||||
//#endif
|
||||
@@ -582,6 +595,9 @@ public class VideoRenderer implements RenderInfo {
|
||||
//#endif
|
||||
mouseX, mouseY, 0);
|
||||
}
|
||||
//#if MC>=12000
|
||||
//$$ drawContext.draw();
|
||||
//#endif
|
||||
//#else
|
||||
//$$ int mouseX = Mouse.getX() * window.getScaledWidth() / mc.displayWidth;
|
||||
//$$ int mouseY = window.getScaledHeight() - Mouse.getY() * window.getScaledHeight() / mc.displayHeight - 1;
|
||||
|
||||
@@ -11,16 +11,16 @@ import com.replaymod.core.utils.Restrictions;
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import com.replaymod.replaystudio.io.ReplayInputStream;
|
||||
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
|
||||
import com.replaymod.replaystudio.protocol.PacketType;
|
||||
import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
|
||||
import com.replaymod.replaystudio.replay.ReplayFile;
|
||||
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
||||
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.OtherClientPlayerEntity;
|
||||
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
|
||||
@@ -28,9 +28,7 @@ import net.minecraft.client.gui.screen.NoticeScreen;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket;
|
||||
@@ -119,7 +117,6 @@ import net.minecraft.util.Identifier;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11200
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import net.minecraft.network.packet.s2c.play.AdvancementUpdateS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.SelectAdvancementTabS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket;
|
||||
@@ -140,7 +137,6 @@ import net.minecraft.network.packet.s2c.play.UnloadChunkS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.ResourcePackSendS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.SetCameraEntityS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.TitleS2CPacket;
|
||||
import net.minecraft.network.NetworkSide;
|
||||
//#else
|
||||
//$$ import org.apache.commons.io.Charsets;
|
||||
//#endif
|
||||
@@ -155,6 +151,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.replaymod.core.utils.Utils.DEFAULT_MS_PER_TICK;
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
import static com.replaymod.replaystudio.util.Utils.readInt;
|
||||
|
||||
@@ -164,7 +161,7 @@ import static com.replaymod.replaystudio.util.Utils.readInt;
|
||||
* the replay restart from the beginning.
|
||||
*/
|
||||
@Sharable
|
||||
public class FullReplaySender extends ChannelDuplexHandler implements ReplaySender {
|
||||
public class FullReplaySender extends ChannelInboundHandlerAdapter implements ReplaySender {
|
||||
/**
|
||||
* These packets are ignored completely during replay.
|
||||
*/
|
||||
@@ -230,9 +227,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
protected ReplayFile replayFile;
|
||||
|
||||
/**
|
||||
* The channel handler context used to send packets to minecraft.
|
||||
* The channel used to send packets to minecraft.
|
||||
*/
|
||||
protected ChannelHandlerContext ctx;
|
||||
protected Channel channel;
|
||||
|
||||
/**
|
||||
* The replay input stream from which new packets are read.
|
||||
@@ -271,6 +268,11 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
*/
|
||||
protected boolean hasWorldLoaded;
|
||||
|
||||
/**
|
||||
* Whether we are currently in the middle of a bundle packet.
|
||||
*/
|
||||
protected boolean inBundle;
|
||||
|
||||
/**
|
||||
* The minecraft instance.
|
||||
*/
|
||||
@@ -303,20 +305,17 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
/**
|
||||
* Create a new replay sender.
|
||||
* @param file The replay file
|
||||
* @param asyncMode {@code true} for async mode, {@code false} otherwise
|
||||
* @see #asyncMode
|
||||
*/
|
||||
public FullReplaySender(ReplayHandler replayHandler, ReplayFile file, boolean asyncMode) throws IOException {
|
||||
public FullReplaySender(ReplayHandler replayHandler, ReplayFile file) throws IOException {
|
||||
this.replayHandler = replayHandler;
|
||||
this.replayFile = file;
|
||||
this.asyncMode = asyncMode;
|
||||
this.replayLength = file.getMetaData().getDuration();
|
||||
|
||||
events.register();
|
||||
|
||||
if (asyncMode) {
|
||||
new Thread(asyncSender, "replaymod-async-sender").start();
|
||||
}
|
||||
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,8 +382,8 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
syncSender.shutdown();
|
||||
events.unregister();
|
||||
try {
|
||||
channelInactive(ctx);
|
||||
ctx.channel().pipeline().close();
|
||||
channel.pipeline().fireChannelInactive();
|
||||
channel.pipeline().close();
|
||||
FileUtils.deleteDirectory(tempResourcePackFolder);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -404,7 +403,12 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
if (mc.world != null) {
|
||||
for (PlayerEntity playerEntity : mc.world.getPlayers()) {
|
||||
if (!playerEntity.updateNeeded && playerEntity instanceof OtherClientPlayerEntity) {
|
||||
// FIXME preprocessor should (and used to) be able to map this
|
||||
//#if MC>=11400
|
||||
playerEntity.tickMovement();
|
||||
//#else
|
||||
//$$ playerEntity.onLivingUpdate();
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,14 +424,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
return;
|
||||
}
|
||||
|
||||
// When a packet is sent directly, perform no filtering
|
||||
if (msg instanceof Packet) {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
if (msg instanceof byte[]) {
|
||||
try {
|
||||
Packet p = deserializePacket((byte[]) msg);
|
||||
Packet p = (Packet) msg;
|
||||
|
||||
if (p != null) {
|
||||
p = processPacket(p);
|
||||
@@ -473,29 +472,6 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
|
||||
}
|
||||
|
||||
private Packet deserializePacket(byte[] bytes) throws IOException, IllegalAccessException, InstantiationException {
|
||||
ByteBuf bb = Unpooled.wrappedBuffer(bytes);
|
||||
PacketByteBuf pb = new PacketByteBuf(bb);
|
||||
|
||||
int i = pb.readVarInt();
|
||||
|
||||
NetworkState state = asMc(registry.getState());
|
||||
//#if MC>=12002
|
||||
//$$ Packet p = state.getHandler(NetworkSide.CLIENTBOUND).createPacket(i, pb);
|
||||
//#elseif MC>=11700
|
||||
//$$ Packet p = state.getPacketHandler(NetworkSide.CLIENTBOUND, i, pb);
|
||||
//#else
|
||||
//#if MC>=10800
|
||||
Packet p = state.getPacketHandler(NetworkSide.CLIENTBOUND, i);
|
||||
//#else
|
||||
//$$ Packet p = Packet.generatePacket(state.func_150755_b(), i);
|
||||
//#endif
|
||||
p.read(pb);
|
||||
//#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// If we do not give minecraft time to tick, there will be dead entity artifacts left in the world
|
||||
// Therefore we have to remove all loaded, dead entities manually if we are in sync mode.
|
||||
// We do this after every SpawnX packet and after the destroy entities packet.
|
||||
@@ -705,6 +681,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
//$$ packet.showDeathScreen(),
|
||||
//$$ packet.doLimitedCrafting(),
|
||||
//$$ withSpectatorMode(packet.commonPlayerSpawnInfo())
|
||||
//#if MC>=12006
|
||||
//$$ , packet.enforcesSecureChat()
|
||||
//#endif
|
||||
//#else
|
||||
//#if MC>=11800
|
||||
//$$ packet.hardcore(),
|
||||
@@ -981,32 +960,6 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
//$$ }
|
||||
//#endif
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
this.ctx = ctx;
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
// The embedded channel's event loop will consider every thread to be in it and as such provides no
|
||||
// guarantees that only one thread is using the pipeline at any one time.
|
||||
// For reading the replay sender (either sync or async) is the only thread ever writing.
|
||||
// For writing it may very well happen that multiple threads want to use the pipline at the same time.
|
||||
// It's unclear whether the EmbeddedChannel is supposed to be thread-safe (the behavior of the event loop
|
||||
// does suggest that). However it seems like it either isn't (likely) or there is a race condition.
|
||||
// See: https://www.replaymod.com/forum/thread/1752#post8045 (https://paste.replaymod.com/lotacatuwo)
|
||||
// To work around this issue, we just outright drop all write/flush requests (they aren't needed anyway).
|
||||
// This still leaves channel handlers upstream with the threading issue but they all seem to cope well with it.
|
||||
promise.setSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush(ChannelHandlerContext ctx) throws Exception {
|
||||
// See write method above
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the speed of the replay. 1 being normal speed, 0.5 half and 2 twice as fast.
|
||||
* If 0 is returned, the replay is paused.
|
||||
@@ -1032,7 +985,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
}
|
||||
TimerAccessor timer = (TimerAccessor) ((MinecraftAccessor) mc).getTimer();
|
||||
//#if MC>=11200
|
||||
timer.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK / (float) d);
|
||||
timer.setTickLength(DEFAULT_MS_PER_TICK / (float) d);
|
||||
//#else
|
||||
//$$ timer.setTimerSpeed((float) d);
|
||||
//#endif
|
||||
@@ -1068,9 +1021,6 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
private Runnable asyncSender = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
while (ctx == null && !terminate) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
REPLAY_LOOP:
|
||||
while (!terminate) {
|
||||
synchronized (FullReplaySender.this) {
|
||||
@@ -1081,7 +1031,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
while (true) {
|
||||
try {
|
||||
// When playback is paused and the world has loaded (we don't want any dirt-screens) we sleep
|
||||
while (paused() && hasWorldLoaded) {
|
||||
while (paused() && hasWorldLoaded && !inBundle) {
|
||||
// Unless we are going to terminate, restart or jump
|
||||
if (terminate || startFromBeginning || desiredTimeStamp != -1) {
|
||||
break;
|
||||
@@ -1089,7 +1039,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
if (terminate) {
|
||||
if (terminate && !inBundle) {
|
||||
break REPLAY_LOOP;
|
||||
}
|
||||
|
||||
@@ -1109,7 +1059,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
|
||||
// If we aren't jumping and the world has already been loaded (no dirt-screens) then wait
|
||||
// the required amount to get proper packet timing
|
||||
if (!isHurrying() && hasWorldLoaded) {
|
||||
if (!isHurrying() && hasWorldLoaded && !inBundle) {
|
||||
// Timestamp of when the next packet should be sent
|
||||
long expectedTime = realTimeStart + (long) (nextTimeStamp / replaySpeed);
|
||||
long now = System.currentTimeMillis();
|
||||
@@ -1120,7 +1070,8 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
}
|
||||
|
||||
// Process packet
|
||||
channelRead(ctx, nextPacket.bytes);
|
||||
if (nextPacket.type == PacketType.Bundle) inBundle = !inBundle;
|
||||
channel.pipeline().fireChannelRead(Unpooled.wrappedBuffer(nextPacket.bytes));
|
||||
nextPacket = null;
|
||||
|
||||
lastTimeStamp = nextTimeStamp;
|
||||
@@ -1131,7 +1082,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
// Might be safe to do the same on older versions too, but I'd rather not poke the
|
||||
// monster that is Forge networking.
|
||||
//#if MC>=12002
|
||||
//$$ while (!ctx.channel().config().isAutoRead()) {
|
||||
//$$ while (!channel.config().isAutoRead()) {
|
||||
//$$ Thread.sleep(0, 100_000);
|
||||
//$$ }
|
||||
//#endif
|
||||
@@ -1167,6 +1118,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
|
||||
// Restart the replay.
|
||||
hasWorldLoaded = false;
|
||||
inBundle = false;
|
||||
lastTimeStamp = 0;
|
||||
registry = getPacketTypeRegistry(State.LOGIN);
|
||||
startFromBeginning = false;
|
||||
@@ -1293,16 +1245,13 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
|
||||
private void doSendPacketsTill(int timestamp) {
|
||||
try {
|
||||
while (ctx == null && !terminate) { // Make sure channel is ready
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (timestamp == lastTimeStamp) { // Do nothing if we're already there
|
||||
return;
|
||||
}
|
||||
if (timestamp < lastTimeStamp) { // Restart the replay if we need to go backwards in time
|
||||
hasWorldLoaded = false;
|
||||
inBundle = false;
|
||||
lastTimeStamp = 0;
|
||||
if (replayIn != null) {
|
||||
replayIn.close();
|
||||
@@ -1331,14 +1280,15 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
}
|
||||
|
||||
int nextTimeStamp = pd.timestamp;
|
||||
if (nextTimeStamp > timestamp) {
|
||||
if (nextTimeStamp > timestamp && !inBundle) {
|
||||
// We are done sending all packets
|
||||
nextPacket = pd;
|
||||
break;
|
||||
}
|
||||
|
||||
// Process packet
|
||||
channelRead(ctx, pd.bytes);
|
||||
if (pd.type == PacketType.Bundle) inBundle = !inBundle;
|
||||
channel.pipeline().fireChannelRead(Unpooled.wrappedBuffer(pd.bytes));
|
||||
|
||||
// MC as of 1.20.2 relies on autoRead, so it can update the connection state on the main
|
||||
// thread before the next packet is read. As such, we need to stall if that was just
|
||||
@@ -1346,7 +1296,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
// Might be safe to do the same on older versions too, but I'd rather not poke the
|
||||
// monster that is Forge networking.
|
||||
//#if MC>=12002
|
||||
//$$ while (!ctx.channel().config().isAutoRead()) {
|
||||
//$$ while (!channel.config().isAutoRead()) {
|
||||
//$$ Thread.sleep(0, 100_000);
|
||||
//$$ }
|
||||
//#endif
|
||||
@@ -1557,6 +1507,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
|
||||
private final int timestamp;
|
||||
private final byte[] bytes;
|
||||
private final PacketType type;
|
||||
|
||||
PacketData(ReplayInputStream in) throws IOException {
|
||||
if (ReplayMod.isMinimalMode()) {
|
||||
@@ -1568,6 +1519,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
}
|
||||
bytes = new byte[length];
|
||||
IOUtils.readFully(in, bytes);
|
||||
type = PacketType.UnknownLogin;
|
||||
} else {
|
||||
com.replaymod.replaystudio.PacketData data = in.readPacket();
|
||||
if (data == null) {
|
||||
@@ -1575,6 +1527,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
||||
}
|
||||
timestamp = (int) data.getTime();
|
||||
com.replaymod.replaystudio.protocol.Packet packet = data.getPacket();
|
||||
type = packet.getType();
|
||||
// We need to re-encode ReplayStudio packets, so we can later decode them as NMS packets
|
||||
// The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able
|
||||
// to apply ViaVersion (and potentially other magic) to it.
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.replaymod.replay;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.replay.camera.CameraController;
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import de.johni0702.minecraft.gui.versions.ScreenExt;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
|
||||
//#if MC>=11802
|
||||
//$$ import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
|
||||
@@ -33,36 +31,10 @@ import org.lwjgl.glfw.GLFW;
|
||||
//$$ import net.minecraft.client.multiplayer.WorldClient;
|
||||
//#endif
|
||||
|
||||
public class InputReplayTimer extends WrappedTimer {
|
||||
private final ReplayModReplay mod;
|
||||
private final MinecraftClient mc;
|
||||
|
||||
public InputReplayTimer(RenderTickCounter wrapped, ReplayModReplay mod) {
|
||||
super(wrapped);
|
||||
this.mod = mod;
|
||||
this.mc = mod.getCore().getMinecraft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
//#if MC>=11600
|
||||
int
|
||||
//#else
|
||||
//$$ void
|
||||
//#endif
|
||||
beginRenderTick(
|
||||
//#if MC>=11400
|
||||
long sysClock
|
||||
//#endif
|
||||
) {
|
||||
//#if MC>=11600
|
||||
int ticksThisFrame =
|
||||
//#endif
|
||||
super.beginRenderTick(
|
||||
//#if MC>=11400
|
||||
sysClock
|
||||
//#endif
|
||||
);
|
||||
public class InputReplayTimer {
|
||||
public static void updateInReplay() {
|
||||
ReplayModReplay mod = ReplayModReplay.instance;
|
||||
MinecraftClient mc = mod.getCore().getMinecraft();
|
||||
|
||||
ReplayMod.instance.runTasks();
|
||||
|
||||
@@ -126,9 +98,6 @@ public class InputReplayTimer extends WrappedTimer {
|
||||
//#endif
|
||||
|
||||
}
|
||||
//#if MC>=11600
|
||||
return ticksThisFrame;
|
||||
//#endif
|
||||
}
|
||||
|
||||
public static void handleScroll(int wheel) {
|
||||
|
||||
@@ -11,6 +11,10 @@ import net.minecraft.client.util.ScreenshotUtils;
|
||||
import static com.replaymod.core.versions.MCVer.popMatrix;
|
||||
import static com.replaymod.core.versions.MCVer.pushMatrix;
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ import net.minecraft.client.render.RenderTickCounter;
|
||||
//#endif
|
||||
|
||||
//#if MC>=11500
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
//#endif
|
||||
@@ -73,8 +77,13 @@ public class NoGuiScreenshot {
|
||||
GlStateManager.enableTexture();
|
||||
//#endif
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ mc.gameRenderer.renderWorld(RenderTickCounter.ONE);
|
||||
//#else
|
||||
float tickDelta = mc.getTickDelta();
|
||||
//#if MC>=11500
|
||||
//#if MC>=12006
|
||||
//$$ mc.gameRenderer.renderWorld(tickDelta, System.nanoTime());
|
||||
//#elseif MC>=11500
|
||||
mc.gameRenderer.renderWorld(tickDelta, System.nanoTime(), new MatrixStack());
|
||||
//#else
|
||||
//#if MC>=11400
|
||||
@@ -87,6 +96,7 @@ public class NoGuiScreenshot {
|
||||
//#endif
|
||||
//#endif
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
mc.getFramebuffer().endWrite();
|
||||
popMatrix();
|
||||
|
||||
@@ -14,24 +14,17 @@ import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
||||
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerAdapter;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.network.NetworkSide;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
//#if MC>=11200
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
//#endif
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.asMc;
|
||||
import static com.replaymod.core.utils.Utils.DEFAULT_MS_PER_TICK;
|
||||
import static com.replaymod.core.versions.MCVer.getMinecraft;
|
||||
import static com.replaymod.core.versions.MCVer.getPacketTypeRegistry;
|
||||
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
||||
@@ -49,7 +42,7 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
|
||||
private final ReplayModReplay mod;
|
||||
private final RandomAccessReplay replay;
|
||||
private final EventHandler eventHandler = new EventHandler();
|
||||
private ChannelHandlerContext ctx;
|
||||
private Channel channel;
|
||||
|
||||
private int currentTimeStamp;
|
||||
private double replaySpeed = 1;
|
||||
@@ -70,6 +63,7 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
|
||||
|
||||
@Override
|
||||
protected void dispatch(com.replaymod.replaystudio.protocol.Packet packet) {
|
||||
// Convert ReplayStudio-Netty buffer into MC-Netty buffer
|
||||
com.github.steveice10.netty.buffer.ByteBuf byteBuf = packet.getBuf();
|
||||
int size = byteBuf.readableBytes();
|
||||
if (buf.length < size) {
|
||||
@@ -78,40 +72,14 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
|
||||
byteBuf.getBytes(byteBuf.readerIndex(), buf, 0, size);
|
||||
ByteBuf wrappedBuf = Unpooled.wrappedBuffer(buf);
|
||||
wrappedBuf.writerIndex(size);
|
||||
PacketByteBuf packetByteBuf = new PacketByteBuf(wrappedBuf);
|
||||
packet.release();
|
||||
|
||||
NetworkState state = asMc(packet.getRegistry().getState());
|
||||
//#if MC>=10809
|
||||
Packet<?> mcPacket;
|
||||
//#else
|
||||
//$$ Packet mcPacket;
|
||||
//#endif
|
||||
//#if MC>=12002
|
||||
//$$ mcPacket = state.getHandler(NetworkSide.CLIENTBOUND).createPacket(packet.getId(), packetByteBuf);
|
||||
//#elseif MC>=11700
|
||||
//$$ mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId(), packetByteBuf);
|
||||
//#elseif MC>=11500
|
||||
mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId());
|
||||
//#else
|
||||
//$$ try {
|
||||
//$$ mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId());
|
||||
//$$ } catch (IllegalAccessException | InstantiationException e) {
|
||||
//$$ e.printStackTrace();
|
||||
//$$ return;
|
||||
//$$ }
|
||||
//#endif
|
||||
if (mcPacket != null) {
|
||||
//#if MC<11700
|
||||
try {
|
||||
mcPacket.read(packetByteBuf);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
//#endif
|
||||
// Combine id + payload
|
||||
ByteBuf bufWithId = channel.alloc().heapBuffer(2 + wrappedBuf.readableBytes());
|
||||
new PacketByteBuf(bufWithId).writeVarInt(packet.getId());
|
||||
bufWithId.writeBytes(wrappedBuf);
|
||||
|
||||
ctx.fireChannelRead(mcPacket);
|
||||
}
|
||||
channel.pipeline().fireChannelRead(bufWithId);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -124,9 +92,8 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
|
||||
eventHandler.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
public void setChannel(Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public ListenableFuture<Void> getInitializationPromise() {
|
||||
@@ -194,7 +161,7 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
|
||||
}
|
||||
TimerAccessor timer = (TimerAccessor) ((MinecraftAccessor) mc).getTimer();
|
||||
//#if MC>=11200
|
||||
timer.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK / (float) factor);
|
||||
timer.setTickLength(DEFAULT_MS_PER_TICK / (float) factor);
|
||||
//#else
|
||||
//$$ timer.setTimerSpeed((float) factor);
|
||||
//#endif
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.replaymod.core.mixin.MinecraftAccessor;
|
||||
import com.replaymod.core.mixin.TimerAccessor;
|
||||
import com.replaymod.core.utils.Restrictions;
|
||||
import com.replaymod.core.utils.Utils;
|
||||
import com.replaymod.core.utils.WrappedTimer;
|
||||
import com.replaymod.replay.camera.CameraEntity;
|
||||
import com.replaymod.replay.camera.SpectatorCameraController;
|
||||
import com.replaymod.replay.events.ReplayClosedCallback;
|
||||
@@ -28,12 +27,16 @@ import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
|
||||
import net.minecraft.client.network.ClientLoginNetworkHandler;
|
||||
import net.minecraft.client.util.Window;
|
||||
import net.minecraft.network.DecoderHandler;
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.network.PacketEncoder;
|
||||
import net.minecraft.util.crash.CrashReport;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@@ -42,15 +45,13 @@ import net.minecraft.network.ClientConnection;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
//#if MC>=12003
|
||||
//$$ import net.minecraft.client.resource.server.ServerResourcePackManager;
|
||||
//#if MC>=12006
|
||||
//$$ import net.minecraft.network.handler.NetworkStateTransitions;
|
||||
//$$ import net.minecraft.network.state.LoginStates;
|
||||
//#endif
|
||||
|
||||
//#if MC>=12002
|
||||
//$$ import io.netty.channel.ChannelDuplexHandler;
|
||||
//$$ import io.netty.channel.ChannelPromise;
|
||||
//$$ import net.minecraft.network.handler.NetworkStateTransitionHandler;
|
||||
//$$ import net.minecraft.network.packet.Packet;
|
||||
//#if MC>=12003
|
||||
//$$ import net.minecraft.client.resource.server.ServerResourcePackManager;
|
||||
//#endif
|
||||
|
||||
//#if MC>=12000
|
||||
@@ -122,6 +123,7 @@ import net.minecraft.network.NetworkSide;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.replaymod.core.utils.Utils.DEFAULT_MS_PER_TICK;
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
||||
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||
@@ -129,6 +131,8 @@ import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
public class ReplayHandler {
|
||||
|
||||
public static final String PACKET_HANDLER_NAME = "ReplayModReplay_packetHandler";
|
||||
|
||||
private static MinecraftClient mc = getMinecraft();
|
||||
|
||||
/**
|
||||
@@ -180,7 +184,7 @@ public class ReplayHandler {
|
||||
|
||||
markers = replayFile.getMarkers().or(Collections.emptySet());
|
||||
|
||||
fullReplaySender = new FullReplaySender(this, replayFile, false);
|
||||
fullReplaySender = new FullReplaySender(this, replayFile);
|
||||
//#if MC>=10800
|
||||
quickReplaySender = new QuickReplaySender(ReplayModReplay.instance, replayFile);
|
||||
//#endif
|
||||
@@ -259,7 +263,7 @@ public class ReplayHandler {
|
||||
|
||||
TimerAccessor timer = (TimerAccessor) ((MinecraftAccessor) mc).getTimer();
|
||||
//#if MC>=11200
|
||||
timer.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK);
|
||||
timer.setTickLength(DEFAULT_MS_PER_TICK);
|
||||
//#else
|
||||
//$$ timer.setTimerSpeed(1);
|
||||
//#endif
|
||||
@@ -319,22 +323,42 @@ public class ReplayHandler {
|
||||
//$$ ChannelOutboundHandlerAdapter dummyHandler = new ChannelOutboundHandlerAdapter();
|
||||
//$$ channel = new EmbeddedChannel(dummyHandler);
|
||||
//$$ channel.pipeline().remove(dummyHandler);
|
||||
//$$ channel.pipeline().removeLast();
|
||||
//#endif
|
||||
channel.pipeline().addFirst("ReplayModReplay_head", new DropOutboundMessagesHandler());
|
||||
|
||||
quickReplaySender.setChannel(channel);
|
||||
fullReplaySender.setChannel(channel);
|
||||
|
||||
//#if MC>=12006
|
||||
//$$ channel.pipeline().addLast("inbound_config", new NetworkStateTransitions.InboundConfigurer());
|
||||
//$$ channel.pipeline().addLast("outbound_config", new NetworkStateTransitions.OutboundConfigurer());
|
||||
//#else
|
||||
//#if MC>=12002
|
||||
//$$ channel.pipeline().addLast("decoder", new DecoderHandler(ClientConnection.CLIENTBOUND_PROTOCOL_KEY));
|
||||
//$$ channel.pipeline().addLast("encoder", new PacketEncoder(ClientConnection.SERVERBOUND_PROTOCOL_KEY));
|
||||
//#else
|
||||
channel.pipeline().addLast("decoder", new DecoderHandler(NetworkSide.CLIENTBOUND));
|
||||
channel.pipeline().addLast("encoder", new PacketEncoder(NetworkSide.SERVERBOUND));
|
||||
//#endif
|
||||
//#if MC>=10800
|
||||
channel.pipeline().addLast("ReplayModReplay_quickReplaySender", quickReplaySender);
|
||||
//#endif
|
||||
channel.pipeline().addLast("ReplayModReplay_replaySender", fullReplaySender);
|
||||
//#if MC>=12002
|
||||
//$$ channel.pipeline().addLast("ReplayModReplay_transition", new DummyNetworkStateTransitionHandler());
|
||||
//$$ channel.pipeline().addLast("bundler", new PacketBundler(ClientConnection.CLIENTBOUND_PROTOCOL_KEY));
|
||||
//#elseif MC>=11904
|
||||
//$$ channel.pipeline().addLast("bundler", new PacketBundler(NetworkSide.CLIENTBOUND));
|
||||
//#endif
|
||||
//#endif
|
||||
channel.pipeline().addLast(PACKET_HANDLER_NAME, quickMode ? quickReplaySender : fullReplaySender);
|
||||
channel.pipeline().addLast("packet_handler", networkManager);
|
||||
channel.pipeline().fireChannelActive();
|
||||
|
||||
// MC usually transitions from handshake to login via the packets it sends.
|
||||
// We don't send any packets (there is no server to receive them), so we need to switch manually.
|
||||
//#if MC>=12006
|
||||
//$$ networkManager.transitionInbound(LoginStates.S2C, new ClientLoginNetworkHandler(
|
||||
//$$ networkManager, mc, null, null, false, null, it -> {}, null
|
||||
//$$ ));
|
||||
//$$ networkManager.transitionOutbound(LoginStates.C2S);
|
||||
//#else
|
||||
//#if MC>=12002
|
||||
//$$ channel.attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY).set(NetworkState.LOGIN.getHandler(NetworkSide.CLIENTBOUND));
|
||||
//$$ channel.attr(ClientConnection.SERVERBOUND_PROTOCOL_KEY).set(NetworkState.LOGIN.getHandler(NetworkSide.SERVERBOUND));
|
||||
@@ -355,6 +379,7 @@ public class ReplayHandler {
|
||||
, it -> {}
|
||||
//#endif
|
||||
));
|
||||
//#endif
|
||||
|
||||
//#if MC>=11400
|
||||
((MinecraftAccessor) mc).setConnection(networkManager);
|
||||
@@ -459,6 +484,8 @@ public class ReplayHandler {
|
||||
targetCameraPosition = null;
|
||||
}
|
||||
|
||||
channel.pipeline().replace(PACKET_HANDLER_NAME, PACKET_HANDLER_NAME, quickMode ? quickReplaySender : fullReplaySender);
|
||||
|
||||
if (quickMode) {
|
||||
quickReplaySender.register();
|
||||
quickReplaySender.restart();
|
||||
@@ -647,7 +674,28 @@ public class ReplayHandler {
|
||||
long diff = targetTime - (replaySender.isHurrying() ? replaySender.getDesiredTimestamp() : replaySender.currentTimeStamp());
|
||||
if (diff != 0) {
|
||||
if (diff > 0 && diff < 5000) { // Small difference and no time travel
|
||||
if (replaySender.paused()) {
|
||||
replaySender.setSyncModeAndWait();
|
||||
do {
|
||||
replaySender.sendPacketsTill(targetTime);
|
||||
targetTime += 500;
|
||||
} while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen);
|
||||
replaySender.setAsyncMode(true);
|
||||
|
||||
for (int i = 0; i < Math.min(diff / 50, 3); i++) {
|
||||
//#if MC>=10800 && MC<11400
|
||||
//$$ try {
|
||||
//$$ mc.runTick();
|
||||
//$$ } catch (IOException e) {
|
||||
//$$ e.printStackTrace(); // This should never be thrown but whatever
|
||||
//$$ }
|
||||
//#else
|
||||
mc.tick();
|
||||
//#endif
|
||||
}
|
||||
} else {
|
||||
replaySender.jumpToTime(targetTime);
|
||||
}
|
||||
} else { // We either have to restart the replay or send a significant amount of packets
|
||||
// Render our please-wait-screen
|
||||
GuiScreen guiScreen = new GuiScreen();
|
||||
@@ -686,9 +734,14 @@ public class ReplayHandler {
|
||||
//$$ , VertexSorter.BY_Z
|
||||
//#endif
|
||||
//$$ );
|
||||
//#if MC>=12006
|
||||
//$$ org.joml.Matrix4fStack matrixStack = RenderSystem.getModelViewStack();
|
||||
//$$ matrixStack.translation(0, 0, -2000);
|
||||
//#else
|
||||
//$$ MatrixStack matrixStack = RenderSystem.getModelViewStack();
|
||||
//$$ matrixStack.loadIdentity();
|
||||
//$$ matrixStack.translate(0, 0, -2000);
|
||||
//#endif
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//$$ DiffuseLighting.enableGuiDepthLighting();
|
||||
//#else
|
||||
@@ -709,7 +762,9 @@ public class ReplayHandler {
|
||||
|
||||
guiScreen.toMinecraft().init(mc, window.getScaledWidth(), window.getScaledHeight());
|
||||
//#if MC>=12000
|
||||
//$$ guiScreen.toMinecraft().render(new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()), 0, 0, 0);
|
||||
//$$ DrawContext drawContext = new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers());
|
||||
//$$ guiScreen.toMinecraft().render(drawContext, 0, 0, 0);
|
||||
//$$ drawContext.draw();
|
||||
//#elseif MC>=11600
|
||||
guiScreen.toMinecraft().render(new MatrixStack(), 0, 0, 0);
|
||||
//#else
|
||||
@@ -811,23 +866,24 @@ public class ReplayHandler {
|
||||
//#endif
|
||||
}
|
||||
|
||||
//#if MC>=12002
|
||||
//$$ private static class DummyNetworkStateTransitionHandler extends ChannelDuplexHandler {
|
||||
//$$ @Override
|
||||
//$$ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
//$$ if (msg instanceof Packet<?> packet) {
|
||||
//$$ NetworkStateTransitionHandler.handle(ctx.channel().attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY), packet);
|
||||
//$$ }
|
||||
//$$ super.channelRead(ctx, msg);
|
||||
//$$ }
|
||||
//$$
|
||||
//$$ @Override
|
||||
//$$ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
//$$ if (msg instanceof Packet<?> packet) {
|
||||
//$$ NetworkStateTransitionHandler.handle(ctx.channel().attr(ClientConnection.SERVERBOUND_PROTOCOL_KEY), packet);
|
||||
//$$ }
|
||||
//$$ super.write(ctx, msg, promise);
|
||||
//$$ }
|
||||
//$$ }
|
||||
//#endif
|
||||
private static class DropOutboundMessagesHandler extends ChannelOutboundHandlerAdapter {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
|
||||
// The embedded channel's event loop will consider every thread to be in it and as such provides no
|
||||
// guarantees that only one thread is using the pipeline at any one time.
|
||||
// For reading the replay sender (either sync or async) is the only thread ever writing.
|
||||
// For writing it may very well happen that multiple threads want to use the pipline at the same time.
|
||||
// It's unclear whether the EmbeddedChannel is supposed to be thread-safe (the behavior of the event loop
|
||||
// does suggest that). However it seems like it either isn't (likely) or there is a race condition.
|
||||
// See: https://www.replaymod.com/forum/thread/1752#post8045 (https://paste.replaymod.com/lotacatuwo)
|
||||
// To work around this issue, we just outright drop all write/flush requests (they aren't needed anyway).
|
||||
// This still leaves channel handlers upstream with the threading issue but they all seem to cope well with it.
|
||||
promise.setSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush(ChannelHandlerContext ctx) {
|
||||
// See write method above
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.replaymod.core.KeyBindingRegistry;
|
||||
import com.replaymod.core.Module;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.mixin.MinecraftAccessor;
|
||||
import com.replaymod.core.utils.ModCompat;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.core.versions.MCVer.Keyboard;
|
||||
@@ -152,9 +151,6 @@ public class ReplayModReplay implements Module {
|
||||
}
|
||||
});
|
||||
|
||||
MinecraftAccessor mc = (MinecraftAccessor) core.getMinecraft();
|
||||
mc.setTimer(new InputReplayTimer(mc.getTimer(), this));
|
||||
|
||||
new GuiHandler(this).register();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,22 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
//#if MC>=12005
|
||||
//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
//$$ import org.joml.Matrix4f;
|
||||
//#endif
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class MixinCamera {
|
||||
@Shadow @Final private MinecraftClient client;
|
||||
//#if MC>=12005
|
||||
//#if MC>=12100
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotation(Lorg/joml/Quaternionfc;)Lorg/joml/Matrix4f;"))
|
||||
//#else
|
||||
//$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;"))
|
||||
//#endif
|
||||
//$$ private Matrix4f applyRoll(Matrix4f matrix) {
|
||||
//#else
|
||||
@Inject(
|
||||
method = "renderWorld",
|
||||
at = @At(
|
||||
@@ -24,9 +37,17 @@ public class MixinCamera {
|
||||
)
|
||||
)
|
||||
private void applyRoll(float float_1, long long_1, MatrixStack matrixStack, CallbackInfo ci) {
|
||||
//#endif
|
||||
Entity entity = this.client.getCameraEntity() == null ? this.client.player : this.client.getCameraEntity();
|
||||
if (entity instanceof CameraEntity) {
|
||||
//#if MC>=12005
|
||||
//$$ matrix.rotateLocal(((CameraEntity) entity).roll * (float) Math.PI / 180f, 0f, 0f, 1f);
|
||||
//#else
|
||||
matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(((CameraEntity) entity).roll));
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
//#if MC>=12005
|
||||
//$$ return matrix;
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.replaymod.replay.mixin;
|
||||
|
||||
import com.replaymod.replay.InputReplayTimer;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public abstract class Mixin_HandleInputsInReplay {
|
||||
@Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=scheduledExecutables"))
|
||||
private void updateInReplay(CallbackInfo ci) {
|
||||
InputReplayTimer.updateInReplay();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector2f;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Point;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||
@@ -153,8 +154,12 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
|
||||
|
||||
final int color = 0xff0000ff;
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
//#if MC>=12100
|
||||
//$$ BufferBuilder buffer = tessellator.begin(net.minecraft.client.render.VertexFormat.DrawMode.LINE_STRIP, VertexFormats.LINES);
|
||||
//#else
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_LINE_STRIP, VertexFormats.POSITION_COLOR);
|
||||
//#endif
|
||||
|
||||
// Start just below the top border of the replay timeline
|
||||
Vector2f p1 = new Vector2f(replayTimelineLeft + positionXReplayTimeline, replayTimelineTop + BORDER_TOP);
|
||||
@@ -165,9 +170,10 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
|
||||
// And finally another vertical bit (the timeline is already crammed enough, so only the border)
|
||||
Vector2f p4 = new Vector2f(keyframeTimelineLeft + positionXKeyframeTimeline, keyframeTimelineTop + BORDER_TOP);
|
||||
|
||||
emitLine(buffer, p1, p2, color);
|
||||
emitLine(buffer, p2, p3, color);
|
||||
emitLine(buffer, p3, p4, color);
|
||||
MatrixStack matrixStack = renderer.getMatrixStack();
|
||||
emitLine(matrixStack, buffer, p1, p2, color);
|
||||
emitLine(matrixStack, buffer, p2, p3, color);
|
||||
emitLine(matrixStack, buffer, p3, p4, color);
|
||||
|
||||
//#if MC>=11700
|
||||
//$$ RenderSystem.setShader(GameRenderer::getRenderTypeLinesShader);
|
||||
@@ -178,7 +184,13 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
|
||||
pushScissorState();
|
||||
setScissorDisabled();
|
||||
GL11.glLineWidth(2);
|
||||
//#if MC>=12100
|
||||
//$$ try (var builtBuffer = buffer.end()) {
|
||||
//$$ net.minecraft.client.render.BufferRenderer.drawWithGlobalProgram(builtBuffer);
|
||||
//$$ }
|
||||
//#else
|
||||
tessellator.draw();
|
||||
//#endif
|
||||
popScissorState();
|
||||
//#if MC<11700
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
|
||||
@@ -46,9 +46,10 @@ import static com.replaymod.core.versions.MCVer.bindTexture;
|
||||
import static com.replaymod.core.versions.MCVer.emitLine;
|
||||
import static com.replaymod.core.versions.MCVer.popMatrix;
|
||||
import static com.replaymod.core.versions.MCVer.pushMatrix;
|
||||
import static de.johni0702.minecraft.gui.versions.MCVer.identifier;
|
||||
|
||||
public class PathPreviewRenderer extends EventRegistrations {
|
||||
private static final Identifier CAMERA_HEAD = new Identifier("replaymod", "camera_head.png");
|
||||
private static final Identifier CAMERA_HEAD = identifier("replaymod", "camera_head.png");
|
||||
private static final MinecraftClient mc = MCVer.getMinecraft();
|
||||
|
||||
private static final int SLOW_PATH_COLOR = 0xffcccc;
|
||||
@@ -108,7 +109,11 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
//#endif
|
||||
|
||||
//#if MC>=11700
|
||||
//#if MC>=12006
|
||||
//$$ RenderSystem.getModelViewStack().mul(matrixStack.peek().getPositionMatrix());
|
||||
//#else
|
||||
//$$ RenderSystem.getModelViewStack().method_34425(matrixStack.peek().getModel());
|
||||
//#endif
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//#elseif MC>=11500
|
||||
RenderSystem.multMatrix(matrixStack.peek().getModel());
|
||||
@@ -242,17 +247,27 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
if (distanceSquared(view, pos2) > renderDistanceSquared) return;
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
//#if MC>=12100
|
||||
//$$ BufferBuilder buffer = tessellator.begin(net.minecraft.client.render.VertexFormat.DrawMode.LINES, VertexFormats.LINES);
|
||||
//#else
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR);
|
||||
//#endif
|
||||
|
||||
emitLine(buffer, Vector3f.sub(pos1, view, null), Vector3f.sub(pos2, view, null), color);
|
||||
emitLine(new MatrixStack(), buffer, Vector3f.sub(pos1, view, null), Vector3f.sub(pos2, view, null), color);
|
||||
|
||||
//#if MC>=11700
|
||||
//$$ RenderSystem.setShader(GameRenderer::getRenderTypeLinesShader);
|
||||
//$$ RenderSystem.disableCull();
|
||||
//#endif
|
||||
GL11.glLineWidth(3);
|
||||
//#if MC>=12100
|
||||
//$$ try (var builtBuffer = buffer.end()) {
|
||||
//$$ net.minecraft.client.render.BufferRenderer.drawWithGlobalProgram(builtBuffer);
|
||||
//$$ }
|
||||
//#else
|
||||
tessellator.draw();
|
||||
//#endif
|
||||
//#if MC>=11700
|
||||
//$$ RenderSystem.enableCull();
|
||||
//#endif
|
||||
@@ -280,8 +295,12 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
float maxY = 0.5f;
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
//#if MC>=12100
|
||||
//$$ BufferBuilder buffer = tessellator.begin(net.minecraft.client.render.VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE);
|
||||
//#else
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_TEXTURE);
|
||||
//#endif
|
||||
|
||||
buffer.vertex(minX, minY, 0).texture(posX + size, posY + size).next();
|
||||
buffer.vertex(minX, maxY, 0).texture(posX + size, posY).next();
|
||||
@@ -299,7 +318,13 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//$$ RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
//#endif
|
||||
//#if MC>=12100
|
||||
//$$ try (var builtBuffer = buffer.end()) {
|
||||
//$$ net.minecraft.client.render.BufferRenderer.drawWithGlobalProgram(builtBuffer);
|
||||
//$$ }
|
||||
//#else
|
||||
tessellator.draw();
|
||||
//#endif
|
||||
|
||||
popMatrix();
|
||||
}
|
||||
@@ -318,10 +343,14 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
|
||||
//draw the position line
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
//#if MC>=12100
|
||||
//$$ BufferBuilder buffer = tessellator.begin(net.minecraft.client.render.VertexFormat.DrawMode.LINES, VertexFormats.LINES);
|
||||
//#else
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR);
|
||||
//#endif
|
||||
|
||||
emitLine(buffer, new Vector3f(0, 0, 0), new Vector3f(0, 0, 2), 0x00ff00aa);
|
||||
emitLine(new MatrixStack(), buffer, new Vector3f(0, 0, 0), new Vector3f(0, 0, 2), 0x00ff00aa);
|
||||
|
||||
//#if MC>=11700
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
@@ -330,7 +359,13 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
//#endif
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ try (var builtBuffer = buffer.end()) {
|
||||
//$$ net.minecraft.client.render.BufferRenderer.drawWithGlobalProgram(builtBuffer);
|
||||
//$$ }
|
||||
//#else
|
||||
tessellator.draw();
|
||||
//#endif
|
||||
|
||||
//#if MC<11700
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
@@ -340,9 +375,17 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
|
||||
float cubeSize = 0.5f;
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ float r = -cubeSize/2;
|
||||
//#else
|
||||
double r = -cubeSize/2;
|
||||
//#endif
|
||||
|
||||
//#if MC>=12100
|
||||
//$$ buffer = tessellator.begin(net.minecraft.client.render.VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
|
||||
//#else
|
||||
buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_TEXTURE_COLOR);
|
||||
//#endif
|
||||
|
||||
//back
|
||||
buffer.vertex(r, r + cubeSize, r).texture(3 * 8 / 64f, 8 / 64f).color(255, 255, 255, 200).next();
|
||||
@@ -384,7 +427,13 @@ public class PathPreviewRenderer extends EventRegistrations {
|
||||
//$$ RenderSystem.applyModelViewMatrix();
|
||||
//$$ RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
|
||||
//#endif
|
||||
//#if MC>=12100
|
||||
//$$ try (var builtBuffer = buffer.end()) {
|
||||
//$$ net.minecraft.client.render.BufferRenderer.drawWithGlobalProgram(builtBuffer);
|
||||
//$$ }
|
||||
//#else
|
||||
tessellator.draw();
|
||||
//#endif
|
||||
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Replay Mod",
|
||||
"description": "A Mod which allows you to record, replay and share your Minecraft experience.",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -20,7 +20,7 @@
|
||||
"name": "Replay Mod - Recording",
|
||||
"description": "Recording Module of the ReplayMod",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -37,7 +37,7 @@
|
||||
"name": "Replay Mod - Replay",
|
||||
"description": "Replay Module of the ReplayMod",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -54,7 +54,7 @@
|
||||
"name": "Replay Mod - Simple Pathing",
|
||||
"description": "Simple Pathing Module of the ReplayMod - aka the original pathing",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -71,7 +71,7 @@
|
||||
"name": "Replay Mod - Render",
|
||||
"description": "Render Module of the ReplayMod",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -88,7 +88,7 @@
|
||||
"name": "Replay Mod - Replay Editor",
|
||||
"description": "Replay Editor Module of the ReplayMod",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -105,7 +105,7 @@
|
||||
"name": "Replay Mod - Extras",
|
||||
"description": "Extras Module of the ReplayMod - Small but neat additions",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
@@ -122,7 +122,7 @@
|
||||
"name": "Replay Mod - Compatibility",
|
||||
"description": "Compatibility Module of the ReplayMod - Adds compatibility with other mods",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"mcversion": "${mcVersionStr}",
|
||||
"url": "https://replaymod.com",
|
||||
"updateUrl": "https://replaymod.com/download",
|
||||
"authorList": [
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"Mixin_ContextualKeyBindings",
|
||||
//#if MC>=11400
|
||||
"AbstractButtonWidgetAccessor",
|
||||
"MixinGameRenderer",
|
||||
"Mixin_PostRenderWorldCalback",
|
||||
"Mixin_PreRenderHandCallback",
|
||||
"Mixin_InjectDynamicResourcePacks",
|
||||
//#endif
|
||||
//#if MC>=11400
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
"client": [
|
||||
"AddServerScreenAccessor",
|
||||
"ClientLoginNetworkHandlerAccessor",
|
||||
//#if MC>=12006
|
||||
//$$ "DecoderHandlerAccessor",
|
||||
//#endif
|
||||
"EntityLivingBaseAccessor",
|
||||
"IntegratedServerAccessor",
|
||||
"NetworkManagerAccessor",
|
||||
@@ -31,6 +34,9 @@
|
||||
//$$ "MixinGuiScreen",
|
||||
//$$ "MixinS26PacketMapChunkBulk",
|
||||
//#endif
|
||||
//#if MC>=12006
|
||||
//$$ "MixinNetHandlerConfigClient",
|
||||
//#endif
|
||||
"MixinNetHandlerLoginClient",
|
||||
"MixinNetHandlerPlayClient",
|
||||
//#if MC<11400
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
"Mixin_ChromaKeyColorSky",
|
||||
"Mixin_ChromaKeyDisableFog",
|
||||
"Mixin_ChromaKeyForceSky",
|
||||
//#if MC>=12100
|
||||
//$$ "Mixin_FakeSystemTimeUniforms_Iris",
|
||||
//#endif
|
||||
"Mixin_ForceChunkLoading",
|
||||
"Mixin_HideNameTags",
|
||||
"Mixin_HideNameTags_LivingEntity",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"entity_tracking.Mixin_FixPartialUpdates",
|
||||
"world_border.Mixin_UseReplayTime_ForMovement",
|
||||
"world_border.Mixin_UseReplayTime_ForTexture",
|
||||
"Mixin_HandleInputsInReplay",
|
||||
"Mixin_FixNPCSkinCaching",
|
||||
//#if MC>=11900
|
||||
//$$ "Mixin_AllowExpiredPlayerKeys",
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.6.15
|
||||
2.6.16
|
||||
|
||||
@@ -27,8 +27,6 @@ import static com.replaymod.core.versions.MCVer.getMinecraft;
|
||||
|
||||
@Mod(modid = ReplayMod.MOD_ID,
|
||||
useMetadata = true,
|
||||
version = "@MOD_VERSION@",
|
||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||
acceptableRemoteVersions = "*",
|
||||
//#if MC>=10800
|
||||
clientSideOnly = true,
|
||||
|
||||
1
versions/1.14.4-forge/gradle.properties
Normal file
1
versions/1.14.4-forge/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
essential.defaults.loom.mappings=de.oceanlabs.mcp:mcp_snapshot:20190719-1.14.3@zip
|
||||
1
versions/1.18.1/gradle.properties
Normal file
1
versions/1.18.1/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
essential.defaults.loom.mappings=net.fabricmc:yarn:1.18.1+build.1:v2
|
||||
1
versions/1.18.2/gradle.properties
Normal file
1
versions/1.18.2/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
essential.defaults.loom.mappings=net.fabricmc:yarn:1.18.2+build.1:v2
|
||||
1
versions/1.19.2/gradle.properties
Normal file
1
versions/1.19.2/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
essential.defaults.loom.mappings=net.fabricmc:yarn:1.19.2+build.28:v2
|
||||
2
versions/1.19.3/gradle.properties
Normal file
2
versions/1.19.3/gradle.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
essential.defaults.loom.minecraft=com.mojang:minecraft:1.19.3-rc3
|
||||
essential.defaults.loom.mappings=net.fabricmc:yarn:1.19.3-rc3+build.1:v2
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.replaymod.render.hooks.ForceChunkLoadingHook;
|
||||
import com.replaymod.render.hooks.IForceChunkLoading;
|
||||
import com.replaymod.render.utils.FlawlessFrames;
|
||||
@@ -50,7 +51,7 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading {
|
||||
@Shadow protected abstract void applyFrustum(Frustum par1);
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V"))
|
||||
private void forceAllChunks(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||
private void forceAllChunks(CallbackInfo ci, @Local(argsOnly = true) Camera camera) {
|
||||
if (replayModRender_hook == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import net.minecraft.network.NetworkState;
|
||||
import net.minecraft.network.handler.DecoderHandler;
|
||||
import net.minecraft.network.listener.PacketListener;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@Mixin(DecoderHandler.class)
|
||||
public interface DecoderHandlerAccessor<T extends PacketListener> {
|
||||
@Accessor
|
||||
@Nonnull
|
||||
NetworkState<T> getState();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.replaymod.recording.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.replaymod.core.versions.MCVer;
|
||||
import com.replaymod.recording.ReplayModRecording;
|
||||
import com.replaymod.recording.packet.PacketListener;
|
||||
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
|
||||
import com.replaymod.replaystudio.protocol.Packet;
|
||||
import com.replaymod.replaystudio.protocol.PacketType;
|
||||
import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
|
||||
import com.replaymod.replaystudio.protocol.packets.PacketEnabledPacksData;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(ClientConfigurationNetworkHandler.class)
|
||||
public abstract class MixinNetHandlerConfigClient {
|
||||
@Inject(method = "onReady", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;transitionInbound(Lnet/minecraft/network/NetworkState;Lnet/minecraft/network/listener/PacketListener;)V"))
|
||||
public void recordEnabledPackData(CallbackInfo ci, @Local DynamicRegistryManager.Immutable registryManager) {
|
||||
PacketListener packetListener = ReplayModRecording.instance.getConnectionEventHandler().getPacketListener();
|
||||
if (packetListener == null) return;
|
||||
|
||||
ByteBuf byteBuf = Unpooled.buffer();
|
||||
PacketByteBuf buf = new PacketByteBuf(byteBuf);
|
||||
buf.writeString(PacketEnabledPacksData.ID);
|
||||
buf.writeVarInt(1);
|
||||
write(buf, registryManager.get(RegistryKeys.DIMENSION_TYPE), DimensionType.CODEC);
|
||||
|
||||
byte[] bytes = new byte[byteBuf.readableBytes()];
|
||||
byteBuf.readBytes(bytes);
|
||||
byteBuf.release();
|
||||
|
||||
PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(State.CONFIGURATION);
|
||||
packetListener.save(new Packet(registry, PacketType.ConfigCustomPayload, com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(bytes)));
|
||||
packetListener.save(new Packet(registry, PacketType.ConfigFinish));
|
||||
}
|
||||
|
||||
@Unique
|
||||
private <T> void write(PacketByteBuf buf, Registry<T> registry, Codec<T> codec) {
|
||||
buf.writeString(registry.getKey().getValue().toString());
|
||||
buf.writeVarInt(registry.size());
|
||||
for (Map.Entry<RegistryKey<T>, T> entry : registry.getEntrySet()) {
|
||||
buf.writeString(entry.getKey().getValue().toString());
|
||||
buf.writeNbt(codec.encodeStart(NbtOps.INSTANCE, entry.getValue()).getOrThrow());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.replaymod.render.mixin;
|
||||
|
||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||
import net.irisshaders.iris.uniforms.SystemTimeUniforms;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
|
||||
@Pseudo
|
||||
@Mixin(value = SystemTimeUniforms.Timer.class, remap = false)
|
||||
public class Mixin_FakeSystemTimeUniforms_Iris {
|
||||
@ModifyVariable(method = "beginFrame", at = @At("HEAD"), argsOnly = true)
|
||||
private long useReplayTimeDuringRender(long frameStartTimeNs) {
|
||||
GameRenderer gameRenderer = MinecraftClient.getInstance().gameRenderer;
|
||||
EntityRendererHandler entityRendererHandler =
|
||||
((EntityRendererHandler.IEntityRenderer) gameRenderer).replayModRender_getHandler();
|
||||
if (entityRendererHandler != null) {
|
||||
frameStartTimeNs = entityRendererHandler.getFakeFinishTimeNano();
|
||||
}
|
||||
return frameStartTimeNs;
|
||||
}
|
||||
}
|
||||
1
versions/1.8.9/gradle.properties
Normal file
1
versions/1.8.9/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
essential.defaults.loom.forge=net.minecraftforge:forge:1.8.9-11.15.1.1722
|
||||
5
versions/mapping-fabric-1.20.1-1.19.4.txt
Normal file
5
versions/mapping-fabric-1.20.1-1.19.4.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
net.irisshaders.iris.Iris net.coderbot.iris.Iris
|
||||
net.irisshaders.iris.config.IrisConfig net.coderbot.iris.config.IrisConfig
|
||||
net.irisshaders.iris.gl.uniform.UniformHolder net.coderbot.iris.gl.uniform.UniformHolder
|
||||
net.irisshaders.iris.gl.uniform.UniformUpdateFrequency net.coderbot.iris.gl.uniform.UniformUpdateFrequency
|
||||
net.irisshaders.iris.uniforms.CommonUniforms net.coderbot.iris.uniforms.CommonUniforms
|
||||
0
versions/mapping-forge-1.11-1.10.2.txt
Normal file
0
versions/mapping-forge-1.11-1.10.2.txt
Normal file
@@ -25,6 +25,8 @@ net.minecraft.network.play.server.SPacketSpawnPlayer getDataManagerEntries() fun
|
||||
net.minecraft.client.multiplayer.ServerList saveSingleServer() func_147414_b()
|
||||
net.minecraft.util.SoundEvent com.replaymod.core.versions.MCVer.SoundEvent
|
||||
|
||||
net.minecraft.network.NettyPacketDecoder net.minecraft.util.MessageDeserializer
|
||||
net.minecraft.network.NettyPacketEncoder net.minecraft.util.MessageSerializer
|
||||
net.minecraft.network.play.server.SPacketJoinGame net.minecraft.network.play.server.S01PacketJoinGame
|
||||
net.minecraft.network.play.server.SPacketChat net.minecraft.network.play.server.S02PacketChat
|
||||
net.minecraft.network.play.server.SPacketParticles net.minecraft.network.play.server.S2APacketParticles
|
||||
Reference in New Issue
Block a user