feat: add Leaves' Creative Fly No Clip feature

fix #16
This commit is contained in:
Helvetica Volubi
2026-03-09 00:13:08 +08:00
parent b22e9e588b
commit 85d2fa3372
3 changed files with 287 additions and 0 deletions
@@ -0,0 +1,25 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.protocol.CarpetServerProtocol;
import java.util.Set;
@ConfigClassInfo(name = "creative_fly_no_clip", category = EnumConfigCategory.FUNCTION)
public class CreativeFlyNoClipConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Whether to enable creative fly no clip.
When enabled, players in creative mode will not collide with blocks while flying.
This allows them to pass through blocks without obstruction.""")
public static boolean enabled = false;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
CarpetServerProtocol.CarpetRules.register(CarpetServerProtocol.CarpetRule.of("carpet", "creativeNoClip", enabled));
}
}
@@ -0,0 +1,114 @@
package org.leavesmc.leaves.protocol;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.CreativeFlyNoClipConfig;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
import org.slf4j.Logger;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@LeavesProtocol.Register(namespace = "carpet")
public class CarpetServerProtocol implements LeavesProtocol {
private static final Logger LOGGER = LogUtils.getClassLogger();
public static final String PROTOCOL_ID = "carpet";
public static final String VERSION = ProtocolUtils.buildProtocolVersion(PROTOCOL_ID);
private static final String HI = "69";
private static final String HELLO = "420";
@Contract("_ -> new")
public static Identifier id(String path) {
return Identifier.fromNamespaceAndPath(PROTOCOL_ID, path);
}
@ProtocolHandler.PlayerJoin
public static void onPlayerJoin(ServerPlayer player) {
CompoundTag data = new CompoundTag();
data.putString(HI, VERSION);
ProtocolUtils.sendPayloadPacket(player, new CarpetPayload(data));
}
@ProtocolHandler.PayloadReceiver(payload = CarpetPayload.class)
private static void handleHello(@NotNull ServerPlayer player, @NotNull CarpetServerProtocol.CarpetPayload payload) {
if (payload.nbt.contains(HELLO)) {
LOGGER.info("Player {} joined with carpet {}", player.getScoreboardName(), payload.nbt.getString(HELLO).orElse("Unknown"));
CompoundTag data = new CompoundTag();
CarpetRules.write(data);
ProtocolUtils.sendPayloadPacket(player, new CarpetPayload(data));
}
}
@Override
public boolean isActive() {
return CreativeFlyNoClipConfig.enabled;
} // re-edit for creative no clip
public static class CarpetRules {
private static final Map<String, CarpetRule> rules = new HashMap<>();
public static void write(@NotNull CompoundTag tag) {
CompoundTag rulesNbt = new CompoundTag();
rules.values().forEach(rule -> rule.writeNBT(rulesNbt));
tag.put("Rules", rulesNbt);
}
public static void register(CarpetRule rule) {
rules.put(rule.name, rule);
}
}
public record CarpetRule(String identifier, String name, String value) {
@NotNull
@Contract("_, _, _ -> new")
public static CarpetRule of(String identifier, String name, Enum<?> value) {
return new CarpetRule(identifier, name, value.name().toLowerCase(Locale.ROOT));
}
@NotNull
@Contract("_, _, _ -> new")
public static CarpetRule of(String identifier, String name, boolean value) {
return new CarpetRule(identifier, name, Boolean.toString(value));
}
public void writeNBT(@NotNull CompoundTag rules) {
CompoundTag rule = new CompoundTag();
String key = name;
while (rules.contains(key)) {
key = key + "2";
}
rule.putString("Value", value);
rule.putString("Manager", identifier);
rule.putString("Rule", name);
rules.put(key, rule);
}
}
public record CarpetPayload(CompoundTag nbt) implements LeavesCustomPayload {
@ID
private static final Identifier HELLO_ID = CarpetServerProtocol.id("hello");
@Codec
private static final StreamCodec<FriendlyByteBuf, CarpetPayload> CODEC = StreamCodec.composite(
ByteBufCodecs.COMPOUND_TAG, CarpetPayload::nbt, CarpetPayload::new
);
}
}