diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-02-15 15:09:38 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2022-02-15 15:09:38 +0800 |
| commit | 75e2b26669d5960aac8626f879b0943224ac4814 (patch) | |
| tree | a2703bb4484206c937ccb7942a73bb04ee160279 | |
| parent | 02f6ba7a5dbdc5b4ef71b52ec0b998a4075535de (diff) | |
| download | RoughlyEnoughItems-75e2b26669d5960aac8626f879b0943224ac4814.tar.gz RoughlyEnoughItems-75e2b26669d5960aac8626f879b0943224ac4814.tar.bz2 RoughlyEnoughItems-75e2b26669d5960aac8626f879b0943224ac4814.zip | |
Close #110
13 files changed, 386 insertions, 206 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java index 4b7ad135b..e60e5da7b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java @@ -86,6 +86,8 @@ public interface ConfigObject { String getWeatherCommand(); + String getTimeCommand(); + int getMaxRecipePerPage(); int getMaxRecipesPageHeight(); diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java index 78cf466ea..edbdef665 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java @@ -57,6 +57,7 @@ import me.shedaniel.rei.plugin.client.categories.crafting.DefaultCraftingCategor import me.shedaniel.rei.plugin.client.exclusionzones.DefaultPotionEffectExclusionZones; import me.shedaniel.rei.plugin.client.exclusionzones.DefaultRecipeBookExclusionZones; import me.shedaniel.rei.plugin.client.favorites.GameModeFavoriteEntry; +import me.shedaniel.rei.plugin.client.favorites.TimeFavoriteEntry; import me.shedaniel.rei.plugin.client.favorites.WeatherFavoriteEntry; import me.shedaniel.rei.plugin.common.displays.*; import me.shedaniel.rei.plugin.common.displays.anvil.AnvilRecipe; @@ -369,6 +370,12 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin Arrays.stream(WeatherFavoriteEntry.Weather.values()), Stream.of((WeatherFavoriteEntry.Weather) null) ).<FavoriteEntry>map(WeatherFavoriteEntry::new).toArray(FavoriteEntry[]::new)); + registry.register(TimeFavoriteEntry.ID, TimeFavoriteEntry.Type.INSTANCE); + registry.getOrCrateSection(new TranslatableComponent(TimeFavoriteEntry.TRANSLATION_KEY)) + .add(Stream.concat( + Arrays.stream(TimeFavoriteEntry.Time.values()), + Stream.of((TimeFavoriteEntry.Time) null) + ).<FavoriteEntry>map(TimeFavoriteEntry::new).toArray(FavoriteEntry[]::new)); } @Override diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/favorites/TimeFavoriteEntry.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/favorites/TimeFavoriteEntry.java new file mode 100644 index 000000000..56b4684e7 --- /dev/null +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/favorites/TimeFavoriteEntry.java @@ -0,0 +1,296 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.plugin.client.favorites; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Lifecycle; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.favorites.CompoundFavoriteRenderer; +import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; +import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; +import me.shedaniel.rei.api.client.gui.AbstractRenderer; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class TimeFavoriteEntry extends FavoriteEntry { + public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "time"); + public static final String TRANSLATION_KEY = "favorite.section.time"; + private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("roughlyenoughitems", "textures/gui/recipecontainer.png"); + public static final String KEY = "mode"; + @Nullable + private final Time time; + + public enum Time { + MORN("1000"), + NOON("6000"), + EVENING("12000"), + NIGHT("18000"), + ; + + String part; + + Time(String part) { + this.part = part; + } + + public String getPart() { + return part; + } + } + + public TimeFavoriteEntry(@Nullable Time time) { + this.time = time; + } + + @Override + public boolean isInvalid() { + return false; + } + + @Override + public Renderer getRenderer(boolean showcase) { + if (time == null) { + List<Renderer> renderers = IntStream.range(0, 4).mapToObj(TimeFavoriteEntry::getRenderer).collect(Collectors.toList()); + return new CompoundFavoriteRenderer(showcase, renderers, () -> Minecraft.getInstance().gameMode.getPlayerMode().getId()) { + @Override + @Nullable + public Tooltip getTooltip(Point mouse) { + return Tooltip.create(mouse, new TranslatableComponent("text.rei.gamemode_button.tooltip.dropdown")); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + return hashCode() == o.hashCode(); + } + + @Override + public int hashCode() { + return Objects.hash(getClass(), showcase); + } + }; + } + return getRenderer(time.ordinal()); + } + + private static Renderer getRenderer(int id) { + Time time = Time.values()[id]; + return new AbstractRenderer() { + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + int color = bounds.contains(mouseX, mouseY) ? 0xFFEEEEEE : 0xFFAAAAAA; + if (bounds.width > 4 && bounds.height > 4) { + matrices.pushPose(); + matrices.translate(bounds.getCenterX(), bounds.getCenterY(), 0); + matrices.scale(bounds.getWidth() / 18f, bounds.getHeight() / 18f, 1); + renderTimeIcon(matrices, time, 0, 0, color); + matrices.popPose(); + } + } + + private void renderTimeIcon(PoseStack matrices, Time time, int centerX, int centerY, int color) { + RenderSystem.setShaderTexture(0, CHEST_GUI_TEXTURE); + blit(matrices, centerX - 7, centerY - 7, time.ordinal() * 14 + 42, 14, 14, 14, 256, 256); + } + + @Override + @Nullable + public Tooltip getTooltip(Point mouse) { + return Tooltip.create(mouse, new TranslatableComponent("text.rei.time_button.tooltip.entry", new TranslatableComponent("text.rei.time_button.name." + time.name().toLowerCase(Locale.ROOT)))); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + return hashCode() == o.hashCode(); + } + + @Override + public int hashCode() { + return Objects.hash(getClass(), false, time); + } + }; + } + + @Override + public boolean doAction(int button) { + if (button == 0) { + Time time = this.time; + if (time == null) { + time = Time.values()[Minecraft.getInstance().gameMode.getPlayerMode().getId() + 1 % 4]; + } + Minecraft.getInstance().player.chat(ConfigObject.getInstance().getTimeCommand().replaceAll("\\{time}", time.getPart().toLowerCase(Locale.ROOT))); + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + return true; + } + return false; + } + + @Override + public Optional<Supplier<Collection<FavoriteMenuEntry>>> getMenuEntries() { + if (time == null) + return Optional.of(this::_getMenuEntries); + return Optional.empty(); + } + + private Collection<FavoriteMenuEntry> _getMenuEntries() { + return CollectionUtils.map(Time.values(), TimeMenuEntry::new); + } + + @Override + public long hashIgnoreAmount() { + return time == null ? -1 : time.ordinal(); + } + + @Override + public FavoriteEntry copy() { + return this; + } + + @Override + public ResourceLocation getType() { + return ID; + } + + @Override + public boolean isSame(FavoriteEntry other) { + if (!(other instanceof TimeFavoriteEntry that)) return false; + return Objects.equals(time, that.time); + } + + public enum Type implements FavoriteEntryType<TimeFavoriteEntry> { + INSTANCE; + + @Override + public DataResult<TimeFavoriteEntry> read(CompoundTag object) { + String stringValue = object.getString(KEY); + Time type = stringValue.equals("NOT_SET") ? null : Time.valueOf(stringValue); + return DataResult.success(new TimeFavoriteEntry(type), Lifecycle.stable()); + } + + @Override + public DataResult<TimeFavoriteEntry> fromArgs(Object... args) { + if (args.length == 0) return DataResult.error("Cannot create GameModeFavoriteEntry from empty args!"); + if (!(args[0] instanceof Time type)) + return DataResult.error("Creation of GameModeFavoriteEntry from args expected Time as the first argument!"); + return DataResult.success(new TimeFavoriteEntry(type), Lifecycle.stable()); + } + + @Override + public CompoundTag save(TimeFavoriteEntry entry, CompoundTag tag) { + tag.putString(KEY, entry.time == null ? "NOT_SET" : entry.time.name()); + return tag; + } + } + + public static class TimeMenuEntry extends FavoriteMenuEntry { + public final String text; + public final Time time; + private int x, y, width; + private boolean selected, containsMouse, rendering; + private int textWidth = -69; + + public TimeMenuEntry(Time time) { + this.text = I18n.get("text.rei.time_button.name." + time.name().toLowerCase(Locale.ROOT)); + this.time = time; + } + + private int getTextWidth() { + if (textWidth == -69) { + this.textWidth = Math.max(0, font.width(text)); + } + return this.textWidth; + } + + @Override + public int getEntryWidth() { + return getTextWidth() + 4; + } + + @Override + public int getEntryHeight() { + return 12; + } + + @Override + public List<? extends GuiEventListener> children() { + return Collections.emptyList(); + } + + @Override + public void updateInformation(int xPos, int yPos, boolean selected, boolean containsMouse, boolean rendering, int width) { + this.x = xPos; + this.y = yPos; + this.selected = selected; + this.containsMouse = containsMouse; + this.rendering = rendering; + this.width = width; + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + if (selected) { + fill(matrices, x, y, x + width, y + 12, -12237499); + } + if (selected && containsMouse) { + REIRuntime.getInstance().queueTooltip(Tooltip.create(new TranslatableComponent("text.rei.time_button.tooltip.entry", text))); + } + font.draw(matrices, text, x + 2, y + 2, selected ? 16777215 : 8947848); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (rendering && mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + 12) { + Minecraft.getInstance().player.chat(ConfigObject.getInstance().getTimeCommand().replaceAll("\\{time}", time.getPart().toLowerCase(Locale.ROOT))); + minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + closeMenu(); + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 4f7a26c09..01c92b70d 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -182,6 +182,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { } @Override + public String getTimeCommand() { + return advanced.commands.timeCommand; + } + + @Override public int getMaxRecipePerPage() { return advanced.layout.maxRecipesPerPage; } @@ -638,6 +643,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @Comment("Declares the command used to change gamemode.") private String gamemodeCommand = "/gamemode {gamemode}"; @Comment("Declares the command used in servers to cheat items.") private String giveCommand = "/give {player_name} {item_identifier}{nbt} {count}"; @Comment("Declares the command used to change weather.") private String weatherCommand = "/weather {weather}"; + @Comment("Declares the command used to change time.") private String timeCommand = "/time set {time}"; } public static class Miscellaneous { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java index 75e77dc99..82439dd62 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java @@ -37,7 +37,6 @@ import me.shedaniel.rei.api.common.registry.ReloadStage; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.mutable.MutableLong; -import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -51,7 +50,8 @@ import java.util.Map; public class FavoriteEntryTypeRegistryImpl implements FavoriteEntryType.Registry { private final BiMap<ResourceLocation, FavoriteEntryType<?>> registry = HashBiMap.create(); private final List<Triple<SystemFavoriteEntryProvider<?>, MutableLong, List<FavoriteEntry>>> systemFavorites = Lists.newArrayList(); - private final Map<Component, FavoriteEntryType.Section> sections = Maps.newLinkedHashMap(); + private final Map<Component, FavoriteEntryType.Section> sections = Maps.newConcurrentMap(); + private final List<FavoriteEntryType.Section> sectionsList = Lists.newCopyOnWriteArrayList(); @Override public ReloadStage getStage() { @@ -81,12 +81,16 @@ public class FavoriteEntryTypeRegistryImpl implements FavoriteEntryType.Registry @Override public FavoriteEntryType.Section getOrCrateSection(Component text) { - return sections.computeIfAbsent(text, SectionImpl::new); + return sections.computeIfAbsent(text, $ -> { + SectionImpl section = new SectionImpl($); + sectionsList.add(section); + return section; + }); } @Override public Iterable<FavoriteEntryType.Section> sections() { - return this.sections.values(); + return sectionsList; } @Override @@ -103,6 +107,7 @@ public class FavoriteEntryTypeRegistryImpl implements FavoriteEntryType.Registry this.registry.clear(); this.systemFavorites.clear(); this.sections.clear(); + this.sectionsList.clear(); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/GameModeMenuEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/GameModeMenuEntry.java deleted file mode 100644 index c5f8ca56a..000000000 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/GameModeMenuEntry.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.shedaniel.rei.impl.client.gui.modules.entries; - -import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.rei.api.client.REIRuntime; -import me.shedaniel.rei.api.client.config.ConfigObject; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; -import me.shedaniel.rei.impl.client.gui.modules.AbstractMenuEntry; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.level.GameType; - -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -public class GameModeMenuEntry extends AbstractMenuEntry { - public final String text; - public final GameType gameMode; - private int textWidth = -69; - - public GameModeMenuEntry(GameType gameMode) { - this.text = gameMode.getLongDisplayName().getString(); - this.gameMode = gameMode; - } - - private int getTextWidth() { - if (textWidth == -69) { - this.textWidth = Math.max(0, font.width(text)); - } - return this.textWidth; - } - - @Override - public int getEntryWidth() { - return getTextWidth() + 4; - } - - @Override - public int getEntryHeight() { - return 12; - } - - @Override - public List<? extends GuiEventListener> children() { - return Collections.emptyList(); - } - - @Override - public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { - if (isSelected()) { - fill(matrices, getX(), getY(), getX() + getWidth(), getY() + getEntryHeight(), -12237499); - } - if (isSelected() && containsMouse()) { - REIRuntime.getInstance().queueTooltip(Tooltip.create(new TranslatableComponent("text.rei.gamemode_button.tooltip.entry", text))); - } - font.draw(matrices, text, getX() + 2, getY() + 2, isSelected() ? 16777215 : 8947848); - } - - @Override - protected boolean onClick(double mouseX, double mouseY, int button) { - Minecraft.getInstance().player.chat(ConfigObject.getInstance().getGamemodeCommand().replaceAll("\\{gamemode}", gameMode.name().toLowerCase(Locale.ROOT))); - minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - REIRuntime.getInstance().getOverlay().get().closeOverlayMenu(); - return true; - } -} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/WeatherMenuEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/WeatherMenuEntry.java deleted file mode 100644 index 5ef1bc79c..000000000 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/modules/entries/WeatherMenuEntry.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package me.shedaniel.rei.impl.client.gui.modules.entries; - -import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.rei.api.client.REIRuntime; -import me.shedaniel.rei.api.client.config.ConfigObject; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; -import me.shedaniel.rei.impl.client.gui.modules.AbstractMenuEntry; -import me.shedaniel.rei.impl.common.util.Weather; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.client.resources.sounds.SimpleSoundInstance; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.sounds.SoundEvents; - -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -public class WeatherMenuEntry extends AbstractMenuEntry { - public final String text; - public final Weather weather; - private int textWidth = -69; - - public WeatherMenuEntry(Weather weather) { - this.text = I18n.get(weather.getTranslateKey()); - this.weather = weather; - } - - private int getTextWidth() { - if (textWidth == -69) { - this.textWidth = Math.max(0, font.width(text)); - } - return this.textWidth; - } - - @Override - public int getEntryWidth() { - return getTextWidth() + 4; - } - - @Override - public int getEntryHeight() { - return 12; - } - - @Override - public List<? extends GuiEventListener> children() { - return Collections.emptyList(); - } - - @Override - public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { - if (isSelected()) { - fill(matrices, getX(), getY(), getX() + getWidth(), getY() + getEntryHeight(), -12237499); - } - if (isSelected() && containsMouse()) { - REIRuntime.getInstance().queueTooltip(Tooltip.create(new TranslatableComponent("text.rei.weather_button.tooltip.entry", text))); - } - font.draw(matrices, text, getX() + 2, getY() + 2, isSelected() ? 16777215 : 8947848); - } - - @Override - protected boolean onClick(double mouseX, double mouseY, int button) { - Minecraft.getInstance().player.chat(ConfigObject.getInstance().getWeatherCommand().replaceAll("\\{weather}", weather.name().toLowerCase(Locale.ROOT))); - minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - REIRuntime.getInstance().getOverlay().get().closeOverlayMenu(); - return true; - } -} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java index 32f072d11..7a676eab6 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java @@ -243,7 +243,14 @@ public class EntryStacksRegionWidget<T extends RegionEntry<T>> extends WidgetWit return Optional.empty(); } - public void setEntries(List<T> newEntries) { + public enum RemovalMode { + THROW_EXCEPTION, + DISAPPEAR, + MIGRATED, + ; + } + + public void setEntries(List<T> newEntries, RemovalMode removalMode) { newEntries = Lists.newArrayList(newEntries); newEntries.removeIf(entry -> entry == null || entry.isEntryInvalid()); @@ -252,9 +259,13 @@ public class EntryStacksRegionWidget<T extends RegionEntry<T>> extends WidgetWit List<RealRegionEntry<T>> removedEntries = Lists.newArrayList(this.entries.values()); removedEntries.removeIf(entry -> newFavoritesHash.contains(entry.hashIgnoreAmount())); - for (RealRegionEntry<T> removedEntry : removedEntries) { - removedEntry.remove(); - this.removedEntries.put(removedEntry.hashIgnoreAmount(), removedEntry); + if (!removedEntries.isEmpty() && removalMode == RemovalMode.THROW_EXCEPTION) { + throw new IllegalStateException("Cannot remove entries from region " + this + ": " + removedEntries); + } else if (removalMode == RemovalMode.DISAPPEAR) { + for (RealRegionEntry<T> removedEntry : removedEntries) { + removedEntry.remove(); + this.removedEntries.put(removedEntry.hashIgnoreAmount(), removedEntry); + } } List<RealRegionEntry<T>> addedEntries = new ArrayList<>(); @@ -459,7 +470,7 @@ public class EntryStacksRegionWidget<T extends RegionEntry<T>> extends WidgetWit setEntries(this.entries.values().stream() .map(RealRegionEntry::getEntry) - .collect(Collectors.toList())); + .collect(Collectors.toList()), RemovalMode.THROW_EXCEPTION); return true; } @@ -467,9 +478,13 @@ public class EntryStacksRegionWidget<T extends RegionEntry<T>> extends WidgetWit return entriesList.indexOf(entry.getWidget()); } - public void remove(RealRegionEntry<T> entry) { - entries.remove(entry.hashIgnoreAmount()); - setEntries(CollectionUtils.map(entries.values(), RealRegionEntry::getEntry)); + public void remove(RealRegionEntry<T> entry, RemovalMode mode) { + RealRegionEntry<T> currentEntry = entries.get(entry.hashIgnoreAmount()); + if (currentEntry != null) { + List<T> newEntries = CollectionUtils.map(entries.values(), RealRegionEntry::getEntry); + newEntries.remove(currentEntry.getEntry()); + setEntries(newEntries, mode); + } } public double getScrollAmount() { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java index f06cd8f20..e8bf8ac15 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java @@ -182,6 +182,11 @@ public class FavoritesListWidget extends WidgetWithBounds implements DraggableSt } @Override + public void onConsumed(RealRegionEntry<FavoriteEntry> entry) { + setSystemRegionEntries(entry); + } + + @Override @Nullable public FavoriteEntry convertDraggableStack(DraggingContext<Screen> context, DraggableStack stack) { return FavoriteEntry.fromEntryStack(stack.getStack().copy()); @@ -198,7 +203,7 @@ public class FavoritesListWidget extends WidgetWithBounds implements DraggableSt for (AddFavoritePanel.Row row : favoritePanel.rows.get()) { if (row instanceof AddFavoritePanel.SectionEntriesRow entriesRow) { for (AddFavoritePanel.SectionEntriesRow.SectionFavoriteWidget widget : entriesRow.widgets) { - if (widget.containsMouse(mouseX, mouseY)) { + if (widget.containsMouse(mouseX, mouseY + favoritePanel.scroller.scrollAmount())) { RealRegionEntry<FavoriteEntry> entry = new RealRegionEntry<>(region, widget.entry.copy(), entrySize()); entry.size.setAs(entrySize() * 100); return new RegionDraggableStack<>(entry, widget); |
