Release 2.6.6
This commit is contained in:
36
build.gradle
36
build.gradle
@@ -1,4 +1,5 @@
|
|||||||
import com.replaymod.gradle.preprocess.PreprocessTask
|
import com.replaymod.gradle.preprocess.PreprocessTask
|
||||||
|
import static gg.essential.gradle.util.PrebundleKt.prebundle
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
def mcVersion
|
def mcVersion
|
||||||
@@ -18,23 +19,23 @@ buildscript {
|
|||||||
name = "fabric"
|
name = "fabric"
|
||||||
url = "https://maven.fabricmc.net/"
|
url = "https://maven.fabricmc.net/"
|
||||||
}
|
}
|
||||||
if (!fabric) {
|
|
||||||
maven {
|
maven {
|
||||||
name = "forge"
|
name = "forge"
|
||||||
url = "https://maven.minecraftforge.net"
|
url = "https://maven.minecraftforge.net"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
maven {
|
maven {
|
||||||
name = "sonatype"
|
name = "sonatype"
|
||||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||||
}
|
}
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url "https://maven.architectury.dev" }
|
||||||
|
maven { url "https://repo.essential.gg/repository/maven-public" }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
|
classpath 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
|
||||||
if (fabric) {
|
if (fabric) {
|
||||||
classpath 'fabric-loom:fabric-loom.gradle.plugin:0.10-SNAPSHOT'
|
classpath 'fabric-loom:fabric-loom.gradle.plugin:0.11-SNAPSHOT'
|
||||||
} else if (mcVersion >= 11400) {
|
} else if (mcVersion >= 11400) {
|
||||||
classpath('net.minecraftforge.gradle:ForgeGradle:5.0.5') { // the FG people still haven't learned to not do breaking changes
|
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
|
exclude group: 'trove', module: 'trove' // preprocessor/idea requires more recent one
|
||||||
@@ -48,6 +49,7 @@ buildscript {
|
|||||||
} else {
|
} else {
|
||||||
classpath 'com.github.ReplayMod:ForgeGradle:a8a9e0ca:all' // FG 1.2
|
classpath 'com.github.ReplayMod:ForgeGradle:a8a9e0ca:all' // FG 1.2
|
||||||
}
|
}
|
||||||
|
classpath 'gg.essential:essential-gradle-toolkit:0.1.10'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +248,7 @@ dependencies {
|
|||||||
11800: '1.18',
|
11800: '1.18',
|
||||||
11801: '1.18.1',
|
11801: '1.18.1',
|
||||||
11802: '1.18.2',
|
11802: '1.18.2',
|
||||||
|
11900: '1.19',
|
||||||
][mcVersion]
|
][mcVersion]
|
||||||
mappings 'net.fabricmc:yarn:' + [
|
mappings 'net.fabricmc:yarn:' + [
|
||||||
11404: '1.14.4+build.16',
|
11404: '1.14.4+build.16',
|
||||||
@@ -258,8 +261,9 @@ dependencies {
|
|||||||
11800: '1.18+build.1:v2',
|
11800: '1.18+build.1:v2',
|
||||||
11801: '1.18.1+build.1:v2',
|
11801: '1.18.1+build.1:v2',
|
||||||
11802: '1.18.2+build.1:v2',
|
11802: '1.18.2+build.1:v2',
|
||||||
|
11900: '1.19+build.2:v2',
|
||||||
][mcVersion]
|
][mcVersion]
|
||||||
modImplementation 'net.fabricmc:fabric-loader:0.12.5'
|
modImplementation 'net.fabricmc:fabric-loader:0.14.6'
|
||||||
def fabricApiVersion = [
|
def fabricApiVersion = [
|
||||||
11404: '0.4.3+build.247-1.14',
|
11404: '0.4.3+build.247-1.14',
|
||||||
11502: '0.5.1+build.294-1.15',
|
11502: '0.5.1+build.294-1.15',
|
||||||
@@ -271,6 +275,7 @@ dependencies {
|
|||||||
11800: '0.43.1+1.18',
|
11800: '0.43.1+1.18',
|
||||||
11801: '0.43.1+1.18',
|
11801: '0.43.1+1.18',
|
||||||
11802: '0.47.9+1.18.2',
|
11802: '0.47.9+1.18.2',
|
||||||
|
11900: '0.55.3+1.19',
|
||||||
][mcVersion]
|
][mcVersion]
|
||||||
def fabricApiModules = [
|
def fabricApiModules = [
|
||||||
"api-base",
|
"api-base",
|
||||||
@@ -279,9 +284,11 @@ dependencies {
|
|||||||
"resource-loader-v0",
|
"resource-loader-v0",
|
||||||
]
|
]
|
||||||
if (mcVersion >= 11600) {
|
if (mcVersion >= 11600) {
|
||||||
|
fabricApiModules.remove("keybindings-v0")
|
||||||
fabricApiModules.add("key-binding-api-v1")
|
fabricApiModules.add("key-binding-api-v1")
|
||||||
}
|
}
|
||||||
if (mcVersion >= 11700) {
|
if (mcVersion >= 11700) {
|
||||||
|
fabricApiModules.remove("networking-v0")
|
||||||
fabricApiModules.add("networking-api-v1")
|
fabricApiModules.add("networking-api-v1")
|
||||||
}
|
}
|
||||||
fabricApiModules.each { module ->
|
fabricApiModules.each { module ->
|
||||||
@@ -318,13 +325,13 @@ dependencies {
|
|||||||
shadow 'com.google.api-client:google-api-client-java6: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'
|
shadow 'com.google.oauth-client:google-oauth-client-jetty:1.20.0'
|
||||||
|
|
||||||
if (mcVersion >= 11400) { // need lwjgl 3
|
def lwjgl = configurations.create("lwjgl")
|
||||||
for (suffix in ['', ':natives-linux', ':natives-windows', ':natives-macos']) {
|
for (suffix in ['', ':natives-linux', ':natives-windows', ':natives-macos', ':natives-macos-arm64']) {
|
||||||
shadow('org.lwjgl:lwjgl-tinyexr:3.2.2' + suffix) {
|
add(lwjgl.name, 'org.lwjgl:lwjgl:3.3.1' + suffix)
|
||||||
exclude group: 'org.lwjgl', module: 'lwjgl' // comes with MC
|
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) {
|
if (mcVersion < 11200) {
|
||||||
// The version which MC ships is too old, we'll need to ship our own
|
// The version which MC ships is too old, we'll need to ship our own
|
||||||
@@ -341,7 +348,10 @@ dependencies {
|
|||||||
|
|
||||||
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
|
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
|
||||||
|
|
||||||
shadow "com.github.ReplayMod:ReplayStudio:6fc8e20", shadeExclusions
|
shadow "com.github.ReplayMod:ReplayStudio:74d8465", 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) {
|
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
|
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
||||||
@@ -349,7 +359,9 @@ dependencies {
|
|||||||
shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66'
|
shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66'
|
||||||
|
|
||||||
if (FABRIC) {
|
if (FABRIC) {
|
||||||
if (mcVersion >= 11802) {
|
if (mcVersion >= 11900) {
|
||||||
|
modCompileOnly 'com.terraformersmc:modmenu:3.1.0' // FIXME update
|
||||||
|
} else if (mcVersion >= 11802) {
|
||||||
modImplementation 'com.terraformersmc:modmenu:3.1.0'
|
modImplementation 'com.terraformersmc:modmenu:3.1.0'
|
||||||
} else if (mcVersion >= 11800) {
|
} else if (mcVersion >= 11800) {
|
||||||
modImplementation 'com.terraformersmc:modmenu:3.0.0'
|
modImplementation 'com.terraformersmc:modmenu:3.0.0'
|
||||||
|
|||||||
2
jGui
2
jGui
Submodule jGui updated: 5e41452b0e...c1e43fc9f0
@@ -2,8 +2,8 @@ import groovy.json.JsonOutput
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("fabric-loom") version "0.10-SNAPSHOT" apply false
|
id("fabric-loom") version "0.11-SNAPSHOT" apply false
|
||||||
id("com.replaymod.preprocess") version "7746c47"
|
id("com.replaymod.preprocess") version "48e02ad"
|
||||||
id("com.github.hierynomus.license") version "0.15.0"
|
id("com.github.hierynomus.license") version "0.15.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +189,7 @@ val doRelease by tasks.registering {
|
|||||||
defaultTasks("bundleJar")
|
defaultTasks("bundleJar")
|
||||||
|
|
||||||
preprocess {
|
preprocess {
|
||||||
|
val mc11900 = createNode("1.19", 11900, "yarn")
|
||||||
val mc11802 = createNode("1.18.2", 11802, "yarn")
|
val mc11802 = createNode("1.18.2", 11802, "yarn")
|
||||||
val mc11801 = createNode("1.18.1", 11801, "yarn")
|
val mc11801 = createNode("1.18.1", 11801, "yarn")
|
||||||
val mc11701 = createNode("1.17.1", 11701, "yarn")
|
val mc11701 = createNode("1.17.1", 11701, "yarn")
|
||||||
@@ -209,6 +210,7 @@ preprocess {
|
|||||||
val mc10800 = createNode("1.8", 10800, "srg")
|
val mc10800 = createNode("1.8", 10800, "srg")
|
||||||
val mc10710 = createNode("1.7.10", 10710, "srg")
|
val mc10710 = createNode("1.7.10", 10710, "srg")
|
||||||
|
|
||||||
|
mc11900.link(mc11802, file("versions/mapping-fabric-1.19-1.18.2.txt"))
|
||||||
mc11802.link(mc11801)
|
mc11802.link(mc11801)
|
||||||
mc11801.link(mc11701, file("versions/mapping-fabric-1.18.1-1.17.1.txt"))
|
mc11801.link(mc11701, file("versions/mapping-fabric-1.18.1-1.17.1.txt"))
|
||||||
mc11701.link(mc11700)
|
mc11701.link(mc11700)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ val jGuiVersions = listOf(
|
|||||||
"1.17.1",
|
"1.17.1",
|
||||||
"1.18.1",
|
"1.18.1",
|
||||||
"1.18.2",
|
"1.18.2",
|
||||||
|
"1.19",
|
||||||
)
|
)
|
||||||
val replayModVersions = listOf(
|
val replayModVersions = listOf(
|
||||||
// "1.7.10",
|
// "1.7.10",
|
||||||
@@ -54,6 +55,7 @@ val replayModVersions = listOf(
|
|||||||
"1.17.1",
|
"1.17.1",
|
||||||
"1.18.1",
|
"1.18.1",
|
||||||
"1.18.2",
|
"1.18.2",
|
||||||
|
"1.19",
|
||||||
)
|
)
|
||||||
|
|
||||||
rootProject.buildFileName = "root.gradle.kts"
|
rootProject.buildFileName = "root.gradle.kts"
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ import net.minecraft.util.crash.CrashException;
|
|||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
import com.replaymod.core.versions.LangResourcePack;
|
import com.replaymod.core.versions.LangResourcePack;
|
||||||
import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
|
//#if MC>=11600
|
||||||
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
|
//#else
|
||||||
|
//$$ import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
|
||||||
|
//#endif
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import static com.replaymod.core.ReplayMod.MOD_ID;
|
import static com.replaymod.core.ReplayMod.MOD_ID;
|
||||||
@@ -35,8 +39,8 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
public class KeyBindingRegistry extends EventRegistrations {
|
public class KeyBindingRegistry extends EventRegistrations {
|
||||||
private static final String CATEGORY = "replaymod.title";
|
private static final String CATEGORY = "replaymod.title";
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1 && MC<11600
|
||||||
static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); }
|
//$$ static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); }
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
private final Map<String, Binding> bindings = new HashMap<>();
|
private final Map<String, Binding> bindings = new HashMap<>();
|
||||||
@@ -63,9 +67,15 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
keyCode = -1;
|
keyCode = -1;
|
||||||
}
|
}
|
||||||
Identifier id = new Identifier(MOD_ID, name.substring(LangResourcePack.LEGACY_KEY_PREFIX.length()));
|
Identifier id = new Identifier(MOD_ID, name.substring(LangResourcePack.LEGACY_KEY_PREFIX.length()));
|
||||||
FabricKeyBinding fabricKeyBinding = FabricKeyBinding.Builder.create(id, InputUtil.Type.KEYSYM, keyCode, CATEGORY).build();
|
//#if MC>=11600
|
||||||
net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.register(fabricKeyBinding);
|
String key = String.format("key.%s.%s", id.getNamespace(), id.getPath());
|
||||||
KeyBinding keyBinding = fabricKeyBinding;
|
KeyBinding keyBinding = new KeyBinding(key, InputUtil.Type.KEYSYM, keyCode, CATEGORY);
|
||||||
|
KeyBindingHelper.registerKeyBinding(keyBinding);
|
||||||
|
//#else
|
||||||
|
//$$ FabricKeyBinding fabricKeyBinding = FabricKeyBinding.Builder.create(id, InputUtil.Type.KEYSYM, keyCode, CATEGORY).build();
|
||||||
|
//$$ net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.register(fabricKeyBinding);
|
||||||
|
//$$ KeyBinding keyBinding = fabricKeyBinding;
|
||||||
|
//#endif
|
||||||
//#else
|
//#else
|
||||||
//$$ KeyBinding keyBinding = new KeyBinding(name, keyCode, CATEGORY);
|
//$$ KeyBinding keyBinding = new KeyBinding(name, keyCode, CATEGORY);
|
||||||
//$$ ClientRegistry.registerKeyBinding(keyBinding);
|
//$$ ClientRegistry.registerKeyBinding(keyBinding);
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import com.replaymod.replaystudio.studio.ReplayStudio;
|
|||||||
import com.replaymod.replaystudio.util.I18n;
|
import com.replaymod.replaystudio.util.I18n;
|
||||||
import com.replaymod.simplepathing.ReplayModSimplePathing;
|
import com.replaymod.simplepathing.ReplayModSimplePathing;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.options.Option;
|
|
||||||
import net.minecraft.resource.DirectoryResourcePack;
|
import net.minecraft.resource.DirectoryResourcePack;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.text.Style;
|
import net.minecraft.text.Style;
|
||||||
@@ -37,6 +36,11 @@ import java.util.List;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
//#if MC>=11900
|
||||||
|
//#else
|
||||||
|
import net.minecraft.client.options.Option;
|
||||||
|
//#endif
|
||||||
|
|
||||||
public class ReplayMod implements Module, Scheduler {
|
public class ReplayMod implements Module, Scheduler {
|
||||||
|
|
||||||
public static final String MOD_ID = "replaymod";
|
public static final String MOD_ID = "replaymod";
|
||||||
@@ -162,7 +166,8 @@ public class ReplayMod implements Module, Scheduler {
|
|||||||
keyBindingRegistry.register();
|
keyBindingRegistry.register();
|
||||||
|
|
||||||
// 1.7.10 crashes when render distance > 16
|
// 1.7.10 crashes when render distance > 16
|
||||||
//#if MC>=10800
|
// Post 1.19 this has become non-trivial to do, install Sodium+Bobby or OptiFine if you need it
|
||||||
|
//#if MC>=10800 && MC<11900
|
||||||
if (!MCVer.hasOptifine()) {
|
if (!MCVer.hasOptifine()) {
|
||||||
Option.RENDER_DISTANCE.setMax(64f);
|
Option.RENDER_DISTANCE.setMax(64f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
// 1.19+
|
||||||
@@ -158,8 +158,12 @@ public class LangResourcePack extends AbstractFileResourcePack {
|
|||||||
String namespace,
|
String namespace,
|
||||||
//#endif
|
//#endif
|
||||||
String path,
|
String path,
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ Predicate<Identifier> filter
|
||||||
|
//#else
|
||||||
int maxDepth,
|
int maxDepth,
|
||||||
Predicate<String> filter
|
Predicate<String> filter
|
||||||
|
//#endif
|
||||||
) {
|
) {
|
||||||
if (resourcePackType == ResourceType.CLIENT_RESOURCES && "lang".equals(path)) {
|
if (resourcePackType == ResourceType.CLIENT_RESOURCES && "lang".equals(path)) {
|
||||||
Path base = baseLangPath();
|
Path base = baseLangPath();
|
||||||
@@ -174,8 +178,13 @@ public class LangResourcePack extends AbstractFileResourcePack {
|
|||||||
.map(LANG_FILE_NAME_PATTERN::matcher)
|
.map(LANG_FILE_NAME_PATTERN::matcher)
|
||||||
.filter(Matcher::matches)
|
.filter(Matcher::matches)
|
||||||
.map(matcher -> String.format("%s_%s.json", matcher.group(1), matcher.group(1)))
|
.map(matcher -> String.format("%s_%s.json", matcher.group(1), matcher.group(1)))
|
||||||
.filter(filter::test)
|
//#if MC<11900
|
||||||
|
.filter(filter)
|
||||||
|
//#endif
|
||||||
.map(name -> new Identifier(ReplayMod.MOD_ID, "lang/" + name))
|
.map(name -> new Identifier(ReplayMod.MOD_ID, "lang/" + name))
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ .filter(filter)
|
||||||
|
//#endif
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import net.minecraft.client.util.Window;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
//#if MC>=11600
|
//#if MC>=11600
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraft.client.resource.language.I18n;
|
//$$ import net.minecraft.client.resource.language.I18n;
|
||||||
@@ -220,7 +221,7 @@ public class MCVer {
|
|||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
public static Optional<AbstractButtonWidget> findButton(Iterable<AbstractButtonWidget> buttonList, @SuppressWarnings("unused") String text, @SuppressWarnings("unused") int id) {
|
public static Optional<AbstractButtonWidget> findButton(Iterable<AbstractButtonWidget> buttonList, @SuppressWarnings("unused") String text, @SuppressWarnings("unused") int id) {
|
||||||
//#if MC>=11600
|
//#if MC>=11600
|
||||||
final TranslatableText message = new TranslatableText(text);
|
final Text message = new TranslatableText(text);
|
||||||
//#else
|
//#else
|
||||||
//$$ final String message = I18n.translate(text);
|
//$$ final String message = I18n.translate(text);
|
||||||
//#endif
|
//#endif
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||||||
import com.replaymod.core.mixin.MinecraftAccessor;
|
import com.replaymod.core.mixin.MinecraftAccessor;
|
||||||
import com.replaymod.gradle.remap.Pattern;
|
import com.replaymod.gradle.remap.Pattern;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.options.GameOptions;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.options.KeyBinding;
|
||||||
import net.minecraft.client.render.VertexFormat;
|
import net.minecraft.client.render.VertexFormat;
|
||||||
import net.minecraft.client.texture.TextureManager;
|
import net.minecraft.client.texture.TextureManager;
|
||||||
@@ -14,6 +15,11 @@ import net.minecraft.client.render.Tessellator;
|
|||||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||||
import net.minecraft.client.sound.PositionedSoundInstance;
|
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.resource.Resource;
|
||||||
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
import net.minecraft.util.crash.CrashException;
|
import net.minecraft.util.crash.CrashException;
|
||||||
import net.minecraft.util.crash.CrashReport;
|
import net.minecraft.util.crash.CrashReport;
|
||||||
import net.minecraft.util.crash.CrashReportSection;
|
import net.minecraft.util.crash.CrashReportSection;
|
||||||
@@ -61,6 +67,7 @@ import net.minecraft.client.render.BufferBuilder;
|
|||||||
//$$ import net.minecraft.entity.EntityLivingBase;
|
//$$ import net.minecraft.entity.EntityLivingBase;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -549,7 +556,9 @@ class Patterns {
|
|||||||
|
|
||||||
@Pattern
|
@Pattern
|
||||||
private static void setCrashReport(MinecraftClient mc, CrashReport report) {
|
private static void setCrashReport(MinecraftClient mc, CrashReport report) {
|
||||||
//#if MC>=11800
|
//#if MC>=11900
|
||||||
|
//$$ mc.setCrashReportSupplier(report);
|
||||||
|
//#elseif MC>=11800
|
||||||
//$$ mc.setCrashReportSupplier(() -> report);
|
//$$ mc.setCrashReportSupplier(() -> report);
|
||||||
//#else
|
//#else
|
||||||
mc.setCrashReport(report);
|
mc.setCrashReport(report);
|
||||||
@@ -573,4 +582,91 @@ class Patterns {
|
|||||||
//$$ return com.replaymod.core.versions.MCVer.getTrackedPosition(entity);
|
//$$ return com.replaymod.core.versions.MCVer.getTrackedPosition(entity);
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static Text newTextLiteral(String str) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return net.minecraft.text.Text.literal(str);
|
||||||
|
//#else
|
||||||
|
return new LiteralText(str);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static Text newTextTranslatable(String key, Object...args) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return net.minecraft.text.Text.translatable(key, args);
|
||||||
|
//#else
|
||||||
|
return new TranslatableText(key, args);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//#if MC>=11500
|
||||||
|
@Pattern
|
||||||
|
private static Vec3d getTrackedPos(Entity entity) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return entity.getTrackedPosition().withDelta(0, 0, 0);
|
||||||
|
//#else
|
||||||
|
return entity.getTrackedPosition();
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
//#else
|
||||||
|
//$$ @Pattern private static void getTrackedPos() {}
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static void setGamma(GameOptions options, double value) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ ((com.replaymod.core.mixin.SimpleOptionAccessor<Double>) (Object) options.getGamma()).setRawValue(value);
|
||||||
|
//#elseif MC>=11400
|
||||||
|
options.gamma = value;
|
||||||
|
//#else
|
||||||
|
//$$ options.gammaSetting = (float) value;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static double getGamma(GameOptions options) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return options.getGamma().getValue();
|
||||||
|
//#else
|
||||||
|
return options.gamma;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static int getViewDistance(GameOptions options) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return options.getViewDistance().getValue();
|
||||||
|
//#else
|
||||||
|
return options.viewDistance;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static double getFov(GameOptions options) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return options.getFov().getValue();
|
||||||
|
//#else
|
||||||
|
return options.fov;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static int getGuiScale(GameOptions options) {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return options.getGuiScale().getValue();
|
||||||
|
//#else
|
||||||
|
return options.guiScale;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static Resource getResource(ResourceManager manager, Identifier id) throws IOException {
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ return manager.getResourceOrThrow(id);
|
||||||
|
//#else
|
||||||
|
return manager.getResource(id);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class MarkerProcessor {
|
|||||||
|
|
||||||
PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(true);
|
PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(true);
|
||||||
DimensionTracker dimensionTracker = new DimensionTracker();
|
DimensionTracker dimensionTracker = new DimensionTracker();
|
||||||
SquashFilter squashFilter = new SquashFilter(null, null);
|
SquashFilter squashFilter = new SquashFilter(null, null, null);
|
||||||
|
|
||||||
List<Pair<Path, ReplayMetaData>> outputPaths = new ArrayList<>();
|
List<Pair<Path, ReplayMetaData>> outputPaths = new ArrayList<>();
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class FullBrightness extends EventRegistrations implements Extra {
|
|||||||
Type type = getType();
|
Type type = getType();
|
||||||
if (type == Type.Gamma || type == Type.Both) {
|
if (type == Type.Gamma || type == Type.Both) {
|
||||||
originalGamma = mc.options.gamma;
|
originalGamma = mc.options.gamma;
|
||||||
mc.options.gamma = 1000;
|
mc.options.gamma = 1000.0;
|
||||||
}
|
}
|
||||||
if (type == Type.NightVision || type == Type.Both) {
|
if (type == Type.NightVision || type == Type.Both) {
|
||||||
if (mc.player != null) {
|
if (mc.player != null) {
|
||||||
|
|||||||
@@ -63,4 +63,9 @@ public class ScreenshotWriter implements FrameConsumer<BitmapFrame> {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
|
|||||||
}.setSize(16, 16),
|
}.setSize(16, 16),
|
||||||
new GuiLabel().setText(
|
new GuiLabel().setText(
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
p.getName().asString()
|
p.getName().getString()
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
//$$ p.getName()
|
//$$ p.getName()
|
||||||
@@ -181,7 +181,7 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
|
|||||||
if (isSpectator(o1) && !isSpectator(o2)) return 1;
|
if (isSpectator(o1) && !isSpectator(o2)) return 1;
|
||||||
if (isSpectator(o2) && !isSpectator(o1)) return -1;
|
if (isSpectator(o2) && !isSpectator(o1)) return -1;
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
return o1.getName().asString().compareToIgnoreCase(o2.getName().asString());
|
return o1.getName().getString().compareToIgnoreCase(o2.getName().getString());
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
//$$ return o1.getName().compareToIgnoreCase(o2.getName());
|
//$$ return o1.getName().compareToIgnoreCase(o2.getName());
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
|
//#if MC>=11700
|
||||||
|
//$$ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
//#else
|
||||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
||||||
|
//#endif
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraftforge.fml.network.NetworkRegistry;
|
//$$ import net.minecraftforge.fml.network.NetworkRegistry;
|
||||||
//#endif
|
//#endif
|
||||||
@@ -68,7 +72,11 @@ public class ReplayModRecording implements Module {
|
|||||||
new GuiHandler(core).register();
|
new GuiHandler(core).register();
|
||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
|
//#if MC>=11700
|
||||||
|
//$$ ClientPlayNetworking.registerGlobalReceiver(Restrictions.PLUGIN_CHANNEL, (client, handler, buf, resp) -> {});
|
||||||
|
//#else
|
||||||
ClientSidePacketRegistry.INSTANCE.register(Restrictions.PLUGIN_CHANNEL, (packetContext, packetByteBuf) -> {});
|
ClientSidePacketRegistry.INSTANCE.register(Restrictions.PLUGIN_CHANNEL, (packetContext, packetByteBuf) -> {});
|
||||||
|
//#endif
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
//$$ NetworkRegistry.newEventChannel(Restrictions.PLUGIN_CHANNEL, () -> "0", any -> true, any -> true);
|
//$$ NetworkRegistry.newEventChannel(Restrictions.PLUGIN_CHANNEL, () -> "0", any -> true, any -> true);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.replaymod.recording.handler;
|
|||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.utils.ModCompat;
|
import com.replaymod.core.utils.ModCompat;
|
||||||
import com.replaymod.core.utils.Utils;
|
import com.replaymod.core.utils.Utils;
|
||||||
import com.replaymod.core.versions.MCVer;
|
|
||||||
import com.replaymod.editor.gui.MarkerProcessor;
|
import com.replaymod.editor.gui.MarkerProcessor;
|
||||||
import com.replaymod.recording.ServerInfoExt;
|
import com.replaymod.recording.ServerInfoExt;
|
||||||
import com.replaymod.recording.Setting;
|
import com.replaymod.recording.Setting;
|
||||||
@@ -43,7 +42,6 @@ import static com.replaymod.core.versions.MCVer.getMinecraft;
|
|||||||
*/
|
*/
|
||||||
public class ConnectionEventHandler {
|
public class ConnectionEventHandler {
|
||||||
|
|
||||||
private static final String packetHandlerKey = "packet_handler";
|
|
||||||
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
||||||
private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
||||||
private static final MinecraftClient mc = getMinecraft();
|
private static final MinecraftClient mc = getMinecraft();
|
||||||
@@ -141,7 +139,13 @@ public class ConnectionEventHandler {
|
|||||||
metaData.setMcVersion(ReplayMod.instance.getMinecraftVersion());
|
metaData.setMcVersion(ReplayMod.instance.getMinecraftVersion());
|
||||||
packetListener = new PacketListener(core, outputPath, replayFile, metaData);
|
packetListener = new PacketListener(core, outputPath, replayFile, metaData);
|
||||||
Channel channel = ((NetworkManagerAccessor) networkManager).getChannel();
|
Channel channel = ((NetworkManagerAccessor) networkManager).getChannel();
|
||||||
channel.pipeline().addBefore(packetHandlerKey, "replay_recorder", packetListener);
|
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);
|
||||||
|
} else {
|
||||||
|
// Integrated server passes packets directly, there's no splitting, decompression or decoding
|
||||||
|
channel.pipeline().addFirst(PacketListener.RAW_RECORDER_KEY, packetListener);
|
||||||
|
}
|
||||||
|
|
||||||
recordingEventHandler = new RecordingEventHandler(packetListener);
|
recordingEventHandler = new RecordingEventHandler(packetListener);
|
||||||
recordingEventHandler.register();
|
recordingEventHandler.register();
|
||||||
|
|||||||
@@ -42,12 +42,9 @@ import java.util.Collections;
|
|||||||
|
|
||||||
//#if MC>=10904
|
//#if MC>=10904
|
||||||
import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket;
|
import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.sound.SoundCategory;
|
|
||||||
import net.minecraft.sound.SoundEvent;
|
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
@@ -91,7 +88,7 @@ public class RecordingEventHandler extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=10904
|
||||||
public void onPacket(Packet<?> packet) {
|
public void onPacket(Packet<?> packet) {
|
||||||
packetListener.save(packet);
|
packetListener.save(packet);
|
||||||
}
|
}
|
||||||
@@ -112,16 +109,6 @@ public class RecordingEventHandler extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=10904
|
//#if MC>=10904
|
||||||
public void onClientSound(SoundEvent sound, SoundCategory category,
|
|
||||||
double x, double y, double z, float volume, float pitch) {
|
|
||||||
try {
|
|
||||||
// Send to all other players in ServerWorldEventHandler#playSoundToAllNearExcept
|
|
||||||
packetListener.save(new PlaySoundS2CPacket(sound, category, x, y, z, volume, pitch));
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClientEffect(int type, BlockPos pos, int data) {
|
public void onClientEffect(int type, BlockPos pos, int data) {
|
||||||
try {
|
try {
|
||||||
// Send to all other players in ServerWorldEventHandler#playEvent
|
// Send to all other players in ServerWorldEventHandler#playEvent
|
||||||
@@ -334,99 +321,6 @@ public class RecordingEventHandler extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if FABRIC>=1
|
|
||||||
// FIXME fabric
|
|
||||||
//#else
|
|
||||||
//$$ @SubscribeEvent
|
|
||||||
//$$ public void onPickupItem(ItemPickupEvent event) {
|
|
||||||
//$$ try {
|
|
||||||
//#if MC>=11100
|
|
||||||
//#if MC>=11200
|
|
||||||
//#if MC>=11400
|
|
||||||
//$$ ItemStack stack = event.getStack();
|
|
||||||
//$$ packetListener.save(new SCollectItemPacket(
|
|
||||||
//$$ event.getOriginalEntity().getEntityId(),
|
|
||||||
//$$ event.getPlayer().getEntityId(),
|
|
||||||
//$$ event.getStack().getCount()
|
|
||||||
//$$ ));
|
|
||||||
//#else
|
|
||||||
//$$ packetListener.save(new SPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId(),
|
|
||||||
//$$ event.pickedUp.getItem().getMaxStackSize()));
|
|
||||||
//#endif
|
|
||||||
//#else
|
|
||||||
//$$ packetListener.save(new SPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId(),
|
|
||||||
//$$ event.pickedUp.getEntityItem().getMaxStackSize()));
|
|
||||||
//#endif
|
|
||||||
//#else
|
|
||||||
//$$ packetListener.save(new SPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
|
|
||||||
//#endif
|
|
||||||
//$$ } catch(Exception e) {
|
|
||||||
//$$ e.printStackTrace();
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=11400
|
|
||||||
// FIXME fabric
|
|
||||||
//#else
|
|
||||||
//$$ @SubscribeEvent
|
|
||||||
//$$ public void onSleep(PlayerSleepInBedEvent event) {
|
|
||||||
//$$ try {
|
|
||||||
//#if MC>=10904
|
|
||||||
//$$ if (event.getEntityPlayer() != mc.player) {
|
|
||||||
//$$ return;
|
|
||||||
//$$ }
|
|
||||||
//$$
|
|
||||||
//$$ packetListener.save(new SPacketUseBed(event.getEntityPlayer(), event.getPos()));
|
|
||||||
//#else
|
|
||||||
//$$ if (event.entityPlayer != mc.thePlayer) {
|
|
||||||
//$$ return;
|
|
||||||
//$$ }
|
|
||||||
//$$
|
|
||||||
//$$ packetListener.save(new S0APacketUseBed(event.entityPlayer,
|
|
||||||
//#if MC>=10800
|
|
||||||
//$$ event.pos
|
|
||||||
//#else
|
|
||||||
//$$ event.x, event.y, event.z
|
|
||||||
//#endif
|
|
||||||
//$$ ));
|
|
||||||
//#endif
|
|
||||||
//$$
|
|
||||||
//$$ wasSleeping = true;
|
|
||||||
//$$
|
|
||||||
//$$ } catch(Exception e) {
|
|
||||||
//$$ e.printStackTrace();
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
/* FIXME event not (yet?) on 1.13
|
|
||||||
@SubscribeEvent
|
|
||||||
public void enterMinecart(MinecartInteractEvent event) {
|
|
||||||
try {
|
|
||||||
//#if MC>=10904
|
|
||||||
if(event.getEntity() != mc.player) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
packetListener.save(new SPacketEntityAttach(event.getPlayer(), event.getMinecart()));
|
|
||||||
|
|
||||||
lastRiding = event.getMinecart().getEntityId();
|
|
||||||
//#else
|
|
||||||
//$$ if(event.entity != mc.thePlayer) {
|
|
||||||
//$$ return;
|
|
||||||
//$$ }
|
|
||||||
//$$
|
|
||||||
//$$ packetListener.save(new S1BPacketEntityAttach(0, event.player, event.minecart));
|
|
||||||
//$$
|
|
||||||
//$$ lastRiding = event.minecart.getEntityId();
|
|
||||||
//#endif
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) {
|
public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) {
|
||||||
//#else
|
//#else
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.replaymod.recording.mixin;
|
||||||
|
|
||||||
|
import com.replaymod.recording.packet.PacketListener;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import net.minecraft.network.ClientConnection;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
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(ClientConnection.class)
|
||||||
|
public abstract class MixinClientConnection {
|
||||||
|
@Shadow
|
||||||
|
private Channel channel;
|
||||||
|
|
||||||
|
@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
|
||||||
|
private void ensureReplayModRecorderIsAfterDecompress(CallbackInfo ci) {
|
||||||
|
ChannelHandler recorder = null;
|
||||||
|
for (Map.Entry<String, ChannelHandler> entry : channel.pipeline()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
if (PacketListener.RAW_RECORDER_KEY.equals(key)) {
|
||||||
|
recorder = entry.getValue();
|
||||||
|
}
|
||||||
|
if (PacketListener.DECOMPRESS_KEY.equals(key)) {
|
||||||
|
if (recorder != null) {
|
||||||
|
// If we've already found the recorder, then that means decompress is after recorder. That's no good
|
||||||
|
// because it means the recorder is getting compressed packets, we need to move the recorder.
|
||||||
|
channel.pipeline().remove(recorder);
|
||||||
|
channel.pipeline().addBefore(PacketListener.DECODER_KEY, PacketListener.RAW_RECORDER_KEY, recorder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,11 @@ public abstract class MixinDownloadingPackFinder implements ResourcePackRecorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ @Inject(method = "loadServerPack(Ljava/io/File;Lnet/minecraft/resource/ResourcePackSource;)Ljava/util/concurrent/CompletableFuture;", at = @At("HEAD"))
|
||||||
|
//#else
|
||||||
@Inject(method = "loadServerPack", at = @At("HEAD"))
|
@Inject(method = "loadServerPack", at = @At("HEAD"))
|
||||||
|
//#endif
|
||||||
private void recordDownloadedPack(
|
private void recordDownloadedPack(
|
||||||
File file,
|
File file,
|
||||||
//#if MC>=11600
|
//#if MC>=11600
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.replaymod.recording.handler.RecordingEventHandler;
|
|||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
|
||||||
import net.minecraft.util.profiler.Profiler;
|
import net.minecraft.util.profiler.Profiler;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvent;
|
import net.minecraft.sound.SoundEvent;
|
||||||
@@ -61,12 +62,20 @@ public abstract class MixinWorldClient extends World implements RecordingEventHa
|
|||||||
//#else
|
//#else
|
||||||
DimensionType dimensionType,
|
DimensionType dimensionType,
|
||||||
//#endif
|
//#endif
|
||||||
Supplier<Profiler> profiler, boolean bl, boolean bl2, long l) {
|
Supplier<Profiler> profiler, boolean bl, boolean bl2, long l
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ , int maxChainedNeighborUpdates
|
||||||
|
//#endif
|
||||||
|
) {
|
||||||
super(mutableWorldProperties, registryKey,
|
super(mutableWorldProperties, registryKey,
|
||||||
//#if MC<11602
|
//#if MC<11602
|
||||||
//$$ registryKey2,
|
//$$ registryKey2,
|
||||||
//#endif
|
//#endif
|
||||||
dimensionType, profiler, bl, bl2, l);
|
dimensionType, profiler, bl, bl2, l
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ , maxChainedNeighborUpdates
|
||||||
|
//#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
@@ -102,7 +111,10 @@ public abstract class MixinWorldClient extends World implements RecordingEventHa
|
|||||||
// but are instead played directly by the client. The server only sends these sounds to
|
// but are instead played directly by the client. The server only sends these sounds to
|
||||||
// other clients so we have to record them manually.
|
// other clients so we have to record them manually.
|
||||||
// E.g. Block place sounds
|
// E.g. Block place sounds
|
||||||
//#if MC>=11400
|
//#if MC>=11900
|
||||||
|
//$$ @Inject(method = "playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FFJ)V",
|
||||||
|
//$$ at = @At("HEAD"))
|
||||||
|
//#elseif MC>=11400
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
@Inject(method = "playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V",
|
@Inject(method = "playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V",
|
||||||
at = @At("HEAD"))
|
at = @At("HEAD"))
|
||||||
@@ -114,12 +126,23 @@ public abstract class MixinWorldClient extends World implements RecordingEventHa
|
|||||||
//$$ @Inject(method = "playSound(Lnet/minecraft/entity/player/EntityPlayer;DDDLnet/minecraft/util/SoundEvent;Lnet/minecraft/util/SoundCategory;FF)V",
|
//$$ @Inject(method = "playSound(Lnet/minecraft/entity/player/EntityPlayer;DDDLnet/minecraft/util/SoundEvent;Lnet/minecraft/util/SoundCategory;FF)V",
|
||||||
//$$ at = @At("HEAD"))
|
//$$ at = @At("HEAD"))
|
||||||
//#endif
|
//#endif
|
||||||
public void replayModRecording_recordClientSound(PlayerEntity player, double x, double y, double z, SoundEvent sound, SoundCategory category,
|
public void replayModRecording_recordClientSound(
|
||||||
float volume, float pitch, CallbackInfo ci) {
|
PlayerEntity player, double x, double y, double z, SoundEvent sound, SoundCategory category,
|
||||||
|
float volume, float pitch,
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ long seed,
|
||||||
|
//#endif
|
||||||
|
CallbackInfo ci) {
|
||||||
if (player == this.client.player) {
|
if (player == this.client.player) {
|
||||||
RecordingEventHandler handler = replayModRecording_getRecordingEventHandler();
|
RecordingEventHandler handler = replayModRecording_getRecordingEventHandler();
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.onClientSound(sound, category, x, y, z, volume, pitch);
|
// Sent to all other players in ServerWorldEventHandler#playSoundToAllNearExcept
|
||||||
|
handler.onPacket(new PlaySoundS2CPacket(
|
||||||
|
sound, category, x, y, z, volume, pitch
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ , seed
|
||||||
|
//#endif
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.replaymod.recording.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.entity.data.DataTracker;
|
|
||||||
import net.minecraft.network.packet.s2c.play.MobSpawnS2CPacket;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(MobSpawnS2CPacket.class)
|
|
||||||
public interface SPacketSpawnMobAccessor {
|
|
||||||
//#if MC<11500
|
//#if MC<11500
|
||||||
|
//$$ package com.replaymod.recording.mixin;
|
||||||
|
//$$
|
||||||
|
//$$ import net.minecraft.entity.data.DataTracker;
|
||||||
|
//$$ import net.minecraft.network.packet.s2c.play.MobSpawnS2CPacket;
|
||||||
|
//$$ import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
//$$ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
//$$
|
||||||
|
//$$ @Mixin(MobSpawnS2CPacket.class)
|
||||||
|
//$$ public interface SPacketSpawnMobAccessor {
|
||||||
//$$ @Accessor("dataTracker")
|
//$$ @Accessor("dataTracker")
|
||||||
//$$ DataTracker getDataManager();
|
//$$ DataTracker getDataManager();
|
||||||
//$$ @Accessor("dataTracker")
|
//$$ @Accessor("dataTracker")
|
||||||
//$$ void setDataManager(DataTracker value);
|
//$$ void setDataManager(DataTracker value);
|
||||||
|
//$$ }
|
||||||
//#endif
|
//#endif
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.replaymod.recording.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.entity.data.DataTracker;
|
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(PlayerSpawnS2CPacket.class)
|
|
||||||
public interface SPacketSpawnPlayerAccessor {
|
|
||||||
//#if MC<11500
|
//#if MC<11500
|
||||||
|
//$$ package com.replaymod.recording.mixin;
|
||||||
|
//$$
|
||||||
|
//$$ import net.minecraft.entity.data.DataTracker;
|
||||||
|
//$$ import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
|
||||||
|
//$$ import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
//$$ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
//$$
|
||||||
|
//$$ @Mixin(PlayerSpawnS2CPacket.class)
|
||||||
|
//$$ public interface SPacketSpawnPlayerAccessor {
|
||||||
//$$ @Accessor("dataTracker")
|
//$$ @Accessor("dataTracker")
|
||||||
//$$ DataTracker getDataManager();
|
//$$ DataTracker getDataManager();
|
||||||
//$$ @Accessor("dataTracker")
|
//$$ @Accessor("dataTracker")
|
||||||
//$$ void setDataManager(DataTracker value);
|
//$$ void setDataManager(DataTracker value);
|
||||||
|
//$$ }
|
||||||
//#endif
|
//#endif
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.replaymod.recording.packet;
|
|||||||
|
|
||||||
import com.github.steveice10.netty.buffer.PooledByteBufAllocator;
|
import com.github.steveice10.netty.buffer.PooledByteBufAllocator;
|
||||||
import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput;
|
import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.utils.Restrictions;
|
import com.replaymod.core.utils.Restrictions;
|
||||||
@@ -13,29 +12,27 @@ import com.replaymod.recording.ReplayModRecording;
|
|||||||
import com.replaymod.recording.Setting;
|
import com.replaymod.recording.Setting;
|
||||||
import com.replaymod.recording.gui.GuiSavingReplay;
|
import com.replaymod.recording.gui.GuiSavingReplay;
|
||||||
import com.replaymod.recording.handler.ConnectionEventHandler;
|
import com.replaymod.recording.handler.ConnectionEventHandler;
|
||||||
import com.replaymod.recording.mixin.SPacketSpawnMobAccessor;
|
|
||||||
import com.replaymod.recording.mixin.SPacketSpawnPlayerAccessor;
|
|
||||||
import com.replaymod.replaystudio.PacketData;
|
import com.replaymod.replaystudio.PacketData;
|
||||||
import com.replaymod.replaystudio.data.Marker;
|
import com.replaymod.replaystudio.data.Marker;
|
||||||
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
||||||
|
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
|
||||||
|
import com.replaymod.replaystudio.protocol.Packet;
|
||||||
import com.replaymod.replaystudio.replay.ReplayFile;
|
import com.replaymod.replaystudio.replay.ReplayFile;
|
||||||
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
||||||
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.network.ClientConnection;
|
import net.minecraft.network.ClientConnection;
|
||||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket;
|
import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.ItemPickupAnimationS2CPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.play.MobSpawnS2CPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
|
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.data.DataTracker;
|
|
||||||
import net.minecraft.network.NetworkState;
|
import net.minecraft.network.NetworkState;
|
||||||
import net.minecraft.network.Packet;
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.util.crash.CrashReport;
|
import net.minecraft.util.crash.CrashReport;
|
||||||
@@ -44,17 +41,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
//#if MC>=11400
|
|
||||||
import net.minecraft.network.packet.s2c.login.LoginSuccessS2CPacket;
|
|
||||||
//#else
|
|
||||||
//$$ import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=10904
|
|
||||||
//#else
|
|
||||||
//$$ import java.util.List;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
//#if MC<10904
|
//#if MC<10904
|
||||||
//$$ import net.minecraft.network.play.server.S46PacketSetCompressionLevel;
|
//$$ import net.minecraft.network.play.server.S46PacketSetCompressionLevel;
|
||||||
@@ -64,7 +50,6 @@ import net.minecraft.network.packet.s2c.play.ResourcePackSendS2CPacket;
|
|||||||
import net.minecraft.network.NetworkSide;
|
import net.minecraft.network.NetworkSide;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -82,12 +67,31 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
import static com.replaymod.core.versions.MCVer.*;
|
import static com.replaymod.core.versions.MCVer.*;
|
||||||
import static com.replaymod.replaystudio.util.Utils.writeInt;
|
import static com.replaymod.replaystudio.util.Utils.writeInt;
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
@ChannelHandler.Sharable // so we can re-order it
|
||||||
public class PacketListener extends ChannelInboundHandlerAdapter {
|
public class PacketListener extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
public static final String RAW_RECORDER_KEY = "replay_recorder_raw";
|
||||||
|
public static final String DECODED_RECORDER_KEY = "replay_recorder_decoded";
|
||||||
|
|
||||||
|
public static final String DECOMPRESS_KEY = "decompress";
|
||||||
|
public static final String DECODER_KEY = "decoder";
|
||||||
|
|
||||||
private static final MinecraftClient mc = getMinecraft();
|
private static final MinecraftClient mc = getMinecraft();
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
|
//#if MC>=11700
|
||||||
|
//$$ private static final int PACKET_ID_RESOURCE_PACK_SEND = getPacketId(NetworkState.PLAY, new ResourcePackSendS2CPacket("", "", false, null));
|
||||||
|
//$$ private static final int PACKET_ID_LOGIN_COMPRESSION = getPacketId(NetworkState.LOGIN, new LoginCompressionS2CPacket(0));
|
||||||
|
//#else
|
||||||
|
private static final int PACKET_ID_RESOURCE_PACK_SEND = getPacketId(NetworkState.PLAY, new ResourcePackSendS2CPacket());
|
||||||
|
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 ReplayMod core;
|
||||||
private final Path outputPath;
|
private final Path outputPath;
|
||||||
private final ReplayFile replayFile;
|
private final ReplayFile replayFile;
|
||||||
@@ -105,13 +109,6 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
private long lastSentPacket;
|
private long lastSentPacket;
|
||||||
private long timePassedWhilePaused;
|
private long timePassedWhilePaused;
|
||||||
private volatile boolean serverWasPaused;
|
private volatile boolean serverWasPaused;
|
||||||
//#if MC>=11400
|
|
||||||
private NetworkState connectionState = NetworkState.LOGIN;
|
|
||||||
private boolean loginPhase = true;
|
|
||||||
//#else
|
|
||||||
//$$ private EnumConnectionState connectionState = EnumConnectionState.PLAY;
|
|
||||||
//$$ private boolean loginPhase = false;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to keep track of the last metadata save job submitted to the save service and
|
* Used to keep track of the last metadata save job submitted to the save service and
|
||||||
@@ -159,6 +156,17 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void save(net.minecraft.network.Packet packet) {
|
||||||
|
Packet encoded;
|
||||||
|
try {
|
||||||
|
encoded = encodeMcPacket(getConnectionState(), packet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Encoding packet:", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
save(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
public void save(Packet packet) {
|
public void save(Packet packet) {
|
||||||
// If we're not on the main thread (i.e. we're on the netty thread), then we need to schedule the saving
|
// If we're not on the main thread (i.e. we're on the netty thread), then we need to schedule the saving
|
||||||
// to happen on the main thread so we can guarantee correct ordering of inbound and inject packets.
|
// to happen on the main thread so we can guarantee correct ordering of inbound and inject packets.
|
||||||
@@ -169,24 +177,12 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(packet instanceof PlayerSpawnS2CPacket) {
|
//#if MC>=11800
|
||||||
//#if MC>=10800
|
if (packet.getRegistry().getState() == State.LOGIN && packet.getId() == PACKET_ID_LOGIN_COMPRESSION) {
|
||||||
UUID uuid = ((PlayerSpawnS2CPacket) packet).getPlayerUuid();
|
|
||||||
//#else
|
|
||||||
//$$ UUID uuid = ((S0CPacketSpawnPlayer) packet).func_148948_e().getId();
|
|
||||||
//#endif
|
|
||||||
Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers()));
|
|
||||||
uuids.add(uuid.toString());
|
|
||||||
metaData.setPlayers(uuids.toArray(new String[uuids.size()]));
|
|
||||||
saveMetaData();
|
|
||||||
}
|
|
||||||
|
|
||||||
//#if MC>=10800
|
|
||||||
if (packet instanceof LoginCompressionS2CPacket) {
|
|
||||||
return; // Replay data is never compressed on the packet level
|
return; // Replay data is never compressed on the packet level
|
||||||
}
|
}
|
||||||
//#if MC<10904
|
//#if MC<10904
|
||||||
//$$ if (packet instanceof S46PacketSetCompressionLevel) {
|
//$$ if (packet.getRegistry().getState() == State.PLAY && packet.getId() == PACKET_ID_PLAY_COMPRESSION) {
|
||||||
//$$ return; // Replay data is never compressed on the packet level
|
//$$ return; // Replay data is never compressed on the packet level
|
||||||
//$$ }
|
//$$ }
|
||||||
//#endif
|
//#endif
|
||||||
@@ -199,7 +195,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
int timestamp = (int) (now - startTime - timePassedWhilePaused);
|
int timestamp = (int) (now - startTime - timePassedWhilePaused);
|
||||||
lastSentPacket = timestamp;
|
lastSentPacket = timestamp;
|
||||||
PacketData packetData = getPacketData(timestamp, packet);
|
PacketData packetData = new PacketData(timestamp, packet);
|
||||||
saveService.submit(() -> {
|
saveService.submit(() -> {
|
||||||
try {
|
try {
|
||||||
if (ReplayMod.isMinimalMode()) {
|
if (ReplayMod.isMinimalMode()) {
|
||||||
@@ -226,18 +222,27 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//#if MC>=11400
|
|
||||||
if (packet instanceof LoginSuccessS2CPacket) {
|
|
||||||
connectionState = NetworkState.PLAY;
|
|
||||||
loginPhase = false;
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
logger.error("Writing packet:", e);
|
logger.error("Writing packet:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@Override
|
||||||
public void channelInactive(ChannelHandlerContext ctx) {
|
public void channelInactive(ChannelHandlerContext ctx) {
|
||||||
metaData.setDuration((int) lastSentPacket);
|
metaData.setDuration((int) lastSentPacket);
|
||||||
@@ -324,139 +329,44 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
this.context = ctx;
|
this.context = ctx;
|
||||||
|
|
||||||
if (msg instanceof Packet) {
|
NetworkState connectionState = getConnectionState();
|
||||||
try {
|
|
||||||
Packet packet = (Packet) msg;
|
|
||||||
|
|
||||||
//#if MC>=10904
|
Packet packet = null;
|
||||||
if(packet instanceof ItemPickupAnimationS2CPacket) {
|
if (msg instanceof ByteBuf) {
|
||||||
if(mc.player != null ||
|
// for regular connections, we're expecting to observe `ByteBuf`s here
|
||||||
((ItemPickupAnimationS2CPacket) packet).getEntityId() == mc.player.getEntityId()) {
|
ByteBuf buf = (ByteBuf) msg;
|
||||||
//#else
|
if (buf.readableBytes() > 0) {
|
||||||
//$$ if(packet instanceof S0DPacketCollectItem) {
|
packet = decodePacket(connectionState, buf);
|
||||||
//$$ if(mc.thePlayer != null || ((S0DPacketCollectItem) packet).getEntityID() == mc.thePlayer.getEntityId()) {
|
|
||||||
//#endif
|
|
||||||
super.channelRead(ctx, msg);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} 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
|
||||||
|
packet = encodeMcPacket(connectionState, (net.minecraft.network.Packet) msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=10800
|
if (packet != null) {
|
||||||
if (packet instanceof ResourcePackSendS2CPacket) {
|
if (connectionState == NetworkState.PLAY && packet.getId() == PACKET_ID_RESOURCE_PACK_SEND) {
|
||||||
ClientConnection connection = ctx.pipeline().get(ClientConnection.class);
|
ClientConnection connection = ctx.pipeline().get(ClientConnection.class);
|
||||||
save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) packet));
|
save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) decodeMcPacket(packet)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//#else
|
|
||||||
//$$ if (packet instanceof S3FPacketCustomPayload) {
|
|
||||||
//$$ S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet;
|
|
||||||
//$$ if ("MC|RPack".equals(p.func_149169_c())) {
|
|
||||||
//$$ save(resourcePackRecorder.handleResourcePack(p));
|
|
||||||
//$$ return;
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC<11400
|
|
||||||
//$$ if (packet instanceof FMLProxyPacket) {
|
|
||||||
//$$ // This packet requires special handling
|
|
||||||
//#if MC>=10800
|
|
||||||
//$$ ((FMLProxyPacket) packet).toS3FPackets().forEach(this::save);
|
|
||||||
//#else
|
|
||||||
//$$ save(((FMLProxyPacket) packet).toS3FPacket());
|
|
||||||
//#endif
|
|
||||||
//$$ super.channelRead(ctx, msg);
|
|
||||||
//$$ return;
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=10800
|
|
||||||
if (packet instanceof CustomPayloadS2CPacket) {
|
|
||||||
// Forge may read from this ByteBuf and/or release it during handling
|
|
||||||
// We want to save the full thing however, so we create a copy and save that one instead of the
|
|
||||||
// original one
|
|
||||||
// Note: This isn't an issue with vanilla MC because our saving code runs on the main thread
|
|
||||||
// shortly before the vanilla handling code does. Forge however does some stuff on the netty
|
|
||||||
// threads which leads to this race condition
|
|
||||||
packet = new CustomPayloadS2CPacket(
|
|
||||||
((CustomPayloadS2CPacket) packet).getChannel(),
|
|
||||||
new PacketByteBuf(((CustomPayloadS2CPacket) packet).getData().slice().retain())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
save(packet);
|
save(packet);
|
||||||
|
|
||||||
if (packet instanceof CustomPayloadS2CPacket) {
|
|
||||||
CustomPayloadS2CPacket p = (CustomPayloadS2CPacket) packet;
|
|
||||||
if (Restrictions.PLUGIN_CHANNEL.equals(p.getChannel())) {
|
|
||||||
packet = new DisconnectS2CPacket(new LiteralText("Please update to view this replay."));
|
|
||||||
save(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(Exception e) {
|
|
||||||
logger.error("Handling packet for recording:", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.channelRead(ctx, msg);
|
super.channelRead(ctx, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=10904
|
private NetworkState getConnectionState() {
|
||||||
private <T> void DataManager_set(DataTracker dataManager, DataTracker.Entry<T> entry) {
|
ChannelHandlerContext ctx = context;
|
||||||
dataManager.startTracking(entry.getData(), entry.get());
|
if (ctx == null) {
|
||||||
|
return NetworkState.LOGIN;
|
||||||
|
}
|
||||||
|
AttributeKey<NetworkState> key = ClientConnection.ATTR_KEY_PROTOCOL;
|
||||||
|
return ctx.channel().attr(key).get();
|
||||||
}
|
}
|
||||||
//#endif
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private PacketData getPacketData(int timestamp, Packet packet) throws Exception {
|
|
||||||
//#if MC<11500
|
|
||||||
//$$ if (packet instanceof MobSpawnS2CPacket) {
|
|
||||||
//$$ MobSpawnS2CPacket p = (MobSpawnS2CPacket) packet;
|
|
||||||
//$$ SPacketSpawnMobAccessor pa = (SPacketSpawnMobAccessor) p;
|
|
||||||
//$$ if (pa.getDataManager() == null) {
|
|
||||||
//$$ pa.setDataManager(new DataTracker(null));
|
|
||||||
//$$ if (p.getTrackedValues() != null) {
|
|
||||||
//$$ Set<Integer> seen = new HashSet<>();
|
|
||||||
//#if MC>=10904
|
|
||||||
//$$ for (DataTracker.Entry<?> entry : Lists.reverse(p.getTrackedValues())) {
|
|
||||||
//$$ if (!seen.add(entry.getData().getId())) continue;
|
|
||||||
//$$ DataManager_set(pa.getDataManager(), entry);
|
|
||||||
//$$ }
|
|
||||||
//#else
|
|
||||||
//$$ for(DataWatcher.WatchableObject wo : Lists.reverse((List<DataWatcher.WatchableObject>) p.func_149027_c())) {
|
|
||||||
//$$ if (!seen.add(wo.getDataValueId())) continue;
|
|
||||||
//$$ pa.getDataManager().addObject(wo.getDataValueId(), wo.getObject());
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//$$
|
|
||||||
//$$ if (packet instanceof PlayerSpawnS2CPacket) {
|
|
||||||
//$$ PlayerSpawnS2CPacket p = (PlayerSpawnS2CPacket) packet;
|
|
||||||
//$$ SPacketSpawnPlayerAccessor pa = (SPacketSpawnPlayerAccessor) p;
|
|
||||||
//$$ if (pa.getDataManager() == null) {
|
|
||||||
//$$ pa.setDataManager(new DataTracker(null));
|
|
||||||
//$$ if (p.getTrackedValues() != null) {
|
|
||||||
//$$ Set<Integer> seen = new HashSet<>();
|
|
||||||
//#if MC>=10904
|
|
||||||
//$$ for (DataTracker.Entry<?> entry : Lists.reverse(p.getTrackedValues())) {
|
|
||||||
//$$ if (!seen.add(entry.getData().getId())) continue;
|
|
||||||
//$$ DataManager_set(pa.getDataManager(), entry);
|
|
||||||
//$$ }
|
|
||||||
//#else
|
|
||||||
//$$ for(DataWatcher.WatchableObject wo : Lists.reverse((List<DataWatcher.WatchableObject>) p.func_148944_c())) {
|
|
||||||
//$$ if (!seen.add(wo.getDataValueId())) continue;
|
|
||||||
//$$ pa.getDataManager().addObject(wo.getDataValueId(), wo.getObject());
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
|
private static Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception {
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
Integer packetId = connectionState.getPacketId(NetworkSide.CLIENTBOUND, packet);
|
Integer packetId = connectionState.getPacketId(NetworkSide.CLIENTBOUND, packet);
|
||||||
//#else
|
//#else
|
||||||
@@ -468,23 +378,55 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
ByteBuf byteBuf = Unpooled.buffer();
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
try {
|
try {
|
||||||
packet.write(new PacketByteBuf(byteBuf));
|
packet.write(new PacketByteBuf(byteBuf));
|
||||||
return new PacketData(timestamp, new com.replaymod.replaystudio.protocol.Packet(
|
return new Packet(
|
||||||
MCVer.getPacketTypeRegistry(loginPhase),
|
MCVer.getPacketTypeRegistry(connectionState == NetworkState.LOGIN),
|
||||||
packetId,
|
packetId,
|
||||||
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(
|
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(
|
||||||
byteBuf.array(),
|
byteBuf.array(),
|
||||||
byteBuf.arrayOffset(),
|
byteBuf.arrayOffset(),
|
||||||
byteBuf.readableBytes()
|
byteBuf.readableBytes()
|
||||||
)
|
)
|
||||||
));
|
);
|
||||||
} finally {
|
} finally {
|
||||||
byteBuf.release();
|
byteBuf.release();
|
||||||
|
|
||||||
//#if MC>=10800
|
|
||||||
if (packet instanceof CustomPayloadS2CPacket) {
|
|
||||||
((CustomPayloadS2CPacket) packet).getData().release();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static net.minecraft.network.Packet decodeMcPacket(Packet packet) throws IOException, IllegalAccessException, InstantiationException {
|
||||||
|
NetworkState connectionState = packet.getRegistry().getState() == State.LOGIN ? NetworkState.LOGIN : NetworkState.PLAY;
|
||||||
|
int packetId = packet.getId();
|
||||||
|
PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.wrappedBuffer(packet.getBuf().nioBuffer()));
|
||||||
|
|
||||||
|
//#if 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
|
//#endif
|
||||||
|
p.read(packetBuf);
|
||||||
|
return p;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Packet decodePacket(NetworkState connectionState, ByteBuf buf) {
|
||||||
|
PacketByteBuf packetBuf = new PacketByteBuf(buf.slice());
|
||||||
|
int packetId = packetBuf.readVarInt();
|
||||||
|
byte[] bytes = new byte[packetBuf.readableBytes()];
|
||||||
|
packetBuf.readBytes(bytes);
|
||||||
|
return new Packet(
|
||||||
|
MCVer.getPacketTypeRegistry(connectionState == NetworkState.LOGIN),
|
||||||
|
packetId,
|
||||||
|
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(bytes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,4 +468,31 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
public void setServerWasPaused() {
|
public void setServerWasPaused() {
|
||||||
this.serverWasPaused = true;
|
this.serverWasPaused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DecodedPacketListener extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
|
|
||||||
|
if (msg instanceof CustomPayloadS2CPacket) {
|
||||||
|
CustomPayloadS2CPacket packet = (CustomPayloadS2CPacket) msg;
|
||||||
|
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannel())) {
|
||||||
|
save(new DisconnectS2CPacket(new LiteralText("Please update to view this replay.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg instanceof PlayerSpawnS2CPacket) {
|
||||||
|
//#if MC>=10800
|
||||||
|
UUID uuid = ((PlayerSpawnS2CPacket) msg).getPlayerUuid();
|
||||||
|
//#else
|
||||||
|
//$$ UUID uuid = ((S0CPacketSpawnPlayer) msg).func_148948_e().getId();
|
||||||
|
//#endif
|
||||||
|
Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers()));
|
||||||
|
uuids.add(uuid.toString());
|
||||||
|
metaData.setPlayers(uuids.toArray(new String[uuids.size()]));
|
||||||
|
saveMetaData();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import net.minecraft.client.resource.ClientBuiltinResourcePackProvider;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ import java.net.MalformedURLException;
|
||||||
|
//$$ import java.net.URL;
|
||||||
|
//#endif
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
//#else
|
//#else
|
||||||
@@ -192,7 +197,18 @@ public class ResourcePackRecorder {
|
|||||||
downloadResourcePack(final int requestId, String url, String hash) {
|
downloadResourcePack(final int requestId, String url, String hash) {
|
||||||
ClientBuiltinResourcePackProvider packFinder = mc.getResourcePackDownloader();
|
ClientBuiltinResourcePackProvider packFinder = mc.getResourcePackDownloader();
|
||||||
((IDownloadingPackFinder) packFinder).setRequestCallback(file -> recordResourcePack(file, requestId));
|
((IDownloadingPackFinder) packFinder).setRequestCallback(file -> recordResourcePack(file, requestId));
|
||||||
//#if MC>=11700
|
//#if MC>=11900
|
||||||
|
//$$ try {
|
||||||
|
//$$ URL theUrl = new URL(url);
|
||||||
|
//$$ String protocol = theUrl.getProtocol();
|
||||||
|
//$$ if (!"http".equals(protocol) && !"https".equals(protocol)) {
|
||||||
|
//$$ throw new MalformedURLException("Unsupported protocol.");
|
||||||
|
//$$ }
|
||||||
|
//$$ return packFinder.download(theUrl, hash, true);
|
||||||
|
//$$ } catch (MalformedURLException e) {
|
||||||
|
//$$ return CompletableFuture.failedFuture(e);
|
||||||
|
//$$ }
|
||||||
|
//#elseif MC>=11700
|
||||||
//$$ return packFinder.download(url, hash, true);
|
//$$ return packFinder.download(url, hash, true);
|
||||||
//#else
|
//#else
|
||||||
return packFinder.download(url, hash);
|
return packFinder.download(url, hash);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
//#if MC>=11400
|
|
||||||
package com.replaymod.render;
|
package com.replaymod.render;
|
||||||
|
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
@@ -6,6 +5,7 @@ import com.replaymod.render.frame.BitmapFrame;
|
|||||||
import com.replaymod.render.rendering.Channel;
|
import com.replaymod.render.rendering.Channel;
|
||||||
import com.replaymod.render.rendering.FrameConsumer;
|
import com.replaymod.render.rendering.FrameConsumer;
|
||||||
import com.replaymod.render.utils.ByteBufferPool;
|
import com.replaymod.render.utils.ByteBufferPool;
|
||||||
|
import com.replaymod.render.utils.Lwjgl3Loader;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||||
import net.minecraft.util.crash.CrashReport;
|
import net.minecraft.util.crash.CrashReport;
|
||||||
import org.lwjgl.PointerBuffer;
|
import org.lwjgl.PointerBuffer;
|
||||||
@@ -27,6 +27,19 @@ import static org.lwjgl.util.tinyexr.TinyEXR.*;
|
|||||||
|
|
||||||
public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
||||||
|
|
||||||
|
public static FrameConsumer<BitmapFrame> create(Path outputFolder, boolean keepAlpha) {
|
||||||
|
return Lwjgl3Loader.createFrameConsumer(
|
||||||
|
EXRWriter.class,
|
||||||
|
new Class[]{ Path.class, boolean.class },
|
||||||
|
new Object[]{ outputFolder, keepAlpha }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compression is pretty slow, so we'll only use it when we've got enough cpu cores to make up for that
|
||||||
|
private static final int COMPRESSION = Runtime.getRuntime().availableProcessors() >= 8
|
||||||
|
? TINYEXR_COMPRESSIONTYPE_ZIPS
|
||||||
|
: TINYEXR_COMPRESSIONTYPE_NONE;
|
||||||
|
|
||||||
private final Path outputFolder;
|
private final Path outputFolder;
|
||||||
private final boolean keepAlpha;
|
private final boolean keepAlpha;
|
||||||
|
|
||||||
@@ -63,6 +76,7 @@ public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
|||||||
header.channels(channelInfos);
|
header.channels(channelInfos);
|
||||||
header.pixel_types(pixelTypes);
|
header.pixel_types(pixelTypes);
|
||||||
header.requested_pixel_types(requestedPixelTypes);
|
header.requested_pixel_types(requestedPixelTypes);
|
||||||
|
header.compression_type(COMPRESSION);
|
||||||
|
|
||||||
// Some readers ignore this, so we use the most expected order
|
// Some readers ignore this, so we use the most expected order
|
||||||
memASCII("A", true, channelInfos.get(0).name());
|
memASCII("A", true, channelInfos.get(0).name());
|
||||||
@@ -127,5 +141,9 @@ public class EXRWriter implements FrameConsumer<BitmapFrame> {
|
|||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//#endif
|
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ public class FFmpegWriter implements FrameConsumer<BitmapFrame> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkSize(ReadableDimension size) {
|
private void checkSize(ReadableDimension size) {
|
||||||
checkSize(size.getWidth(), size.getHeight());
|
checkSize(size.getWidth(), size.getHeight());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,4 +71,9 @@ public class PNGWriter implements FrameConsumer<BitmapFrame> {
|
|||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,13 +105,6 @@ public class RenderSettings {
|
|||||||
public boolean isSupported() {
|
public boolean isSupported() {
|
||||||
if (this == BLEND) {
|
if (this == BLEND) {
|
||||||
return RenderMethod.BLEND.isSupported();
|
return RenderMethod.BLEND.isSupported();
|
||||||
} else if (this == EXR) {
|
|
||||||
// Need LJWGL 3
|
|
||||||
//#if MC>=11400
|
|
||||||
return true;
|
|
||||||
//#else
|
|
||||||
//$$ return false;
|
|
||||||
//#endif
|
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend;
|
package com.replaymod.render.blend;
|
||||||
|
|
||||||
import com.replaymod.render.blend.data.DMaterial;
|
import com.replaymod.render.blend.data.DMaterial;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.replaymod.render.blend;
|
|||||||
|
|
||||||
import com.replaymod.render.blend.data.DScene;
|
import com.replaymod.render.blend.data.DScene;
|
||||||
import com.replaymod.render.blend.data.Serializer;
|
import com.replaymod.render.blend.data.Serializer;
|
||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
// FIXME 1.15
|
// FIXME 1.15
|
||||||
//#if MC<11500
|
//#if MC<11500
|
||||||
//$$ import com.replaymod.render.blend.exporters.ChunkExporter;
|
//$$ import com.replaymod.render.blend.exporters.ChunkExporter;
|
||||||
@@ -53,7 +53,7 @@ public class BlendState implements Exporter {
|
|||||||
this.blenderFile = BlenderFactory.newBlenderFile(file);
|
this.blenderFile = BlenderFactory.newBlenderFile(file);
|
||||||
this.factory = new BlenderFactory(blenderFile);
|
this.factory = new BlenderFactory(blenderFile);
|
||||||
|
|
||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
RenderState renderState = new RenderState(this);
|
RenderState renderState = new RenderState(this);
|
||||||
register(renderState);
|
register(renderState);
|
||||||
// FIXME 1.15
|
// FIXME 1.15
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendMeshBuilder;
|
import com.replaymod.render.blend.BlendMeshBuilder;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendMeshBuilder;
|
import com.replaymod.render.blend.BlendMeshBuilder;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.exporters;
|
package com.replaymod.render.blend.exporters;
|
||||||
|
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.mixin;
|
package com.replaymod.render.blend.mixin;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.mixin;
|
package com.replaymod.render.blend.mixin;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.mixin;
|
package com.replaymod.render.blend.mixin;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//#if MC>=10800
|
//#if MC>=10800 && MC<11900
|
||||||
package com.replaymod.render.blend.mixin;
|
package com.replaymod.render.blend.mixin;
|
||||||
|
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.replaymod.render.mixin;
|
|||||||
//#if MC>=10904
|
//#if MC>=10904
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
import com.replaymod.render.blend.BlendState;
|
import com.replaymod.render.blend.BlendState;
|
||||||
import com.replaymod.render.blend.exporters.ParticlesExporter;
|
|
||||||
import com.replaymod.render.hooks.EntityRendererHandler;
|
import com.replaymod.render.hooks.EntityRendererHandler;
|
||||||
import net.minecraft.client.particle.Particle;
|
import net.minecraft.client.particle.Particle;
|
||||||
import net.minecraft.client.particle.ParticleManager;
|
import net.minecraft.client.particle.ParticleManager;
|
||||||
@@ -12,6 +11,11 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
//#if MC>=11900
|
||||||
|
//#else
|
||||||
|
import com.replaymod.render.blend.exporters.ParticlesExporter;
|
||||||
|
//#endif
|
||||||
|
|
||||||
//#if MC>=11500
|
//#if MC>=11500
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.util.math.Quaternion;
|
import net.minecraft.util.math.Quaternion;
|
||||||
@@ -52,10 +56,12 @@ public abstract class MixinParticleManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void buildGeometry(Particle particle, VertexConsumer vertexConsumer, Camera camera, float partialTicks) {
|
private void buildGeometry(Particle particle, VertexConsumer vertexConsumer, Camera camera, float partialTicks) {
|
||||||
|
//#if MC<11900
|
||||||
BlendState blendState = BlendState.getState();
|
BlendState blendState = BlendState.getState();
|
||||||
if (blendState != null) {
|
if (blendState != null) {
|
||||||
blendState.get(ParticlesExporter.class).onRender(particle, partialTicks);
|
blendState.get(ParticlesExporter.class).onRender(particle, partialTicks);
|
||||||
}
|
}
|
||||||
|
//#endif
|
||||||
particle.buildGeometry(vertexConsumer, camera, partialTicks);
|
particle.buildGeometry(vertexConsumer, camera, partialTicks);
|
||||||
}
|
}
|
||||||
//#else
|
//#else
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
//#if MC>=11400
|
|
||||||
package com.replaymod.render.mixin;
|
|
||||||
|
|
||||||
import org.lwjgl.system.Library;
|
|
||||||
import org.lwjgl.system.Platform;
|
|
||||||
import org.lwjgl.util.tinyexr.TinyEXR;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It appears like natives on Windows cannot be loaded if one of their dependencies has already been loaded by a
|
|
||||||
* different class loader. In our case we cannot load tinyexr (on the knot class loader) because lwjgl has already
|
|
||||||
* been loaded on the system class loader.
|
|
||||||
*
|
|
||||||
* If we force the tinyexr native to load on the system class loader (by calling `Library.loadSystem(absPath)`),
|
|
||||||
* it'll load but we'll get an error when we call any of the native methods.
|
|
||||||
*
|
|
||||||
* We can't really load TinyEXR itself via the system class loader because Java does not provide any methods for
|
|
||||||
* modifying the system class path at runtime and we'd have to use JVM-specific hacks.
|
|
||||||
*
|
|
||||||
* Strangely, if we use System.loadLibrary instead of System.load, then it all just works. This mixin implements
|
|
||||||
* that workaround by finding MC's natives folder, extracting the dll from our jar into that folder and then replacing
|
|
||||||
* the context class passed to Library.loadSystem (which it uses to find dlls in jars) with Library (which is on the
|
|
||||||
* system class loader) so it cannot find the dll in our jar and falls back to using System.loadLibrary.
|
|
||||||
*/
|
|
||||||
@Mixin(value = TinyEXR.class, remap = false)
|
|
||||||
public class Mixin_WindowsWorkaroundForTinyEXRNatives {
|
|
||||||
private static final String LOAD_SYSTEM_CONSUMERS = "Lorg/lwjgl/system/Library;loadSystem(Ljava/util/function/Consumer;Ljava/util/function/Consumer;Ljava/lang/Class;Ljava/lang/String;)V";
|
|
||||||
|
|
||||||
@ModifyArg(method = "<clinit>", at = @At(value = "INVOKE", target = LOAD_SYSTEM_CONSUMERS))
|
|
||||||
private static Class<?> uglyWindowsHacks(Consumer<String> load, Consumer<String> loadLibrary, Class<?> context, String name) throws IOException {
|
|
||||||
if (Platform.get() != Platform.WINDOWS) {
|
|
||||||
return context; // works out of the box on linux
|
|
||||||
}
|
|
||||||
|
|
||||||
name = System.mapLibraryName(name);
|
|
||||||
|
|
||||||
URL libURL = context.getClassLoader().getResource(name);
|
|
||||||
if (libURL == null) {
|
|
||||||
throw new UnsatisfiedLinkError("Failed to locate library: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
String lwjglLibName = Library.JNI_LIBRARY_NAME;
|
|
||||||
if (!lwjglLibName.endsWith(".dll")) {
|
|
||||||
lwjglLibName = System.mapLibraryName(lwjglLibName);
|
|
||||||
}
|
|
||||||
|
|
||||||
String paths = System.getProperty("java.library.path");
|
|
||||||
Path nativesDir = null;
|
|
||||||
for (String dir : Pattern.compile(File.pathSeparator).split(paths)) {
|
|
||||||
Path path = Paths.get(dir);
|
|
||||||
if (Files.isReadable(path.resolve(lwjglLibName))) {
|
|
||||||
nativesDir = path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nativesDir == null) {
|
|
||||||
throw new UnsatisfiedLinkError("Failed to locate natives folder in " + paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
Path libPath = nativesDir.resolve(name);
|
|
||||||
try (InputStream source = libURL.openStream()) {
|
|
||||||
Files.copy(source, libPath, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Library.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
@@ -7,4 +7,6 @@ public interface FrameConsumer<P extends Frame> extends Closeable {
|
|||||||
|
|
||||||
void consume(Map<Channel, P> channels);
|
void consume(Map<Channel, P> channels);
|
||||||
|
|
||||||
|
boolean isParallelCapable();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.minecraft.util.crash.CrashException;
|
|||||||
import net.minecraft.util.crash.CrashReport;
|
import net.minecraft.util.crash.CrashReport;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
@@ -25,8 +26,6 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
|||||||
private final FrameCapturer<R> capturer;
|
private final FrameCapturer<R> capturer;
|
||||||
private final FrameProcessor<R, P> processor;
|
private final FrameProcessor<R, P> processor;
|
||||||
private final GlToAbsoluteDepthProcessor depthProcessor;
|
private final GlToAbsoluteDepthProcessor depthProcessor;
|
||||||
private int consumerNextFrame;
|
|
||||||
private final Object consumerLock = new Object();
|
|
||||||
private final FrameConsumer<P> consumer;
|
private final FrameConsumer<P> consumer;
|
||||||
|
|
||||||
private volatile boolean abort;
|
private volatile boolean abort;
|
||||||
@@ -35,7 +34,7 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
|||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
this.capturer = capturer;
|
this.capturer = capturer;
|
||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
this.consumer = consumer;
|
this.consumer = new ParallelSafeConsumer<>(consumer);
|
||||||
|
|
||||||
float near = 0.05f;
|
float near = 0.05f;
|
||||||
float far = getMinecraft().options.viewDistance * 16 * 4;
|
float far = getMinecraft().options.viewDistance * 16 * 4;
|
||||||
@@ -44,7 +43,6 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void run() {
|
public synchronized void run() {
|
||||||
consumerNextFrame = 0;
|
|
||||||
int processors = Runtime.getRuntime().availableProcessors();
|
int processors = Runtime.getRuntime().availableProcessors();
|
||||||
int processThreads = Math.max(1, processors - 2); // One processor for the main thread and one for ffmpeg, sorry OS :(
|
int processThreads = Math.max(1, processors - 2); // One processor for the main thread and one for ffmpeg, sorry OS :(
|
||||||
ExecutorService processService = new ThreadPoolExecutor(processThreads, processThreads,
|
ExecutorService processService = new ThreadPoolExecutor(processThreads, processThreads,
|
||||||
@@ -106,7 +104,6 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Integer frameId = null;
|
|
||||||
Map<Channel, P> processedChannels = new HashMap<>();
|
Map<Channel, P> processedChannels = new HashMap<>();
|
||||||
for (Map.Entry<Channel, R> entry : rawChannels.entrySet()) {
|
for (Map.Entry<Channel, R> entry : rawChannels.entrySet()) {
|
||||||
P processedFrame = processor.process(entry.getValue());
|
P processedFrame = processor.process(entry.getValue());
|
||||||
@@ -114,27 +111,57 @@ public class Pipeline<R extends Frame, P extends Frame> implements Runnable {
|
|||||||
depthProcessor.process((BitmapFrame) processedFrame);
|
depthProcessor.process((BitmapFrame) processedFrame);
|
||||||
}
|
}
|
||||||
processedChannels.put(entry.getKey(), processedFrame);
|
processedChannels.put(entry.getKey(), processedFrame);
|
||||||
frameId = processedFrame.getFrameId();
|
|
||||||
}
|
}
|
||||||
if (frameId == null) {
|
if (processedChannels.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (consumerLock) {
|
|
||||||
while (consumerNextFrame != frameId) {
|
|
||||||
try {
|
|
||||||
consumerLock.wait();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
consumer.consume(processedChannels);
|
consumer.consume(processedChannels);
|
||||||
consumerNextFrame++;
|
|
||||||
consumerLock.notifyAll();
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
CrashReport crashReport = CrashReport.create(t, "Processing frame");
|
CrashReport crashReport = CrashReport.create(t, "Processing frame");
|
||||||
MCVer.getMinecraft().setCrashReport(crashReport);
|
MCVer.getMinecraft().setCrashReport(crashReport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ParallelSafeConsumer<P extends Frame> implements FrameConsumer<P> {
|
||||||
|
private final FrameConsumer<P> inner;
|
||||||
|
|
||||||
|
private int nextFrame;
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
private ParallelSafeConsumer(FrameConsumer<P> inner) {
|
||||||
|
this.inner = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consume(Map<Channel, P> channels) {
|
||||||
|
if (inner.isParallelCapable()) {
|
||||||
|
inner.consume(channels);
|
||||||
|
} else {
|
||||||
|
int frameId = channels.values().iterator().next().getFrameId();
|
||||||
|
synchronized (lock) {
|
||||||
|
while (nextFrame != frameId) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inner.consume(channels);
|
||||||
|
nextFrame++;
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
inner.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,11 @@ public class Pipelines {
|
|||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return new Pipeline<>(worldRenderer, capturer, new DummyProcessor<>(), consumer);
|
return new Pipeline<>(worldRenderer, capturer, new DummyProcessor<>(), consumer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.replaymod.core.versions.MCVer;
|
|||||||
import com.replaymod.pathing.player.AbstractTimelinePlayer;
|
import com.replaymod.pathing.player.AbstractTimelinePlayer;
|
||||||
import com.replaymod.pathing.properties.TimestampProperty;
|
import com.replaymod.pathing.properties.TimestampProperty;
|
||||||
import com.replaymod.render.CameraPathExporter;
|
import com.replaymod.render.CameraPathExporter;
|
||||||
|
import com.replaymod.render.EXRWriter;
|
||||||
import com.replaymod.render.PNGWriter;
|
import com.replaymod.render.PNGWriter;
|
||||||
import com.replaymod.render.RenderSettings;
|
import com.replaymod.render.RenderSettings;
|
||||||
import com.replaymod.render.ReplayModRender;
|
import com.replaymod.render.ReplayModRender;
|
||||||
@@ -55,7 +56,6 @@ import org.lwjgl.opengl.GL11;
|
|||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
import com.replaymod.render.EXRWriter;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
//#else
|
//#else
|
||||||
@@ -129,11 +129,7 @@ public class VideoRenderer implements RenderInfo {
|
|||||||
} else {
|
} else {
|
||||||
FrameConsumer<BitmapFrame> frameConsumer;
|
FrameConsumer<BitmapFrame> frameConsumer;
|
||||||
if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.EXR) {
|
if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.EXR) {
|
||||||
//#if MC>=11400
|
frameConsumer = EXRWriter.create(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
||||||
frameConsumer = new EXRWriter(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
|
||||||
//#else
|
|
||||||
//$$ throw new UnsupportedOperationException("EXR requires LWJGL3");
|
|
||||||
//#endif
|
|
||||||
} else if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.PNG) {
|
} else if (settings.getEncodingPreset() == RenderSettings.EncodingPreset.PNG) {
|
||||||
frameConsumer = new PNGWriter(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
frameConsumer = new PNGWriter(settings.getOutputFile().toPath(), settings.isIncludeAlphaChannel());
|
||||||
} else {
|
} else {
|
||||||
@@ -141,12 +137,20 @@ public class VideoRenderer implements RenderInfo {
|
|||||||
}
|
}
|
||||||
ffmpegWriter = frameConsumer instanceof FFmpegWriter ? (FFmpegWriter) frameConsumer : null;
|
ffmpegWriter = frameConsumer instanceof FFmpegWriter ? (FFmpegWriter) frameConsumer : null;
|
||||||
FrameConsumer<BitmapFrame> previewingFrameConsumer = new FrameConsumer<BitmapFrame>() {
|
FrameConsumer<BitmapFrame> previewingFrameConsumer = new FrameConsumer<BitmapFrame>() {
|
||||||
|
private int lastFrameId = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consume(Map<Channel, BitmapFrame> channels) {
|
public void consume(Map<Channel, BitmapFrame> channels) {
|
||||||
BitmapFrame bgra = channels.get(Channel.BRGA);
|
BitmapFrame bgra = channels.get(Channel.BRGA);
|
||||||
if (bgra != null) {
|
if (bgra != null) {
|
||||||
|
synchronized (this) {
|
||||||
|
int frameId = bgra.getFrameId();
|
||||||
|
if (lastFrameId < frameId) {
|
||||||
|
lastFrameId = frameId;
|
||||||
gui.updatePreview(bgra.getByteBuffer(), bgra.getSize());
|
gui.updatePreview(bgra.getByteBuffer(), bgra.getSize());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
frameConsumer.consume(channels);
|
frameConsumer.consume(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +158,11 @@ public class VideoRenderer implements RenderInfo {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
frameConsumer.close();
|
frameConsumer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParallelCapable() {
|
||||||
|
return frameConsumer.isParallelCapable();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
this.renderingPipeline = Pipelines.newPipeline(settings.getRenderMethod(), this, previewingFrameConsumer);
|
this.renderingPipeline = Pipelines.newPipeline(settings.getRenderMethod(), this, previewingFrameConsumer);
|
||||||
}
|
}
|
||||||
|
|||||||
132
src/main/java/com/replaymod/render/utils/Lwjgl3Loader.java
Normal file
132
src/main/java/com/replaymod/render/utils/Lwjgl3Loader.java
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package com.replaymod.render.utils;
|
||||||
|
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.render.rendering.Frame;
|
||||||
|
import com.replaymod.render.rendering.FrameConsumer;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||||
|
|
||||||
|
public class Lwjgl3Loader extends URLClassLoader {
|
||||||
|
static { registerAsParallelCapable(); }
|
||||||
|
private static Path tempJarFile;
|
||||||
|
private static Lwjgl3Loader instance;
|
||||||
|
|
||||||
|
private final Set<String> implClasses = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
private Lwjgl3Loader(Path jarFile) throws IOException, ReflectiveOperationException {
|
||||||
|
super(new URL[] { jarFile.toUri().toURL() }, Lwjgl3Loader.class.getClassLoader());
|
||||||
|
|
||||||
|
// Need to use a different directory for natives than MC because native files can only be loaded once
|
||||||
|
Path nativesDir = ReplayMod.instance.folders.getCacheFolder().resolve("lwjgl-natives");
|
||||||
|
|
||||||
|
Class<?> configClass = Class.forName("org.lwjgl.system.Configuration", true, this);
|
||||||
|
Object extractDirField = configClass.getField("SHARED_LIBRARY_EXTRACT_DIRECTORY").get(null);
|
||||||
|
Method setMethod = configClass.getMethod("set", Object.class);
|
||||||
|
setMethod.invoke(extractDirField, nativesDir.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canBeSharedWithMc(String name) {
|
||||||
|
if (name.startsWith("org.lwjgl.")) {
|
||||||
|
return false; // MC may have a different version
|
||||||
|
}
|
||||||
|
for (String implClass : implClasses) {
|
||||||
|
if (name.startsWith(implClass)) {
|
||||||
|
return false; // depends on above lwjgl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
if (!canBeSharedWithMc(name)) {
|
||||||
|
synchronized (getClassLoadingLock(name)) {
|
||||||
|
Class<?> cls = findLoadedClass(name);
|
||||||
|
if (cls == null) {
|
||||||
|
cls = findClass(name);
|
||||||
|
}
|
||||||
|
if (resolve) {
|
||||||
|
resolveClass(cls);
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return super.loadClass(name, resolve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
return super.findClass(name);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
String path = name.replace('.', '/').concat(".class");
|
||||||
|
URL url = getParent().getResource(path);
|
||||||
|
if (url == null) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] bytes = IOUtils.toByteArray(url);
|
||||||
|
return defineClass(name, bytes, 0, bytes.length, (ProtectionDomain) null);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
throw new ClassNotFoundException(name, e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized Path getJarFile() throws IOException {
|
||||||
|
if (tempJarFile == null) {
|
||||||
|
Path jarFile = Files.createTempFile("replaymod-lwjgl", ".jar");
|
||||||
|
jarFile.toFile().deleteOnExit();
|
||||||
|
try (InputStream in = Lwjgl3Loader.class.getResourceAsStream("lwjgl.jar")) {
|
||||||
|
if (in == null) {
|
||||||
|
throw new IOException("Failed to find embedded lwjgl.jar file.");
|
||||||
|
}
|
||||||
|
Files.copy(in, jarFile, REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
tempJarFile = jarFile;
|
||||||
|
}
|
||||||
|
return tempJarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized Lwjgl3Loader instance() {
|
||||||
|
if (instance == null) {
|
||||||
|
try {
|
||||||
|
instance = new Lwjgl3Loader(getJarFile());
|
||||||
|
} catch (IOException | ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <P extends Frame> FrameConsumer<P> createFrameConsumer(
|
||||||
|
Class<? extends FrameConsumer<P>> implClass,
|
||||||
|
Class<?>[] parameterTypes,
|
||||||
|
Object[] args
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
Lwjgl3Loader loader = instance();
|
||||||
|
loader.implClasses.add(implClass.getName());
|
||||||
|
Class<?> realClass = Class.forName(implClass.getName(), true, loader);
|
||||||
|
Constructor<?> constructor = realClass.getConstructor(parameterTypes);
|
||||||
|
return (FrameConsumer<P>) constructor.newInstance(args);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,8 +44,6 @@ import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
|
|||||||
import net.minecraft.network.packet.s2c.play.ScreenHandlerPropertyUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ScreenHandlerPropertyUpdateS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.login.LoginSuccessS2CPacket;
|
import net.minecraft.network.packet.s2c.login.LoginSuccessS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.MobSpawnS2CPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.play.PaintingSpawnS2CPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket;
|
import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
|
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
|
||||||
@@ -59,6 +57,12 @@ import net.minecraft.util.math.Vec3d;
|
|||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
//#if MC>=11900
|
||||||
|
//#else
|
||||||
|
import net.minecraft.network.packet.s2c.play.MobSpawnS2CPacket;
|
||||||
|
import net.minecraft.network.packet.s2c.play.PaintingSpawnS2CPacket;
|
||||||
|
//#endif
|
||||||
|
|
||||||
//#if MC>=11600
|
//#if MC>=11600
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraft.network.packet.s2c.play.EntitySpawnGlobalS2CPacket;
|
//$$ import net.minecraft.network.packet.s2c.play.EntitySpawnGlobalS2CPacket;
|
||||||
@@ -472,11 +476,13 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
|
|
||||||
boolean relevantPacket = packet instanceof PlayerSpawnS2CPacket
|
boolean relevantPacket = packet instanceof PlayerSpawnS2CPacket
|
||||||
|| packet instanceof EntitySpawnS2CPacket
|
|| packet instanceof EntitySpawnS2CPacket
|
||||||
|
//#if MC<11900
|
||||||
|| packet instanceof MobSpawnS2CPacket
|
|| packet instanceof MobSpawnS2CPacket
|
||||||
|
|| packet instanceof PaintingSpawnS2CPacket
|
||||||
|
//#endif
|
||||||
//#if MC<11600
|
//#if MC<11600
|
||||||
//$$ || packet instanceof EntitySpawnGlobalS2CPacket
|
//$$ || packet instanceof EntitySpawnGlobalS2CPacket
|
||||||
//#endif
|
//#endif
|
||||||
|| packet instanceof PaintingSpawnS2CPacket
|
|
||||||
|| packet instanceof ExperienceOrbSpawnS2CPacket
|
|| packet instanceof ExperienceOrbSpawnS2CPacket
|
||||||
|| packet instanceof EntitiesDestroyS2CPacket;
|
|| packet instanceof EntitiesDestroyS2CPacket;
|
||||||
if (!relevantPacket) {
|
if (!relevantPacket) {
|
||||||
@@ -688,6 +694,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
, packet.isDebugWorld()
|
, packet.isDebugWorld()
|
||||||
, packet.isFlatWorld()
|
, packet.isFlatWorld()
|
||||||
//#endif
|
//#endif
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ , java.util.Optional.empty()
|
||||||
|
//#endif
|
||||||
);
|
);
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
@@ -744,6 +753,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
//$$ respawn.getGeneratorType(),
|
//$$ respawn.getGeneratorType(),
|
||||||
//$$ GameMode.SPECTATOR
|
//$$ GameMode.SPECTATOR
|
||||||
//#endif
|
//#endif
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ , java.util.Optional.empty()
|
||||||
|
//#endif
|
||||||
);
|
);
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=10809
|
//#if MC>=10809
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ import net.minecraft.stat.StatHandler;
|
|||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.Box;
|
import net.minecraft.util.math.Box;
|
||||||
|
|
||||||
//#if MC>=11802
|
|
||||||
//$$ import net.minecraft.tag.TagKey;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraftforge.client.event.EntityViewRenderEvent;
|
//$$ import net.minecraftforge.client.event.EntityViewRenderEvent;
|
||||||
@@ -47,7 +43,11 @@ import net.minecraft.util.math.Box;
|
|||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.fluid.Fluid;
|
import net.minecraft.fluid.Fluid;
|
||||||
|
//#if MC>=11802
|
||||||
|
//$$ import net.minecraft.tag.TagKey;
|
||||||
|
//#else
|
||||||
import net.minecraft.tag.Tag;
|
import net.minecraft.tag.Tag;
|
||||||
|
//#endif
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
//#else
|
//#else
|
||||||
@@ -547,7 +547,11 @@ public class CameraEntity
|
|||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
@Override
|
@Override
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ public void onEquipStack(EquipmentSlot slot, ItemStack stack, ItemStack itemStack) {
|
||||||
|
//#else
|
||||||
protected void onEquipStack(ItemStack itemStack_1) {
|
protected void onEquipStack(ItemStack itemStack_1) {
|
||||||
|
//#endif
|
||||||
// Suppress equip sounds
|
// Suppress equip sounds
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import static net.minecraft.util.math.MathHelper.sin;
|
|||||||
|
|
||||||
// TODO: Marius is responsible for this. Please, someone clean it up.
|
// TODO: Marius is responsible for this. Please, someone clean it up.
|
||||||
public class ClassicCameraController implements CameraController {
|
public class ClassicCameraController implements CameraController {
|
||||||
private static final double SPEED_CHANGE = 0.5;
|
private static final double LOWER_SPEED = 0.2;
|
||||||
private static final double LOWER_SPEED = 2;
|
private static final double UPPER_SPEED = 200;
|
||||||
private static final double UPPER_SPEED = 20;
|
private static final double SPEED_CHANGE = (UPPER_SPEED - LOWER_SPEED) / 20000;
|
||||||
|
|
||||||
private final CameraEntity camera;
|
private final CameraEntity camera;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import net.minecraft.client.options.KeyBinding;
|
|||||||
* Camera controller performing vanilla creative-like camera movements.
|
* Camera controller performing vanilla creative-like camera movements.
|
||||||
*/
|
*/
|
||||||
public class VanillaCameraController implements CameraController {
|
public class VanillaCameraController implements CameraController {
|
||||||
private static final int MAX_SPEED = 1000;
|
private static final int MAX_SPEED = 2000;
|
||||||
private static final int MIN_SPEED = -1000;
|
private static final int MIN_SPEED = -1000;
|
||||||
|
|
||||||
private static final Vector3f[] DIRECTIONS = new Vector3f[]{
|
private static final Vector3f[] DIRECTIONS = new Vector3f[]{
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ public class GuiHandler extends EventRegistrations {
|
|||||||
mod.getReplayHandler().getReplaySender().setReplaySpeed(0);
|
mod.getReplayHandler().getReplaySender().setReplaySpeed(0);
|
||||||
|
|
||||||
//#if MC>=11600
|
//#if MC>=11600
|
||||||
final TranslatableText BUTTON_OPTIONS = new TranslatableText("menu.options");
|
final Text BUTTON_OPTIONS = new TranslatableText("menu.options");
|
||||||
final TranslatableText BUTTON_EXIT_SERVER = new TranslatableText("menu.disconnect");
|
final Text BUTTON_EXIT_SERVER = new TranslatableText("menu.disconnect");
|
||||||
final TranslatableText BUTTON_ADVANCEMENTS = new TranslatableText("gui.advancements");
|
final Text BUTTON_ADVANCEMENTS = new TranslatableText("gui.advancements");
|
||||||
final TranslatableText BUTTON_STATS = new TranslatableText("gui.stats");
|
final Text BUTTON_STATS = new TranslatableText("gui.stats");
|
||||||
final TranslatableText BUTTON_OPEN_TO_LAN = new TranslatableText("menu.shareToLan");
|
final Text BUTTON_OPEN_TO_LAN = new TranslatableText("menu.shareToLan");
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
//$$ final String BUTTON_OPTIONS = I18n.translate("menu.options");
|
//$$ final String BUTTON_OPTIONS = I18n.translate("menu.options");
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.7.0",
|
"fabricloader": ">=0.7.0",
|
||||||
"fabric-networking-v0": "*",
|
"fabric-networking-v0": "*",
|
||||||
"fabric-keybindings-v0": "*",
|
"fabric-key-binding-api-v1": "*",
|
||||||
"fabric-resource-loader-v0": "*"
|
"fabric-resource-loader-v0": "*"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
"GuiScreenAccessor",
|
"GuiScreenAccessor",
|
||||||
"KeyBindingAccessor",
|
"KeyBindingAccessor",
|
||||||
"MinecraftAccessor",
|
"MinecraftAccessor",
|
||||||
|
//#if MC>=11900
|
||||||
|
//$$ "SimpleOptionAccessor",
|
||||||
|
//#endif
|
||||||
"TimerAccessor"
|
"TimerAccessor"
|
||||||
],
|
],
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
"EntityLivingBaseAccessor",
|
"EntityLivingBaseAccessor",
|
||||||
"IntegratedServerAccessor",
|
"IntegratedServerAccessor",
|
||||||
"NetworkManagerAccessor",
|
"NetworkManagerAccessor",
|
||||||
"SPacketSpawnMobAccessor",
|
"MixinClientConnection",
|
||||||
"SPacketSpawnPlayerAccessor",
|
//#if MC<11500
|
||||||
|
//$$ "SPacketSpawnMobAccessor",
|
||||||
|
//$$ "SPacketSpawnPlayerAccessor",
|
||||||
|
//#endif
|
||||||
"MixinServerInfo",
|
"MixinServerInfo",
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
"MixinDownloadingPackFinder",
|
"MixinDownloadingPackFinder",
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
"ItemRendererAccessor",
|
"ItemRendererAccessor",
|
||||||
//#endif
|
//#endif
|
||||||
"ParticleAccessor",
|
"ParticleAccessor",
|
||||||
|
//#if MC<11900
|
||||||
"MixinRenderGlobal",
|
"MixinRenderGlobal",
|
||||||
"MixinRenderItem",
|
"MixinRenderItem",
|
||||||
"MixinRenderLivingBase",
|
"MixinRenderLivingBase",
|
||||||
"MixinRenderManager"
|
"MixinRenderManager"
|
||||||
//#endif
|
//#endif
|
||||||
|
//#endif
|
||||||
],
|
],
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"minVersion": "0.6.11",
|
"minVersion": "0.6.11",
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
//#endif
|
//#endif
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
"Mixin_PreserveDepthDuringHandRendering",
|
"Mixin_PreserveDepthDuringHandRendering",
|
||||||
"Mixin_WindowsWorkaroundForTinyEXRNatives",
|
|
||||||
//#endif
|
//#endif
|
||||||
"GameRendererAccessor",
|
"GameRendererAccessor",
|
||||||
"MainWindowAccessor",
|
"MainWindowAccessor",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.6.5
|
2.6.6
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ net.minecraft.potion.EffectInstance net.minecraft.potion.PotionEffect
|
|||||||
net.minecraft.client.gui.screen.AddServerScreen net.minecraft.client.gui.GuiScreenAddServer
|
net.minecraft.client.gui.screen.AddServerScreen net.minecraft.client.gui.GuiScreenAddServer
|
||||||
net.minecraft.resources.AbstractResourcePack net.minecraft.client.resources.AbstractResourcePack
|
net.minecraft.resources.AbstractResourcePack net.minecraft.client.resources.AbstractResourcePack
|
||||||
net.minecraft.resources.FolderPack net.minecraft.client.resources.FolderResourcePack
|
net.minecraft.resources.FolderPack net.minecraft.client.resources.FolderResourcePack
|
||||||
|
net.minecraft.resources.IResource net.minecraft.client.resources.IResource
|
||||||
|
net.minecraft.resources.IResourceManager net.minecraft.client.resources.IResourceManager
|
||||||
net.minecraft.client.resources.DownloadingPackFinder net.minecraft.client.resources.ResourcePackRepository
|
net.minecraft.client.resources.DownloadingPackFinder net.minecraft.client.resources.ResourcePackRepository
|
||||||
net.minecraft.client.renderer.chunk.ChunkRenderTask net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator
|
net.minecraft.client.renderer.chunk.ChunkRenderTask net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator
|
||||||
net.minecraft.client.settings.AbstractOption net.minecraft.client.settings.GameSettings.Options
|
net.minecraft.client.settings.AbstractOption net.minecraft.client.settings.GameSettings.Options
|
||||||
|
|||||||
60
versions/1.15.2/src/main/resources/fabric.mod.json
Normal file
60
versions/1.15.2/src/main/resources/fabric.mod.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "replaymod",
|
||||||
|
"version": "${version}",
|
||||||
|
|
||||||
|
"name": "Replay Mod",
|
||||||
|
"description": "A Mod which allows you to record, replay and share your Minecraft experience.",
|
||||||
|
"authors": [
|
||||||
|
"CrushedPixel",
|
||||||
|
"johni0702"
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"homepage": "https://replaymod.com/",
|
||||||
|
"sources": "https://github.com/ReplayMod/ReplayMod"
|
||||||
|
},
|
||||||
|
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"icon": "assets/replaymod/favicon_logo.png",
|
||||||
|
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"client": [
|
||||||
|
"com.replaymod.core.ReplayModBackend"
|
||||||
|
],
|
||||||
|
"modmenu": [
|
||||||
|
"com.replaymod.core.gui.ModMenuApiImpl"
|
||||||
|
],
|
||||||
|
"frex_flawless_frames": [
|
||||||
|
"com.replaymod.render.utils.FlawlessFrames::registerConsumer"
|
||||||
|
],
|
||||||
|
"preLaunch": [
|
||||||
|
"com.replaymod.core.DummyChainLoadEntryPoint"
|
||||||
|
],
|
||||||
|
"mm:early_risers": [
|
||||||
|
"com.replaymod.core.ReplayModMMLauncher"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mixins": [
|
||||||
|
"mixins.jgui.json",
|
||||||
|
"mixins.nonmmlauncher.replaymod.json"
|
||||||
|
],
|
||||||
|
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.7.0",
|
||||||
|
"fabric-networking-v0": "*",
|
||||||
|
"fabric-keybindings-v0": "*",
|
||||||
|
"fabric-resource-loader-v0": "*"
|
||||||
|
},
|
||||||
|
|
||||||
|
"conflicts": {
|
||||||
|
"iris": "<1.1.3"
|
||||||
|
},
|
||||||
|
|
||||||
|
"custom": {
|
||||||
|
"mm:early_risers": [
|
||||||
|
"com.replaymod.core.ReplayModMMLauncher"
|
||||||
|
],
|
||||||
|
"modmenu:clientsideOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
60
versions/1.17/src/main/resources/fabric.mod.json
Normal file
60
versions/1.17/src/main/resources/fabric.mod.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "replaymod",
|
||||||
|
"version": "${version}",
|
||||||
|
|
||||||
|
"name": "Replay Mod",
|
||||||
|
"description": "A Mod which allows you to record, replay and share your Minecraft experience.",
|
||||||
|
"authors": [
|
||||||
|
"CrushedPixel",
|
||||||
|
"johni0702"
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"homepage": "https://replaymod.com/",
|
||||||
|
"sources": "https://github.com/ReplayMod/ReplayMod"
|
||||||
|
},
|
||||||
|
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"icon": "assets/replaymod/favicon_logo.png",
|
||||||
|
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"client": [
|
||||||
|
"com.replaymod.core.ReplayModBackend"
|
||||||
|
],
|
||||||
|
"modmenu": [
|
||||||
|
"com.replaymod.core.gui.ModMenuApiImpl"
|
||||||
|
],
|
||||||
|
"frex_flawless_frames": [
|
||||||
|
"com.replaymod.render.utils.FlawlessFrames::registerConsumer"
|
||||||
|
],
|
||||||
|
"preLaunch": [
|
||||||
|
"com.replaymod.core.DummyChainLoadEntryPoint"
|
||||||
|
],
|
||||||
|
"mm:early_risers": [
|
||||||
|
"com.replaymod.core.ReplayModMMLauncher"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mixins": [
|
||||||
|
"mixins.jgui.json",
|
||||||
|
"mixins.nonmmlauncher.replaymod.json"
|
||||||
|
],
|
||||||
|
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.7.0",
|
||||||
|
"fabric-networking-api-v1": "*",
|
||||||
|
"fabric-key-binding-api-v1": "*",
|
||||||
|
"fabric-resource-loader-v0": "*"
|
||||||
|
},
|
||||||
|
|
||||||
|
"conflicts": {
|
||||||
|
"iris": "<1.1.3"
|
||||||
|
},
|
||||||
|
|
||||||
|
"custom": {
|
||||||
|
"mm:early_risers": [
|
||||||
|
"com.replaymod.core.ReplayModMMLauncher"
|
||||||
|
],
|
||||||
|
"modmenu:clientsideOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
0
versions/1.19/.gitkeep
Normal file
0
versions/1.19/.gitkeep
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.replaymod.core.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.option.SimpleOption;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(SimpleOption.class)
|
||||||
|
public interface SimpleOptionAccessor<T> {
|
||||||
|
@Accessor("value")
|
||||||
|
void setRawValue(T value);
|
||||||
|
}
|
||||||
4
versions/mapping-fabric-1.19-1.18.2.txt
Normal file
4
versions/mapping-fabric-1.19-1.18.2.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# FIXME remap should be able to map these without us explicitly declaring them
|
||||||
|
net.minecraft.client.render.WorldRenderer fullUpdateFuture field_34808
|
||||||
|
net.minecraft.client.render.WorldRenderer updateFinished field_34809
|
||||||
|
net.minecraft.client.render.WorldRenderer shouldUpdate field_34810
|
||||||
Reference in New Issue
Block a user