Skip to content
Merged
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
10 changes: 4 additions & 6 deletions src/main/java/de/rettichlp/ucutils/UCUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import org.slf4j.Logger;
Expand Down Expand Up @@ -62,7 +61,7 @@ public void onInitialize() {
player = client.player;
networkHandler = handler;

boolean isUnicaCity = isUnicaCity();
boolean isUnicaCity = isUnicaCity(handler);
storage.setUnicaCity(isUnicaCity);
if (isUnicaCity) {
client.execute(() -> {
Expand All @@ -74,19 +73,18 @@ public void onInitialize() {
}
});

syncService.checkThirst();

ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> this.registry.registerCommands(dispatcher));

ClientLifecycleEvents.CLIENT_STOPPING.register(client -> configuration.saveToFile());
}

private boolean isUnicaCity() {
private boolean isUnicaCity(ClientPlayNetworkHandler networkHandler) {
if (getBoolean("fabric.development")) {
return true;
}

MinecraftClient client = MinecraftClient.getInstance();

ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (isNull(networkHandler)) {
LOGGER.warn("Not connected to UnicaCity: Network handler is null");
return false;
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/de/rettichlp/ucutils/common/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ public class Storage {

@Getter
@Setter
private boolean unicaCity = false;
private double thirst = -1.0;

@Getter
@Setter
private ToggledChat toggledChat = NONE;

@Getter
@Setter
private boolean unicaCity = false;

{
this.blackMarkets.addAll(stream(BlackMarket.Type.values())
.map(type -> new BlackMarket(type, null, false))
Expand Down Expand Up @@ -158,10 +162,12 @@ public void print() {
LOGGER.info("minecartEntityToHighlight: {}", this.minecartEntityToHighlight);
// moneyAtmAmount
LOGGER.info("moneyAtmAmount: {}", this.moneyAtmAmount);
// unicaCity
LOGGER.info("unicaCity: {}", this.unicaCity);
// thirst
LOGGER.info("thirst: {}", this.thirst);
// toggledChat
LOGGER.info("toggledChat: {}", this.toggledChat);
// unicaCity
LOGGER.info("unicaCity: {}", this.unicaCity);
}

public Faction getCachedFaction(String playerName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class Options {
private ReinforcementType reinforcementType = UNICACITYADDON;
private boolean customSounds = true;
private AtmInformationType atmInformationType = NONE;
private boolean showThirst = true;

@Getter
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public class MainOptionsScreen extends OptionsScreen {
private static final Text NOTIFICATION_SOUNDS_NAME = translatable("ucutils.options.notification_sounds.name");
private static final Text NOTIFICATION_SOUNDS_TOOLTIP = translatable("ucutils.options.notification_sounds.tooltip");
private static final Text BANK_INFORMATION_NAME = translatable("ucutils.options.atm_information.name");
private static final Text THIRST_NAME = translatable("ucutils.options.thirst.name");
private static final Text THIRST_TOOLTIP = translatable("ucutils.options.thirst.tooltip");

public MainOptionsScreen() {
super(new GameMenuScreen(true));
Expand All @@ -44,6 +46,9 @@ public void initBody() {
renderService.addButton(directionalLayoutWidget3, TEXT_WIDGETS, button -> this.client.setScreen(new WidgetOptionsScreen(this)), 150);
renderService.addCyclingButton(directionalLayoutWidget3, BANK_INFORMATION_NAME, Options.AtmInformationType.values(), Options.AtmInformationType::getDisplayName, Options::atmInformationType, Options::atmInformationType, 150);

DirectionalLayoutWidget directionalLayoutWidget4 = directionalLayoutWidget.add(horizontal().spacing(8));
renderService.addToggleButton(directionalLayoutWidget4, THIRST_NAME, THIRST_TOOLTIP, Options::showThirst, Options::showThirst, 150);

directionalLayoutWidget.forEachChild(this::addDrawableChild);
}
}
102 changes: 102 additions & 0 deletions src/main/java/de/rettichlp/ucutils/common/services/SyncService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@
import de.rettichlp.ucutils.common.models.Faction;
import de.rettichlp.ucutils.common.models.FactionEntry;
import lombok.Getter;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.text.HoverEvent;
import net.minecraft.text.Text;

import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import static de.rettichlp.ucutils.UCUtils.LOGGER;
import static de.rettichlp.ucutils.UCUtils.api;
Expand All @@ -31,6 +42,16 @@ public class SyncService {
@Getter
private boolean gameSyncProcessActive = false;

private ScheduledExecutorService scheduler;
private ScheduledFuture<?> scheduledTask;

private boolean executedByTask = false;
private int healthMessageLineCount = 0;

private static final Pattern HEALTH_STATUS_PATTERN = Pattern.compile(
"=== Zustand von .+ ===|Gesundheit|Blut|Hunger|Durst|Fett|Muskeln"
);

public void syncFactionMembers() {
for (Faction faction : Faction.values()) {
if (faction == NULL) {
Expand Down Expand Up @@ -93,4 +114,85 @@ public void checkForUpdates() {
}
});
}

public void checkThirst() {

ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> {

String plainText = message.getString();

if (this.executedByTask && HEALTH_STATUS_PATTERN.matcher(plainText).find()) {
this.healthMessageLineCount++;
if (this.healthMessageLineCount >= 7) {
this.executedByTask = false;
this.healthMessageLineCount = 0;
}
} else {
return true;
}

if (plainText.contains("Durst")) {
for (Text child : message.getSiblings()) {
HoverEvent hoverEvent = child.getStyle().getHoverEvent();
if (hoverEvent != null && hoverEvent.getAction() == HoverEvent.Action.SHOW_TEXT) {
if (hoverEvent instanceof HoverEvent.ShowText(Text value)) {
String hoverText = value.getString();
double thirst = this.parseFirstValue(hoverText);
storage.setThirst(thirst);
LOGGER.debug("Set Thirst: {}", thirst);
}
}
}
}

return false;
});

ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
if (!storage.isUnicaCity()) {
return;
}

LOGGER.info("Starting thirst monitoring scheduler");

this.scheduler = Executors.newSingleThreadScheduledExecutor();
this.scheduledTask = this.scheduler.scheduleAtFixedRate(() -> {
MinecraftClient instance = MinecraftClient.getInstance();
ClientPlayNetworkHandler networkHandler = instance.getNetworkHandler();
if (networkHandler == null) {
return;
}
instance.execute(() -> {
this.executedByTask = true;
this.healthMessageLineCount = 0;
networkHandler.sendChatCommand("health");
});
}, 0, 10, TimeUnit.SECONDS);

LOGGER.debug("Thirst monitoring scheduler started");
});

ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> {

storage.setThirst(-1.0);

this.executedByTask = false;
this.healthMessageLineCount = 0;
if (this.scheduledTask != null && !this.scheduledTask.isCancelled()) {
this.scheduledTask.cancel(false);
}
if (this.scheduler != null && !this.scheduler.isShutdown()) {
this.scheduler.shutdown();
}
});
}

private double parseFirstValue(String text) {
String cleaned = text.replaceAll("§.", "");
String[] parts = cleaned.split("/");
if (parts.length > 0) {
return Double.parseDouble(parts[0].trim());
}
return 0.0;
}
}
66 changes: 66 additions & 0 deletions src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package de.rettichlp.ucutils.mixin;

import com.llamalad7.mixinextras.sugar.Local;
import de.rettichlp.ucutils.UCUtils;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profilers;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(InGameHud.class)
public abstract class InGameHudMixin {

@Unique
private static final Identifier THIRST_EMPTY_TEXTURE =
Identifier.of("ucutils", "textures/hud/thirst_empty.png");
@Unique
private static final Identifier THIRST_HALF_TEXTURE =
Identifier.of("ucutils", "textures/hud/thirst_half.png");
@Unique
private static final Identifier THIRST_FULL_TEXTURE =
Identifier.of("ucutils", "textures/hud/thirst_full.png");

@Inject(
method = "renderStatusBars",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHealthBar(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/entity/player/PlayerEntity;IIIIFIIIZ)V",
shift = At.Shift.AFTER
)
)
private void inject(DrawContext context, CallbackInfo ci, @Local(ordinal = 3) int m, @Local(ordinal = 8) int r) {
if (!UCUtils.configuration.getOptions().showThirst() || UCUtils.storage.getThirst() == -1) {
return;
}
Profilers.get().swap("thirst");
this.ucutils$renderThirst(context, r, m);
}

@Unique
private void ucutils$renderThirst(DrawContext context, int y, int rightX) {
double thirst = UCUtils.storage.getThirst();

for (int i = 0; i < 10; ++i) {
int x = rightX - (i * 8) - 10;

double currentThirst = thirst - (i * 2.0);

Identifier texture;
if (currentThirst >= 2.0) {
texture = THIRST_FULL_TEXTURE;
} else if (currentThirst >= 1.0) {
texture = THIRST_HALF_TEXTURE;
} else {
texture = THIRST_EMPTY_TEXTURE;
}

context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, x, y, 0, 0, 9, 9, 9, 9);
}
}
}
4 changes: 3 additions & 1 deletion src/main/resources/assets/ucutils/lang/de_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,7 @@
"ucutils.screen.faction.blacklist.header.reason": "Grund",
"ucutils.screen.faction.blacklist.header.price": "Preis",
"ucutils.screen.faction.blacklist.header.kills": "Tode",
"ucutils.screen.shutdown_abort.button.name": "Herunterfahren abbrechen"
"ucutils.screen.shutdown_abort.button.name": "Herunterfahren abbrechen",
"ucutils.options.thirst.name": "Zeige Durst",
"ucutils.options.thirst.tooltip": "Zeige deinen Durst in deiner Hotbar an"
}
4 changes: 3 additions & 1 deletion src/main/resources/assets/ucutils/lang/en_gb.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,7 @@
"ucutils.screen.faction.blacklist.header.reason": "Reason",
"ucutils.screen.faction.blacklist.header.price": "Price",
"ucutils.screen.faction.blacklist.header.kills": "Kills",
"ucutils.screen.shutdown_abort.button.name": "Abort shutdown"
"ucutils.screen.shutdown_abort.button.name": "Abort shutdown",
"ucutils.options.thirst.name": "Show Thirst",
"ucutils.options.thirst.tooltip": "Display your thirst on your hotbar"
}
4 changes: 3 additions & 1 deletion src/main/resources/assets/ucutils/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,7 @@
"ucutils.screen.faction.blacklist.header.reason": "Reason",
"ucutils.screen.faction.blacklist.header.price": "Price",
"ucutils.screen.faction.blacklist.header.kills": "Kills",
"ucutils.screen.shutdown_abort.button.name": "Abort shutdown"
"ucutils.screen.shutdown_abort.button.name": "Abort shutdown",
"ucutils.options.thirst.name": "Show Thirst",
"ucutils.options.thirst.tooltip": "Display your thirst on your hotbar"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/main/resources/ucutils.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"ChatScreenMixin",
"ClientPlayerEntityMixin",
"GameMenuScreenMixin",
"InGameHudMixin",
"PlayerEntityRendererMixin",
"PlayerListHudMixin"
]
Expand Down