1
0

Controlify, Feather Client, Bugfixes

Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Lixfel 2024-03-20 10:08:23 +01:00
Ursprung a6feb68bf3
Commit 59b2e397ba
9 geänderte Dateien mit 218 neuen und 86 gelöschten Zeilen

Datei anzeigen

@ -41,6 +41,9 @@ import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
import java.util.logging.Level;
@ -57,6 +60,32 @@ public class PluginMessage extends BasicListener {
player.sendData(channel, data);
}
public static byte[] genBufPacket(Consumer<ByteBuf> generator) {
ByteBuf buf = Unpooled.buffer();
generator.accept(buf);
byte[] packet = new byte[buf.readableBytes()];
buf.readBytes(packet);
return packet;
}
public static byte[] genStreamPacket(StreamConsumer generator) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(stream);
try {
generator.accept(out);
} catch (IOException e) {
throw new SecurityException("Could not create PluginMessage packet", e);
}
return stream.toByteArray();
}
public interface StreamConsumer {
void accept(DataOutputStream out) throws IOException;
}
private static final Parser UNKNOWN = event -> BungeeCore.get().getLogger().log(Level.WARNING, () -> "Undefined PluginMessage on channel " + event.getTag() + " from " + event.getSender() + " received.\n" + new String(event.getData()) + "\n" + Arrays.toString(event.getData()));
private static final Parser PASS_THROUGH = event -> event.setCancelled(false);
private static final Parser DROP = event -> {};
@ -68,12 +97,11 @@ public class PluginMessage extends BasicListener {
private final Map<String, Parser> handlers = new HashMap<>();
public PluginMessage() {
//TODO interface generalisation
LabyMod labyMod = new LabyMod();
FML fml = new FML();
FabricModSender fabricModSender = new FabricModSender();
WorldDownloader wdl = new WorldDownloader();
knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod"));
knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod", "Feather Fabric"));
for(String channel : Arrays.asList(
"fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync",
@ -99,6 +127,14 @@ public class PluginMessage extends BasicListener {
"libgui:screen_message_s2c", //https://github.com/CottonMC/LibGui
"minecraft:intave", //https://intave.ac seems to be a client side integration of intave with labymod 4
"midnightcontrols:feature", "midnightcontrols:controls_mode", //https://modrinth.com/mod/midnightcontrols
"controlify:vibrate_from_origin", "controlify:vibration", "controlify:vibrate_from_entity",
"carpet:structures", //https://modrinth.com/mod/carpet
"appleskin:exhaustion_sync", "appleskin:saturation_sync", //https://modrinth.com/mod/appleskin
"puzzleslib:1/1", //https://modrinth.com/mod/puzzles-lib
"pickupnotifier:1/1", //https://modrinth.com/mod/pick-up-notifier
"plasmo:voice/v2/installed", "plasmo:voice/v2", //https://modrinth.com/plugin/plasmo-voice
"whereisit:s2c_founditem", //https://modrinth.com/mod/where-is-it (needs server side component to work)
"inventorysorter:sync_blacklist_packet", //https://github.com/cpw/inventorysorter (needs server side component to work)
//https://github.com/bernie-g/geckolib
"geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync",
@ -107,15 +143,18 @@ public class PluginMessage extends BasicListener {
//https://github.com/Noxcrew/noxesium
"noxesium-v1:reset", "noxesium-v1:change_server_rules", "noxesium-v1:server_info",
"noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules"
"noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules",
"noxesium-v1:stop_sound", "noxesium-v1:start_sound", "noxesium-v1:modify_sound"
))
channelRegisterHandlers.put(channel, player -> {});
channelRegisterHandlers.put(ApolloManager.PLUGIN_MESSAGE_CHANNEL, lunar::sendRestrictions);
channelRegisterHandlers.put(Feather.CHANNEL, new Feather()::sendRestrictions);
channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(ChatMessageType.SYSTEM, new TextComponent("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap
channelRegisterHandlers.put("litemoretica:init_easy_place", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "litematica")))); //https://github.com/Earthcomputer/litemoretica/tree/master
channelRegisterHandlers.put("voxelmap:settings", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "voxelmap")))); //https://modrinth.com/mod/voxelmap-updated undocumented
channelRegisterHandlers.put("worldinfo:world_id", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "minimap")))); // JourneyMap and VoxelMap
channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister);
registerBiDirPassthrough("worldedit:cui");
@ -133,10 +172,21 @@ public class PluginMessage extends BasicListener {
"axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer"
);
for(String channel : Arrays.asList(
"UNREGISTER", "minecraft:unregister", // used by carpet and servux
"WDL|REQUEST", "wdl:request",
"minecraft:intave", //undocumented, byte stringlength, clientconfig, byte length, json {"legacySneakHeight":false,"legacyOldRange":false,"legacyOldSlowdown":false}
"waila:entity", "waila:block",
"lambdacontrols:hello",
"midnightcontrols:controls_mode",
"inventorysorter:sync_settings_packet",
"voicechat:request_secret", "voicechat:update_state", //https://modrinth.com/plugin/simple-voice-chat
"shulkerboxtooltip:c2s_handshake"
))
register(channel, false, directional(UNKNOWN, DROP));
register("REGISTER", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("minecraft:register", false, directional(this::serverRegistersChannel, this::clientRegistersChannel));
register("UNREGISTER", false, DROP);
register("minecraft:unregister", false, DROP); // used by carpet and servux
register("BungeeCord", false, onlySWSource(PASS_THROUGH));
register("bungeecord:main", false, onlySWSource(PASS_THROUGH));
@ -146,28 +196,20 @@ public class PluginMessage extends BasicListener {
//Needs to be registered cause paper refuses to send PluginMessages on unregistered channels...
register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo(((Server) event.getSender()).getInfo()), event.getData()))), UNKNOWN));
register("sw:hotkeys", false, directional(UNKNOWN, PASS_THROUGH));
register("fabricmodsender:mods", true, directional(UNKNOWN, async(fabricModSender::handlePluginMessage)));
register("fabricmodsender:mods", true, directional(UNKNOWN, async(new FabricModSender()::handlePluginMessage)));
register("WDL|REQUEST", false, DROP);
register("wdl:request", false, DROP);
register("WDL|INIT", true, directional(UNKNOWN, wdl::handlePluginMessage));
register("wdl:init", true, directional(UNKNOWN, wdl::handlePluginMessage));
register("minecraft:intave", false, directional(UNKNOWN, DROP)); //undocumented, byte stringlength, clientconfig, byte length, json {"legacySneakHeight":false,"legacyOldRange":false,"legacyOldSlowdown":false}
register("waila:block", false, directional(UNKNOWN, DROP));
register("waila:entity", false, directional(UNKNOWN, DROP));
register("lambdacontrols:hello", false, directional(UNKNOWN, DROP));
register("midnightcontrols:controls_mode", false, directional(UNKNOWN, DROP));
register(ApolloManager.PLUGIN_MESSAGE_CHANNEL, true, async(lunar::handlePluginMessage));
register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage)));
register("labymod:neo", false, directional(UNKNOWN, DROP)); //undocumented, JSON format "0" byte, packetlängen byte, {"version":"4.1.25"}
register(FML.CHANNEL, true, directional(UNKNOWN, async(fml::handlePluginMessage)));
register(FML.CHANNEL, true, directional(UNKNOWN, async(new FML()::handlePluginMessage)));
//vanilla does not register any channels (sends only one minecraft:brand vanilla, nothing else (potential spoofed client detection))
//Forge interestingly registers all channels the server registers
//meteor https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java
//feather:client https://github.com/Koupah/Feather-Client-API/blob/main/src/club/koupah/feather/handler/FeatherHandler.java
//litematica/malilib https://github.com/maruohon/litematica/issues/75 https://github.com/maruohon/malilib/blob/liteloader_1.12.2/src/main/java/malilib/network/message/ConfigLockPacketHandler.java#L65
// Hackclientlike modsuppressor for labymod: https://github.com/Neocraftr/LabyMod-NeoEssentials (Potentially recognizable from NO Addons/NO Mods?) https://github.com/Neocraftr/LabyMod-NeoEssentials/blob/master/src/main/java/de/neocraftr/neoessentials/utils/BytecodeMethods.java
}

Datei anzeigen

@ -0,0 +1,52 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.mods;
import de.steamwar.bungeecore.listeners.PluginMessage;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.DefinedPacket;
public class Controlify {
//https://modrinth.com/mod/controlify
//https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicyPacket.java
//https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicies.java
public static final String CHANNEL = "controlify:server_policy";
private final byte[][] packets;
public Controlify() {
packets = new byte[][] {
restrict("reachAround"),
restrict("disableFlyDrifting")
};
}
private byte[] restrict(String name) {
return PluginMessage.genBufPacket(buf -> {
DefinedPacket.writeString(name, buf);
buf.writeBoolean(false);
});
}
public void onRegister(ProxiedPlayer player) {
for(byte[] packet : packets)
player.sendData(CHANNEL, packet);
}
}

Datei anzeigen

@ -22,6 +22,7 @@ package de.steamwar.bungeecore.mods;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.BasicListener;
import de.steamwar.bungeecore.listeners.IPSanitizer;
import de.steamwar.bungeecore.listeners.PluginMessage;
import de.steamwar.sql.Mod;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@ -55,19 +56,17 @@ public class FML2 extends BasicListener {
public FML2() {
fml2ModListPacket = generateModListPacket(false);
fml3ModListPacket = generateModListPacket(true);
forgeModListPacket = PluginMessage.genBufPacket(buf -> {
buf.writeByte(0); // Login wrapper packet
DefinedPacket.writeString("forge:handshake", buf);
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
ByteBuf wrapper = Unpooled.buffer();
wrapper.writeByte(0); // Login wrapper packet
DefinedPacket.writeString("forge:handshake", wrapper);
DefinedPacket.writeVarInt(packet.readableBytes(), wrapper);
wrapper.writeBytes(packet);
forgeModListPacket = new byte[wrapper.readableBytes()];
wrapper.readBytes(forgeModListPacket);
DefinedPacket.writeVarInt(packet.readableBytes(), buf);
buf.writeBytes(packet);
});
}
@EventHandler
@ -90,30 +89,28 @@ public class FML2 extends BasicListener {
}
private byte[] generateModListPacket(boolean fml3) {
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
return PluginMessage.genBufPacket(buf -> {
DefinedPacket.writeString("fml:handshake", buf);
if(fml3) {
DefinedPacket.writeVarInt(1, packet); // Channel amount
DefinedPacket.writeString("forge:tier_sorting", packet);
DefinedPacket.writeString("1.0", packet);
} else {
DefinedPacket.writeVarInt(0, packet); // Channel amount
}
ByteBuf packet = Unpooled.buffer();
packet.writeByte(1); // Mod list packet
DefinedPacket.writeVarInt(0, packet); // Mod amount
DefinedPacket.writeVarInt(0, packet); // Registries amount
if(fml3)
DefinedPacket.writeVarInt(0, packet); // DataPacks amount
if(fml3) {
DefinedPacket.writeVarInt(1, packet); // Channel amount
DefinedPacket.writeString("forge:tier_sorting", packet);
DefinedPacket.writeString("1.0", packet);
} else {
DefinedPacket.writeVarInt(0, packet); // Channel amount
}
ByteBuf wrapper = Unpooled.buffer();
DefinedPacket.writeString("fml:handshake", wrapper);
DefinedPacket.writeVarInt(packet.readableBytes(), wrapper);
wrapper.writeBytes(packet);
DefinedPacket.writeVarInt(0, packet); // Registries amount
if(fml3)
DefinedPacket.writeVarInt(0, packet); // DataPacks amount
byte[] data = new byte[wrapper.readableBytes()];
wrapper.readBytes(data);
return data;
DefinedPacket.writeVarInt(packet.readableBytes(), buf);
buf.writeBytes(packet);
});
}
private static class FML2LoginHandler extends PacketHandler {

Datei anzeigen

@ -0,0 +1,56 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bungeecore.mods;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class Feather {
//https://github.com/Koupah/Feather-Client-API/blob/main/src/club/koupah/feather/packets/FeatherMod.java
//https://archive.org/details/feather-server-api
public static final String CHANNEL = "feather:client";
private final byte[] packet;
public Feather() {
JsonArray array = new JsonArray();
array.add("clearWater");
array.add("coordinates");
array.add("coordinates");
array.add("hitbox");
array.add("hypixel");
array.add("reachDisplay");
array.add("snaplook");
array.add("toggleSprint");
JsonObject mods = new JsonObject();
mods.add("mods", array);
JsonObject obj = new JsonObject();
obj.addProperty("packetType", "DISABLE_MODS");
obj.add("payload", mods);
packet = obj.toString().getBytes();
}
public void sendRestrictions(ProxiedPlayer player) {
player.sendData(CHANNEL, packet);
}
}

Datei anzeigen

@ -44,6 +44,7 @@ public class Hostname extends BasicListener {
knownHostnames.add("@mat:matdoes.dev "); //https://github.com/mat-1/matscan
knownHostnames.add("wtf.mynx.lol"); //https://discord.com/invite/serverseeker
knownHostnames.add("masscan");
knownHostnames.add("aaa");
knownExtraData.add("");
knownExtraData.add("\0FML\0");

Datei anzeigen

@ -23,6 +23,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.listeners.PluginMessage;
import de.steamwar.sql.Mod;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@ -41,18 +42,16 @@ public class LabyMod {
private final byte[] gameInfoPacket;
public LabyMod() {
ByteBuf buf = Unpooled.buffer();
DefinedPacket.writeString("discord_rpc", buf);
gameInfoPacket = PluginMessage.genBufPacket(buf -> {
DefinedPacket.writeString("discord_rpc", buf);
JsonObject json = new JsonObject();
json.addProperty("hasGame", true);
json.addProperty("game_mode", "steamwar.de");
json.addProperty("game_startTime", 0);
json.addProperty("game_endTime", 0);
DefinedPacket.writeString(json.toString(), buf);
gameInfoPacket = new byte[buf.readableBytes()];
buf.readBytes(gameInfoPacket);
JsonObject json = new JsonObject();
json.addProperty("hasGame", true);
json.addProperty("game_mode", "steamwar.de");
json.addProperty("game_startTime", 0);
json.addProperty("game_endTime", 0);
DefinedPacket.writeString(json.toString(), buf);
});
}
public void handlePluginMessage(PluginMessageEvent event) {
@ -67,9 +66,11 @@ public class LabyMod {
JsonObject message = JsonParser.parseString(DefinedPacket.readString(buf)).getAsJsonObject();
List<Mod> mods = new LinkedList<>();
for(JsonElement element : message.getAsJsonArray("addons")) {
JsonObject addon = element.getAsJsonObject();
mods.add(Mod.getOrCreate(addon.get("name").getAsString(), Mod.Platform.LABYMOD));
if(message.has("addons")) {
for(JsonElement element : message.getAsJsonArray("addons")) {
JsonObject addon = element.getAsJsonObject();
mods.add(Mod.getOrCreate(addon.get("name").getAsString(), Mod.Platform.LABYMOD));
}
}
if(message.has("mods")) {

Datei anzeigen

@ -50,7 +50,7 @@ public class Lunar {
private final ApolloModuleManager manager = new ApolloModuleManagerImpl().addModule(ModSettingModule.class);
public Lunar() {
public Lunar() { //TODO seems defunct
Options modSettings = manager.getModule(ModSettingModule.class).getOptions();
modSettings.set(ModReplaymod.ENABLED, false); // TODO check if restrictions working
modSettings.set(ModFreelook.ENABLED, false);

Datei anzeigen

@ -31,8 +31,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.event.EventHandler;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class ReplayMod extends BasicListener {
@ -43,18 +41,14 @@ public class ReplayMod extends BasicListener {
private final byte[] restrict;
public ReplayMod() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
restrict = PluginMessage.genStreamPacket(out -> {
for(String restriction : Arrays.asList("no_xray", "no_noclip", "only_first_person", "only_recording_player")) {
byte[] bytes = restriction.getBytes();
stream.write(bytes.length);
stream.write(bytes);
stream.write(1); // restrict
out.writeByte(bytes.length);
out.write(bytes);
out.writeBoolean(true); // restrict
}
} catch (IOException e) {
throw new SecurityException(e);
}
restrict = stream.toByteArray();
});
}
@EventHandler

Datei anzeigen

@ -23,10 +23,6 @@ import de.steamwar.bungeecore.listeners.PluginMessage;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class WorldDownloader {
// https://wiki.vg/Plugin_channels/World_downloader
// https://github.com/Pokechu22/WorldDownloader-Serverside-Companion
@ -35,10 +31,7 @@ public class WorldDownloader {
private final byte[] controlPacket;
public WorldDownloader() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(stream);
try {
controlPacket = PluginMessage.genStreamPacket(out -> {
out.writeInt(1); // basic data packet
out.writeBoolean(false); // General download enabled
out.writeInt(-1); // Save radius
@ -46,11 +39,7 @@ public class WorldDownloader {
out.writeBoolean(false); // Entity saving enabled
out.writeBoolean(false); // Tile entity saving disabled
out.writeBoolean(false); // Container saving disabled
} catch (IOException e) {
throw new SecurityException("Could not create AntiWDL packet", e);
}
controlPacket = stream.toByteArray();
});
}
public void handlePluginMessage(PluginMessageEvent event) {