From 3ab47771b5b6ab61cb8de33a41425ce459a127d1 Mon Sep 17 00:00:00 2001 From: Hadron67 <604700341@qq.com> Date: Sun, 9 Aug 2020 19:07:49 +0800 Subject: [PATCH] use another way to change recording view distance --- build.gradle | 3 +- gradle.properties | 3 +- .../com/hadroncfy/sreplay/SReplayMod.java | 39 ++++++----- .../MultipleOrdinalFieldInjectionPoint.java | 37 ++++++++++ .../mixin/MixinThreadedAnvilChunkStorage.java | 67 +++++++++++-------- .../sreplay/recording/Photographer.java | 28 +++----- 6 files changed, 113 insertions(+), 64 deletions(-) create mode 100644 src/main/java/com/hadroncfy/sreplay/asm/MultipleOrdinalFieldInjectionPoint.java diff --git a/build.gradle b/build.gradle index c77ec8e..81e4bde 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,7 @@ def shadeExclusions = { } shadowJar { + // XXX: exclude a lot of things by hand... from project.configurations.shade configurations = [ project.configurations.shade @@ -51,7 +52,7 @@ dependencies { // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. // You may need to force-disable transitiveness on them. - shade "com.github.ReplayMod.ReplayStudio:${project.minecraft_version}:be6a680", shadeExclusions + shade "com.github.ReplayMod.ReplayStudio:${project.minecraft_version}:${project.replaystudio_commit}", shadeExclusions compileOnly "com.google.code.gson:gson:2.8.6" } diff --git a/gradle.properties b/gradle.properties index ce9a97b..aeb99bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,10 +9,11 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.9.0+build.204 # Mod Properties - mod_version = 0.2.1 + mod_version = 0.2.2 maven_group = test archives_base_name = sreplay # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api #fabric_version=0.3.0-pre+build.166 + replaystudio_commit = be6a680 \ No newline at end of file diff --git a/src/main/java/com/hadroncfy/sreplay/SReplayMod.java b/src/main/java/com/hadroncfy/sreplay/SReplayMod.java index d19d90a..ae1b866 100644 --- a/src/main/java/com/hadroncfy/sreplay/SReplayMod.java +++ b/src/main/java/com/hadroncfy/sreplay/SReplayMod.java @@ -18,6 +18,7 @@ import java.util.List; import com.google.gson.JsonParseException; +import com.hadroncfy.sreplay.asm.MultipleOrdinalFieldInjectionPoint; import com.hadroncfy.sreplay.command.SReplayCommand; import com.hadroncfy.sreplay.config.Config; import com.hadroncfy.sreplay.config.Formats; @@ -26,6 +27,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.injection.InjectionPoint; public class SReplayMod implements ModInitializer { @@ -35,15 +37,15 @@ public class SReplayMod implements ModInitializer { public static final SReplayCommand SREPLAY_COMMAND = new SReplayCommand(); - public static Photographer getFake(MinecraftServer server, String name){ + public static Photographer getFake(MinecraftServer server, String name) { ServerPlayerEntity player = server.getPlayerManager().getPlayer(name); - if (player != null && player instanceof Photographer){ + if (player != null && player instanceof Photographer) { return (Photographer) player; } return null; } - public static Server getServer(){ + public static Server getServer() { return downloadServer; } @@ -55,50 +57,57 @@ public static List listRecordings() { public static void loadConfig() throws IOException, JsonParseException { File dir = new File("config"); - if (!dir.exists()){ + if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, "sreplay.json"); - if (file.exists()){ - try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)){ + if (file.exists()) { + try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { config = Config.GSON.fromJson(reader, Config.class); } - } - else { + } else { config = new Config(); } - try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)){ + try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { writer.write(Config.GSON.toJson(config)); } } - public static Config getConfig(){ + public static Config getConfig() { return config; } - public static Formats getFormats(){ + public static Formats getFormats() { return config.formats; } @Override public void onInitialize() { + InjectionPoint.register(MultipleOrdinalFieldInjectionPoint.class); + try { SReplayMod.loadConfig(); Lang.load("zh_cn"); LOGGER.info("SReplay: Initialzed"); - } - catch(Throwable e) { + } catch (Throwable e) { LOGGER.error("Exception initializing mod: " + e); e.printStackTrace(); } - if (config == null){ + if (config == null) { config = new Config(); } - if (!config.savePath.exists()){ + if (!config.savePath.exists()) { config.savePath.mkdirs(); } + + try { + LOGGER.info("!!!! test: {}", + Class.forName("com.hadroncfy.sreplay.asm.MultipleOrdinalFieldInjectionPoint").getName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } } } \ No newline at end of file diff --git a/src/main/java/com/hadroncfy/sreplay/asm/MultipleOrdinalFieldInjectionPoint.java b/src/main/java/com/hadroncfy/sreplay/asm/MultipleOrdinalFieldInjectionPoint.java new file mode 100644 index 0000000..99c2187 --- /dev/null +++ b/src/main/java/com/hadroncfy/sreplay/asm/MultipleOrdinalFieldInjectionPoint.java @@ -0,0 +1,37 @@ +package com.hadroncfy.sreplay.asm; + +import java.util.HashSet; +import java.util.Set; + +import org.spongepowered.asm.mixin.injection.InjectionPoint.AtCode; +import org.spongepowered.asm.mixin.injection.points.BeforeFieldAccess; +import org.spongepowered.asm.mixin.injection.struct.InjectionPointData; + +@AtCode("sreplay_MultipleOrdinalField") +public class MultipleOrdinalFieldInjectionPoint extends BeforeFieldAccess { + private final Set ordinals = new HashSet<>(); + + public MultipleOrdinalFieldInjectionPoint(InjectionPointData data) { + super(data); + for (String part: data.get("ordinals", "").split(",")){ + part = part.trim(); + try { + if (part.indexOf("..") != -1){ + String[] s = part.split("\\.\\."); + for (int i = Integer.parseInt(s[0]); i <= Integer.parseInt(s[1]); i++){ + ordinals.add(i); + } + } + else { + ordinals.add(Integer.parseInt(part)); + } + } catch(NumberFormatException e){ + } + } + } + + @Override + protected boolean matchesOrdinal(int ordinal) { + return ordinals.contains(ordinal); + } +} \ No newline at end of file diff --git a/src/main/java/com/hadroncfy/sreplay/mixin/MixinThreadedAnvilChunkStorage.java b/src/main/java/com/hadroncfy/sreplay/mixin/MixinThreadedAnvilChunkStorage.java index 2ff63cb..17bafcc 100644 --- a/src/main/java/com/hadroncfy/sreplay/mixin/MixinThreadedAnvilChunkStorage.java +++ b/src/main/java/com/hadroncfy/sreplay/mixin/MixinThreadedAnvilChunkStorage.java @@ -1,12 +1,8 @@ package com.hadroncfy.sreplay.mixin; -import java.util.function.Predicate; -import java.util.stream.Stream; -import com.hadroncfy.sreplay.interfaces.IChunkSender; +import com.hadroncfy.sreplay.recording.Photographer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -16,40 +12,57 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.chunk.WorldChunk; import static com.hadroncfy.sreplay.recording.Photographer.getRealViewDistance; @Mixin(ThreadedAnvilChunkStorage.class) -public abstract class MixinThreadedAnvilChunkStorage implements IChunkSender { - private static final Logger LOGGER = LogManager.getLogger(); +public abstract class MixinThreadedAnvilChunkStorage { @Shadow private int watchDistance; @Shadow private static int getChebyshevDistance(ChunkPos pos, ServerPlayerEntity player, boolean useCameraPosition){ return 0; } - @Shadow - abstract void sendChunkDataPackets(ServerPlayerEntity player, Packet[] packets, WorldChunk chunk); + @Redirect(method = "method_18707", at = @At( + value = "FIELD", + target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;watchDistance:I" + )) + private int getWatchDistance$lambda0$getPlayersWatchingChunk(ThreadedAnvilChunkStorage cela, ChunkPos pos, boolean bl, ServerPlayerEntity player){ + return getRealViewDistance(player, watchDistance); + } - @Override - public void sendChunk(ServerPlayerEntity player, WorldChunk chunk) { - Packet[] packets = new Packet[2]; - sendChunkDataPackets(player, packets, chunk); + @Redirect(method = "method_17219", at = @At( + value = "FIELD", + target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;watchDistance:I" + )) + private int getWatchDistance$lambda0$setViewDistance(ThreadedAnvilChunkStorage cela, ChunkPos pos, int previousViewDistance, Packet[] packets, ServerPlayerEntity player){ + return getRealViewDistance(player, watchDistance); + } + + @Redirect(method = "updateCameraPosition", at = @At( + value = "sreplay_MultipleOrdinalField", + target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;watchDistance:I", + args = { + "ordinals=2, 3, 6, 8..11" + } + )) + private int getPreviousWatchDistance(ThreadedAnvilChunkStorage cela, ServerPlayerEntity player){ + if (player instanceof Photographer){ + return ((Photographer)player).getCurrentWatchDistance(); + } + return watchDistance; } - @Redirect(method = "getPlayersWatchingChunk", at = @At( - value = "INVOKE", - target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;" + @Redirect(method = "updateCameraPosition", at = @At( + value = "sreplay_MultipleOrdinalField", + target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;watchDistance:I", + args = { + "ordinals=4, 5, 7, 12..15" + } )) - private Stream filterPlayers(Stream stream, Predicate entity, ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge){ - return stream.filter(player -> { - int d = getRealViewDistance(player, watchDistance); - int i = getChebyshevDistance(chunkPos, player, true); - if (i > d) { - return false; - } else { - return !onlyOnWatchDistanceEdge || i == d; - } - }); + private int getCurrentWatchDistance(ThreadedAnvilChunkStorage cela, ServerPlayerEntity player){ + if (player instanceof Photographer){ + return ((Photographer)player).getRecordingParam().watchDistance; + } + return watchDistance; } } \ No newline at end of file diff --git a/src/main/java/com/hadroncfy/sreplay/recording/Photographer.java b/src/main/java/com/hadroncfy/sreplay/recording/Photographer.java index fd338c2..7bc31e5 100644 --- a/src/main/java/com/hadroncfy/sreplay/recording/Photographer.java +++ b/src/main/java/com/hadroncfy/sreplay/recording/Photographer.java @@ -122,17 +122,14 @@ public void setSaveName(String name){ } private void setWatchDistance(int distance){ + ServerChunkManager chunkManager = getServerWorld().getChunkManager(); recorder.onPacket(new ChunkLoadDistanceS2CPacket(distance)); - int cx = MathHelper.floor(x) >> 4, cz = MathHelper.floor(z) >> 4; - ServerChunkManager chunkManager = (ServerChunkManager) world.getChunkManager(); - for (int i = -distance; i <= distance; i++){ - for (int j = -distance; j <= distance; j++){ - WorldChunk chunk = chunkManager.method_21730(cx + i, cz + j); - if (chunk != null){ - ((IChunkSender)chunkManager.threadedAnvilChunkStorage).sendChunk(this, chunk); - } - } - } + chunkManager.updateCameraPosition(this); + currentWatchDistance = rparam.watchDistance; + } + + public int getCurrentWatchDistance(){ + return currentWatchDistance; } private void connect() throws IOException{ @@ -164,7 +161,6 @@ public void syncParams(){ updatePause(); if (currentWatchDistance != rparam.watchDistance){ setWatchDistance(rparam.watchDistance); - currentWatchDistance = rparam.watchDistance; } } } @@ -264,15 +260,7 @@ public Text method_14206() { size += "/" + rparam.sizeLimit + "M"; } Text ret = new LiteralText(getGameProfile().getName()).setStyle(new Style().setItalic(true).setColor(Formatting.AQUA)); - if (rparam.watchDistance != server.getPlayerManager().getViewDistance()){ - ret.append(new LiteralText(" (" + rparam.watchDistance + ")").setStyle(new Style().setColor(Formatting.GRAY))); - } - if (rparam.autoReconnect){ - ret.append(new LiteralText(" [R]").setStyle(new Style().setItalic(false).setColor(Formatting.DARK_PURPLE))); - } - if (rparam.autoPause){ - ret.append(new LiteralText("[P]").setStyle(new Style().setItalic(false).setColor(Formatting.GOLD))); - } + ret.append(new LiteralText(" " + time).setStyle(new Style().setItalic(false).setColor(Formatting.GREEN))) .append(new LiteralText(" " + size).setStyle(new Style().setItalic(false).setColor(Formatting.GREEN))); return ret;