Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6427fdd
Update dependency maven.modrinth:the-rettington-companion to v2.3.1
renovate[bot] Aug 5, 2026
1f09df7
Merge pull request #511 from UnicacityAddon/renovate/maven.modrinth-t…
rettichlp Aug 5, 2026
83d273c
Add FontSetMixin to filter excluded glyphs from random glyph selection
rettichlp Aug 6, 2026
b0aea24
Update Gradle to v9.7.0
renovate[bot] Aug 7, 2026
b8e36cc
Update README with server-side bug fixes description for masked playe…
rettichlp Aug 7, 2026
8dedea9
Merge pull request #513 from UnicacityAddon/feature/fix-texture-bug-f…
rettichlp Aug 7, 2026
8ed6ad9
Merge pull request #514 from UnicacityAddon/renovate/gradle-9.x
rettichlp Aug 7, 2026
d79b682
Add option to block "Malle, I love you" sound
rettichlp Aug 7, 2026
cdaacf7
Update README to include optional "Malle, I love you" sound toggle
rettichlp Aug 7, 2026
79a3196
Merge pull request #515 from UnicacityAddon/feature/remove-malle-sound
rettichlp Aug 7, 2026
26c697e
Make "Auto trash can" customizable with per-item collection options a…
rettichlp Aug 8, 2026
0707239
Clarify automated trashcan item collection description in README
rettichlp Aug 8, 2026
d3be9c7
Refactor options screens to use GridLayout for improved layout struct…
rettichlp Aug 8, 2026
5270ad4
Merge pull request #516 from UnicacityAddon/bugfix/auto-trash-can-not…
rettichlp Aug 8, 2026
16a0afa
Optimize captcha map texture loading to avoid redundant updates
rettichlp Aug 10, 2026
fd9aeec
Replace Timer with ScheduledExecutorService for delayed actions in Ut…
rettichlp Aug 10, 2026
cda3679
Refactor NameTagService to streamline AFK and duty check logic
rettichlp Aug 10, 2026
5424de1
Add rich taxes command for non-premium players
rettichlp Aug 17, 2026
8e298a2
Merge pull request #518 from UnicacityAddon/feature/rich-taxes-comman…
rettichlp Aug 17, 2026
fcb713a
Update localization strings for "Handy" menu and app-related cases
rettichlp Aug 18, 2026
5648e5d
Pathfinding: Handle edge case for insolvent companies in StockMarketE…
rettichlp Aug 18, 2026
a27aea7
Merge pull request #519 from UnicacityAddon/feature/adjust-stock-mark…
rettichlp Aug 18, 2026
084c60c
Add support for parsing lumberjack sell messages and updating cash am…
rettichlp Aug 18, 2026
dbc02c1
Merge pull request #520 from UnicacityAddon/feature/adjust-lumberjack…
rettichlp Aug 18, 2026
fed0fc6
Update regex patterns in TheRettingtonCompanionIntegration to enforce…
rettichlp Aug 18, 2026
626569c
Merge pull request #521 from UnicacityAddon/feature/pattern-anchors-i…
rettichlp Aug 18, 2026
6200154
Merge branch 'develop' into feature/performance-improvements
rettichlp Aug 18, 2026
72741d5
Pathfinding: Document rich taxes command in README.md for non-premium…
rettichlp Aug 18, 2026
a2c3e16
Simplify config loading by using try-with-resources
rettichlp Aug 18, 2026
a520152
Optimize corpse scan logic by using time-based checks to reduce redun…
rettichlp Aug 18, 2026
9044e48
Clear player faction cache before syncing faction members to ensure d…
rettichlp Aug 18, 2026
6358846
Improve captcha image saving by offloading to a dedicated single-thre…
rettichlp Aug 18, 2026
91b06b9
Extract playerFaction logic in SoundTriggerListener into a dedicated …
rettichlp Aug 18, 2026
91e5228
Replace Timer with ScheduledExecutorService in CommandService for imp…
rettichlp Aug 18, 2026
8285456
Optimize listener retrieval using a cached map to improve performance…
rettichlp Aug 18, 2026
1bcd6ff
Update dependency maven.modrinth:the-rettington-companion to v2.4.0
renovate[bot] Aug 18, 2026
3d86bc0
Update required dependency version for TheRettingtonCompanion to >=2.4.0
rettichlp Aug 18, 2026
14302d4
Merge pull request #522 from UnicacityAddon/renovate/maven.modrinth-t…
rettichlp Aug 18, 2026
b2bbe8f
Add "Auto siren" option and implement automatic siren activation on duty
rettichlp Aug 18, 2026
a581697
Document siren auto-activation option in README
rettichlp Aug 18, 2026
c20dcf9
Merge pull request #523 from UnicacityAddon/feature/auto-siren
rettichlp Aug 18, 2026
6894386
Minor bug fixes
rettichlp Aug 19, 2026
a5ea312
Merge pull request #517 from UnicacityAddon/feature/performance-impro…
rettichlp Aug 19, 2026
abc6c0b
Update Gradle to v9.7.1
renovate[bot] Aug 19, 2026
e6f6101
Merge pull request #524 from UnicacityAddon/renovate/gradle-9.x
rettichlp Aug 20, 2026
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
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,15 @@ und [The Rettington Companion](https://modrinth.com/mod/the-rettington-companion
der so viel Geld einzahlt, bis der Bankautomat voll ist
- Mit dem `/aktien` Befehl wird die Aktien-App auf dem Händy direkt geöffnet, sodass man nicht mehr manuell durch das Handy navigieren
muss
- Kisten werden automatisch aus Mülleimern eingesammelt
- Gegenstände werden automatisch aus Mülleimern eingesammelt
- Es werden bestimmte Nachrichten im Chat ausgeblendet (konfigurierbar
über [The Rettington Companion](https://modrinth.com/mod/the-rettington-companion))
- Sollte ein Spieler abwesend sein, wird bei `/id` angezeigt wie lang dieser schon abwesend ist
- Die Nachricht, dass man keine Bandage vergeben kann, wird nur noch in der ActionBar angezeigt, da der Chat durch diese Nachrichten
zugespammt wird
- Beim Öffnen von Schatzkisten können die Delfine deaktiviert werden
- Der "Malle, I love you" Sound kann nun optional deaktiviert werden
- `/reichensteuer` Befehl für Spieler ohne Premium Rang

### Auto

Expand All @@ -92,6 +97,9 @@ und [The Rettington Companion](https://modrinth.com/mod/the-rettington-companion
- Für den Bluthändler, Dealer und Schwarzmarkt wird (in der Übersicht) angezeigt, an welchem Ort er gefunden wurde
- Es gibt einen Hotkey, um (für die entsprechende Fraktion relevante) Reinforcements automatisch anzunehmen (diese Reinforcements sind
mit ✨ markiert)
- Leichen werden leuchtend hervorgehoben, wenn man sich in der Nähe befindet (aktuell deaktiviert, da es gegen Server-Richtlinien
verstößt)
- Es gibt eine Option, die für Polizei, FBI und Rettungsdienst die Sirene aktiviert, sobald man den Dienst betritt

### Jobs

Expand All @@ -113,6 +121,14 @@ und [The Rettington Companion](https://modrinth.com/mod/the-rettington-companion
- Informationen über den PayDay (Dauer bis zum nächsten PayDay, Gehalt und Erfahrung) einschließlich Reichensteuer-Warnung
- Offene Notrufe

### Fehlerbehebungen auf Serverseite

> ℹ️ Folgende Funktionen sind Fehlerbehebungen für UnicaCity, die das Serverteam selbst nicht beheben kann:

- Maskierte Spieler haben einen verschleierten Namen (`§k`). Die Verschleierung nutzt auch Buchstaben, die im Resourcepack des Servers
zu Texturen überschrieben wurden. Dadurch wird in den Namen für maskierte Spieler ab und zu eine Textur anstatt Buchstaben angezeigt.
Dieses Problem wird durch die Mod behoben.

## Befehle

### Allgemein
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ dependencies {
implementation("org.atteo.classindex:classindex:3.13")
annotationProcessor("org.atteo.classindex:classindex:3.13")

compileOnly("maven.modrinth:the-rettington-companion:2.2.0")
compileOnly("maven.modrinth:the-rettington-companion:2.4.0")
}

tasks.processResources {
Expand Down
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-9.6.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/rettichlp/ucutils/command/ModCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public LiteralArgumentBuilder<FabricClientCommandSource> execute(@NotNull Litera
messageService.sendModMessage("UCUtils Version " + version, false);

messageService.sendModMessage(empty()
.append(Component.literal("Autors").withStyle(GRAY))
.append(Component.literal("Authors").withStyle(GRAY))
.append(Component.literal(":").withStyle(DARK_GRAY)).append(" ")
.append(Component.literal(authors).withStyle(WHITE)), false);

Expand Down
63 changes: 63 additions & 0 deletions src/main/java/de/rettichlp/ucutils/command/RichTaxesCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package de.rettichlp.ucutils.command;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import de.rettichlp.ucutils.common.registry.CommandBase;
import de.rettichlp.ucutils.common.registry.UCUtilsCommand;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import org.jetbrains.annotations.NotNull;

import static de.rettichlp.ucutils.UCUtils.commandService;
import static de.rettichlp.ucutils.UCUtils.configuration;
import static de.rettichlp.ucutils.UCUtils.messageService;
import static de.rettichlp.ucutils.UCUtils.storage;
import static de.rettichlp.ucutils.UCUtils.utilService;
import static de.rettichlp.ucutils.common.services.CommandService.COMMAND_COOLDOWN_MILLIS;

@UCUtilsCommand(label = "reichensteuer")
public class RichTaxesCommand extends CommandBase {

private static final int RICH_TAXES_THRESHOLD = 100000;

@Override
public LiteralArgumentBuilder<FabricClientCommandSource> execute(@NotNull LiteralArgumentBuilder<FabricClientCommandSource> node) {
return node
.executes(context -> {
if (storage.isPremium()) {
commandService.sendCommand("reichensteuern");
return 1;
}

// execute command to check money on the bank of player
commandService.sendCommand("atminfo");

// handle money withdraw
utilService.delayedAction(() -> {
int moneyAtmAmount = storage.getMoneyAtmAmount();
int moneyBankAmount = configuration.getMoneyBankAmount();

// check atm has money
if (moneyAtmAmount <= 0) {
messageService.sendModMessage("Der ATM hat kein Geld.", false);
return;
}

// check player has rich taxes
if (moneyBankAmount <= RICH_TAXES_THRESHOLD) {
messageService.sendModMessage("Du hast nicht ausreichend Geld auf der Bank.", false);
return;
}

int moneyThatNeedsToBeWithdrawn = moneyBankAmount - RICH_TAXES_THRESHOLD;

if (moneyAtmAmount >= moneyThatNeedsToBeWithdrawn) {
commandService.sendCommand("bank abbuchen " + moneyThatNeedsToBeWithdrawn);
} else {
commandService.sendCommand("bank abbuchen " + moneyAtmAmount);
messageService.sendModMessage("Du musst noch " + (moneyThatNeedsToBeWithdrawn - moneyAtmAmount) + "$ abbuchen.", false);
}
}, COMMAND_COOLDOWN_MILLIS);

return 1;
});
}
}
11 changes: 11 additions & 0 deletions src/main/java/de/rettichlp/ucutils/common/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ public class Storage {
@Setter
private Minecart minecartEntityToHighlight;

@Getter
@Setter
private int moneyAtmAmount = 0;

@Getter
@Setter
private boolean premium = false;
Expand Down Expand Up @@ -171,6 +175,8 @@ public void print() {
LOGGER.info("joinTimestamp: {}", this.joinTimestamp);
// minecartEntityToHighlight
LOGGER.info("minecartEntityToHighlight: {}", this.minecartEntityToHighlight);
// moneyAtmAmount
LOGGER.info("moneyAtmAmount: {}", this.moneyAtmAmount);
// premium
LOGGER.info("premium: {}", this.premium);
// stockMarketCommandRunning
Expand All @@ -186,6 +192,11 @@ public void print() {
}

public Faction getFaction(String playerName) {
Faction cachedFaction = this.playerFactionCache.get(playerName);
if (cachedFaction != null) {
return cachedFaction;
}

Faction faction = this.factionEntries.stream()
.filter(factionEntry -> factionEntry.members().stream()
.anyMatch(factionMember -> factionMember.username().equalsIgnoreCase(playerName)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ public Configuration loadFromFile() {
}

// load existing config
try {
Reader reader = newBufferedReader(CONFIG_PATH);
try (Reader reader = newBufferedReader(CONFIG_PATH)) {
return api.getGson().fromJson(reader, Configuration.class);
} catch (Exception e) {
LOGGER.error("Failed to load config from {}", CONFIG_PATH, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ public class MiscellaneousOptions {

private boolean showHydration = true;
private AtmInformationType atmInformationType = NONE;
private boolean autoCollectChestsFromTrashCans = false;
private boolean highlightCorpses = false; // feature rejected by UnicaCity team
private boolean hideDolphins = false;
private boolean blockMalleSound = false;
private boolean autoSiren = true;

@Getter
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.util.HashSet;
import java.util.Set;

import static de.rettichlp.ucutils.common.configuration.options.Options.ReinforcementType.UNICACITYADDON;
import static net.minecraft.ChatFormatting.AQUA;
import static net.minecraft.ChatFormatting.BLUE;
Expand All @@ -18,6 +21,9 @@
import static net.minecraft.client.gui.components.Tooltip.create;
import static net.minecraft.network.chat.Component.empty;
import static net.minecraft.network.chat.Component.literal;
import static net.minecraft.world.item.Items.CHEST;
import static net.minecraft.world.item.Items.ENDER_CHEST;
import static net.minecraft.world.item.Items.TRAPPED_CHEST;

@Getter
@Setter
Expand All @@ -33,6 +39,7 @@ public class Options {

private boolean checkUnicacityServer = true;
private ReinforcementType reinforcementType = UNICACITYADDON;
private Set<String> autoCollectFromTrashCan = new HashSet<>(Set.of(CHEST.toString(), TRAPPED_CHEST.toString(), ENDER_CHEST.toString()));

@Getter
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

import de.rettichlp.ucutils.common.configuration.options.MiscellaneousOptions;
import de.rettichlp.ucutils.common.gui.screens.OptionsScreen;
import de.rettichlp.ucutils.common.gui.screens.components.CyclingButtonEntry;
import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.layouts.GridLayout;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;

import static de.rettichlp.ucutils.UCUtils.commandService;
import static de.rettichlp.ucutils.UCUtils.renderService;
import static net.minecraft.client.gui.layouts.LinearLayout.horizontal;
import static net.minecraft.client.gui.layouts.LinearLayout.vertical;
import static de.rettichlp.ucutils.UCUtils.configuration;
import static net.minecraft.client.gui.components.Tooltip.create;
import static net.minecraft.network.chat.CommonComponents.NEW_LINE;
import static net.minecraft.network.chat.Component.translatable;
import static net.minecraft.util.CommonColors.RED;
Expand All @@ -27,27 +29,63 @@ public class MiscellaneousOptionsScreen extends OptionsScreen {
private static final Component HIGHLIGHT_CORPSES_TOOLTIP = translatable("ucutils.options.highlight_corpses.tooltip").append(NEW_LINE).append(translatable("ucutils.feature_disabled").withColor(RED));
private static final Component HIDE_DOLPHINS_NAME = translatable("ucutils.options.hide_dolphins.name");
private static final Component HIDE_DOLPHINS_TOOLTIP = translatable("ucutils.options.hide_dolphins.tooltip");
private static final Component BLOCK_MALLE_SOUND_NAME = translatable("ucutils.options.block_malle_sound.name");
private static final Component BLOCK_MALLE_SOUND_TOOLTIP = translatable("ucutils.options.block_malle_sound.tooltip");
private static final Component AUTO_SIREN_NAME = translatable("ucutils.options.auto_siren.name");
private static final Component AUTO_SIREN_TOOLTIP = translatable("ucutils.options.auto_siren.tooltip");

public MiscellaneousOptionsScreen(Screen parent) {
super(parent, TEXT_MISCELLANEOUS);
}

@Override
public void initBody() {
LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4));
GridLayout gridLayout = this.layout.addToContents(new GridLayout());
gridLayout.columnSpacing(8).rowSpacing(4);
GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2);

LinearLayout directionalLayoutWidget1 = directionalLayoutWidget.addChild(horizontal().spacing(8));
renderService.addToggleButton(directionalLayoutWidget1, HYDRATION_NAME, HYDRATION_TOOLTIP, (options, value) -> options.miscellaneous().showHydration(value), options -> options.miscellaneous().showHydration(), 150);
renderService.addCyclingButton(directionalLayoutWidget1, BANK_INFORMATION_NAME, MiscellaneousOptions.AtmInformationType.values(), MiscellaneousOptions.AtmInformationType::getDisplayName, (options, value) -> options.miscellaneous().atmInformationType(value), options -> options.miscellaneous().atmInformationType(), 150);
MiscellaneousOptions miscellaneousOptions = configuration.getOptions().miscellaneous();

LinearLayout directionalLayoutWidget2 = directionalLayoutWidget.addChild(horizontal().spacing(8));
renderService.addToggleButton(directionalLayoutWidget2, AUTO_TRASH_CAN_NAME, AUTO_TRASH_CAN_TOOLTIP, (options, value) -> options.miscellaneous().autoCollectChestsFromTrashCans(value), options -> options.miscellaneous().autoCollectChestsFromTrashCans(), 150);
ToggleButtonWidget toggleButtonWidget = renderService.addToggleButton(directionalLayoutWidget2, HIGHLIGHT_CORPSES_NAME, HIGHLIGHT_CORPSES_TOOLTIP, (options, value) -> options.miscellaneous().highlightCorpses(value), options -> options.miscellaneous().highlightCorpses(), 150);
toggleButtonWidget.active = commandService.isSuperUser();
ToggleButtonWidget toggleButton1 = new ToggleButtonWidget(HYDRATION_NAME, miscellaneousOptions::showHydration, miscellaneousOptions.showHydration());
toggleButton1.setWidth(150);
toggleButton1.setTooltip(create(HYDRATION_TOOLTIP));
gridLayoutRowHelper.addChild(toggleButton1);

LinearLayout directionalLayoutWidget3 = directionalLayoutWidget.addChild(horizontal().spacing(8));
renderService.addToggleButton(directionalLayoutWidget3, HIDE_DOLPHINS_NAME, HIDE_DOLPHINS_TOOLTIP, (options, value) -> options.miscellaneous().hideDolphins(value), options -> options.miscellaneous().hideDolphins(), 150);
CycleButton<MiscellaneousOptions.AtmInformationType> cycleButton1 = CycleButton.builder(MiscellaneousOptions.AtmInformationType::getDisplayName, miscellaneousOptions.atmInformationType())
.withValues(MiscellaneousOptions.AtmInformationType.values())
.withTooltip(CyclingButtonEntry::getTooltip)
.create(BANK_INFORMATION_NAME, (_, value) -> miscellaneousOptions.atmInformationType(value));
cycleButton1.setWidth(150);
gridLayoutRowHelper.addChild(cycleButton1);

directionalLayoutWidget.visitWidgets(this::addRenderableWidget);
Button button1 = Button.builder(AUTO_TRASH_CAN_NAME, _ -> this.minecraft.gui.setScreen(new TrashCanOptionsScreen(this)))
.tooltip(create(AUTO_TRASH_CAN_TOOLTIP))
.width(150)
.build();
gridLayoutRowHelper.addChild(button1);

ToggleButtonWidget toggleButton2 = new ToggleButtonWidget(HIGHLIGHT_CORPSES_NAME, miscellaneousOptions::highlightCorpses, miscellaneousOptions.highlightCorpses());
toggleButton2.setWidth(150);
toggleButton2.setTooltip(create(HIGHLIGHT_CORPSES_TOOLTIP));
toggleButton2.active = commandService.isSuperUser();
gridLayoutRowHelper.addChild(toggleButton2);

ToggleButtonWidget toggleButton3 = new ToggleButtonWidget(HIDE_DOLPHINS_NAME, miscellaneousOptions::hideDolphins, miscellaneousOptions.hideDolphins());
toggleButton3.setWidth(150);
toggleButton3.setTooltip(create(HIDE_DOLPHINS_TOOLTIP));
gridLayoutRowHelper.addChild(toggleButton3);

ToggleButtonWidget toggleButton4 = new ToggleButtonWidget(BLOCK_MALLE_SOUND_NAME, miscellaneousOptions::blockMalleSound, miscellaneousOptions.blockMalleSound());
toggleButton4.setWidth(150);
toggleButton4.setTooltip(create(BLOCK_MALLE_SOUND_TOOLTIP));
gridLayoutRowHelper.addChild(toggleButton4);

ToggleButtonWidget toggleButton5 = new ToggleButtonWidget(AUTO_SIREN_NAME, miscellaneousOptions::autoSiren, miscellaneousOptions.autoSiren());
toggleButton5.setWidth(150);
toggleButton5.setTooltip(create(AUTO_SIREN_TOOLTIP));
gridLayoutRowHelper.addChild(toggleButton5);

gridLayout.arrangeElements();
gridLayout.visitWidgets(this::addRenderableWidget);
}
}
Loading