Skip to content
Open
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
15 changes: 12 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ buildscript {
plugins {
id 'java'
id 'idea'
id 'fabric-loom' version '0.6-SNAPSHOT'
}

// --
// Variables
// --
version = '2.6.1'
version = '2.6.2'
group = 'net.tcpshield.tcpshield'
archivesBaseName = 'TCPShield'

Expand Down Expand Up @@ -90,6 +91,9 @@ repositories {
maven {
url = "https://repo.opencollab.dev/maven-snapshots/"
}
maven {
url = 'https://maven.fabricmc.net/'
}
}

dependencies {
Expand All @@ -106,6 +110,11 @@ dependencies {
// Velocity
compileOnly group: 'com.velocitypowered', name: 'velocity-api', version: '1.0.0-SNAPSHOT'

// Fabric
minecraft "com.mojang:minecraft:1.16.5"
mappings "net.fabricmc:yarn:1.16.5+build.5:v2"
modImplementation group: 'net.fabricmc', name: 'fabric-loader', version: '0.11.2'

// Testing
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0-M1'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.7.0-M1'
Expand All @@ -128,8 +137,8 @@ configurations {
}

task updateVersion {
updateYamls()
updateJsons()
// updateYamls()
// updateJsons()
}

void updateYamls() {
Expand Down
11 changes: 10 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
rootProject.name = 'TCPShield'
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}

rootProject.name = 'TCPShield'
54 changes: 54 additions & 0 deletions src/main/java/net/tcpshield/tcpshield/fabric/TCPShieldFabric.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package net.tcpshield.tcpshield.fabric;

import net.fabricmc.api.DedicatedServerModInitializer;
import net.tcpshield.tcpshield.TCPShieldPacketHandler;
import net.tcpshield.tcpshield.TCPShieldPlugin;
import net.tcpshield.tcpshield.fabric.impl.FabricConfig;
import net.tcpshield.tcpshield.provider.ConfigProvider;
import net.tcpshield.tcpshield.util.Debugger;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.logging.Logger;

public class TCPShieldFabric implements DedicatedServerModInitializer, TCPShieldPlugin {

public static final Logger LOGGER = Logger.getLogger("TCPShield");
public static TCPShieldPacketHandler packetHandler;
private FabricConfig config;
private Debugger debugger;

@Override
public void onInitializeServer() {
try {
config = new FabricConfig();
debugger = Debugger.createDebugger(this);
packetHandler = new TCPShieldPacketHandler(this);
} catch (NoSuchAlgorithmException | IOException | InvalidKeySpecException exception) {
exception.printStackTrace();
}

LOGGER.info("TCPShield has been loaded.");
}

@Override
public ConfigProvider getConfigProvider() {
return config;
}

@Override
public Logger getLogger() {
return LOGGER;
}

@Override
public TCPShieldPacketHandler getPacketHandler() {
return packetHandler;
}

@Override
public Debugger getDebugger() {
return debugger;
}
}
124 changes: 124 additions & 0 deletions src/main/java/net/tcpshield/tcpshield/fabric/impl/FabricConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package net.tcpshield.tcpshield.fabric.impl;

import net.fabricmc.loader.api.FabricLoader;
import net.tcpshield.tcpshield.fabric.TCPShieldFabric;
import net.tcpshield.tcpshield.provider.ConfigProvider;
import net.tcpshield.tcpshield.util.exception.config.ConfigLoadException;
import net.tcpshield.tcpshield.util.exception.config.ConfigReloadException;
import net.tcpshield.tcpshield.util.exception.config.ConfigResetException;
import net.tcpshield.tcpshield.util.exception.phase.ConfigException;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FabricConfig extends ConfigProvider {

private final Map<String, String> values = new HashMap<>();

public FabricConfig() {
this.dataFolder = new File(FabricLoader.getInstance().getConfigDir().toString());
this.configFile = new File(dataFolder, "config.yml");

try {
reload();
} catch (Exception e) {
throw new ConfigException(e);
}
}

@Override
protected void checkNodes(String... nodes) throws ConfigException {
for (String node : nodes) {
if(!values.containsKey(node))
throw new ConfigException("The node \"" + node + "\" does not exist in the config.");
}
}

@Override
protected void reset() throws ConfigResetException {
try {
values.clear();

try {
configFile.delete();
} catch (Exception ignored) {
// Just ignore since it either does not exist, or we can overwrite
}

// Copy the config.yml data from our mod jar to the loader config folder.
try (InputStream in = getClass().getClassLoader().getResourceAsStream("config.yml")) {
Files.copy(in, configFile.toPath());
}
} catch (Exception e) {
throw new ConfigResetException(e);
}
}

@Override
protected void load() throws ConfigLoadException {
try {
values.clear();
values.putAll(loadConfig());

checkNodes("only-allow-proxy-connections", "timestamp-validation", "debug-mode", "enable-geyser-support", "prefer-protocollib");

this.onlyProxy = Boolean.parseBoolean(values.get("only-allow-proxy-connections"));
this.timestampValidationMode = values.get("timestamp-validation");
this.doDebug = Boolean.parseBoolean(values.get("debug-mode"));
this.geyser = Boolean.parseBoolean(values.get("enable-geyser-support"));
this.preferProtocolLib = Boolean.parseBoolean(values.get("prefer-protocollib"));
} catch (Exception e) {
throw new ConfigLoadException(e);
}
}

@Override
public void reload() throws ConfigReloadException {
try {
if(!dataFolder.exists())
dataFolder.mkdir();

if(!configFile.exists())
reset();

try {
load();
} catch (ConfigLoadException exception) {
TCPShieldFabric.LOGGER.warning("Config loading failed, resetting to default config. (This can be ignored if you just switched builds of TCPShield)");
reset();
reload(); // Redo cycle, possible StackOverFlow, but realistically only happens if reset fails
}
} catch (Exception e) {
throw new ConfigReloadException(e);
}
}

private Map<String, String> loadConfig() {
Map<String, String> configValues = new HashMap<>();

try {
List<String> strings = Files.readAllLines(configFile.toPath());

// Rudimentary config parsing
for (String line : strings) {
String[] entry = line.replace(" ", "").split(":");

// A config option will only be valid if it is in the format 'a: b'.
// Ensure that is the case now.
if (entry.length == 2) {
String key = entry[0];
String value = entry[1];
configValues.put(key, value);
}
}
} catch (Exception e) {
throw new ConfigException("Couldn't load config at config/config.yml!");
}

return configValues;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.tcpshield.tcpshield.fabric.impl;

import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import net.tcpshield.tcpshield.fabric.mixin.HandshakeC2SPacketAccessor;
import net.tcpshield.tcpshield.provider.PacketProvider;
import net.tcpshield.tcpshield.util.exception.manipulate.PacketManipulationException;

public class FabricPacket implements PacketProvider {

private final HandshakeC2SPacket handshake;

public FabricPacket(HandshakeC2SPacket handshake) {
this.handshake = handshake;
}

@Override
public String getPayloadString() {
return ((HandshakeC2SPacketAccessor) handshake).getAddress();
}

@Override
public void setPacketHostname(String hostname) throws PacketManipulationException {
// NO OPERATION
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package net.tcpshield.tcpshield.fabric.impl;

import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import net.minecraft.text.LiteralText;
import net.tcpshield.tcpshield.fabric.mixin.ClientConnectionAccessor;
import net.tcpshield.tcpshield.provider.PlayerProvider;

import java.net.InetSocketAddress;

public class FabricPlayer implements PlayerProvider {

private final ClientConnection connection;
private String ip;

public FabricPlayer(HandshakeC2SPacket packet, ClientConnection connection) {
this.connection = connection;
this.ip = ((InetSocketAddress) ((ClientConnectionAccessor) connection).getChannel().remoteAddress()).getAddress().getHostAddress();
}

@Override
public String getUUID() {
return "unknown";
}

@Override
public String getName() {
return "unknown";
}

@Override
public String getIP() {
return ip;
}

@Override
public void setIP(InetSocketAddress ip) {
// At this point, the IP/connection believe the player has the IP of TCPShield.
// The ip passed into this method contains their CORRECT data, which we have to assign to the player network connection.
((ClientConnectionAccessor) connection).setAddress(ip);
this.ip = ((InetSocketAddress) ((ClientConnectionAccessor) connection).getChannel().remoteAddress()).getAddress().getHostAddress();
}

@Override
public void disconnect() {
connection.disconnect(new LiteralText("Connection failed. Please try again or contact an administrator."));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package net.tcpshield.tcpshield.fabric.mixin;

import io.netty.channel.Channel;
import net.minecraft.network.ClientConnection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.net.SocketAddress;

@Mixin(ClientConnection.class)
public interface ClientConnectionAccessor {

@Accessor
void setAddress(SocketAddress address);

@Accessor
Channel getChannel();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.tcpshield.tcpshield.fabric.mixin;

import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(HandshakeC2SPacket.class)
public interface HandshakeC2SPacketAccessor {
@Accessor
String getAddress();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package net.tcpshield.tcpshield.fabric.mixin;

import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import net.minecraft.server.network.ServerHandshakeNetworkHandler;
import net.tcpshield.tcpshield.fabric.TCPShieldFabric;
import net.tcpshield.tcpshield.fabric.impl.FabricPacket;
import net.tcpshield.tcpshield.fabric.impl.FabricPlayer;
import net.tcpshield.tcpshield.provider.PacketProvider;
import net.tcpshield.tcpshield.provider.PlayerProvider;
import org.spongepowered.asm.mixin.Final;
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;

@Mixin(ServerHandshakeNetworkHandler.class)
public class ServerHandshakeMixin {

@Shadow @Final private ClientConnection connection;

@Inject(
method = "onHandshake",
at = @At("HEAD"))
private void onHandshake(HandshakeC2SPacket handshake, CallbackInfo ci) {
PacketProvider packet = new FabricPacket(handshake);
PlayerProvider player = new FabricPlayer(handshake, connection);

TCPShieldFabric.packetHandler.handleHandshake(packet, player);
}
}
Loading