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
22 changes: 22 additions & 0 deletions docs/wiki/Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,18 @@ Dropping can be configured based on modes:

Automatically eats food when health or hunger is below a set threshold.



Which foods to eat can be configured based on modes:



* `all`: any food

* `whitelist`: only added foods

* `blacklist`: any food not added

**Usage**

```autoEat on/off```
Expand All @@ -1480,6 +1492,16 @@ Automatically eats food when health or hunger is below a set threshold.

```autoEat allowUnsafeFood on/off```

```autoEat mode <all/whitelist/blacklist>```

```autoEat add/del <food>```

```autoEat addAll <food1>,<food2>,...```

```autoEat list```

```autoEat clear```


### autoFish

Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/zenith/command/brigadier/FoodArgument.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.zenith.command.brigadier;

import com.mojang.brigadier.LiteralMessage;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.zenith.mc.food.FoodData;
import com.zenith.mc.food.FoodRegistry;
import lombok.Data;
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandParser;
import org.jspecify.annotations.NonNull;

import java.util.concurrent.CompletableFuture;

@Data
public class FoodArgument implements SerializableArgumentType<FoodData> {
public static final SimpleCommandExceptionType INVALID_ITEM_EXCEPTION = new SimpleCommandExceptionType(
new LiteralMessage("Invalid item")
);

public static FoodArgument food() {
return new FoodArgument();
}

@Override
public FoodData parse(final StringReader reader) throws CommandSyntaxException {
int i = reader.getCursor();
var itemName = readItemString(reader);
if (itemName.contains(":")) {
// may look like minecraft:item_name
var itemNameNamespaceSplit = itemName.split(":");
if (itemNameNamespaceSplit.length != 2) {
reader.setCursor(i);
throw INVALID_ITEM_EXCEPTION.create();
}
itemName = itemNameNamespaceSplit[1];
}
var itemData = FoodRegistry.REGISTRY.get(itemName);
if (itemData == null) {
reader.setCursor(i);
throw INVALID_ITEM_EXCEPTION.create();
}
return itemData;
}

public static FoodData getFood(final CommandContext<com.zenith.command.api.CommandContext> context, String name) {
return context.getArgument(name, FoodData.class);
}

private String readItemString(StringReader reader) throws CommandSyntaxException {
final int start = reader.getCursor();
while (reader.canRead() && isAllowedInItemString(reader.peek())) {
reader.skip();
}
if (reader.getCursor() == start) {
reader.setCursor(start);
throw INVALID_ITEM_EXCEPTION.createWithContext(reader);
}
return reader.getString().substring(start, reader.getCursor());
}

private static boolean isAllowedInItemString(final char c) {
return c >= 'A' && c <= 'Z'
|| c >= 'a' && c <= 'z'
|| c == '_' || c == ':';
}

@Override
public @NonNull CommandParser commandParser() {
return CommandParser.ITEM_STACK;
}

@Override
public CompletableFuture<Suggestions> listSuggestions(final CommandContext context, final SuggestionsBuilder builder) {
return RegistryDataArgument.listRegistrySuggestions(context, builder, FoodRegistry.REGISTRY);
}
}
97 changes: 92 additions & 5 deletions src/main/java/com/zenith/command/impl/AutoEatCommand.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
package com.zenith.command.impl;

import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.zenith.command.api.Command;
import com.zenith.command.api.CommandCategory;
import com.zenith.command.api.CommandContext;
import com.zenith.command.api.CommandUsage;
import com.zenith.discord.Embed;
import com.zenith.mc.food.FoodRegistry;
import com.zenith.module.impl.AutoEat;
import com.zenith.util.config.Config;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.zenith.Globals.CONFIG;
import static com.zenith.Globals.MODULE;
import static com.zenith.command.brigadier.CustomStringArgumentType.getString;
import static com.zenith.command.brigadier.FoodArgument.food;
import static com.zenith.command.brigadier.FoodArgument.getFood;
import static com.zenith.command.brigadier.ItemArgument.item;
import static com.zenith.command.brigadier.ToggleArgumentType.getToggle;
import static com.zenith.command.brigadier.ToggleArgumentType.toggle;

Expand All @@ -23,13 +33,24 @@ public CommandUsage commandUsage() {
.category(CommandCategory.MODULE)
.description("""
Automatically eats food when health or hunger is below a set threshold.

Which foods to eat can be configured based on modes:

* `all`: any food
* `whitelist`: only added foods
* `blacklist`: any food not added
""")
.usageLines(
"on/off",
"health <int>",
"hunger <int>",
"warning on/off",
"allowUnsafeFood on/off"
"allowUnsafeFood on/off",
"mode <all/whitelist/blacklist>",
"add/del <food>",
"addAll <food1>,<food2>,...",
"list",
"clear"
)
.build();
}
Expand Down Expand Up @@ -66,17 +87,83 @@ public LiteralArgumentBuilder<CommandContext> register() {
CONFIG.client.extra.autoEat.allowUnsafeFood = getToggle(c, "toggle");
c.getSource().getEmbed()
.title("AutoEat Allow Unsafe Food " + toggleStrCaps(CONFIG.client.extra.autoEat.allowUnsafeFood));
})));
})))
.then(literal("mode").then(argument("mode", enumStrings("all", "whitelist", "blacklist")).executes(c -> {
var modeString = getString(c, "mode").toUpperCase();
CONFIG.client.extra.autoEat.mode = Config.Client.Extra.AutoEat.Mode.valueOf(modeString);
c.getSource().getEmbed()
.title("Mode Set");
})))
.then(literal("add").then(argument("food", food()).executes(c -> {
var food = getFood(c, "food");
CONFIG.client.extra.autoEat.foods.add(food.name());
CONFIG.client.extra.autoEat.foods.removeIf(i -> FoodRegistry.REGISTRY.get(i) == null);
c.getSource().getEmbed()
.title("Food Added")
.description(foodList());
})))
.then(literal("addAll").then(argument("foods", StringArgumentType.greedyString()).executes(c -> {
var foodList = getString(c, "foods").split(",");
List<String> invalidFoods = new ArrayList<>();
for (var food : foodList) {
var foodData = FoodRegistry.REGISTRY.get(food);
if (foodData == null) {
invalidFoods.add(food);
continue;
}
CONFIG.client.extra.autoEat.foods.add(foodData.name());
}
c.getSource().getEmbed()
.title("Foods Added")
.addField("Added Foods Count", foodList.length - invalidFoods.size())
.description(foodList());
if (!invalidFoods.isEmpty()) {
c.getSource().getEmbed()
.addField("Invalid Foods", invalidFoods.stream().map(s -> "`" + s + "`").reduce((a, b) -> a + ", " + b).orElse(""));
}
})))
.then(literal("del").then(argument("food", item()).executes(c -> {
var food = getFood(c, "food");
CONFIG.client.extra.autoEat.foods.remove(food.name());
CONFIG.client.extra.autoEat.foods.removeIf(i -> FoodRegistry.REGISTRY.get(i) == null);
c.getSource().getEmbed()
.title("Food Deleted")
.description(foodList());
})))
.then(literal("list").executes(c -> {
CONFIG.client.extra.autoEat.foods.removeIf(i -> FoodRegistry.REGISTRY.get(i) == null);
c.getSource().getEmbed()
.title("Food Blacklist")
.description(foodList());
}))
.then(literal("clear").executes(c -> {
CONFIG.client.extra.autoEat.foods.clear();
c.getSource().getEmbed()
.title("Food Blacklist Cleared")
.description(foodList());
}));
}

@Override
public void defaultEmbed(final Embed builder) {
builder
public void defaultHandler(final CommandContext context) {
if (context.getData().containsKey("noDefaultEmbed")) return;
context.getEmbed()
.addField("AutoEat", toggleStr(CONFIG.client.extra.autoEat.enabled))
.addField("Mode", CONFIG.client.extra.autoEat.mode.name().toLowerCase())
.addField("Health Threshold", CONFIG.client.extra.autoEat.healthThreshold)
.addField("Hunger Threshold", CONFIG.client.extra.autoEat.hungerThreshold)
.addField("Warning", toggleStr(CONFIG.client.extra.autoEat.warning))
.addField("Allow Unsafe Food", toggleStr(CONFIG.client.extra.autoEat.allowUnsafeFood))
.primaryColor();
}

String foodList() {
var items = new ArrayList<>(CONFIG.client.extra.autoEat.foods);
Collections.sort(items);
String list = "**Food List**:\n" + String.join("\n", items);
if (list.length() > 4000) {
list = list.substring(0, 4000) + "\n... (and more)";
}
return list;
}
}
17 changes: 15 additions & 2 deletions src/main/java/com/zenith/module/impl/AutoEat.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,22 @@ public boolean itemPredicate(final ItemStack itemStack) {

boolean hasFood(boolean ignoreHunger, ItemStack itemStack) {
FoodData foodData = FoodRegistry.REGISTRY.get(itemStack.getId());
if (foodData == null) return false;
switch (CONFIG.client.extra.autoEat.mode) {
case BLACKLIST -> {
if (CONFIG.client.extra.autoEat.foods.contains(foodData.name())) {
return false;
}
}
case WHITELIST -> {
if (!CONFIG.client.extra.autoEat.foods.contains(foodData.name())) {
return false;
}
}
case ALL -> {}
}
boolean canEat = ignoreHunger || CACHE.getPlayerCache().getThePlayer().getFood() < 20;
return foodData != null
&& (CONFIG.client.extra.autoEat.allowUnsafeFood || foodData.isSafeFood())
return (CONFIG.client.extra.autoEat.allowUnsafeFood || foodData.isSafeFood())
&& (canEat || foodData.canAlwaysEat());
}

Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/zenith/util/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,13 @@ public static final class AutoEat {
public boolean warning = true;
public boolean warningMention = false;
public boolean allowUnsafeFood = false;
public Mode mode = Mode.ALL;
public enum Mode {
ALL,
BLACKLIST,
WHITELIST
}
public HashSet<String> foods = new HashSet<>();
}

public static final class AutoOmen {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2678,6 +2678,20 @@
}
]
},
{
"type": "com.zenith.util.config.Config$Client$Extra$AutoEat$Mode",
"fields": [
{
"name": "ALL"
},
{
"name": "BLACKLIST"
},
{
"name": "WHITELIST"
}
]
},
{
"type": "com.zenith.util.config.Config$Client$Extra$AutoFish",
"allDeclaredFields": true,
Expand Down Expand Up @@ -8776,4 +8790,4 @@
}
]
}
}
}
Loading