Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/fabric' into fabric
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/resources/assets/clientcommands/lang/en_us.json
  • Loading branch information
RealRTTV committed May 29, 2024
2 parents cca658f + 037fedc commit 4dc01d5
Show file tree
Hide file tree
Showing 27 changed files with 632 additions and 177 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ org.gradle.jvmargs=-Xmx2G
# Dependencies
# also check this on https://fabricmc.net/develop/
fabric_version=0.97.8+1.20.6
clientarguments_version=1.8.2
clientarguments_version=1.8.3
betterconfig_version=1.2.1
seedfinding_core_version=1.192.1
seedfinding_biome_version=1.171.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public static void registerCommands(CommandDispatcher<FabricClientCommandSource>
SnakeCommand.register(dispatcher);
StartupCommand.register(dispatcher);
TaskCommand.register(dispatcher);
TicTacToeCommand.register(dispatcher);
TooltipCommand.register(dispatcher, context);
TranslateCommand.register(dispatcher);
UsageTreeCommand.register(dispatcher);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.logging.LogUtils;
import io.netty.buffer.Unpooled;
import net.earthcomputer.clientcommands.c2c.packets.MessageC2CPacket;
import net.earthcomputer.clientcommands.c2c.packets.PutTicTacToeMarkC2CPacket;
import net.earthcomputer.clientcommands.c2c.packets.StartTicTacToeGameC2CPacket;
import net.earthcomputer.clientcommands.command.ListenCommand;
import net.earthcomputer.clientcommands.interfaces.IClientPacketListener_C2C;
import net.earthcomputer.clientcommands.command.TicTacToeCommand;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.AccountProfileKeyPairManager;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.network.ConnectionProtocol;
import net.minecraft.network.FriendlyByteBuf;
Expand All @@ -19,19 +28,28 @@
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.ProtocolInfoBuilder;
import net.minecraft.world.entity.player.ProfileKeyPair;
import net.minecraft.world.entity.player.ProfilePublicKey;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

import java.security.PublicKey;
import java.util.Arrays;
import java.util.Optional;

public class C2CPacketHandler implements C2CPacketListener {
private static final Logger LOGGER = LogUtils.getLogger();

private static final DynamicCommandExceptionType MESSAGE_TOO_LONG_EXCEPTION = new DynamicCommandExceptionType(d -> Component.translatable("c2cpacket.messageTooLong", d));
private static final SimpleCommandExceptionType PUBLIC_KEY_NOT_FOUND_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("c2cpacket.publicKeyNotFound"));
private static final SimpleCommandExceptionType ENCRYPTION_FAILED_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("c2cpacket.encryptionFailed"));

public static final ProtocolInfo<C2CPacketListener> C2C = ProtocolInfoBuilder.<C2CPacketListener, RegistryFriendlyByteBuf>protocolUnbound(ConnectionProtocol.PLAY, PacketFlow.CLIENTBOUND, builder -> builder
public static final ProtocolInfo.Unbound<C2CPacketListener, RegistryFriendlyByteBuf> PROTOCOL_UNBOUND = ProtocolInfoBuilder.protocolUnbound(ConnectionProtocol.PLAY, PacketFlow.CLIENTBOUND, builder -> builder
.addPacket(MessageC2CPacket.ID, MessageC2CPacket.CODEC)
).bind(RegistryFriendlyByteBuf.decorator(Minecraft.getInstance().getConnection().registryAccess()));
.addPacket(StartTicTacToeGameC2CPacket.ID, StartTicTacToeGameC2CPacket.CODEC)
.addPacket(PutTicTacToeMarkC2CPacket.ID, PutTicTacToeMarkC2CPacket.CODEC)
);

private static final C2CPacketHandler instance = new C2CPacketHandler();

Expand All @@ -48,15 +66,23 @@ public void sendPacket(Packet<C2CPacketListener> packet, PlayerInfo recipient) t
throw PUBLIC_KEY_NOT_FOUND_EXCEPTION.create();
}
ProfilePublicKey ppk = session.profilePublicKey();
//noinspection ConstantValue
if (ppk == null) {
throw PUBLIC_KEY_NOT_FOUND_EXCEPTION.create();
}
PublicKey key = ppk.data().key();
FriendlyByteBuf buf = PacketByteBufs.create();
C2C.codec().encode(buf, packet);
ProtocolInfo<C2CPacketListener> protocolInfo = getCurrentProtocolInfo();
if (protocolInfo == null) {
return;
}
protocolInfo.codec().encode(buf, packet);
byte[] uncompressed = new byte[buf.readableBytes()];
buf.getBytes(0, uncompressed);
byte[] compressed = ConversionHelper.Gzip.compress(uncompressed);
if (compressed == null) {
return;
}
// split compressed into 245 byte chunks
int chunks = (compressed.length + 244) / 245;
byte[][] chunked = new byte[chunks][];
Expand All @@ -81,14 +107,77 @@ public void sendPacket(Packet<C2CPacketListener> packet, PlayerInfo recipient) t
}
String packetString = ConversionHelper.BaseUTF8.toUnicode(joined);
String commandString = "w " + recipient.getProfile().getName() + " CCENC:" + packetString;
if (commandString.length() >= 256) {
if (commandString.length() >= SharedConstants.MAX_CHAT_LENGTH) {
throw MESSAGE_TOO_LONG_EXCEPTION.create(commandString.length());
}
ListenCommand.onPacket(packet, ListenCommand.PacketFlow.C2C_OUTBOUND);
Minecraft.getInstance().getConnection().sendCommand(commandString);
OutgoingPacketFilter.addPacket(packetString);
}

public static boolean handleC2CPacket(String content) {
byte[] encrypted = ConversionHelper.BaseUTF8.fromUnicode(content);
// round down to multiple of 256 bytes
int length = encrypted.length & ~0xFF;
// copy to new array of arrays
byte[][] encryptedArrays = new byte[length / 256][];
for (int i = 0; i < length; i += 256) {
encryptedArrays[i / 256] = Arrays.copyOfRange(encrypted, i, i + 256);
}
if (!(Minecraft.getInstance().getProfileKeyPairManager() instanceof AccountProfileKeyPairManager profileKeyPairManager)) {
return false;
}
Optional<ProfileKeyPair> keyPair = profileKeyPairManager.keyPair.join();
if (keyPair.isEmpty()) {
return false;
}
// decrypt
int len = 0;
byte[][] decryptedArrays = new byte[encryptedArrays.length][];
for (int i = 0; i < encryptedArrays.length; i++) {
decryptedArrays[i] = ConversionHelper.RsaEcb.decrypt(encryptedArrays[i], keyPair.get().privateKey());
if (decryptedArrays[i] == null) {
return false;
}
len += decryptedArrays[i].length;
}
// copy to new array
byte[] decrypted = new byte[len];
int pos = 0;
for (byte[] decryptedArray : decryptedArrays) {
System.arraycopy(decryptedArray, 0, decrypted, pos, decryptedArray.length);
pos += decryptedArray.length;
}
byte[] uncompressed = ConversionHelper.Gzip.decompress(decrypted);
if (uncompressed == null) {
return false;
}
ProtocolInfo<C2CPacketListener> protocolInfo = getCurrentProtocolInfo();
if (protocolInfo == null) {
return false;
}
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(uncompressed));
Packet<? super C2CPacketListener> packet;
try {
packet = protocolInfo.codec().decode(buf);
} catch (Throwable e) {
LOGGER.error("Error decoding C2C packet", e);
return false;
}
if (buf.readableBytes() > 0) {
LOGGER.error("Found extra bytes while reading C2C packet {}", packet.type());
return false;
}
ListenCommand.onPacket(packet, ListenCommand.PacketFlow.C2C_INBOUND);
try {
packet.handle(C2CPacketHandler.getInstance());
} catch (Throwable e) {
Minecraft.getInstance().gui.getChat().addMessage(Component.nullToEmpty(e.getMessage()));
LOGGER.error("Error handling C2C packet", e);
}
return true;
}

@Override
public void onMessageC2CPacket(MessageC2CPacket packet) {
String sender = packet.sender();
Expand All @@ -103,13 +192,32 @@ public void onMessageC2CPacket(MessageC2CPacket packet) {
}

@Override
public PacketFlow flow() {
return C2C.flow();
public void onStartTicTacToeGameC2CPacket(StartTicTacToeGameC2CPacket packet) {
TicTacToeCommand.onStartTicTacToeGameC2CPacket(packet);
}

@Override
public void onPutTicTacToeMarkC2CPacket(PutTicTacToeMarkC2CPacket packet) {
TicTacToeCommand.onPutTicTacToeMarkC2CPacket(packet);
}

@Nullable
public static ProtocolInfo<C2CPacketListener> getCurrentProtocolInfo() {
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection == null) {
return null;
}
return ((IClientPacketListener_C2C) connection).clientcommands_getC2CProtocolInfo();
}

@Override
public @NotNull PacketFlow flow() {
return PacketFlow.CLIENTBOUND;
}

@Override
public ConnectionProtocol protocol() {
return C2C.id();
public @NotNull ConnectionProtocol protocol() {
return ConnectionProtocol.PLAY;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package net.earthcomputer.clientcommands.c2c;

import net.earthcomputer.clientcommands.c2c.packets.MessageC2CPacket;
import net.earthcomputer.clientcommands.c2c.packets.PutTicTacToeMarkC2CPacket;
import net.earthcomputer.clientcommands.c2c.packets.StartTicTacToeGameC2CPacket;
import net.minecraft.network.PacketListener;

public interface C2CPacketListener extends PacketListener {
void onMessageC2CPacket(MessageC2CPacket packet);

void onStartTicTacToeGameC2CPacket(StartTicTacToeGameC2CPacket packet);

void onPutTicTacToeMarkC2CPacket(PutTicTacToeMarkC2CPacket packet);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package net.earthcomputer.clientcommands.c2c;

import com.mojang.logging.LogUtils;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

import javax.crypto.Cipher;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
Expand All @@ -12,6 +16,7 @@
import java.util.zip.GZIPOutputStream;

public class ConversionHelper {
private static final Logger LOGGER = LogUtils.getLogger();

/**
* @author Wagyourtail
Expand Down Expand Up @@ -91,20 +96,21 @@ private static int unmapCodepoint(int codepoint) {
* @author Wagyourtail
*/
public static class Gzip {
public static byte[] compress(byte[] bytes) {
public static byte @Nullable [] compress(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
gzip.write(bytes);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error compressing", e);
return null;
}
return out.toByteArray();
}

public static byte[] uncompress(byte[] bytes) {
public static byte @Nullable [] decompress(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
Expand All @@ -117,7 +123,8 @@ public static byte[] uncompress(byte[] bytes) {
out.write(buffer, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error decompressing", e);
return null;
}
return out.toByteArray();
}
Expand All @@ -130,7 +137,7 @@ public static byte[] encrypt(byte[] bytes, PublicKey key) {
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(bytes);
} catch (GeneralSecurityException e) {
e.printStackTrace();
LOGGER.error("Error encrypting", e);
return null;
}
}
Expand All @@ -141,7 +148,7 @@ public static byte[] decrypt(byte[] bytes, PrivateKey key) {
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(bytes);
} catch (GeneralSecurityException e) {
e.printStackTrace();
LOGGER.error("Error decrypting", e);
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.earthcomputer.clientcommands.c2c.packets;

import net.earthcomputer.clientcommands.c2c.C2CPacketListener;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.PacketType;
import net.minecraft.resources.ResourceLocation;

public record PutTicTacToeMarkC2CPacket(String sender, byte x, byte y) implements Packet<C2CPacketListener> {
public static final StreamCodec<RegistryFriendlyByteBuf, PutTicTacToeMarkC2CPacket> CODEC = Packet.codec(PutTicTacToeMarkC2CPacket::write, PutTicTacToeMarkC2CPacket::new);
public static final PacketType<PutTicTacToeMarkC2CPacket> ID = new PacketType<>(PacketFlow.CLIENTBOUND, new ResourceLocation("clientcommands", "put_tic_tac_toe_mark"));

public PutTicTacToeMarkC2CPacket(FriendlyByteBuf buf) {
this(buf.readUtf(), buf.readByte(), buf.readByte());
}

public void write(FriendlyByteBuf buf) {
buf.writeUtf(this.sender);
buf.writeByte(this.x);
buf.writeByte(this.y);
}

@Override
public void handle(C2CPacketListener handler) {
handler.onPutTicTacToeMarkC2CPacket(this);
}

@Override
public PacketType<? extends Packet<C2CPacketListener>> type() {
return ID;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.earthcomputer.clientcommands.c2c.packets;

import net.earthcomputer.clientcommands.c2c.C2CPacketListener;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.PacketType;
import net.minecraft.resources.ResourceLocation;

public record StartTicTacToeGameC2CPacket(String sender, boolean accept) implements Packet<C2CPacketListener> {
public static final StreamCodec<RegistryFriendlyByteBuf, StartTicTacToeGameC2CPacket> CODEC = Packet.codec(StartTicTacToeGameC2CPacket::write, StartTicTacToeGameC2CPacket::new);
public static final PacketType<StartTicTacToeGameC2CPacket> ID = new PacketType<>(PacketFlow.CLIENTBOUND, new ResourceLocation("clientcommands", "start_tic_tac_toe_game"));

public StartTicTacToeGameC2CPacket(FriendlyByteBuf buf) {
this(buf.readUtf(), buf.readBoolean());
}

public void write(FriendlyByteBuf buf) {
buf.writeUtf(this.sender);
buf.writeBoolean(this.accept);
}

@Override
public void handle(C2CPacketListener handler) {
handler.onStartTicTacToeGameC2CPacket(this);
}

@Override
public PacketType<? extends Packet<C2CPacketListener>> type() {
return ID;
}
}
Loading

0 comments on commit 4dc01d5

Please sign in to comment.