diff options
| author | shedaniel <daniel@shedaniel.me> | 2020-10-26 10:49:27 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2020-10-29 14:02:27 +0800 |
| commit | 9ea4a22e9a194fd8fdc2fb03226ab38ee175a6cc (patch) | |
| tree | b4db2569bc4a90d7bb835ff451fe5e11e86e8968 /RoughlyEnoughItems-default-plugin/src | |
| parent | b7f8fc61dcaa6d202809651d46cf0946b63beef7 (diff) | |
| download | RoughlyEnoughItems-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')
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); + } + } +} |
