Skip to content

Commit

Permalink
new: add ext_render_distance_v1 protocol for 127+ RD multiplayer
Browse files Browse the repository at this point in the history
  • Loading branch information
ishland committed Feb 16, 2024
1 parent ad4660d commit 4a0a320
Show file tree
Hide file tree
Showing 23 changed files with 360 additions and 4 deletions.
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ configure (allprojects - project(":tests")) {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

[
"fabric-networking-api-v1"
].forEach {
modCompileOnly(fabricApi.module(it, "${project.fabric_version}"))
}
}

loom {
Expand Down Expand Up @@ -123,7 +129,6 @@ configure (allprojects - project(":tests")) {
implementation "org.threadly:threadly:${threadly_version}"
implementation "net.objecthunter:exp4j:${exp4j_version}"
implementation "com.ishland.flowsched:flowsched"

}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ishland.c2me.base.common;

public class C2MEConstants {

public static final String MODID = "c2me";
public static final String EXT_RENDER_DISTANCE_ID = "ext_render_distance_v1"; // consists of one VarInt

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ishland.c2me.base.common.config;

import net.fabricmc.loader.api.FabricLoader;

public class ModStatuses {

public static final boolean fabric_networking_api_v1 = FabricLoader.getInstance().isModLoaded("fabric-networking-api-v1");

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ishland.c2me.base.common.network;

import com.ishland.c2me.base.common.C2MEConstants;
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.api.networking.v1.PacketType;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;

public record ExtRenderDistance(int renderDistance) implements FabricPacket {

public static PacketType<ExtRenderDistance> TYPE = PacketType.create(
new Identifier(C2MEConstants.MODID, C2MEConstants.EXT_RENDER_DISTANCE_ID),
ExtRenderDistance::new
);

public ExtRenderDistance(PacketByteBuf buf) {
this(buf.readVarInt());
}

@Override
public void write(PacketByteBuf buf) {
buf.writeVarInt(renderDistance);
}

@Override
public PacketType<?> getType() {
return TYPE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ishland.c2me.base.mixin.access;

import net.minecraft.network.packet.c2s.common.SyncedClientOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(SyncedClientOptions.class)
public interface ISyncedClientOptions {

@Mutable
@Accessor
void setViewDistance(int viewDistance);

}
1 change: 1 addition & 0 deletions c2me-base/src/main/resources/c2me-base.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"access.IStructurePiece",
"access.IStructureStart",
"access.IStructureWeightSampler",
"access.ISyncedClientOptions",
"access.IThreadedAnvilChunkStorage",
"access.IVersionedChunkStorage",
"access.IWeightedList",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.ishland.c2me.client.uncapvd.common;

import com.ishland.c2me.base.common.network.ExtRenderDistance;
import net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.BooleanSupplier;

public class ClientExtNetworking {

public static final Logger LOGGER = LoggerFactory.getLogger("C2ME ClientExtNetworking");

public static void sendViewDistance(int viewDistance) {
if (!MinecraftClient.getInstance().isOnThread()) {
new IllegalStateException("Tried to send packet not on client thread!").printStackTrace();
return;
}
if (catchExceptions(() -> ClientPlayNetworking.canSend(ExtRenderDistance.TYPE))) {
LOGGER.info("Changing view distance to {} (play stage)", viewDistance);
ClientPlayNetworking.send(new ExtRenderDistance(viewDistance));
return;
}
if (catchExceptions(() -> ClientConfigurationNetworking.canSend(ExtRenderDistance.TYPE))) {
LOGGER.info("Changing view distance to {} (config stage)", viewDistance);
ClientConfigurationNetworking.send(new ExtRenderDistance(viewDistance));
return;
}
}

private static boolean catchExceptions(BooleanSupplier supplier) {
try {
return supplier.getAsBoolean();
} catch (IllegalStateException e) {
return false; // not connected
}
}

public static void registerListeners() {
C2SPlayChannelEvents.REGISTER.register((handler, sender, client, channels) -> {
if (channels.contains(ExtRenderDistance.TYPE.getId())) {
if (Config.enableExtRenderDistanceProtocol) {
LOGGER.info("Joined server with {} support", ExtRenderDistance.TYPE.getId());
MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().options.sendClientSettings());
} else {
LOGGER.info("Server supports {} but it is disabled in config", ExtRenderDistance.TYPE.getId());
}
}
});
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.ishland.c2me.client.uncapvd.common;

import com.ishland.c2me.base.common.C2MEConstants;
import com.ishland.c2me.base.common.config.ConfigSystem;
import com.ishland.c2me.base.common.config.ModStatuses;
import io.netty.util.internal.PlatformDependent;

public class Config {
Expand All @@ -10,6 +12,18 @@ public class Config {
.comment("Max render distance allowed in game options")
.getLong(getDefaultMaxVD(), getDefaultMaxVD(), ConfigSystem.LongChecks.POSITIVE_VALUES_ONLY);

public static final boolean enableExtRenderDistanceProtocol = new ConfigSystem.ConfigAccessor()
.key("clientSideConfig.modifyMaxVDConfig.enableExtRenderDistanceProtocol")
.comment("""
Enable client-side support for extended render distance protocol (c2me:%s)
This allows requesting render distances higher than 127 chunks from the server
Requires Fabric API (currently %s)
Note: The server must advertise support this protocol for this to work
""".formatted(C2MEConstants.EXT_RENDER_DISTANCE_ID, ModStatuses.fabric_networking_api_v1 ? "available" : "unavailable"))
.getBoolean(true, false);

private static int getDefaultMaxVD() {
final double memoryInGiB = memoryInGiB();
if (memoryInGiB < 1.0) return 16;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ishland.c2me.client.uncapvd.common;

import com.ishland.c2me.base.common.config.ModStatuses;
import net.fabricmc.api.ClientModInitializer;

public class UncapVDInitializer implements ClientModInitializer {

@Override
public void onInitializeClient() {
if (ModStatuses.fabric_networking_api_v1) {
ClientExtNetworking.registerListeners();
}
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.ishland.c2me.client.uncapvd.mixin;

import com.ishland.c2me.base.common.config.ModStatuses;
import com.ishland.c2me.client.uncapvd.common.ClientExtNetworking;
import com.ishland.c2me.client.uncapvd.common.Config;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.network.packet.c2s.common.SyncedClientOptions;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -11,15 +15,28 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(GameOptions.class)
public class MixinGameOptions {
public abstract class MixinGameOptions {

@Shadow @Final private SimpleOption<Integer> viewDistance;

@Shadow protected MinecraftClient client;

@Shadow public abstract SyncedClientOptions getSyncedOptions();

@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/GameOptions;load()V", shift = At.Shift.BEFORE))
private void onInit(CallbackInfo ci) {
final SimpleOption.ValidatingIntSliderCallbacks callbacks = new SimpleOption.ValidatingIntSliderCallbacks(2, Config.maxViewDistance);
((ISimpleOption<Integer>) this.viewDistance).setCallbacks(callbacks);
((ISimpleOption<Integer>) this.viewDistance).setCodec(callbacks.codec());
}

@Inject(method = "sendClientSettings", at = @At("HEAD"))
private void beforeSendSettings(CallbackInfo ci) {
if (!Config.enableExtRenderDistanceProtocol) return;
if (!ModStatuses.fabric_networking_api_v1) return;

ClientExtNetworking.sendViewDistance(this.getSyncedOptions().viewDistance());

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ishland.c2me.client.uncapvd.mixin;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.network.packet.c2s.common.SyncedClientOptions;
import net.minecraft.util.math.MathHelper;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(SyncedClientOptions.class)
public class MixinSyncedClientOptions {

@WrapOperation(method = "write", at = @At(value = "FIELD", target = "Lnet/minecraft/network/packet/c2s/common/SyncedClientOptions;viewDistance:I", opcode = Opcodes.GETFIELD))
private int wrapRenderDistance(SyncedClientOptions instance, Operation<Integer> original) {
return MathHelper.clamp(instance.viewDistance(), 2, Byte.MAX_VALUE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"mixins": [
"ISimpleOption",
"MixinGameOptions",
"MixinSodiumUserConfigCategories"
"MixinSodiumUserConfigCategories",
"MixinSyncedClientOptions"
]
}
5 changes: 5 additions & 0 deletions c2me-client-uncapvd/src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
"fabricloader": "*",
"c2me-base": "*"
},
"entrypoints": {
"client": [
"com.ishland.c2me.client.uncapvd.common.UncapVDInitializer"
]
},

"authors": [
"RelativityMC",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.ishland.c2me.notickvd;

import com.ishland.c2me.base.common.ModuleMixinPlugin;
import com.ishland.c2me.notickvd.common.Config;

public class MixinPlugin extends ModuleMixinPlugin {

@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (!super.shouldApplyMixin(targetClassName, mixinClassName)) return false;

if (mixinClassName.startsWith("com.ishland.c2me.notickvd.mixin.ext_render_distance.")) {
return Config.enableExtRenderDistanceProtocol;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.ishland.c2me.notickvd.common;

import com.ishland.c2me.base.common.C2MEConstants;
import com.ishland.c2me.base.common.GlobalExecutors;
import com.ishland.c2me.base.common.config.ConfigSystem;
import com.ishland.c2me.base.common.config.ModStatuses;

public class Config {

Expand All @@ -17,6 +19,16 @@ public class Config {
" This may fix some mod compatibility issues")
.getBoolean(true, true);

public static final boolean enableExtRenderDistanceProtocol = new ConfigSystem.ConfigAccessor()
.key("noTickViewDistance.enableExtRenderDistanceProtocol")
.comment("""
Enable server-side support for extended render distance protocol (c2me:%s)
This allows requesting render distances higher than 127 chunks from the server
Requires Fabric API (currently %s)
""".formatted(C2MEConstants.EXT_RENDER_DISTANCE_ID, ModStatuses.fabric_networking_api_v1 ? "available" : "unavailable"))
.getBoolean(true, false);

public static final boolean ensureChunkCorrectness = new ConfigSystem.ConfigAccessor()
.key("noTickViewDistance.ensureChunkCorrectness")
.comment("Whether to ensure correct chunks within normal render distance \n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.ishland.c2me.notickvd.common;

public interface IRenderDistanceOverride {

void c2me_notickvd$setRenderDistance(int renderDistance);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ishland.c2me.notickvd.common;

import com.ishland.c2me.base.common.config.ModStatuses;
import net.fabricmc.api.ModInitializer;

public class NoTickVDInitializer implements ModInitializer {
@Override
public void onInitialize() {
if (Config.enableExtRenderDistanceProtocol && ModStatuses.fabric_networking_api_v1) {
ServerExtNetworking.registerListeners();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.ishland.c2me.notickvd.common;

import com.ishland.c2me.base.common.network.ExtRenderDistance;
import net.fabricmc.fabric.api.networking.v1.ServerConfigurationNetworking;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;

public class ServerExtNetworking {

public static void registerListeners() {
ServerPlayNetworking.registerGlobalReceiver(
ExtRenderDistance.TYPE,
(packet, player, responseSender) ->
((IRenderDistanceOverride) player.networkHandler).c2me_notickvd$setRenderDistance(packet.renderDistance())
);
ServerConfigurationNetworking.registerGlobalReceiver(
ExtRenderDistance.TYPE,
(packet, networkHandler, responseSender) ->
((IRenderDistanceOverride) networkHandler).c2me_notickvd$setRenderDistance(packet.renderDistance())
);
}

}
Loading

0 comments on commit 4a0a320

Please sign in to comment.