Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d9bd998
Basic packets & rendering.
S-N00B-1 Mar 6, 2025
5da92a4
Player Bar rendering & Packet
S-N00B-1 Mar 7, 2025
d441701
Refine playerbar rendering.
S-N00B-1 Mar 7, 2025
b291ef3
Improve player bar mod compat
S-N00B-1 Mar 8, 2025
84cbaba
Improve player bar mod compat
S-N00B-1 Mar 8, 2025
8132581
Merge remote-tracking branch 'origin/1.21-HUD' into 1.21-HUD
S-N00B-1 Mar 8, 2025
b2d33ce
Prepare Banner Packet
S-N00B-1 Mar 8, 2025
cd8698a
Handle server info outside of hud rendering.
S-N00B-1 Mar 9, 2025
388cceb
Handle spectator player bar rendering.
S-N00B-1 Mar 9, 2025
8d51d50
Replace inRound boolean with Phase enum
S-N00B-1 Mar 9, 2025
3fe5d69
Accept enum ordinals in packets.
S-N00B-1 Mar 11, 2025
fd2a9b6
Prep banner rendering.
S-N00B-1 Mar 11, 2025
facd097
Banner rendering.
S-N00B-1 Apr 18, 2025
e0a32dd
Port to Mojmaps Begin L4J/LCH Compat
S-N00B-1 Jun 13, 2025
be91aed
Minor L4J playerbar fix
S-N00B-1 Jun 13, 2025
d77d5e1
Disable Experience bar for non-l4j users
S-N00B-1 Jun 14, 2025
757df72
Prepare changes to ClientDataNetworking
S-N00B-1 Nov 11, 2025
db4ac53
Pull dependency versions from gradle properties
S-N00B-1 Nov 11, 2025
f1ee4bb
Update listed licence to match actual licence
S-N00B-1 Nov 11, 2025
04737d9
Prep HideVanillaHidMod
S-N00B-1 Nov 11, 2025
558a213
Fix gradle and loom
S-N00B-1 Nov 11, 2025
d412587
Incomplete port to 1.21.10
S-N00B-1 Nov 11, 2025
3e8f896
Fix PlayerBarRenderer
S-N00B-1 Nov 11, 2025
e024ee5
Evil Recipe Book code
S-N00B-1 Nov 11, 2025
7733395
Glide HUD rendering and Banner Rendering fixes
S-N00B-1 Nov 12, 2025
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
21 changes: 12 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.7-SNAPSHOT'
id 'fabric-loom' version "1.13-SNAPSHOT"
id 'maven-publish'
}

Expand All @@ -21,29 +21,32 @@ loom {
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
mappings loom.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"

modImplementation('net.kyrptonaught:kyrptconfig:1.6.1-1.21')
include('net.kyrptonaught:kyrptconfig:1.6.1-1.21')
modImplementation("net.kyrptonaught:kyrptconfig:${project.kyrptconfig_version}")
include("net.kyrptonaught:kyrptconfig:${project.kyrptconfig_version}")

modImplementation ("com.terraformersmc:modmenu:11.0.1"){
modImplementation ("com.terraformersmc:modmenu:${project.modmenu_version}"){
transitive(false)
}

modImplementation "com.ptsmods:devlogin:3.5"
modImplementation "com.ptsmods:devlogin:${project.devlogin_version}"

//midnightcontrols
modImplementation "maven.modrinth:obsidianui:0.2.6+mc1.21-fabric"
modImplementation "maven.modrinth:midnightlib:1.5.7-fabric"
modImplementation "maven.modrinth:midnightcontrols:1.9.7+1.21"
modImplementation "maven.modrinth:obsidianui:${project.obsidianui_version}"
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
modImplementation "maven.modrinth:midnightcontrols:${project.midnightcontrols_version}"
api('org.aperlambda:lambdajcommon:1.8.1') {
exclude group: 'com.google.code.gson'
exclude group: 'com.google.guava'
}

modCompileOnly("maven.modrinth:legacy4j:${project.legacy4j_version}")
modCompileOnly("maven.modrinth:factory-api:${project.factoryapi_version}")
}

base {
Expand Down
24 changes: 18 additions & 6 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true

# Loom Properties
loom_version=1.13-SNAPSHOT

# Fabric Properties
minecraft_version=1.21
yarn_mappings=1.21+build.2
loader_version=0.15.11
minecraft_version=1.21.10
loader_version=0.17.3

# Fabric API
fabric_version=0.100.4+1.21
fabric_version=0.138.3+1.21.10

# Mod Properties
mod_version=0.0.27-1.21
mod_version=0.0.28-1.21.10
maven_group=net.kyrptonaught
archives_base_name=lemclienthelper
archives_base_name=lemclienthelper

# Dependency Properties
kyrptconfig_version=1.6.1-1.21.4
modmenu_version=16.0.0-rc.1
devlogin_version=3.5
obsidianui_version=0.2.12+mc1.21.6-fabric
midnightlib_version=1.8.3+1.21.9-fabric
midnightcontrols_version=1.11.3-beta.3-fabric
legacy4j_version=1.21.10-1.8.5.2545.5+fabric
factoryapi_version=1.21.10-2.2.6.2545.1+fabric
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ public static boolean isOptifineLoaded(FabricLoader loader) {
return loader.isModLoaded("optifabric") || loader.isModLoaded("optifine");
}

public static boolean isL4JLoaded(FabricLoader loader) {
return loader.isModLoaded("legacy");
}

public static boolean isControllerModLoaded(FabricLoader loader) {
return loader.isModLoaded("midnightcontrols") ||
// loader.isModLoaded("legacy") || // Should L4J be counted as a controller mod?
loader.isModLoaded("lambdacontrols") ||
loader.isModLoaded("controllable") ||
loader.isModLoaded("controllermod");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,30 @@
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.kyrptonaught.lemclienthelper.ServerConfigs.ServerConfigsMod;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;

import java.util.concurrent.CompletableFuture;

public class ClientDataNetworking {
public static final Identifier HAS_MODS_PACKET = Identifier.of("scoreboardplayerinfo", "has_mods_packet");
public static final ResourceLocation HAS_MODS_PACKET = ResourceLocation.fromNamespaceAndPath("scoreboardplayerinfo", "has_mods_packet");


@Environment(EnvType.CLIENT)
public static void sendHasLEMPacket() {
ClientLoginNetworking.registerGlobalReceiver(HAS_MODS_PACKET, (client, handler, buf, listenerAdder) -> {
FabricLoader loader = FabricLoader.getInstance();

PacketByteBuf respondeBuf = new PacketByteBuf(Unpooled.buffer());
FriendlyByteBuf respondeBuf = new FriendlyByteBuf(Unpooled.buffer());
respondeBuf.writeBoolean(true); //LEMClientHelper, Always true
// TODO: Start sending LCH version, this can help when diagnosing issues caused by differences between
// server Heirloom ver and client LCH ver.
// respondeBuf.writeString(LEMClientHelperMod.MOD_VERSION);
respondeBuf.writeBoolean(ClientDataMod.isOptifineLoaded(loader));
respondeBuf.writeBoolean(ClientDataMod.isControllerModLoaded(loader));
// TODO: Send L4J info,
// (Note, probably should also send version for this, as L4J tends to change alot update to update.)
// respondeBuf.writeBoolean(ClientDataMod.isL4JLoaded(loader));
respondeBuf.writeInt(ServerConfigsMod.getConfig().guiScale);
respondeBuf.writeInt(ServerConfigsMod.getConfig().panScale);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,22 @@
import net.kyrptonaught.lemclienthelper.ClientData.ClientDataMod;
import net.kyrptonaught.lemclienthelper.ResourcePreloader.ResourcePreloaderMod;
import net.kyrptonaught.lemclienthelper.ServerConfigs.ServerConfigsMod;
import net.kyrptonaught.lemclienthelper.ServerInfo.ServerInfoMod;
import net.kyrptonaught.lemclienthelper.SmallInv.SmallInvMod;
import net.kyrptonaught.lemclienthelper.SpectateSqueaker.SpectateSqueakerMod;
import net.kyrptonaught.lemclienthelper.TakeEverything.TakeEverythingMod;
import net.kyrptonaught.lemclienthelper.customWorldBorder.CustomWorldBorderMod;
import net.kyrptonaught.lemclienthelper.hud.HudMod;
import net.kyrptonaught.lemclienthelper.syncedKeybinds.SyncedKeybindsMod;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.KeyMapping;
import com.mojang.blaze3d.platform.InputConstants;

public class LEMClientHelperMod implements ClientModInitializer {
public static final String MOD_ID = "lemclienthelper";

//TODO Find a better way to get this value.
public static final String MOD_VERSION = FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow().getMetadata().getVersion().getFriendlyString();

public static ConfigManager.MultiConfigManager configManager = new ConfigManager.MultiConfigManager(MOD_ID);


Expand All @@ -27,6 +32,7 @@ public void onInitializeClient() {
ResourcePreloaderMod.onInitialize();
SmallInvMod.onInitialize();
ClientDataMod.onInitialize();
ServerInfoMod.onInitialize();
SyncedKeybindsMod.onInitialize();
SpectateSqueakerMod.onInitialize();
ServerConfigsMod.onInitialize();
Expand All @@ -43,14 +49,14 @@ public static void registerControllerKeys() {
TakeEverythingMod.registerControllerKeys();
}

public static boolean isKeybindPressed(KeyBinding keyBinding, int pressedKeyCode, boolean isMouse) {
InputUtil.Key keycode = KeyBindingHelper.getBoundKeyOf(keyBinding);
public static boolean isKeybindPressed(KeyMapping keyBinding, int pressedKeyCode, boolean isMouse) {
InputConstants.Key keycode = KeyBindingHelper.getBoundKeyOf(keyBinding);

if (isMouse) {
if (keycode.getCategory() != InputUtil.Type.MOUSE) return false;
if (keycode.getType() != InputConstants.Type.MOUSE) return false;
} else {
if (keycode.getCategory() != InputUtil.Type.KEYSYM) return false;
if (keycode.getType() != InputConstants.Type.KEYSYM) return false;
}
return keycode.getCode() == pressedKeyCode;
return keycode.getValue() == pressedKeyCode;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.kyrptonaught.lemclienthelper.ResourcePreloader;

import net.minecraft.text.Text;
import net.minecraft.network.chat.Component;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -14,8 +14,8 @@ public static class RPOption {
public String url;

public UUID uuid;
public Text status;
public Text status2;
public Component status;
public Component status2;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.mojang.realmsclient.Unit;
import com.mojang.util.UndashedUuid;
import net.kyrptonaught.jankson.Jankson;
import net.kyrptonaught.lemclienthelper.LEMClientHelperMod;
import net.minecraft.GameVersion;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.realms.SizeUnit;
import net.minecraft.client.session.Session;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.resource.ResourceType;
import net.minecraft.text.Text;
import net.minecraft.util.NetworkUtils;
import net.minecraft.util.Util;
import net.minecraft.util.path.CacheFiles;
import net.minecraft.WorldVersion;
import net.minecraft.client.Minecraft;
import net.minecraft.client.User;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.network.chat.Component;
import net.minecraft.server.packs.DownloadCacheCleaner;
import net.minecraft.server.packs.PackType;
import net.minecraft.util.HttpUtil;
import net.minecraft.Util;

import java.io.InputStream;
import java.net.Proxy;
Expand Down Expand Up @@ -61,18 +61,18 @@ public static void getPackList() {
}

public static void downloadPacks() {
Path downloadsDirectory = MinecraftClient.getInstance().runDirectory.toPath().resolve("downloads");
Path downloadsDirectory = Minecraft.getInstance().gameDirectory.toPath().resolve("downloads");
HashFunction SHA1 = Hashing.sha1();
Map<String, String> headers = getHeaders(MinecraftClient.getInstance().getSession());
Proxy proxy = MinecraftClient.getInstance().getNetworkProxy();
Map<String, String> headers = getHeaders(Minecraft.getInstance().getUser());
Proxy proxy = Minecraft.getInstance().getProxy();

AtomicInteger counter = new AtomicInteger(allPacks.packs.size());
for (AllPacks.RPOption rpOption : allPacks.packs) {
if (!checkPack(rpOption.uuid)) {
Util.getDownloadWorkerExecutor().execute(() -> downloadPack(rpOption, downloadsDirectory, SHA1, headers, proxy, () -> {
Util.nonCriticalIoPool().execute(() -> downloadPack(rpOption, downloadsDirectory, SHA1, headers, proxy, () -> {
counter.getAndDecrement();
if (counter.get() <= 0 && getConfig().toastComplete) {
SystemToast.add(MinecraftClient.getInstance().getToastManager(), SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("key.lemclienthelper.alldownloadcomplete"), null);
SystemToast.add(Minecraft.getInstance().getToastManager(), SystemToast.SystemToastId.PERIODIC_NOTIFICATION, Component.translatable("key.lemclienthelper.alldownloadcomplete"), null);
}
}));
}
Expand All @@ -81,29 +81,29 @@ public static void downloadPacks() {

public static void downloadPack(AllPacks.RPOption rpOption, Path downloadsDirectory, HashFunction SHA1, Map<String, String> headers, Proxy proxy, Runnable onComplete) {
try {
NetworkUtils.download(downloadsDirectory.resolve(rpOption.uuid.toString()), new URL(rpOption.url), headers, SHA1, null, 0xFA00000, proxy, createListener(rpOption, onComplete));
HttpUtil.downloadFile(downloadsDirectory.resolve(rpOption.uuid.toString()), new URL(rpOption.url), headers, SHA1, null, 0xFA00000, proxy, createListener(rpOption, onComplete));
} catch (Exception e) {
e.printStackTrace();
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloaderror"), null);
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloaderror"), null);
}
}

public static void deletePacks() {
CacheFiles.clear(MinecraftClient.getInstance().runDirectory.toPath().resolve("downloads"), 0);
DownloadCacheCleaner.vacuumCacheDir(Minecraft.getInstance().gameDirectory.toPath().resolve("downloads"), 0);
}

private static boolean checkPack(UUID packID) {
Path downloadsDirectory = MinecraftClient.getInstance().runDirectory.toPath().resolve("downloads");
Path downloadsDirectory = Minecraft.getInstance().gameDirectory.toPath().resolve("downloads");
if (Files.exists(downloadsDirectory.resolve(packID.toString()))) {
setStatus(packID, Text.translatable("key.lemclienthelper.alreadydownloaded"), null);
setStatus(packID, Component.translatable("key.lemclienthelper.alreadydownloaded"), null);
return true;
}

setStatus(packID, null, null);
return false;
}

public static void setStatus(UUID packID, Text status, Text status2) {
public static void setStatus(UUID packID, Component status, Component status2) {
for (AllPacks.RPOption rpOption : allPacks.packs) {
if (rpOption.uuid == packID) {
rpOption.status = status;
Expand All @@ -112,41 +112,41 @@ public static void setStatus(UUID packID, Text status, Text status2) {
}
}

private static Map<String, String> getHeaders(Session session) {
GameVersion gameVersion = SharedConstants.getGameVersion();
return Map.of("X-Minecraft-Username", session.getUsername(), "X-Minecraft-UUID", UndashedUuid.toString(session.getUuidOrNull()), "X-Minecraft-Version", gameVersion.getName(), "X-Minecraft-Version-ID", gameVersion.getId(), "X-Minecraft-Pack-Format", String.valueOf(gameVersion.getResourceVersion(ResourceType.CLIENT_RESOURCES)), "User-Agent", "Minecraft Java/" + gameVersion.getName());
private static Map<String, String> getHeaders(User session) {
WorldVersion gameVersion = SharedConstants.getCurrentVersion();
return Map.of("X-Minecraft-Username", session.getName(), "X-Minecraft-UUID", UndashedUuid.toString(session.getProfileId()), "X-Minecraft-Version", gameVersion.name(), "X-Minecraft-Version-ID", gameVersion.id(), "X-Minecraft-Pack-Format", String.valueOf(gameVersion.packVersion(PackType.CLIENT_RESOURCES)), "User-Agent", "Minecraft Java/" + gameVersion.name());
}

private static NetworkUtils.DownloadListener createListener(AllPacks.RPOption rpOption, Runnable onComplete) {
return new NetworkUtils.DownloadListener() {
private static HttpUtil.DownloadProgressListener createListener(AllPacks.RPOption rpOption, Runnable onComplete) {
return new HttpUtil.DownloadProgressListener() {
private OptionalLong contentLength = OptionalLong.empty();

private Text getProgress(long writtenBytes) {
return this.contentLength.isPresent() ? Text.translatable("download.pack.progress.percent", writtenBytes * 100L / this.contentLength.getAsLong()) : Text.translatable("download.pack.progress.bytes", SizeUnit.getUserFriendlyString(writtenBytes));
private Component getProgress(long writtenBytes) {
return this.contentLength.isPresent() ? Component.translatable("download.pack.progress.percent", writtenBytes * 100L / this.contentLength.getAsLong()) : Component.translatable("download.pack.progress.bytes", Unit.humanReadable(writtenBytes));
}

@Override
public void onStart() {
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloading"), null);
public void requestStart() {
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloading"), null);
}

@Override
public void onContentLength(OptionalLong contentLength) {
public void downloadStart(OptionalLong contentLength) {
this.contentLength = contentLength;
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloading"), getProgress(0L));
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloading"), getProgress(0L));
}

@Override
public void onProgress(long writtenBytes) {
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloading"), getProgress(writtenBytes));
public void downloadedBytes(long writtenBytes) {
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloading"), getProgress(writtenBytes));
}

@Override
public void onFinish(boolean success) {
public void requestFinished(boolean success) {
if (!success) {
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloaderror"), null);
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloaderror"), null);
} else {
setStatus(rpOption.uuid, Text.translatable("key.lemclienthelper.downloadcomplete"), null);
setStatus(rpOption.uuid, Component.translatable("key.lemclienthelper.downloadcomplete"), null);
}
onComplete.run();
}
Expand Down
Loading
Loading