feat: wool hopper counter(#27)
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ mcVersion=1.21.8
|
|||||||
release=2
|
release=2
|
||||||
# 0 for skip release, 1 for pre-release, 2 for release
|
# 0 for skip release, 1 for pre-release, 2 for release
|
||||||
|
|
||||||
luminolRef=b0decfdae082c290eeb39c553ba4e44f829dbad1
|
luminolRef=db9feeb2b0114cff9815b8b16ac3416846985693
|
||||||
|
|
||||||
org.gradle.configuration-cache=true
|
org.gradle.configuration-cache=true
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||||
|
Date: Mon, 27 Oct 2025 15:38:29 +0800
|
||||||
|
Subject: [PATCH] Leaves: Wool Hopper Counter
|
||||||
|
|
||||||
|
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||||
|
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
Licensed under: MIT
|
||||||
|
|
||||||
|
This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
|
index 55cbf9b4cc568fb9b418433f597ed6b64e4409b0..8449623a313edbe95941a2e328fe47269015f7fb 100644
|
||||||
|
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
|
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||||
|
@@ -232,8 +232,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
|
flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - Wool hopper counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
|
||||||
|
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockEntity.getBlockPos().relative(state.getValue(HopperBlock.FACING)));
|
||||||
|
+ if (woolColor != null) {
|
||||||
|
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
|
||||||
|
+ flag |= suckInItems(level, blockEntity);
|
||||||
|
+ if (!flag) {
|
||||||
|
+ break;
|
||||||
|
+ } else {
|
||||||
|
+ woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - Wool hopper counter
|
||||||
|
+
|
||||||
|
if (flag) {
|
||||||
|
blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot
|
||||||
|
+ // Leaves start - Wool hopper counter
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && woolHopperCounter(level, pos, state, HopperBlockEntity.getContainerAt(level, pos))) {
|
||||||
|
+ blockEntity.setCooldown(0);
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - Wool hopper counter
|
||||||
|
setChanged(level, pos, state);
|
||||||
|
// Leaves start - Lithium Sleeping Block Entity
|
||||||
|
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled
|
||||||
|
@@ -464,6 +486,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
|
// Paper end - Perf: Optimize Hoppers
|
||||||
|
|
||||||
|
private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) {
|
||||||
|
+ // Leaves start - hopper counter
|
||||||
|
+ if (org.leavesmc.leaves.util.HopperCounter.isEnabled()) {
|
||||||
|
+ if (woolHopperCounter(level, pos, level.getBlockState(pos), HopperBlockEntity.getContainerAt(level, pos))) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - hopper counter
|
||||||
|
Container attachedContainer = me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled ? blockEntity.getInsertInventory(level, pos, blockEntity) : getAttachedContainer(level, pos, blockEntity); // Leaves - Lithium Sleeping Block Entity
|
||||||
|
if (attachedContainer == null) {
|
||||||
|
return false;
|
||||||
|
@@ -554,6 +583,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Leaves start - hopper counter
|
||||||
|
+ private static boolean woolHopperCounter(Level level, BlockPos blockPos, BlockState state, @Nullable Container container) {
|
||||||
|
+ if (container == null) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ net.minecraft.world.item.DyeColor woolColor = org.leavesmc.leaves.util.WoolUtils.getWoolColorAtPosition(level, blockPos.relative(state.getValue(HopperBlock.FACING)));
|
||||||
|
+ if (woolColor != null) {
|
||||||
|
+ for (int i = 0; i < container.getContainerSize(); ++i) {
|
||||||
|
+ if (!container.getItem(i).isEmpty()) {
|
||||||
|
+ ItemStack itemstack = container.getItem(i);
|
||||||
|
+ org.leavesmc.leaves.util.HopperCounter.getCounter(woolColor).add(level, itemstack);
|
||||||
|
+ container.setItem(i, ItemStack.EMPTY);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ // Leaves end - hopper counter
|
||||||
|
+
|
||||||
|
private static int[] getSlots(Container container, Direction direction) {
|
||||||
|
if (container instanceof WorldlyContainer worldlyContainer) {
|
||||||
|
return worldlyContainer.getSlotsForFace(direction);
|
||||||
|
@@ -710,6 +759,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean addItem(Container container, ItemEntity item) {
|
||||||
|
+ if (fun.bm.lophine.config.modules.function.WoolHopperCounterConfig.unlimitedSpeed && org.leavesmc.leaves.util.HopperCounter.isEnabled() && item.isRemoved()) return false; // Leaves - Wool hopper counter
|
||||||
|
boolean flag = false;
|
||||||
|
// CraftBukkit start
|
||||||
|
if (org.bukkit.event.inventory.InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package fun.bm.lophine.command.counter;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import fun.bm.lophine.command.counter.sub.DisplayCommand;
|
||||||
|
import fun.bm.lophine.command.counter.sub.ResetCommand;
|
||||||
|
import fun.bm.lophine.command.counter.sub.ToggleCommand;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.JoinConfiguration;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.command.CommandContext;
|
||||||
|
import org.leavesmc.leaves.command.RootNode;
|
||||||
|
import org.leavesmc.leaves.util.HopperCounter;
|
||||||
|
|
||||||
|
public class CounterCommand extends RootNode {
|
||||||
|
private final String PERM_BASE;
|
||||||
|
|
||||||
|
public CounterCommand() {
|
||||||
|
super("counter", "lophine.commands.counter");
|
||||||
|
this.PERM_BASE = "lophine.commands.counter";
|
||||||
|
children(
|
||||||
|
new ToggleCommand(this),
|
||||||
|
new ResetCommand(this),
|
||||||
|
new DisplayCommand(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||||
|
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
||||||
|
Component.text("Hopper Counter: ", NamedTextColor.GRAY),
|
||||||
|
Component.text(HopperCounter.isEnabled(), HopperCounter.isEnabled() ? NamedTextColor.AQUA : NamedTextColor.GRAY)
|
||||||
|
));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPermission(@NotNull CommandSender sender, String... subcommand) {
|
||||||
|
return hasPermission(PERM_BASE, sender, subcommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package fun.bm.lophine.command.counter;
|
||||||
|
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.command.LiteralNode;
|
||||||
|
|
||||||
|
public class CounterSubCommand extends LiteralNode {
|
||||||
|
protected final CounterCommand parent;
|
||||||
|
|
||||||
|
protected CounterSubCommand(String name, CounterCommand parent) {
|
||||||
|
super(name);
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requires(@NotNull CommandSourceStack source) {
|
||||||
|
return hasPermission(source.getSender());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasPermission(CommandSender sender) {
|
||||||
|
return parent.hasPermission(sender, this.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package fun.bm.lophine.command.counter.sub;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import fun.bm.lophine.command.counter.CounterCommand;
|
||||||
|
import fun.bm.lophine.command.counter.CounterSubCommand;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.command.ArgumentNode;
|
||||||
|
import org.leavesmc.leaves.command.CommandContext;
|
||||||
|
import org.leavesmc.leaves.util.HopperCounter;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class DisplayCommand extends CounterSubCommand {
|
||||||
|
public DisplayCommand(CounterCommand parent) {
|
||||||
|
super("display", parent);
|
||||||
|
children(
|
||||||
|
DyeColorArg::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void displayCounter(CommandContext context, @NotNull HopperCounter counter, boolean realTime) {
|
||||||
|
for (Component component : counter.format(MinecraftServer.getServer(), context.getSource().getLevel(), realTime)) {
|
||||||
|
context.getSender().sendMessage(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DyeColorArg extends ArgumentNode<String> {
|
||||||
|
protected DyeColorArg() {
|
||||||
|
super("color", StringArgumentType.string());
|
||||||
|
children(
|
||||||
|
TimeArg::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) {
|
||||||
|
String color0 = context.getArgument(DyeColorArg.class);
|
||||||
|
DyeColor color = DyeColor.byName(color0, null);
|
||||||
|
if (color == null) return true;
|
||||||
|
HopperCounter counter = HopperCounter.getCounter(color);
|
||||||
|
displayCounter(context, counter, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
|
||||||
|
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
|
||||||
|
for (DyeColor value : DyeColor.values()) {
|
||||||
|
String color = value.getName();
|
||||||
|
if (color.startsWith(path)) {
|
||||||
|
builder.suggest(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.buildFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TimeArg extends ArgumentNode<String> {
|
||||||
|
protected TimeArg() {
|
||||||
|
super("time", StringArgumentType.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) {
|
||||||
|
String color0 = context.getArgument(DyeColorArg.class);
|
||||||
|
DyeColor color = DyeColor.byName(color0, null);
|
||||||
|
if (color == null) return true;
|
||||||
|
HopperCounter counter = HopperCounter.getCounter(color);
|
||||||
|
String timeType = context.getArgument(TimeArg.class);
|
||||||
|
switch (timeType) {
|
||||||
|
case "realtime" -> displayCounter(context, counter, true);
|
||||||
|
case "gametick" -> displayCounter(context, counter, false);
|
||||||
|
default ->
|
||||||
|
context.getSender().sendMessage(Component.text("Invalid time type: " + timeType, NamedTextColor.RED));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
|
||||||
|
builder.suggest("realtime");
|
||||||
|
builder.suggest("gametick");
|
||||||
|
return builder.buildFuture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package fun.bm.lophine.command.counter.sub;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import fun.bm.lophine.command.counter.CounterCommand;
|
||||||
|
import fun.bm.lophine.command.counter.CounterSubCommand;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.JoinConfiguration;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.command.ArgumentNode;
|
||||||
|
import org.leavesmc.leaves.command.CommandContext;
|
||||||
|
import org.leavesmc.leaves.util.HopperCounter;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class ResetCommand extends CounterSubCommand {
|
||||||
|
public ResetCommand(CounterCommand parent) {
|
||||||
|
super("reset", parent);
|
||||||
|
children(
|
||||||
|
DyeColorArg::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||||
|
HopperCounter.resetAll(context.getSource().getLevel(), false);
|
||||||
|
context.getSender().sendMessage(Component.text("Restarted all counters."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DyeColorArg extends ArgumentNode<String> {
|
||||||
|
protected DyeColorArg() {
|
||||||
|
super("color", StringArgumentType.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) {
|
||||||
|
String color0 = context.getArgument(DyeColorArg.class);
|
||||||
|
if (color0.equals("all")) {
|
||||||
|
HopperCounter.resetAll(context.getSource().getLevel(), false);
|
||||||
|
context.getSender().sendMessage(Component.text("Restarted all counters."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DyeColor color = DyeColor.byName(color0, null);
|
||||||
|
if (color == null) return true;
|
||||||
|
HopperCounter counter = HopperCounter.getCounter(color);
|
||||||
|
counter.reset(context.getSource().getLevel());
|
||||||
|
context.getSender().sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
||||||
|
Component.text("Restarted "),
|
||||||
|
Component.text(color.getName(), TextColor.color(color.getTextColor())),
|
||||||
|
Component.text(" counter.")
|
||||||
|
));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CompletableFuture<Suggestions> getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) {
|
||||||
|
String path = context.getArgumentOrDefault(DyeColorArg.class, "");
|
||||||
|
if ("all".startsWith(path)) {
|
||||||
|
builder.suggest("all");
|
||||||
|
}
|
||||||
|
for (DyeColor value : DyeColor.values()) {
|
||||||
|
String color = value.getName();
|
||||||
|
if (color.startsWith(path)) {
|
||||||
|
builder.suggest(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.buildFuture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package fun.bm.lophine.command.counter.sub;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import fun.bm.lophine.command.counter.CounterCommand;
|
||||||
|
import fun.bm.lophine.command.counter.CounterSubCommand;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.leavesmc.leaves.command.ArgumentNode;
|
||||||
|
import org.leavesmc.leaves.command.CommandContext;
|
||||||
|
import org.leavesmc.leaves.util.HopperCounter;
|
||||||
|
|
||||||
|
public class ToggleCommand extends CounterSubCommand {
|
||||||
|
public ToggleCommand(CounterCommand parent) {
|
||||||
|
super("toggle", parent);
|
||||||
|
children(
|
||||||
|
BooleanArg::new
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException {
|
||||||
|
if (!HopperCounter.isEnabled()) {
|
||||||
|
HopperCounter.setEnabled(true);
|
||||||
|
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
|
||||||
|
} else {
|
||||||
|
HopperCounter.setEnabled(false);
|
||||||
|
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BooleanArg extends ArgumentNode<Boolean> {
|
||||||
|
protected BooleanArg() {
|
||||||
|
super("enabled", BoolArgumentType.bool());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean execute(@NotNull CommandContext context) {
|
||||||
|
boolean enabled = context.getArgument(BooleanArg.class);
|
||||||
|
if (enabled == HopperCounter.isEnabled()) {
|
||||||
|
context.getSender().sendMessage(Component.text("Hopper Counter is already " + (enabled ? "enabled" : "disabled") + ".", NamedTextColor.GRAY));
|
||||||
|
} else {
|
||||||
|
HopperCounter.setEnabled(enabled);
|
||||||
|
if (enabled) {
|
||||||
|
context.getSender().sendMessage(Component.text("Hopper Counter now is enabled.", NamedTextColor.AQUA));
|
||||||
|
} else {
|
||||||
|
context.getSender().sendMessage(Component.text("Hopper Counter now is disabled.", NamedTextColor.RED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package fun.bm.lophine.config.modules.function;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
import fun.bm.lophine.command.counter.CounterCommand;
|
||||||
|
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.bukkit.Bukkit;
|
||||||
|
|
||||||
|
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "wool-hopper-counter")
|
||||||
|
public class WoolHopperCounterConfig implements IConfigModule {
|
||||||
|
@ConfigInfo(name = "enabled")
|
||||||
|
public static boolean enabled = false;
|
||||||
|
|
||||||
|
@ConfigInfo(name = "unlimited-speed")
|
||||||
|
public static boolean unlimitedSpeed = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaded(CommentedFileConfig configInstance) {
|
||||||
|
if (enabled) new CounterCommand().register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnloaded(CommentedFileConfig configInstance) {
|
||||||
|
Bukkit.getCommandMap().getKnownCommands().remove("luminol:tpsbar");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
*
|
||||||
|
* Leaves is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Leaves is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.leavesmc.leaves.util;
|
||||||
|
|
||||||
|
import fun.bm.lophine.config.modules.function.WoolHopperCounterConfig;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2LongLinkedOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.context.ContextMap;
|
||||||
|
import net.minecraft.world.item.*;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.world.item.crafting.Recipe;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeManager;
|
||||||
|
import net.minecraft.world.item.crafting.display.RecipeDisplay;
|
||||||
|
import net.minecraft.world.item.crafting.display.SlotDisplayContext;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.AbstractBannerBlock;
|
||||||
|
import net.minecraft.world.level.block.BeaconBeamBlock;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.material.MapColor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
|
// Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet)
|
||||||
|
|
||||||
|
public class HopperCounter {
|
||||||
|
|
||||||
|
private static boolean enabled = false;
|
||||||
|
private static final Map<DyeColor, HopperCounter> COUNTERS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
EnumMap<DyeColor, HopperCounter> counterMap = new EnumMap<>(DyeColor.class);
|
||||||
|
for (DyeColor color : DyeColor.values()) {
|
||||||
|
counterMap.put(color, new HopperCounter(color));
|
||||||
|
}
|
||||||
|
COUNTERS = Collections.unmodifiableMap(counterMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DyeColor color;
|
||||||
|
private final TextComponent coloredName;
|
||||||
|
private final Object2LongMap<Item> counter = new Object2LongLinkedOpenHashMap<>();
|
||||||
|
private long startTick;
|
||||||
|
private long startMillis;
|
||||||
|
|
||||||
|
private HopperCounter(DyeColor color) {
|
||||||
|
this.startTick = -1;
|
||||||
|
this.color = color;
|
||||||
|
this.coloredName = Component.text(color.getName(), TextColor.color(color.getTextColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Level level, ItemStack stack) {
|
||||||
|
if (startTick < 0) {
|
||||||
|
startTick = level.getGameTime();
|
||||||
|
startMillis = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
Item item = stack.getItem();
|
||||||
|
counter.put(item, counter.getLong(item) + stack.getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset(Level level) {
|
||||||
|
counter.clear();
|
||||||
|
startTick = level.getGameTime();
|
||||||
|
startMillis = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetAll(Level level, boolean fresh) {
|
||||||
|
for (HopperCounter counter : COUNTERS.values()) {
|
||||||
|
counter.reset(level);
|
||||||
|
if (fresh) {
|
||||||
|
counter.startTick = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Component> format(MinecraftServer server, Level level, boolean realTime) {
|
||||||
|
long ticks = Math.max(realTime ? (System.currentTimeMillis() - startMillis) / 50 : level.getGameTime() - startTick, -1);
|
||||||
|
|
||||||
|
if (startTick < 0 || ticks == -1) {
|
||||||
|
return Collections.singletonList(Component.text().append(coloredName, Component.text(" hasn't started counting yet")).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
long total = getTotalItems();
|
||||||
|
if (total <= 0) {
|
||||||
|
return Collections.singletonList(Component.text()
|
||||||
|
.append(Component.text("No items for "), coloredName)
|
||||||
|
.append(Component.text(" yet ("), Component.text(String.format("%.2f ", ticks / (20.0 * 60.0)), Style.style(TextDecoration.BOLD)))
|
||||||
|
.append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text(")"))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Component> items = new ArrayList<>();
|
||||||
|
items.add(Component.text()
|
||||||
|
.append(Component.text("Items for "), coloredName, Component.text(" "))
|
||||||
|
.append(Component.text("("), Component.text(String.format("%.2f ", ticks * 1.0 / (20 * 60)), Style.style(TextDecoration.BOLD)))
|
||||||
|
.append(Component.text("min"), Component.text(realTime ? " - real time" : ""), Component.text("), "))
|
||||||
|
.append(Component.text("total: "), Component.text(total, Style.style(TextDecoration.BOLD)), Component.text(", "))
|
||||||
|
.append(Component.text("("), Component.text(String.format("%.1f", total * 1.0 * (20 * 60 * 60) / ticks), Style.style(TextDecoration.BOLD)))
|
||||||
|
.append(Component.text("/h):"))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(entry -> {
|
||||||
|
Item item = entry.getKey();
|
||||||
|
Component name = Component.translatable(item.getDescriptionId());
|
||||||
|
TextColor textColor = guessColor(server, item);
|
||||||
|
|
||||||
|
if (textColor != null) {
|
||||||
|
name = name.style(name.style().merge(Style.style(textColor)));
|
||||||
|
} else {
|
||||||
|
name = name.style(name.style().merge(Style.style(TextDecoration.ITALIC)));
|
||||||
|
}
|
||||||
|
|
||||||
|
long count = entry.getLongValue();
|
||||||
|
return Component.text()
|
||||||
|
.append(Component.text("- ", NamedTextColor.GRAY))
|
||||||
|
.append(name)
|
||||||
|
.append(Component.text(": ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(count, Style.style(TextDecoration.BOLD)), Component.text(", ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(String.format("%.1f", count * (20.0 * 60.0 * 60.0) / ticks), Style.style(TextDecoration.BOLD)))
|
||||||
|
.append(Component.text("/h"))
|
||||||
|
.build();
|
||||||
|
}).toList());
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<Item, Block> DEFAULTS = Map.<Item, Block>ofEntries(
|
||||||
|
entry(Items.DANDELION, Blocks.YELLOW_WOOL),
|
||||||
|
entry(Items.POPPY, Blocks.RED_WOOL),
|
||||||
|
entry(Items.BLUE_ORCHID, Blocks.LIGHT_BLUE_WOOL),
|
||||||
|
entry(Items.ALLIUM, Blocks.MAGENTA_WOOL),
|
||||||
|
entry(Items.AZURE_BLUET, Blocks.SNOW_BLOCK),
|
||||||
|
entry(Items.RED_TULIP, Blocks.RED_WOOL),
|
||||||
|
entry(Items.ORANGE_TULIP, Blocks.ORANGE_WOOL),
|
||||||
|
entry(Items.WHITE_TULIP, Blocks.SNOW_BLOCK),
|
||||||
|
entry(Items.PINK_TULIP, Blocks.PINK_WOOL),
|
||||||
|
entry(Items.OXEYE_DAISY, Blocks.SNOW_BLOCK),
|
||||||
|
entry(Items.CORNFLOWER, Blocks.BLUE_WOOL),
|
||||||
|
entry(Items.WITHER_ROSE, Blocks.BLACK_WOOL),
|
||||||
|
entry(Items.LILY_OF_THE_VALLEY, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.BROWN_MUSHROOM, Blocks.BROWN_MUSHROOM_BLOCK),
|
||||||
|
entry(Items.RED_MUSHROOM, Blocks.RED_MUSHROOM_BLOCK),
|
||||||
|
entry(Items.STICK, Blocks.OAK_PLANKS),
|
||||||
|
entry(Items.GOLD_INGOT, Blocks.GOLD_BLOCK),
|
||||||
|
entry(Items.IRON_INGOT, Blocks.IRON_BLOCK),
|
||||||
|
entry(Items.DIAMOND, Blocks.DIAMOND_BLOCK),
|
||||||
|
entry(Items.NETHERITE_INGOT, Blocks.NETHERITE_BLOCK),
|
||||||
|
entry(Items.SUNFLOWER, Blocks.YELLOW_WOOL),
|
||||||
|
entry(Items.LILAC, Blocks.MAGENTA_WOOL),
|
||||||
|
entry(Items.ROSE_BUSH, Blocks.RED_WOOL),
|
||||||
|
entry(Items.PEONY, Blocks.PINK_WOOL),
|
||||||
|
entry(Items.CARROT, Blocks.ORANGE_WOOL),
|
||||||
|
entry(Items.APPLE, Blocks.RED_WOOL),
|
||||||
|
entry(Items.WHEAT, Blocks.HAY_BLOCK),
|
||||||
|
entry(Items.PORKCHOP, Blocks.PINK_WOOL),
|
||||||
|
entry(Items.RABBIT, Blocks.PINK_WOOL),
|
||||||
|
entry(Items.CHICKEN, Blocks.WHITE_TERRACOTTA),
|
||||||
|
entry(Items.BEEF, Blocks.NETHERRACK),
|
||||||
|
entry(Items.ENCHANTED_GOLDEN_APPLE, Blocks.GOLD_BLOCK),
|
||||||
|
entry(Items.COD, Blocks.WHITE_TERRACOTTA),
|
||||||
|
entry(Items.SALMON, Blocks.ACACIA_PLANKS),
|
||||||
|
entry(Items.ROTTEN_FLESH, Blocks.BROWN_WOOL),
|
||||||
|
entry(Items.PUFFERFISH, Blocks.YELLOW_TERRACOTTA),
|
||||||
|
entry(Items.TROPICAL_FISH, Blocks.ORANGE_WOOL),
|
||||||
|
entry(Items.POTATO, Blocks.WHITE_TERRACOTTA),
|
||||||
|
entry(Items.MUTTON, Blocks.RED_WOOL),
|
||||||
|
entry(Items.BEETROOT, Blocks.NETHERRACK),
|
||||||
|
entry(Items.MELON_SLICE, Blocks.MELON),
|
||||||
|
entry(Items.POISONOUS_POTATO, Blocks.SLIME_BLOCK),
|
||||||
|
entry(Items.SPIDER_EYE, Blocks.NETHERRACK),
|
||||||
|
entry(Items.GUNPOWDER, Blocks.GRAY_WOOL),
|
||||||
|
entry(Items.TURTLE_SCUTE, Blocks.LIME_WOOL),
|
||||||
|
entry(Items.ARMADILLO_SCUTE, Blocks.ANCIENT_DEBRIS),
|
||||||
|
entry(Items.FEATHER, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.FLINT, Blocks.BLACK_WOOL),
|
||||||
|
entry(Items.LEATHER, Blocks.SPRUCE_PLANKS),
|
||||||
|
entry(Items.GLOWSTONE_DUST, Blocks.GLOWSTONE),
|
||||||
|
entry(Items.PAPER, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.BRICK, Blocks.BRICKS),
|
||||||
|
entry(Items.INK_SAC, Blocks.BLACK_WOOL),
|
||||||
|
entry(Items.SNOWBALL, Blocks.SNOW_BLOCK),
|
||||||
|
entry(Items.WATER_BUCKET, Blocks.WATER),
|
||||||
|
entry(Items.LAVA_BUCKET, Blocks.LAVA),
|
||||||
|
entry(Items.MILK_BUCKET, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.CLAY_BALL, Blocks.CLAY),
|
||||||
|
entry(Items.COCOA_BEANS, Blocks.COCOA),
|
||||||
|
entry(Items.BONE, Blocks.BONE_BLOCK),
|
||||||
|
entry(Items.COD_BUCKET, Blocks.BROWN_TERRACOTTA),
|
||||||
|
entry(Items.PUFFERFISH_BUCKET, Blocks.YELLOW_TERRACOTTA),
|
||||||
|
entry(Items.SALMON_BUCKET, Blocks.PINK_TERRACOTTA),
|
||||||
|
entry(Items.TROPICAL_FISH_BUCKET, Blocks.ORANGE_TERRACOTTA),
|
||||||
|
entry(Items.SUGAR, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.BLAZE_POWDER, Blocks.GOLD_BLOCK),
|
||||||
|
entry(Items.ENDER_PEARL, Blocks.WARPED_PLANKS),
|
||||||
|
entry(Items.NETHER_STAR, Blocks.DIAMOND_BLOCK),
|
||||||
|
entry(Items.PRISMARINE_CRYSTALS, Blocks.SEA_LANTERN),
|
||||||
|
entry(Items.PRISMARINE_SHARD, Blocks.PRISMARINE),
|
||||||
|
entry(Items.RABBIT_HIDE, Blocks.OAK_PLANKS),
|
||||||
|
entry(Items.CHORUS_FRUIT, Blocks.PURPUR_BLOCK),
|
||||||
|
entry(Items.SHULKER_SHELL, Blocks.SHULKER_BOX),
|
||||||
|
entry(Items.NAUTILUS_SHELL, Blocks.BONE_BLOCK),
|
||||||
|
entry(Items.HEART_OF_THE_SEA, Blocks.CONDUIT),
|
||||||
|
entry(Items.HONEYCOMB, Blocks.HONEYCOMB_BLOCK),
|
||||||
|
entry(Items.NAME_TAG, Blocks.BONE_BLOCK),
|
||||||
|
entry(Items.TOTEM_OF_UNDYING, Blocks.YELLOW_TERRACOTTA),
|
||||||
|
entry(Items.TRIDENT, Blocks.PRISMARINE),
|
||||||
|
entry(Items.GHAST_TEAR, Blocks.WHITE_WOOL),
|
||||||
|
entry(Items.PHANTOM_MEMBRANE, Blocks.BONE_BLOCK),
|
||||||
|
entry(Items.EGG, Blocks.BONE_BLOCK),
|
||||||
|
entry(Items.COPPER_INGOT, Blocks.COPPER_BLOCK),
|
||||||
|
entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK)
|
||||||
|
);
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Nullable
|
||||||
|
public static TextColor guessColor(@NotNull MinecraftServer server, Item item) {
|
||||||
|
RegistryAccess registryAccess = server.registryAccess();
|
||||||
|
TextColor direct = fromItem(item, registryAccess);
|
||||||
|
if (direct != null) {
|
||||||
|
return direct;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation id = registryAccess.lookupOrThrow(Registries.ITEM).getKey(item);
|
||||||
|
if (id == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (Recipe<?> recipe : getRecipesForOutput(server.getRecipeManager(), id, server.overworld())) {
|
||||||
|
for (Ingredient ingredient : recipe.placementInfo().ingredients()) {
|
||||||
|
Optional<Holder<Item>> match = ingredient.items().filter(stack -> fromItem(stack.value(), registryAccess) != null).findFirst();
|
||||||
|
if (match.isPresent()) {
|
||||||
|
return fromItem(match.get().value(), registryAccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<Recipe<?>> getRecipesForOutput(@NotNull RecipeManager recipeManager, ResourceLocation id, Level level) {
|
||||||
|
List<Recipe<?>> results = new ArrayList<>();
|
||||||
|
ContextMap context = SlotDisplayContext.fromLevel(level);
|
||||||
|
recipeManager.getRecipes().forEach(recipe -> {
|
||||||
|
for (RecipeDisplay recipeDisplay : recipe.value().display()) {
|
||||||
|
recipeDisplay.result().resolveForStacks(context).forEach(stack -> {
|
||||||
|
if (BuiltInRegistries.ITEM.wrapAsHolder(stack.getItem()).unwrapKey().map(ResourceKey::location).orElseThrow(IllegalStateException::new).equals(id)) {
|
||||||
|
results.add(recipe.value());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static TextColor fromItem(Item item, RegistryAccess registryAccess) {
|
||||||
|
if (DEFAULTS.containsKey(item)) {
|
||||||
|
return TextColor.color(appropriateColor(DEFAULTS.get(item).defaultMapColor().col));
|
||||||
|
}
|
||||||
|
if (item instanceof DyeItem dye) {
|
||||||
|
return TextColor.color(appropriateColor(dye.getDyeColor().getMapColor().col));
|
||||||
|
}
|
||||||
|
|
||||||
|
Block block = null;
|
||||||
|
final Registry<Item> itemRegistry = registryAccess.lookupOrThrow(Registries.ITEM);
|
||||||
|
final Registry<Block> blockRegistry = registryAccess.lookupOrThrow(Registries.BLOCK);
|
||||||
|
ResourceLocation id = itemRegistry.getKey(item);
|
||||||
|
if (item instanceof BlockItem blockItem) {
|
||||||
|
block = blockItem.getBlock();
|
||||||
|
} else if (blockRegistry.getOptional(id).isPresent()) {
|
||||||
|
block = blockRegistry.getValue(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block != null) {
|
||||||
|
if (block instanceof AbstractBannerBlock) {
|
||||||
|
return TextColor.color(appropriateColor(((AbstractBannerBlock) block).getColor().getMapColor().col));
|
||||||
|
} else if (block instanceof BeaconBeamBlock) {
|
||||||
|
return TextColor.color(appropriateColor(((BeaconBeamBlock) block).getColor().getMapColor().col));
|
||||||
|
}
|
||||||
|
return TextColor.color(appropriateColor(block.defaultMapColor().col));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int appropriateColor(int color) {
|
||||||
|
if (color == 0) {
|
||||||
|
return MapColor.SNOW.col;
|
||||||
|
}
|
||||||
|
int r = (color >> 16 & 255);
|
||||||
|
int g = (color >> 8 & 255);
|
||||||
|
int b = (color & 255);
|
||||||
|
if (r < 70) {
|
||||||
|
r = 70;
|
||||||
|
}
|
||||||
|
if (g < 70) {
|
||||||
|
g = 70;
|
||||||
|
}
|
||||||
|
if (b < 70) {
|
||||||
|
b = 70;
|
||||||
|
}
|
||||||
|
return (r << 16) + (g << 8) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotalItems() {
|
||||||
|
return counter.isEmpty() ? 0 : counter.values().longStream().sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HopperCounter getCounter(DyeColor color) {
|
||||||
|
return COUNTERS.get(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setEnabled(boolean is) {
|
||||||
|
enabled = is;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEnabled() {
|
||||||
|
return WoolHopperCounterConfig.enabled && enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||||
|
*
|
||||||
|
* Leaves is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Leaves is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.leavesmc.leaves.util;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.item.DyeColor;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.util.Map.entry;
|
||||||
|
|
||||||
|
public class WoolUtils {
|
||||||
|
private static final Map<Block, DyeColor> WOOL_BLOCK_TO_DYE = Map.ofEntries(
|
||||||
|
entry(Blocks.WHITE_WOOL, DyeColor.WHITE),
|
||||||
|
entry(Blocks.ORANGE_WOOL, DyeColor.ORANGE),
|
||||||
|
entry(Blocks.MAGENTA_WOOL, DyeColor.MAGENTA),
|
||||||
|
entry(Blocks.LIGHT_BLUE_WOOL, DyeColor.LIGHT_BLUE),
|
||||||
|
entry(Blocks.YELLOW_WOOL, DyeColor.YELLOW),
|
||||||
|
entry(Blocks.LIME_WOOL, DyeColor.LIME),
|
||||||
|
entry(Blocks.PINK_WOOL, DyeColor.PINK),
|
||||||
|
entry(Blocks.GRAY_WOOL, DyeColor.GRAY),
|
||||||
|
entry(Blocks.LIGHT_GRAY_WOOL, DyeColor.LIGHT_GRAY),
|
||||||
|
entry(Blocks.CYAN_WOOL, DyeColor.CYAN),
|
||||||
|
entry(Blocks.PURPLE_WOOL, DyeColor.PURPLE),
|
||||||
|
entry(Blocks.BLUE_WOOL, DyeColor.BLUE),
|
||||||
|
entry(Blocks.BROWN_WOOL, DyeColor.BROWN),
|
||||||
|
entry(Blocks.GREEN_WOOL, DyeColor.GREEN),
|
||||||
|
entry(Blocks.RED_WOOL, DyeColor.RED),
|
||||||
|
entry(Blocks.BLACK_WOOL, DyeColor.BLACK)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static DyeColor getWoolColorAtPosition(Level worldIn, BlockPos pos) {
|
||||||
|
BlockState state = worldIn.getBlockState(pos);
|
||||||
|
return WOOL_BLOCK_TO_DYE.get(state.getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user