Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ subprojects {
plugins.apply("java-library")

group = "ru.bk.oharass.freedomchat"
version = "1.7.7"
version = "1.7.8"
description = "Liberate your server from the chat-reporting bourgeoisie! Disable chat signing server-side."

tasks {
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
languageVersion.set(JavaLanguageVersion.of(25))
}
}

Expand Down
31 changes: 19 additions & 12 deletions fabric/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id("dev.architectury.loom") version "1.13-SNAPSHOT"
id("net.fabricmc.fabric-loom") version "1.16-SNAPSHOT"
id("com.gradleup.shadow") version "8.3.9"
}

Expand All @@ -13,31 +13,38 @@ repositories {
}

dependencies {
minecraft(group = "com.mojang", name = "minecraft", version = "1.21.11")
mappings(group = "net.fabricmc", name = "yarn", version = "1.21.11+build.1", classifier = "v2")
modImplementation(group = "net.fabricmc", name = "fabric-loader", version = "0.18.2")
modImplementation(group = "net.fabricmc.fabric-api", name = "fabric-api", version = "0.139.4+1.21.11")
minecraft(group = "com.mojang", name = "minecraft", version = "26.1.2")
implementation(group = "net.fabricmc", name = "fabric-loader", version = "0.19.2")
implementation(group = "net.fabricmc.fabric-api", name = "fabric-api", version = "0.147.0+26.1.2")
shade(implementation(group = "org.spongepowered", name = "configurate-yaml", version = "4.2.0"))
}

tasks {
processResources {
filesMatching("fabric.mod.json") {
expand(
expand(mapOf(
"version" to project.version,
"description" to project.description,
)
"description" to project.description
))
}
}
shadowJar {

val shadowJarTask = named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
// Relocate configurate & its dependencies
relocate("org.spongepowered.configurate", "ru.bk.oharass.freedomchat.lib.org.spongepowered.configurate")
relocate("io.leangen.geantyref", "ru.bk.oharass.freedomchat.lib.io.leangen.geantyref")
relocate("org.yaml.snakeyaml", "ru.bk.oharass.freedomchat.lib.org.yaml.snakeyaml")
configurations = listOf(shade)
archiveClassifier.set("dev")
archiveClassifier.set("")
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)

named<Jar>("jar") {
enabled = false
}
shadowJarTask.configure {
archiveClassifier.set("")
}
assemble {
dependsOn(shadowJarTask)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public class FreedomChat implements ModInitializer {
public void onInitialize() {
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
this.server = server;
if (!Boolean.getBoolean("im.evan.freedomchat.bypassprotocolcheck") && SharedConstants.getProtocolVersion() != 774) {
logger.warn("This version of FreedomChat only supports protocol version 774 (1.21.11). Please use the appropriate version of FreedomChat for your server");
if (!Boolean.getBoolean("im.evan.freedomchat.bypassprotocolcheck") && SharedConstants.getProtocolVersion() != 775) {
logger.warn("This version of FreedomChat only supports protocol version 775 (26.1). Please use the appropriate version of FreedomChat for your server");
logger.warn("If you know what you are doing, set the im.evan.freedomchat.bypassprotocolcheck system property to true to bypass this check");
return;
}
Expand Down
78 changes: 39 additions & 39 deletions fabric/src/main/java/ru/bk/oharass/freedomchat/FreedomHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.message.MessageType;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
import net.minecraft.network.packet.s2c.query.QueryResponseS2CPacket;
import net.minecraft.network.state.PlayStateFactories;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.server.ServerMetadata;
import net.minecraft.text.Text;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket;
import net.minecraft.network.protocol.game.ClientboundSystemChatPacket;
import net.minecraft.network.protocol.game.GameProtocols;
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
import net.minecraft.network.protocol.status.ServerStatus;
import ru.bk.oharass.freedomchat.rewrite.CustomServerMetadata;

import java.util.Objects;
Expand All @@ -27,16 +27,16 @@
@ChannelHandler.Sharable
public class FreedomHandler extends MessageToByteEncoder<Packet<?>> {
private static final int STATUS_RESPONSE_PACKET_ID = 0x00;
private final PacketCodec<ByteBuf, Packet<? super ClientPlayPacketListener>> s2cPlayPacketCodec;
private final StreamCodec<ByteBuf, Packet<? super ClientGamePacketListener>> s2cPlayPacketCodec;
private final boolean rewriteChat;
private final boolean claimSecureChatEnforced;
private final boolean noChatReports;
private final boolean bedrockOnly;

public FreedomHandler(final FreedomChat freedom, final boolean rewriteChat, final boolean claimSecureChatEnforced, final boolean noChatReports, final boolean bedrockOnly) {
final DynamicRegistryManager registryAccess = freedom.getServer().getRegistryManager();
final Function<ByteBuf, RegistryByteBuf> bufRegistryAccess = RegistryByteBuf.makeFactory(registryAccess);
this.s2cPlayPacketCodec = PlayStateFactories.S2C.bind(bufRegistryAccess).codec();
final RegistryAccess registryAccess = freedom.getServer().registryAccess();
final Function<ByteBuf, RegistryFriendlyByteBuf> bufRegistryAccess = RegistryFriendlyByteBuf.decorator(registryAccess);
this.s2cPlayPacketCodec = GameProtocols.CLIENTBOUND_TEMPLATE.bind(bufRegistryAccess).codec();
this.rewriteChat = rewriteChat;
this.claimSecureChatEnforced = claimSecureChatEnforced;
this.noChatReports = noChatReports;
Expand All @@ -45,42 +45,42 @@ public FreedomHandler(final FreedomChat freedom, final boolean rewriteChat, fina

@Override
public boolean acceptOutboundMessage(final Object msg) {
return (rewriteChat && msg instanceof ChatMessageS2CPacket packet && (!bedrockOnly || isBedrockPlayer(packet.sender())))
|| noChatReports && msg instanceof QueryResponseS2CPacket
|| claimSecureChatEnforced && msg instanceof GameJoinS2CPacket;
return (rewriteChat && msg instanceof ClientboundPlayerChatPacket packet && (!bedrockOnly || isBedrockPlayer(packet.sender())))
|| noChatReports && msg instanceof ClientboundStatusResponsePacket
|| claimSecureChatEnforced && msg instanceof ClientboundLoginPacket;
}

@Override
protected void encode(final ChannelHandlerContext ctx, final Packet msg, final ByteBuf out) {
final PacketByteBuf fbb = new PacketByteBuf(out);
final FriendlyByteBuf fbb = new FriendlyByteBuf(out);

if (msg instanceof final ChatMessageS2CPacket packet) {
if (msg instanceof final ClientboundPlayerChatPacket packet) {
encode(ctx, packet, fbb);
} else if (msg instanceof final QueryResponseS2CPacket packet) {
} else if (msg instanceof final ClientboundStatusResponsePacket packet) {
encode(ctx, packet, fbb);
} else if (msg instanceof final GameJoinS2CPacket packet) {
} else if (msg instanceof final ClientboundLoginPacket packet) {
encode(ctx, packet, fbb);
}
}

private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final ChatMessageS2CPacket msg, final PacketByteBuf buf) {
final Text content = Objects.requireNonNullElseGet(msg.unsignedContent(), () -> Text.literal(msg.body().content()));
private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final ClientboundPlayerChatPacket msg, final FriendlyByteBuf buf) {
final Component content = Objects.requireNonNullElseGet(msg.unsignedContent(), () -> Component.literal(msg.body().content()));

final MessageType.Parameters chatType = msg.serializedParameters();
final Text decoratedContent = chatType.applyChatDecoration(content);
final ChatType.Bound chatType = msg.chatType();
final Component decoratedContent = chatType.decorate(content);

final GameMessageS2CPacket system = new GameMessageS2CPacket(decoratedContent, false);
final ClientboundSystemChatPacket system = new ClientboundSystemChatPacket(decoratedContent, false);

s2cPlayPacketCodec.encode(buf, system);
}

private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final GameJoinS2CPacket msg, final PacketByteBuf buf) {
final GameJoinS2CPacket rewritten = new GameJoinS2CPacket(
msg.playerEntityId(),
private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final ClientboundLoginPacket msg, final FriendlyByteBuf buf) {
final ClientboundLoginPacket rewritten = new ClientboundLoginPacket(
msg.playerId(),
msg.hardcore(),
msg.dimensionIds(),
msg.levels(),
msg.maxPlayers(),
msg.viewDistance(),
msg.chunkRadius(),
msg.simulationDistance(),
msg.reducedDebugInfo(),
msg.showDeathScreen(),
Expand All @@ -91,20 +91,20 @@ private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx,
s2cPlayPacketCodec.encode(buf, rewritten);
}

private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final QueryResponseS2CPacket msg, final PacketByteBuf buf) {
final ServerMetadata status = msg.metadata();
private void encode(@SuppressWarnings("unused") final ChannelHandlerContext ctx, final ClientboundStatusResponsePacket msg, final FriendlyByteBuf buf) {
final ServerStatus status = msg.status();

final CustomServerMetadata customStatus = new CustomServerMetadata(
status.description(),
status.players(),
status.version(),
status.favicon(),
status.secureChatEnforced(),
status.enforcesSecureChat(),
true
);

buf.writeVarInt(STATUS_RESPONSE_PACKET_ID);
buf.encodeAsJson(CustomServerMetadata.CODEC, customStatus);
buf.writeJsonWithCodec(CustomServerMetadata.CODEC, customStatus);
}

private boolean isBedrockPlayer(final UUID uuid) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package ru.bk.oharass.freedomchat.mixins;

import io.netty.channel.Channel;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.Connection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import ru.bk.oharass.freedomchat.access.ClientConnectionAccess;

@Mixin(ClientConnection.class)
@Mixin(Connection.class)
public class ClientConnectionMixin implements ClientConnectionAccess {
@Shadow
private Channel channel;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package ru.bk.oharass.freedomchat.mixins;

import io.netty.channel.ChannelPipeline;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ConnectedClientData;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.network.Connection;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.server.players.PlayerList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bk.oharass.freedomchat.FreedomChat;
import ru.bk.oharass.freedomchat.access.ServerCommonNetworkHandlerAccess;

@Mixin(PlayerManager.class)
@Mixin(PlayerList.class)
public class PlayerManagerMixin {
@Inject(method = "onPlayerConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;transitionInbound(Lnet/minecraft/network/state/NetworkState;Lnet/minecraft/network/listener/PacketListener;)V", shift = At.Shift.AFTER))
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) {
final ChannelPipeline pipeline = ((ServerCommonNetworkHandlerAccess) player.networkHandler).getConnectionAccess().getChannel().pipeline();
@Inject(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;setupInboundProtocol(Lnet/minecraft/network/ProtocolInfo;Lnet/minecraft/network/PacketListener;)V", shift = At.Shift.AFTER))
public void onPlayerConnect(Connection connection, ServerPlayer player, CommonListenerCookie clientData, CallbackInfo ci) {
final ChannelPipeline pipeline = ((ServerCommonNetworkHandlerAccess) player.connection).getConnectionAccess().getChannel().pipeline();
pipeline.addAfter("packet_handler", "freedom_handler", FreedomChat.getHandler());
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package ru.bk.oharass.freedomchat.mixins;

import net.minecraft.network.ClientConnection;
import net.minecraft.server.network.ServerCommonNetworkHandler;
import net.minecraft.network.Connection;
import net.minecraft.server.network.ServerCommonPacketListenerImpl;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import ru.bk.oharass.freedomchat.access.ClientConnectionAccess;
import ru.bk.oharass.freedomchat.access.ServerCommonNetworkHandlerAccess;

@Mixin(ServerCommonNetworkHandler.class)
@Mixin(ServerCommonPacketListenerImpl.class)
public class ServerCommonNetworkHandlerMixin implements ServerCommonNetworkHandlerAccess {
@Final
@Shadow
protected ClientConnection connection;
protected Connection connection;

@Override
public ClientConnectionAccess getConnectionAccess() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,45 @@

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.server.ServerMetadata;
import net.minecraft.text.Text;
import net.minecraft.text.TextCodecs;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.protocol.status.ServerStatus;

import java.util.Optional;

public record CustomServerMetadata(Text description, Optional<ServerMetadata.Players> players,
Optional<ServerMetadata.Version> version, Optional<ServerMetadata.Favicon> favicon,
public record CustomServerMetadata(Component description, Optional<ServerStatus.Players> players,
Optional<ServerStatus.Version> version, Optional<ServerStatus.Favicon> favicon,
boolean secureChatEnforced, boolean preventsChatReports) {
public static final Codec<CustomServerMetadata> CODEC = RecordCodecBuilder
.create((instance) -> instance.group(
TextCodecs.CODEC.lenientOptionalFieldOf("description", ScreenTexts.EMPTY)
ComponentSerialization.CODEC.lenientOptionalFieldOf("description", CommonComponents.EMPTY)
.forGetter(CustomServerMetadata::description),
ServerMetadata.Players.CODEC.lenientOptionalFieldOf("players")
ServerStatus.Players.CODEC.lenientOptionalFieldOf("players")
.forGetter(CustomServerMetadata::players),
ServerMetadata.Version.CODEC.lenientOptionalFieldOf("version")
ServerStatus.Version.CODEC.lenientOptionalFieldOf("version")
.forGetter(CustomServerMetadata::version),
ServerMetadata.Favicon.CODEC.lenientOptionalFieldOf("favicon")
ServerStatus.Favicon.CODEC.lenientOptionalFieldOf("favicon")
.forGetter(CustomServerMetadata::favicon),
Codec.BOOL.lenientOptionalFieldOf("enforcesSecureChat", false)
.forGetter(CustomServerMetadata::secureChatEnforced),
Codec.BOOL.lenientOptionalFieldOf("preventsChatReports", false)
.forGetter(CustomServerMetadata::preventsChatReports))
.apply(instance, CustomServerMetadata::new));

public Text description() {
public Component description() {
return this.description;
}

public Optional<ServerMetadata.Players> players() {
public Optional<ServerStatus.Players> players() {
return this.players;
}

public Optional<ServerMetadata.Version> version() {
public Optional<ServerStatus.Version> version() {
return this.version;
}

public Optional<ServerMetadata.Favicon> favicon() {
public Optional<ServerStatus.Favicon> favicon() {
return this.favicon;
}

Expand Down
8 changes: 4 additions & 4 deletions fabric/src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
"freedomchat.mixins.json"
],
"depends": {
"fabricloader": ">=0.15.11",
"fabric": "*",
"minecraft": ">=1.21",
"java": ">=21"
"fabricloader": ">=0.18.5",
"fabric-api": "*",
"minecraft": ">=26.1",
"java": ">=25"
}
}
2 changes: 1 addition & 1 deletion fabric/src/main/resources/freedomchat.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"required": true,
"minVersion": "0.8",
"package": "ru.bk.oharass.freedomchat.mixins",
"compatibilityLevel": "JAVA_21",
"compatibilityLevel": "JAVA_25",
"mixins": [
"ClientConnectionMixin",
"PlayerManagerMixin",
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 3 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading
Loading