aboutsummaryrefslogtreecommitdiff
path: root/RoughlyEnoughItems-default-plugin/src/main
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2020-10-26 10:49:27 +0800
committershedaniel <daniel@shedaniel.me>2020-10-29 14:02:27 +0800
commit9ea4a22e9a194fd8fdc2fb03226ab38ee175a6cc (patch)
treeb4db2569bc4a90d7bb835ff451fe5e11e86e8968 /RoughlyEnoughItems-default-plugin/src/main
parentb7f8fc61dcaa6d202809651d46cf0946b63beef7 (diff)
downloadRoughlyEnoughItems-9ea4a22e9a194fd8fdc2fb03226ab38ee175a6cc.tar.gz
RoughlyEnoughItems-9ea4a22e9a194fd8fdc2fb03226ab38ee175a6cc.tar.bz2
RoughlyEnoughItems-9ea4a22e9a194fd8fdc2fb03226ab38ee175a6cc.zip
Favorites Dragging
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'RoughlyEnoughItems-default-plugin/src/main')
-rw-r--r--RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java9
-rw-r--r--RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/Animator.java97
-rw-r--r--RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/GameModeFavoriteEntry.java273
3 files changed, 379 insertions, 0 deletions
diff --git a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
index b8c3b7a23..fe76dfcab 100644
--- a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
+++ b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java
@@ -31,6 +31,8 @@ import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceSet;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.*;
+import me.shedaniel.rei.api.favorites.FavoriteEntry;
+import me.shedaniel.rei.api.favorites.FavoriteEntryType;
import me.shedaniel.rei.api.fluid.FluidSupportProvider;
import me.shedaniel.rei.api.fractions.Fraction;
import me.shedaniel.rei.api.plugins.REIPluginV0;
@@ -52,6 +54,7 @@ import me.shedaniel.rei.plugin.crafting.DefaultCraftingCategory;
import me.shedaniel.rei.plugin.crafting.DefaultCustomDisplay;
import me.shedaniel.rei.plugin.crafting.DefaultShapedDisplay;
import me.shedaniel.rei.plugin.crafting.DefaultShapelessDisplay;
+import me.shedaniel.rei.plugin.favorites.GameModeFavoriteEntry;
import me.shedaniel.rei.plugin.fuel.DefaultFuelCategory;
import me.shedaniel.rei.plugin.fuel.DefaultFuelDisplay;
import me.shedaniel.rei.plugin.information.DefaultInformationCategory;
@@ -79,6 +82,7 @@ import net.minecraft.client.gui.screens.inventory.*;
import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener;
import net.minecraft.core.Registry;
import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
@@ -91,6 +95,7 @@ import net.minecraft.world.item.alchemy.PotionUtils;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
+import net.minecraft.world.level.GameType;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.ComposterBlock;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
@@ -418,6 +423,10 @@ public class DefaultPlugin implements REIPluginV0, BuiltinPlugin {
// SubsetsRegistry subsetsRegistry = SubsetsRegistry.INSTANCE;
// subsetsRegistry.registerPathEntry("roughlyenoughitems:food", EntryStack.create(Items.MILK_BUCKET));
// subsetsRegistry.registerPathEntry("roughlyenoughitems:food/roughlyenoughitems:cookies", EntryStack.create(Items.COOKIE));
+
+ FavoriteEntryType.registry().register(GameModeFavoriteEntry.ID, GameModeFavoriteEntry.Type.INSTANCE);
+ FavoriteEntryType.registry().getOrCrateSection(new TranslatableComponent(GameModeFavoriteEntry.TRANSLATION_KEY))
+ .add(Arrays.stream(GameType.values()).<FavoriteEntry>map(GameModeFavoriteEntry.Type.INSTANCE::fromArgs).toArray(FavoriteEntry[]::new));
}
@Override
diff --git a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/Animator.java b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/Animator.java
new file mode 100644
index 000000000..3c7cf651c
--- /dev/null
+++ b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/Animator.java
@@ -0,0 +1,97 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 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.favorites;
+
+import me.shedaniel.clothconfig2.api.ScrollingContainer;
+import net.minecraft.Util;
+import org.jetbrains.annotations.ApiStatus;
+
+@ApiStatus.Internal
+public final class Animator extends Number {
+ private double amount;
+ private double target;
+ private long start;
+ private long duration;
+
+ public Animator() {
+ }
+
+ public Animator(double amount) {
+ setAs(amount);
+ }
+
+ public void setAs(double value) {
+ this.set(value, false, 0);
+ }
+
+ public void setTo(double value, long duration) {
+ if (target != value)
+ this.set(value, true, duration);
+ }
+
+ private void set(double value, boolean animated, long duration) {
+ this.target = value;
+ this.start = Util.getMillis();
+
+ if (animated) {
+ this.duration = duration;
+ } else {
+ this.duration = 0;
+ this.amount = this.target;
+ }
+ }
+
+ public void update(double delta) {
+ if (duration != 0) {
+ if (amount < target)
+ this.amount = Math.min(ScrollingContainer.ease(amount, target + (target - amount), Math.min(((double) Util.getMillis() - start) / duration * delta * 3.0D, 1.0D), v -> v), target);
+ else if (amount > target)
+ this.amount = Math.max(ScrollingContainer.ease(amount, target - (amount - target), Math.min(((double) Util.getMillis() - start) / duration * delta * 3.0D, 1.0D), v -> v), target);
+ }
+ }
+
+ @Override
+ public int intValue() {
+ return (int) amount;
+ }
+
+ @Override
+ public long longValue() {
+ return (long) amount;
+ }
+
+ @Override
+ public float floatValue() {
+ return (float) amount;
+ }
+
+ @Override
+ public double doubleValue() {
+ return amount;
+ }
+
+ public double target() {
+ return target;
+ }
+}
diff --git a/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/GameModeFavoriteEntry.java b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/GameModeFavoriteEntry.java
new file mode 100644
index 000000000..727dce65f
--- /dev/null
+++ b/RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/favorites/GameModeFavoriteEntry.java
@@ -0,0 +1,273 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 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.favorites;
+
+import com.google.gson.JsonObject;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.ScissorsHandler;
+import me.shedaniel.math.Point;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.ConfigObject;
+import me.shedaniel.rei.api.EntryStack;
+import me.shedaniel.rei.api.REIHelper;
+import me.shedaniel.rei.api.favorites.FavoriteEntry;
+import me.shedaniel.rei.api.favorites.FavoriteEntryType;
+import me.shedaniel.rei.api.favorites.FavoriteMenuEntry;
+import me.shedaniel.rei.api.widgets.Tooltip;
+import me.shedaniel.rei.impl.RenderingEntry;
+import me.shedaniel.rei.utils.CollectionUtils;
+import net.minecraft.ChatFormatting;
+import net.minecraft.Util;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.resources.sounds.SimpleSoundInstance;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.util.GsonHelper;
+import net.minecraft.world.level.GameType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.function.Supplier;
+
+public class GameModeFavoriteEntry extends FavoriteEntry {
+ public static final ResourceLocation ID = new ResourceLocation("roughlyenoughitems", "gamemode");
+ public static final String TRANSLATION_KEY = "favorite.section.gamemode";
+ public static final String KEY = "mode";
+ private GameType gameMode;
+
+ public GameModeFavoriteEntry(GameType gameMode) {
+ this.gameMode = Objects.requireNonNull(gameMode);
+ }
+
+ @Override
+ public boolean isInvalid() {
+ return false;
+ }
+
+ @Override
+ public EntryStack getWidget(boolean showcase) {
+ return new RenderingEntry() {
+ private Animator notSetOffset = new Animator(0);
+ private Rectangle notSetScissorArea = new Rectangle();
+ private long nextSwitch = -1;
+
+ @Override
+ public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) {
+ int color = bounds.contains(mouseX, mouseY) ? 0xFFEEEEEE : 0xFFAAAAAA;
+ fillGradient(matrices, bounds.getX(), bounds.getY(), bounds.getMaxX(), bounds.getY() + 1, color, color);
+ fillGradient(matrices, bounds.getX(), bounds.getMaxY() - 1, bounds.getMaxX(), bounds.getMaxY(), color, color);
+ fillGradient(matrices, bounds.getX(), bounds.getY(), bounds.getX() + 1, bounds.getMaxY(), color, color);
+ fillGradient(matrices, bounds.getMaxX() - 1, bounds.getY(), bounds.getMaxX(), bounds.getMaxY(), color, color);
+ if (bounds.width > 4 && bounds.height > 4) {
+ if (gameMode == GameType.NOT_SET) {
+ updateAnimator(delta);
+ notSetScissorArea.setBounds(bounds.x + 2, bounds.y + 2, bounds.width - 4, bounds.height - 4);
+ ScissorsHandler.INSTANCE.scissor(notSetScissorArea);
+ int offset = Math.round(notSetOffset.floatValue() * bounds.getHeight());
+ for (int i = 0; i <= 3; i++) {
+ GameType type = GameType.byId(i);
+ renderGameModeText(matrices, type, bounds.getCenterX(), bounds.getCenterY() + bounds.getHeight() * i - offset, color);
+ }
+ ScissorsHandler.INSTANCE.removeLastScissor();
+ } else {
+ renderGameModeText(matrices, gameMode, bounds.getCenterX(), bounds.getCenterY(), color);
+ }
+ }
+ }
+
+ private void updateAnimator(float delta) {
+ notSetOffset.update(delta);
+ if (showcase) {
+ if (nextSwitch == -1) {
+ nextSwitch = Util.getMillis();
+ }
+ if (Util.getMillis() - nextSwitch > 1000) {
+ nextSwitch = Util.getMillis();
+ notSetOffset.setTo(((int) notSetOffset.target() + 1) % 4, 500);
+ }
+ } else {
+ notSetOffset.setTo((Minecraft.getInstance().gameMode.getPlayerMode().getId() + 1) % 4, 500);
+ }
+ }
+
+ private void renderGameModeText(PoseStack matrices, GameType type, int centerX, int centerY, int color) {
+ Component s = new TranslatableComponent("text.rei.short_gamemode." + type.getName());
+ Font font = Minecraft.getInstance().font;
+ font.draw(matrices, s, centerX - font.width(s) / 2 + (type == GameType.NOT_SET ? 0 : 0.5f), centerY - 3.5f, color);
+ }
+
+ @Override
+ public @Nullable Tooltip getTooltip(Point mouse) {
+ if (gameMode == GameType.NOT_SET)
+ return Tooltip.create(mouse, new TranslatableComponent("text.rei.gamemode_button.tooltip.all"));
+ return Tooltip.create(mouse, new TranslatableComponent("text.rei.gamemode_button.tooltip.entry", gameMode.getDisplayName().getString()));
+ }
+ };
+ }
+
+ @Override
+ public boolean doAction(int button) {
+ if (button == 0) {
+ GameType type = gameMode;
+ if (type == GameType.NOT_SET) {
+ type = GameType.byId(Minecraft.getInstance().gameMode.getPlayerMode().getId() + 1 % 4);
+ }
+ Minecraft.getInstance().player.chat(ConfigObject.getInstance().getGamemodeCommand().replaceAll("\\{gamemode}", type.name().toLowerCase(Locale.ROOT)));
+ Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public @NotNull Optional<Supplier<Collection<@NotNull FavoriteMenuEntry>>> getMenuEntries() {
+ if (gameMode == GameType.NOT_SET)
+ return Optional.of(this::_getMenuEntries);
+ return Optional.empty();
+ }
+
+ private Collection<FavoriteMenuEntry> _getMenuEntries() {
+ return CollectionUtils.filterAndMap(Arrays.asList(GameType.values()), mode -> mode != GameType.NOT_SET, GameModeMenuEntry::new);
+ }
+
+ @Override
+ public int hashIgnoreAmount() {
+ return gameMode.ordinal();
+ }
+
+ @Override
+ public FavoriteEntry copy() {
+ return this;
+ }
+
+ @Override
+ public ResourceLocation getType() {
+ return ID;
+ }
+
+ @Override
+ public boolean isSame(FavoriteEntry other) {
+ if (!(other instanceof GameModeFavoriteEntry)) return false;
+ GameModeFavoriteEntry that = (GameModeFavoriteEntry) other;
+ return Objects.equals(gameMode, that.gameMode);
+ }
+
+ public enum Type implements FavoriteEntryType<GameModeFavoriteEntry> {
+ INSTANCE;
+
+ @Override
+ public @NotNull GameModeFavoriteEntry fromJson(@NotNull JsonObject object) {
+ return new GameModeFavoriteEntry(GameType.valueOf(GsonHelper.getAsString(object, KEY)));
+ }
+
+ @Override
+ public @NotNull GameModeFavoriteEntry fromArgs(Object... args) {
+ return new GameModeFavoriteEntry((GameType) args[0]);
+ }
+
+ @Override
+ public @NotNull JsonObject toJson(@NotNull GameModeFavoriteEntry entry, @NotNull JsonObject object) {
+ object.addProperty(KEY, entry.gameMode.name());
+ return object;
+ }
+ }
+
+ public static class GameModeMenuEntry extends FavoriteMenuEntry {
+ public final String text;
+ public final GameType gameMode;
+ private int x, y, width;
+ private boolean selected, containsMouse, rendering;
+ private int textWidth = -69;
+
+ public GameModeMenuEntry(GameType gameMode) {
+ this.text = gameMode.getDisplayName().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 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) {
+ boolean disabled = this.minecraft.gameMode.getPlayerMode() == gameMode;
+ if (selected && !disabled) {
+ fill(matrices, x, y, x + width, y + 12, -12237499);
+ }
+ if (!disabled && selected && containsMouse) {
+ REIHelper.getInstance().queueTooltip(Tooltip.create(new TranslatableComponent("text.rei.gamemode_button.tooltip.entry", text)));
+ }
+ String s = text;
+ if (disabled) {
+ s = ChatFormatting.STRIKETHROUGH.toString() + s;
+ }
+ font.draw(matrices, s, x + 2, y + 2, selected && !disabled ? 16777215 : 8947848);
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ boolean disabled = this.minecraft.gameMode.getPlayerMode() == gameMode;
+ if (!disabled && rendering && mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + 12) {
+ 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));
+ closeMenu();
+ return true;
+ }
+ return super.mouseClicked(mouseX, mouseY, button);
+ }
+ }
+}