From a9d695d8c237b114cc397d154a8d4412547310e9 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:59:28 +0300 Subject: [PATCH 1/7] 1 --- .../net/entityoutliner/EntityOutliner.java | 113 -------- .../mixin/MixinMinecraftClient.java | 23 -- .../mixin/MixinWorldRenderer.java | 46 --- .../net/entityoutliner/ui/ColorWidget.java | 107 ------- .../entityoutliner/ui/EntityListWidget.java | 171 ------------ .../net/entityoutliner/ui/EntitySelector.java | 261 ------------------ .../entityoutliner/ui/ModMenuIntegration.java | 11 - .../resources/assets/entityoutliner/icon.png | Bin 11147 -> 0 bytes .../assets/entityoutliner/lang/en_us.json | 13 - .../assets/entityoutliner/lang/fr_fr.json | 13 - .../assets/entityoutliner/lang/zh_cn.json | 13 - .../entityoutliner/textures/gui/colors.png | Bin 417 -> 0 bytes src/main/resources/entityoutliner.mixins.json | 15 - src/main/resources/fabric.mod.json | 45 --- 14 files changed, 831 deletions(-) delete mode 100644 src/main/java/net/entityoutliner/EntityOutliner.java delete mode 100644 src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java delete mode 100644 src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java delete mode 100644 src/main/java/net/entityoutliner/ui/ColorWidget.java delete mode 100644 src/main/java/net/entityoutliner/ui/EntityListWidget.java delete mode 100644 src/main/java/net/entityoutliner/ui/EntitySelector.java delete mode 100644 src/main/java/net/entityoutliner/ui/ModMenuIntegration.java delete mode 100644 src/main/resources/assets/entityoutliner/icon.png delete mode 100644 src/main/resources/assets/entityoutliner/lang/en_us.json delete mode 100644 src/main/resources/assets/entityoutliner/lang/fr_fr.json delete mode 100644 src/main/resources/assets/entityoutliner/lang/zh_cn.json delete mode 100644 src/main/resources/assets/entityoutliner/textures/gui/colors.png delete mode 100644 src/main/resources/entityoutliner.mixins.json delete mode 100644 src/main/resources/fabric.mod.json diff --git a/src/main/java/net/entityoutliner/EntityOutliner.java b/src/main/java/net/entityoutliner/EntityOutliner.java deleted file mode 100644 index 8a1616a..0000000 --- a/src/main/java/net/entityoutliner/EntityOutliner.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.entityoutliner; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - - -import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import org.lwjgl.glfw.GLFW; - -import net.entityoutliner.ui.EntitySelector; -import net.entityoutliner.ui.ColorWidget.Color; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import net.minecraft.entity.EntityType; -import net.minecraft.registry.Registries; - -public class EntityOutliner implements ClientModInitializer { - private static final Gson GSON = new Gson(); - public static boolean outliningEntities; - - private static final KeyBinding CONFIG_BIND = new KeyBinding( - "key.entity-outliner.selector", - InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_SEMICOLON, - "title.entity-outliner.title" - ); - - private static final KeyBinding OUTLINE_BIND = new KeyBinding( - "key.entity-outliner.outline", - InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_O, - "title.entity-outliner.title" - ); - - @Override - public void onInitializeClient() { - KeyBindingHelper.registerKeyBinding(CONFIG_BIND); - KeyBindingHelper.registerKeyBinding(OUTLINE_BIND); - - loadConfig(); - - ClientTickEvents.END_CLIENT_TICK.register(this::onEndTick); - } - - private static Path getConfigPath() { - return FabricLoader.getInstance().getConfigDir().resolve("entityoutliner.json"); - } - - public static void saveConfig() { - JsonObject config = new JsonObject(); - - List> outlinedEntityNames = EntitySelector.outlinedEntityTypes.entrySet().stream() - .map(entry -> List.of(EntityType.getId(entry.getKey()).toString(), entry.getValue().name())) - .collect(Collectors.toList()); - - config.add("outlinedEntities", GSON.toJsonTree(outlinedEntityNames)); - - try { - Files.write(getConfigPath(), GSON.toJson(config).getBytes()); - } - catch (IOException ex) { - logException(ex, "Failed to save EntityOutliner config"); - } - } - - private void loadConfig() { - try { - JsonObject config = GSON.fromJson(new String(Files.readAllBytes(getConfigPath())), JsonObject.class); - if (config.has("outlinedEntities")) { - Type setType = new TypeToken>>(){}.getType(); - List> outlinedEntityNames = GSON.fromJson(config.get("outlinedEntities"), setType); - - Map, Color> outlinedEntityTypes = outlinedEntityNames.stream() - .collect(Collectors.toMap(list -> EntityType.get(list.get(0)).get(), list -> Color.valueOf(list.get(1))));; - - for (EntityType entityType : Registries.ENTITY_TYPE) - if (outlinedEntityTypes.containsKey(entityType)) - EntitySelector.outlinedEntityTypes.put(entityType, outlinedEntityTypes.get(entityType)); - } - } - catch (IOException | JsonSyntaxException ex) { - logException(ex, "Failed to load EntityOutliner config"); - } - } - - private void onEndTick(MinecraftClient client) { - while (OUTLINE_BIND.wasPressed()) { - outliningEntities = !outliningEntities; - } - - if (CONFIG_BIND.isPressed()) { - client.setScreen(new EntitySelector(null)); - } - } - - public static void logException(Exception ex, String message) { - System.err.printf("[EntityOutliner] %s (%s: %s)", message, ex.getClass().getSimpleName(), ex.getLocalizedMessage()); - } -} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java b/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java deleted file mode 100644 index bce1fa6..0000000 --- a/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.entityoutliner.mixin; - -import net.entityoutliner.EntityOutliner; -import net.entityoutliner.ui.EntitySelector; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(MinecraftClient.class) -public abstract class MixinMinecraftClient { - - @Inject(method = "hasOutline", at = @At("HEAD"), cancellable = true) - private void outlineEntities(Entity entity, CallbackInfoReturnable ci) { - if (EntityOutliner.outliningEntities && EntitySelector.outlinedEntityTypes != null) { - if (EntitySelector.outlinedEntityTypes.containsKey(entity.getType())) { - ci.setReturnValue(true); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java b/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java deleted file mode 100644 index 173b87e..0000000 --- a/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.entityoutliner.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.entityoutliner.EntityOutliner; -import net.entityoutliner.ui.EntitySelector; -import net.entityoutliner.ui.ColorWidget.Color; -import net.minecraft.client.render.OutlineVertexConsumerProvider; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.WorldRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.scoreboard.AbstractTeam; - -@Mixin(WorldRenderer.class) -public abstract class MixinWorldRenderer { - - @Inject(method = "renderEntity", at = @At("HEAD")) - private void renderEntity(Entity entity, double cameraX, double cameraY, double cameraZ, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { - if (EntityOutliner.outliningEntities - && vertexConsumers instanceof OutlineVertexConsumerProvider - && EntitySelector.outlinedEntityTypes.containsKey(entity.getType())) { - - Color color = EntitySelector.outlinedEntityTypes.get(entity.getType()); - OutlineVertexConsumerProvider outlineVertexConsumers = (OutlineVertexConsumerProvider) vertexConsumers; - outlineVertexConsumers.setColor(color.red, color.green, color.blue, 255); - - if (entity.getType() == EntityType.PLAYER) { - PlayerEntity player = (PlayerEntity) entity; - AbstractTeam team = player.getScoreboardTeam(); - if (team != null && team.getColor().getColorValue() != null) { - int hexColor = team.getColor().getColorValue(); - int blue = hexColor % 256; - int green = (hexColor / 256) % 256; - int red = (hexColor / 65536) % 256; - outlineVertexConsumers.setColor(red, green, blue, 255); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/ui/ColorWidget.java b/src/main/java/net/entityoutliner/ui/ColorWidget.java deleted file mode 100644 index 6652977..0000000 --- a/src/main/java/net/entityoutliner/ui/ColorWidget.java +++ /dev/null @@ -1,107 +0,0 @@ -package net.entityoutliner.ui; - -import java.util.Map; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; -import net.minecraft.client.gui.widget.PressableWidget; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -@Environment(EnvType.CLIENT) -public class ColorWidget extends PressableWidget { - private static final Identifier TEXTURE = new Identifier("entityoutliner:textures/gui/colors.png"); - private Color color; - private EntityType entityType; - - private ColorWidget(int x, int y, int width, int height, Text message, EntityType entityType) { - super(x, y, width, height, message); - this.entityType = entityType; - - if (EntitySelector.outlinedEntityTypes.containsKey(this.entityType)) - onShow(); - } - - public ColorWidget(int x, int y, int width, int height, EntityType entityType) { - this(x, y, width, height, Text.translatable("options.chat.color"), entityType); - } - - public void onShow() { - this.color = EntitySelector.outlinedEntityTypes.get(this.entityType); - } - - public void onPress() { - this.color = this.color.next(); - EntitySelector.outlinedEntityTypes.put(this.entityType, this.color); - } - - public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { - MinecraftClient minecraftClient = MinecraftClient.getInstance(); - RenderSystem.setShaderTexture(0, TEXTURE); - RenderSystem.enableDepthTest(); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); - drawTexture(matrices, this.getX(), this.getY(), this.isFocused() ? 20.0F : 0.0F, this.color.ordinal() * 20, 20, 20, 40, 180); - this.renderBackground(matrices, minecraftClient, mouseX, mouseY); - } - - public enum Color { - WHITE(255, 255, 255), - BLACK(0, 0, 0), - RED(255, 0, 0), - ORANGE(255, 127, 0), - YELLOW(255, 255, 0), - GREEN(0, 255, 0), - BLUE(0, 0, 255), - PURPLE(127, 0, 127), - PINK(255, 155, 182); - - public int red; - public int green; - public int blue; - - private static final Map spawnGroupColors = Map.of( - SpawnGroup.AMBIENT, Color.PURPLE, - SpawnGroup.AXOLOTLS, Color.PINK, - SpawnGroup.CREATURE, Color.YELLOW, - SpawnGroup.MISC, Color.WHITE, - SpawnGroup.MONSTER, Color.RED, - SpawnGroup.UNDERGROUND_WATER_CREATURE, Color.ORANGE, - SpawnGroup.WATER_AMBIENT, Color.GREEN, - SpawnGroup.WATER_CREATURE, Color.BLUE - ); - - private static Color[] colors = Color.values(); - - private Color(int red, int green, int blue) { - this.red = red; - this.green = green; - this.blue = blue; - } - - public static Color of(SpawnGroup group) { - return spawnGroupColors.get(group); - } - - public Color next() { - return get((this.ordinal() + 1) % colors.length); - } - - public Color get(int index) { - return colors[index]; - } - } - - @Override - protected void appendClickableNarrations(NarrationMessageBuilder builder) {} -} diff --git a/src/main/java/net/entityoutliner/ui/EntityListWidget.java b/src/main/java/net/entityoutliner/ui/EntityListWidget.java deleted file mode 100644 index 9a8d31e..0000000 --- a/src/main/java/net/entityoutliner/ui/EntityListWidget.java +++ /dev/null @@ -1,171 +0,0 @@ -package net.entityoutliner.ui; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; - -import net.entityoutliner.ui.ColorWidget.Color; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawableHelper; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.Selectable; -import net.minecraft.client.gui.widget.CheckboxWidget; -import net.minecraft.client.gui.widget.ElementListWidget; -import net.minecraft.client.gui.widget.PressableWidget; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.util.Language; - -@Environment(EnvType.CLIENT) -public class EntityListWidget extends ElementListWidget { - - public EntityListWidget(MinecraftClient client, int width, int height, int top, int bottom, int itemHeight) { - super(client, width, height, top, bottom, itemHeight); - this.centerListVertically = false; - } - - public void addListEntry(EntityListWidget.Entry entry) { - super.addEntry(entry); - } - - public void clearListEntries() { - super.clearEntries(); - } - - public int getRowWidth() { - return 400; - } - - protected int getScrollbarPositionX() { - return super.getScrollbarPositionX() + 32; - } - - @Environment(EnvType.CLIENT) - public static abstract class Entry extends ElementListWidget.Entry { } - - @Environment(EnvType.CLIENT) - public static class EntityEntry extends EntityListWidget.Entry { - - private final CheckboxWidget checkbox; - private final ColorWidget color; - private final EntityType entityType; - private final List children = new ArrayList<>(); - - private EntityEntry(CheckboxWidget checkbox, ColorWidget color, EntityType entityType) { - this.checkbox = checkbox; - this.entityType = entityType; - this.color = color; - - this.children.add(checkbox); - if (EntitySelector.outlinedEntityTypes.containsKey(entityType)) - this.children.add(color); - } - - public static EntityListWidget.EntityEntry create(EntityType entityType, int width) { - return new EntityListWidget.EntityEntry( - new CheckboxWidget(width / 2 - 155, 0, 310, 20, entityType.getName(), EntitySelector.outlinedEntityTypes.containsKey(entityType)), - new ColorWidget(width / 2 + 130, 0, 310, 20, entityType), - entityType - ); - } - - public void render(MatrixStack matrices, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { - this.checkbox.setY(j); - this.checkbox.render(matrices, n, o, f); - - if (this.children.contains(this.color)) { - this.color.setY(j); - this.color.render(matrices, n, o, f); - } - } - - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (EntitySelector.outlinedEntityTypes.containsKey(entityType)) { - if (this.color.isMouseOver(mouseX, mouseY)) { - this.color.onPress(); - } else { - EntitySelector.outlinedEntityTypes.remove(entityType); - - this.checkbox.onPress(); - this.children.remove(this.color); - } - } else { - EntitySelector.outlinedEntityTypes.put(entityType, Color.of(entityType.getSpawnGroup())); - - this.color.onShow(); - this.checkbox.onPress(); - this.children.add(this.color); - } - - return true; - } - - public List children() { - return this.children; - } - - public EntityType getEntityType() { - return this.entityType; - } - - public CheckboxWidget getCheckbox() { - return this.checkbox; - } - - public List selectableChildren() { - return this.children; - } - } - - @Environment(EnvType.CLIENT) - public static class HeaderEntry extends EntityListWidget.Entry { - - private final TextRenderer font; - private final String title; - private final int width; - private final int height; - - private HeaderEntry(SpawnGroup category, TextRenderer font, int width, int height) { - this.font = font; - this.width = width; - this.height = height; - - if (category != null) { - String title = ""; - for (String term : category.getName().split("\\p{Punct}|\\p{Space}")) { - title += StringUtils.capitalize(term) + " "; - } - this.title = title.trim(); - } else { - this.title = Language.getInstance().get("gui.entity-outliner.no_results"); - } - - } - - public static EntityListWidget.HeaderEntry create(SpawnGroup category, TextRenderer font, int width, int height) { - return new EntityListWidget.HeaderEntry(category, font, width, height); - } - - public void render(MatrixStack matrices, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { - DrawableHelper.drawCenteredText(matrices, this.font, this.title, this.width / 2, j + (this.height / 2) - (this.font.fontHeight / 2), 16777215); - } - - public List children() { - return new ArrayList<>(); - } - - public String toString() { - return this.title; - } - - @Override - public List selectableChildren() { - return new ArrayList<>(); - } - } -} diff --git a/src/main/java/net/entityoutliner/ui/EntitySelector.java b/src/main/java/net/entityoutliner/ui/EntitySelector.java deleted file mode 100644 index f6eb31a..0000000 --- a/src/main/java/net/entityoutliner/ui/EntitySelector.java +++ /dev/null @@ -1,261 +0,0 @@ -package net.entityoutliner.ui; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; - -import net.entityoutliner.EntityOutliner; -import net.entityoutliner.ui.ColorWidget.Color; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; - -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.entity.EntityType; -import net.minecraft.text.Text; -// import net.minecraft.util.registry.Registry; -import net.minecraft.registry.Registries; - -public class EntitySelector extends Screen { - protected final Screen parent; - - private TextFieldWidget searchField; - private EntityListWidget list; - public static boolean groupByCategory = true; - private static String searchText = ""; - public static HashMap>> searcher; // Prefix -> arr of results - public static HashMap, Color> outlinedEntityTypes = new HashMap<>(); - - public EntitySelector(Screen parent) { - super(Text.translatable("title.entity-outliner.selector")); - this.parent = parent; - } - - public void onClose() { - this.client.setScreen(this.parent); - } - - protected void init() { - if (searcher == null) { - initializePrefixTree(); - } - - this.list = new EntityListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); - this.addSelectableChild(list); - - // Create search field - this.searchField = new TextFieldWidget(this.textRenderer, this.width / 2 - 100, 6, 200, 20, Text.of(searchText)); - this.searchField.setText(searchText); - this.searchField.setChangedListener(this::onSearchFieldUpdate); - this.addSelectableChild(searchField); - - // Create buttons - int buttonWidth = 80; - int buttonHeight = 20; - int buttonInterval = (this.width - 4 * buttonWidth) / 5; - int buttonOffset = buttonInterval; - int buttonY = this.height - 16 - (buttonHeight / 2); - - // Add sort type button - // this.addDrawableChild(new ButtonWidget(buttonOffset, buttonY, buttonWidth, buttonHeight, Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories"), (button) -> { - // groupByCategory = !groupByCategory; - // this.onSearchFieldUpdate(this.searchField.getText()); - // button.setMessage(Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories")); - // })); - - this.addDrawableChild( - ButtonWidget.builder( - Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories"), - (button) -> { - groupByCategory = !groupByCategory; - this.onSearchFieldUpdate(this.searchField.getText()); - button.setMessage(Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories")); - } - ).size(buttonWidth, buttonHeight).position(buttonOffset, buttonY).build() - ); - - // Add Deselect All button - // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval), buttonY, buttonWidth, buttonHeight, Text.translatable("button.entity-outliner.deselect"), (button) -> { - // outlinedEntityTypes.clear(); - // this.onSearchFieldUpdate(this.searchField.getText()); - // })); - - this.addDrawableChild( - ButtonWidget.builder( - Text.translatable("button.entity-outliner.deselect"), - (button) -> { - outlinedEntityTypes.clear(); - this.onSearchFieldUpdate(this.searchField.getText()); - } - ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval), buttonY).build() - ); - - // Add toggle outlining button - // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval) * 2, buttonY, buttonWidth, buttonHeight, Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off"), (button) -> { - // EntityOutliner.outliningEntities = !EntityOutliner.outliningEntities; - // button.setMessage(Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off")); - // })); - - this.addDrawableChild( - ButtonWidget.builder( - Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off"), - (button) -> { - EntityOutliner.outliningEntities = !EntityOutliner.outliningEntities; - button.setMessage(Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off")); - } - ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval) * 2, buttonY).build() - ); - - // Add Done button - // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval) * 3, buttonY, buttonWidth, buttonHeight, Text.translatable("button.entity-outliner.done"), (button) -> { - // this.client.setScreen(null); - // })); - - this.addDrawableChild( - ButtonWidget.builder( - Text.translatable("button.entity-outliner.done"), - (button) -> { this.client.setScreen(null); } - ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval) * 3, buttonY).build() - ); - - this.setInitialFocus(this.searchField); - this.onSearchFieldUpdate(this.searchField.getText()); - } - - // Initializes the prefix tree used for searching in the entity selector screen - private void initializePrefixTree() { - EntitySelector.searcher = new HashMap<>(); - - // Initialize no-text results - List> allResults = new ArrayList>(); - EntitySelector.searcher.put("", allResults); - - // Get sorted list of entity types - List> entityTypes = new ArrayList<>(); - for (EntityType entityType : Registries.ENTITY_TYPE) { - entityTypes.add(entityType); - } - entityTypes.sort(new Comparator>() { - @Override - public int compare(EntityType o1, EntityType o2) { - return o1.getName().getString().compareTo(o2.getName().getString()); - } - }); - - // Add each entity type to everywhere it belongs in the prefix "tree" - for (EntityType entityType : entityTypes) { - - String name = entityType.getName().getString().toLowerCase(); - allResults.add(entityType); - - List prefixes = new ArrayList<>(); - prefixes.add(""); - - // By looping over the name's length, we add to every possible prefix - for (int i = 0; i < name.length(); i++) { - char character = name.charAt(i); - - // Loop over every prefix - for (int p = 0; p < prefixes.size(); p++) { - String prefix = prefixes.get(p) + character; - prefixes.set(p, prefix); - - // Get results for current prefix - List> results; - if (EntitySelector.searcher.containsKey(prefix)) { - results = EntitySelector.searcher.get(prefix); - } else { - results = new ArrayList>(); - EntitySelector.searcher.put(prefix, results); - } - - results.add(entityType); - } - - // Add another prefix to allow searching by second/third/... word - if (Character.isWhitespace(character)) { - prefixes.add(""); - } - } - } - } - - // Callback provided to TextFieldWidget triggered when its text updates - private void onSearchFieldUpdate(String text) { - searchText = text; - text = text.toLowerCase().trim(); - - this.list.clearListEntries(); - - if (searcher.containsKey(text)) { - List> results = searcher.get(text); - - // Splits results into categories and separates them with headers - if (groupByCategory) { - HashMap>> resultsByCategory = new HashMap<>(); - - for (EntityType entityType : results) { - SpawnGroup category = entityType.getSpawnGroup(); - if (!resultsByCategory.containsKey(category)) { - resultsByCategory.put(category, new ArrayList<>()); - } - - resultsByCategory.get(category).add(entityType); - } - - for (SpawnGroup category : SpawnGroup.values()) { - if (resultsByCategory.containsKey(category)) { - this.list.addListEntry(EntityListWidget.HeaderEntry.create(category, this.client.textRenderer, this.width, 25)); - - for (EntityType entityType : resultsByCategory.get(category)) { - this.list.addListEntry(EntityListWidget.EntityEntry.create(entityType, this.width)); - } - - } - } - - } else { - for (EntityType entityType : results) { - this.list.addListEntry(EntityListWidget.EntityEntry.create(entityType, this.width)); - } - } - } else { // If there are no results, let the user know - this.list.addListEntry(EntityListWidget.HeaderEntry.create(null, this.client.textRenderer, this.width, 25)); - } - - // This prevents an overscroll when the user is already scrolled down and the results list is shortened - this.list.setScrollAmount(this.list.getScrollAmount()); - } - - // Called when config screen is escaped - public void removed() { - EntityOutliner.saveConfig(); - } - - public void tick() { - this.searchField.tick(); - } - - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - // Render dirt background - this.renderBackground(matrices); - - // Render scrolling list - this.list.render(matrices, mouseX, mouseY, delta); - - // Render our search bar - this.setFocused(this.searchField); - this.searchField.setTextFieldFocused(true); - this.searchField.render(matrices, mouseX, mouseY, delta); - - // Render buttons - super.render(matrices, mouseX, mouseY, delta); - } - - // Sends mouseDragged event to the scrolling list - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - return this.list.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - } -} diff --git a/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java b/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java deleted file mode 100644 index 5ed0ffd..0000000 --- a/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.entityoutliner.ui; - -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; - -public class ModMenuIntegration implements ModMenuApi { - @Override - public ConfigScreenFactory getModConfigScreenFactory() { - return EntitySelector::new; - } -} \ No newline at end of file diff --git a/src/main/resources/assets/entityoutliner/icon.png b/src/main/resources/assets/entityoutliner/icon.png deleted file mode 100644 index 036b6f86e23b516c04f0380400ede5561d1f7018..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11147 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 Ib4q9e00}m*6#xJL diff --git a/src/main/resources/entityoutliner.mixins.json b/src/main/resources/entityoutliner.mixins.json deleted file mode 100644 index d9dab59..0000000 --- a/src/main/resources/entityoutliner.mixins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "net.entityoutliner.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - ], - "client": [ - "MixinMinecraftClient", - "MixinWorldRenderer" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index 04d78f5..0000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schemaVersion": 1, - "id": "entityoutliner", - "version": "${version}", - - "name": "Entity Outliner", - "description": "Allows you to select entity types to outline, making them visible through all obstructions within render distance.", - "authors": [ - "adamviola" - ], - "contact": { - "homepage": "https://github.com/adamviola/EntityOutliner", - "sources": "https://github.com/adamviola/EntityOutliner" - }, - - "license": "MIT", - "icon": "assets/entityoutliner/icon.png", - - "environment": "client", - "entrypoints": { - "client": [ - "net.entityoutliner.EntityOutliner" - ], - "modmenu": [ - "net.entityoutliner.ui.ModMenuIntegration" - ] - }, - "mixins": [ - { - "config": "entityoutliner.mixins.json", - "environment": "client" - } - ], - - "depends": { - "fabricloader": ">=0.7.4", - "fabric": "*", - "fabric-lifecycle-events-v1": "*", - "fabric-key-binding-api-v1": "*", - "minecraft": ">=1.19" - }, - "suggests": { - "flamingo": "*" - } -} From 189ac1eb43da46f84c7a9c5c44dee49862881405 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Tue, 13 Jun 2023 15:00:37 +0300 Subject: [PATCH 2/7] src 1.20 --- .../net/entityoutliner/EntityOutliner.java | 113 ++++++++ .../mixin/MixinMinecraftClient.java | 23 ++ .../mixin/MixinWorldRenderer.java | 46 +++ .../net/entityoutliner/ui/ColorWidget.java | 101 +++++++ .../entityoutliner/ui/EntityListWidget.java | 171 ++++++++++++ .../net/entityoutliner/ui/EntitySelector.java | 261 ++++++++++++++++++ .../entityoutliner/ui/ModMenuIntegration.java | 11 + .../resources/assets/entityoutliner/icon.png | Bin 0 -> 11147 bytes .../assets/entityoutliner/lang/en_us.json | 13 + .../assets/entityoutliner/lang/fr_fr.json | 13 + .../assets/entityoutliner/lang/zh_cn.json | 13 + .../entityoutliner/textures/gui/colors.png | Bin 0 -> 417 bytes src/main/resources/entityoutliner.mixins.json | 15 + src/main/resources/fabric.mod.json | 44 +++ 14 files changed, 824 insertions(+) create mode 100644 src/main/java/net/entityoutliner/EntityOutliner.java create mode 100644 src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java create mode 100644 src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java create mode 100644 src/main/java/net/entityoutliner/ui/ColorWidget.java create mode 100644 src/main/java/net/entityoutliner/ui/EntityListWidget.java create mode 100644 src/main/java/net/entityoutliner/ui/EntitySelector.java create mode 100644 src/main/java/net/entityoutliner/ui/ModMenuIntegration.java create mode 100644 src/main/resources/assets/entityoutliner/icon.png create mode 100644 src/main/resources/assets/entityoutliner/lang/en_us.json create mode 100644 src/main/resources/assets/entityoutliner/lang/fr_fr.json create mode 100644 src/main/resources/assets/entityoutliner/lang/zh_cn.json create mode 100644 src/main/resources/assets/entityoutliner/textures/gui/colors.png create mode 100644 src/main/resources/entityoutliner.mixins.json create mode 100644 src/main/resources/fabric.mod.json diff --git a/src/main/java/net/entityoutliner/EntityOutliner.java b/src/main/java/net/entityoutliner/EntityOutliner.java new file mode 100644 index 0000000..8a1616a --- /dev/null +++ b/src/main/java/net/entityoutliner/EntityOutliner.java @@ -0,0 +1,113 @@ +package net.entityoutliner; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import org.lwjgl.glfw.GLFW; + +import net.entityoutliner.ui.EntitySelector; +import net.entityoutliner.ui.ColorWidget.Color; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import net.minecraft.entity.EntityType; +import net.minecraft.registry.Registries; + +public class EntityOutliner implements ClientModInitializer { + private static final Gson GSON = new Gson(); + public static boolean outliningEntities; + + private static final KeyBinding CONFIG_BIND = new KeyBinding( + "key.entity-outliner.selector", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_SEMICOLON, + "title.entity-outliner.title" + ); + + private static final KeyBinding OUTLINE_BIND = new KeyBinding( + "key.entity-outliner.outline", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_O, + "title.entity-outliner.title" + ); + + @Override + public void onInitializeClient() { + KeyBindingHelper.registerKeyBinding(CONFIG_BIND); + KeyBindingHelper.registerKeyBinding(OUTLINE_BIND); + + loadConfig(); + + ClientTickEvents.END_CLIENT_TICK.register(this::onEndTick); + } + + private static Path getConfigPath() { + return FabricLoader.getInstance().getConfigDir().resolve("entityoutliner.json"); + } + + public static void saveConfig() { + JsonObject config = new JsonObject(); + + List> outlinedEntityNames = EntitySelector.outlinedEntityTypes.entrySet().stream() + .map(entry -> List.of(EntityType.getId(entry.getKey()).toString(), entry.getValue().name())) + .collect(Collectors.toList()); + + config.add("outlinedEntities", GSON.toJsonTree(outlinedEntityNames)); + + try { + Files.write(getConfigPath(), GSON.toJson(config).getBytes()); + } + catch (IOException ex) { + logException(ex, "Failed to save EntityOutliner config"); + } + } + + private void loadConfig() { + try { + JsonObject config = GSON.fromJson(new String(Files.readAllBytes(getConfigPath())), JsonObject.class); + if (config.has("outlinedEntities")) { + Type setType = new TypeToken>>(){}.getType(); + List> outlinedEntityNames = GSON.fromJson(config.get("outlinedEntities"), setType); + + Map, Color> outlinedEntityTypes = outlinedEntityNames.stream() + .collect(Collectors.toMap(list -> EntityType.get(list.get(0)).get(), list -> Color.valueOf(list.get(1))));; + + for (EntityType entityType : Registries.ENTITY_TYPE) + if (outlinedEntityTypes.containsKey(entityType)) + EntitySelector.outlinedEntityTypes.put(entityType, outlinedEntityTypes.get(entityType)); + } + } + catch (IOException | JsonSyntaxException ex) { + logException(ex, "Failed to load EntityOutliner config"); + } + } + + private void onEndTick(MinecraftClient client) { + while (OUTLINE_BIND.wasPressed()) { + outliningEntities = !outliningEntities; + } + + if (CONFIG_BIND.isPressed()) { + client.setScreen(new EntitySelector(null)); + } + } + + public static void logException(Exception ex, String message) { + System.err.printf("[EntityOutliner] %s (%s: %s)", message, ex.getClass().getSimpleName(), ex.getLocalizedMessage()); + } +} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java b/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java new file mode 100644 index 0000000..bce1fa6 --- /dev/null +++ b/src/main/java/net/entityoutliner/mixin/MixinMinecraftClient.java @@ -0,0 +1,23 @@ +package net.entityoutliner.mixin; + +import net.entityoutliner.EntityOutliner; +import net.entityoutliner.ui.EntitySelector; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(MinecraftClient.class) +public abstract class MixinMinecraftClient { + + @Inject(method = "hasOutline", at = @At("HEAD"), cancellable = true) + private void outlineEntities(Entity entity, CallbackInfoReturnable ci) { + if (EntityOutliner.outliningEntities && EntitySelector.outlinedEntityTypes != null) { + if (EntitySelector.outlinedEntityTypes.containsKey(entity.getType())) { + ci.setReturnValue(true); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java b/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java new file mode 100644 index 0000000..173b87e --- /dev/null +++ b/src/main/java/net/entityoutliner/mixin/MixinWorldRenderer.java @@ -0,0 +1,46 @@ +package net.entityoutliner.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.entityoutliner.EntityOutliner; +import net.entityoutliner.ui.EntitySelector; +import net.entityoutliner.ui.ColorWidget.Color; +import net.minecraft.client.render.OutlineVertexConsumerProvider; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.scoreboard.AbstractTeam; + +@Mixin(WorldRenderer.class) +public abstract class MixinWorldRenderer { + + @Inject(method = "renderEntity", at = @At("HEAD")) + private void renderEntity(Entity entity, double cameraX, double cameraY, double cameraZ, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { + if (EntityOutliner.outliningEntities + && vertexConsumers instanceof OutlineVertexConsumerProvider + && EntitySelector.outlinedEntityTypes.containsKey(entity.getType())) { + + Color color = EntitySelector.outlinedEntityTypes.get(entity.getType()); + OutlineVertexConsumerProvider outlineVertexConsumers = (OutlineVertexConsumerProvider) vertexConsumers; + outlineVertexConsumers.setColor(color.red, color.green, color.blue, 255); + + if (entity.getType() == EntityType.PLAYER) { + PlayerEntity player = (PlayerEntity) entity; + AbstractTeam team = player.getScoreboardTeam(); + if (team != null && team.getColor().getColorValue() != null) { + int hexColor = team.getColor().getColorValue(); + int blue = hexColor % 256; + int green = (hexColor / 256) % 256; + int red = (hexColor / 65536) % 256; + outlineVertexConsumers.setColor(red, green, blue, 255); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/entityoutliner/ui/ColorWidget.java b/src/main/java/net/entityoutliner/ui/ColorWidget.java new file mode 100644 index 0000000..c30a05b --- /dev/null +++ b/src/main/java/net/entityoutliner/ui/ColorWidget.java @@ -0,0 +1,101 @@ +package net.entityoutliner.ui; + +import java.util.Map; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.PressableWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +public class ColorWidget extends PressableWidget { + private static final Identifier TEXTURE = new Identifier("entityoutliner:textures/gui/colors.png"); + private Color color; + private EntityType entityType; + + private ColorWidget(int x, int y, int width, int height, Text message, EntityType entityType) { + super(x, y, width, height, message); + this.entityType = entityType; + + if (EntitySelector.outlinedEntityTypes.containsKey(this.entityType)) + onShow(); + } + + public ColorWidget(int x, int y, int width, int height, EntityType entityType) { + this(x, y, width, height, Text.translatable("options.chat.color"), entityType); + } + + public void onShow() { + this.color = EntitySelector.outlinedEntityTypes.get(this.entityType); + } + + public void onPress() { + this.color = this.color.next(); + EntitySelector.outlinedEntityTypes.put(this.entityType, this.color); + } + + public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) { + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.enableDepthTest(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); + RenderSystem.enableBlend(); + context.drawTexture(TEXTURE, this.getX(), this.getY(), this.isFocused() ? 20.0F : 0.0F, this.color.ordinal() * 20, 20, 20, 40, 180); + } + + public enum Color { + WHITE(255, 255, 255), + BLACK(0, 0, 0), + RED(255, 0, 0), + ORANGE(255, 127, 0), + YELLOW(255, 255, 0), + GREEN(0, 255, 0), + BLUE(0, 0, 255), + PURPLE(127, 0, 127), + PINK(255, 155, 182); + + public int red; + public int green; + public int blue; + + private static final Map spawnGroupColors = Map.of( + SpawnGroup.AMBIENT, Color.PURPLE, + SpawnGroup.AXOLOTLS, Color.PINK, + SpawnGroup.CREATURE, Color.YELLOW, + SpawnGroup.MISC, Color.WHITE, + SpawnGroup.MONSTER, Color.RED, + SpawnGroup.UNDERGROUND_WATER_CREATURE, Color.ORANGE, + SpawnGroup.WATER_AMBIENT, Color.GREEN, + SpawnGroup.WATER_CREATURE, Color.BLUE + ); + + private static Color[] colors = Color.values(); + + private Color(int red, int green, int blue) { + this.red = red; + this.green = green; + this.blue = blue; + } + + public static Color of(SpawnGroup group) { + return spawnGroupColors.get(group); + } + + public Color next() { + return get((this.ordinal() + 1) % colors.length); + } + + public Color get(int index) { + return colors[index]; + } + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) {} +} diff --git a/src/main/java/net/entityoutliner/ui/EntityListWidget.java b/src/main/java/net/entityoutliner/ui/EntityListWidget.java new file mode 100644 index 0000000..99a3db6 --- /dev/null +++ b/src/main/java/net/entityoutliner/ui/EntityListWidget.java @@ -0,0 +1,171 @@ +package net.entityoutliner.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import net.entityoutliner.ui.ColorWidget.Color; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.widget.CheckboxWidget; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.gui.widget.PressableWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.Language; +import net.minecraft.client.gui.DrawContext; + +@Environment(EnvType.CLIENT) +public class EntityListWidget extends ElementListWidget { + + public EntityListWidget(MinecraftClient client, int width, int height, int top, int bottom, int itemHeight) { + super(client, width, height, top, bottom, itemHeight); + this.centerListVertically = false; + } + + public void addListEntry(EntityListWidget.Entry entry) { + super.addEntry(entry); + } + + public void clearListEntries() { + super.clearEntries(); + } + + public int getRowWidth() { + return 400; + } + + protected int getScrollbarPositionX() { + return super.getScrollbarPositionX() + 32; + } + + @Environment(EnvType.CLIENT) + public static abstract class Entry extends ElementListWidget.Entry { } + + @Environment(EnvType.CLIENT) + public static class EntityEntry extends EntityListWidget.Entry { + + private final CheckboxWidget checkbox; + private final ColorWidget color; + private final EntityType entityType; + private final List children = new ArrayList<>(); + + private EntityEntry(CheckboxWidget checkbox, ColorWidget color, EntityType entityType) { + this.checkbox = checkbox; + this.entityType = entityType; + this.color = color; + + this.children.add(checkbox); + if (EntitySelector.outlinedEntityTypes.containsKey(entityType)) + this.children.add(color); + } + + public static EntityListWidget.EntityEntry create(EntityType entityType, int width) { + return new EntityListWidget.EntityEntry( + new CheckboxWidget(width / 2 - 155, 0, 310, 20, entityType.getName(), EntitySelector.outlinedEntityTypes.containsKey(entityType)), + new ColorWidget(width / 2 + 130, 0, 310, 20, entityType), + entityType + ); + } + + public void render(DrawContext context, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { + this.checkbox.setY(j); + this.checkbox.render(context, n, o, f); + + if (this.children.contains(this.color)) { + this.color.setY(j); + this.color.render(context, n, o, f); + } + } + + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (EntitySelector.outlinedEntityTypes.containsKey(entityType)) { + if (this.color.isMouseOver(mouseX, mouseY)) { + this.color.onPress(); + } else { + EntitySelector.outlinedEntityTypes.remove(entityType); + + this.checkbox.onPress(); + this.children.remove(this.color); + } + } else { + EntitySelector.outlinedEntityTypes.put(entityType, Color.of(entityType.getSpawnGroup())); + + this.color.onShow(); + this.checkbox.onPress(); + this.children.add(this.color); + } + + return true; + } + + public List children() { + return this.children; + } + + public EntityType getEntityType() { + return this.entityType; + } + + public CheckboxWidget getCheckbox() { + return this.checkbox; + } + + public List selectableChildren() { + return this.children; + } + } + + @Environment(EnvType.CLIENT) + public static class HeaderEntry extends EntityListWidget.Entry { + + private final TextRenderer font; + private final String title; + private final int width; + private final int height; + + private HeaderEntry(SpawnGroup category, TextRenderer font, int width, int height) { + this.font = font; + this.width = width; + this.height = height; + + if (category != null) { + String title = ""; + for (String term : category.getName().split("\\p{Punct}|\\p{Space}")) { + title += StringUtils.capitalize(term) + " "; + } + this.title = title.trim(); + } else { + this.title = Language.getInstance().get("gui.entity-outliner.no_results"); + } + + } + + public static EntityListWidget.HeaderEntry create(SpawnGroup category, TextRenderer font, int width, int height) { + return new EntityListWidget.HeaderEntry(category, font, width, height); + } + + public void render(DrawContext context, int i, int j, int k, int l, int m, int n, int o, boolean bl, float f) { + context.drawCenteredTextWithShadow(this.font, this.title, this.width / 2, j + (this.height / 2) - (this.font.fontHeight / 2), 16777215); + } + + public List children() { + return new ArrayList<>(); + } + + public String toString() { + return this.title; + } + + @Override + public List selectableChildren() { + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/net/entityoutliner/ui/EntitySelector.java b/src/main/java/net/entityoutliner/ui/EntitySelector.java new file mode 100644 index 0000000..1b7b091 --- /dev/null +++ b/src/main/java/net/entityoutliner/ui/EntitySelector.java @@ -0,0 +1,261 @@ +package net.entityoutliner.ui; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; + +import net.entityoutliner.EntityOutliner; +import net.entityoutliner.ui.ColorWidget.Color; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; + +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.EntityType; +import net.minecraft.text.Text; +// import net.minecraft.util.registry.Registry; +import net.minecraft.registry.Registries; +import net.minecraft.client.gui.DrawContext; + +public class EntitySelector extends Screen { + protected final Screen parent; + + private TextFieldWidget searchField; + private EntityListWidget list; + public static boolean groupByCategory = true; + private static String searchText = ""; + public static HashMap>> searcher; // Prefix -> arr of results + public static HashMap, Color> outlinedEntityTypes = new HashMap<>(); + + public EntitySelector(Screen parent) { + super(Text.translatable("title.entity-outliner.selector")); + this.parent = parent; + } + + public void onClose() { + this.client.setScreen(this.parent); + } + + protected void init() { + if (searcher == null) { + initializePrefixTree(); + } + + this.list = new EntityListWidget(this.client, this.width, this.height, 32, this.height - 32, 25); + this.addSelectableChild(list); + + // Create search field + this.searchField = new TextFieldWidget(this.textRenderer, this.width / 2 - 100, 6, 200, 20, Text.of(searchText)); + this.searchField.setText(searchText); + this.searchField.setChangedListener(this::onSearchFieldUpdate); + this.addSelectableChild(searchField); + + // Create buttons + int buttonWidth = 80; + int buttonHeight = 20; + int buttonInterval = (this.width - 4 * buttonWidth) / 5; + int buttonOffset = buttonInterval; + int buttonY = this.height - 16 - (buttonHeight / 2); + + // Add sort type button + // this.addDrawableChild(new ButtonWidget(buttonOffset, buttonY, buttonWidth, buttonHeight, Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories"), (button) -> { + // groupByCategory = !groupByCategory; + // this.onSearchFieldUpdate(this.searchField.getText()); + // button.setMessage(Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories")); + // })); + + this.addDrawableChild( + ButtonWidget.builder( + Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories"), + (button) -> { + groupByCategory = !groupByCategory; + this.onSearchFieldUpdate(this.searchField.getText()); + button.setMessage(Text.translatable(groupByCategory ? "button.entity-outliner.categories" : "button.entity-outliner.no-categories")); + } + ).size(buttonWidth, buttonHeight).position(buttonOffset, buttonY).build() + ); + + // Add Deselect All button + // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval), buttonY, buttonWidth, buttonHeight, Text.translatable("button.entity-outliner.deselect"), (button) -> { + // outlinedEntityTypes.clear(); + // this.onSearchFieldUpdate(this.searchField.getText()); + // })); + + this.addDrawableChild( + ButtonWidget.builder( + Text.translatable("button.entity-outliner.deselect"), + (button) -> { + outlinedEntityTypes.clear(); + this.onSearchFieldUpdate(this.searchField.getText()); + } + ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval), buttonY).build() + ); + + // Add toggle outlining button + // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval) * 2, buttonY, buttonWidth, buttonHeight, Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off"), (button) -> { + // EntityOutliner.outliningEntities = !EntityOutliner.outliningEntities; + // button.setMessage(Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off")); + // })); + + this.addDrawableChild( + ButtonWidget.builder( + Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off"), + (button) -> { + EntityOutliner.outliningEntities = !EntityOutliner.outliningEntities; + button.setMessage(Text.translatable(EntityOutliner.outliningEntities ? "button.entity-outliner.on" : "button.entity-outliner.off")); + } + ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval) * 2, buttonY).build() + ); + + // Add Done button + // this.addDrawableChild(new ButtonWidget(buttonOffset + (buttonWidth + buttonInterval) * 3, buttonY, buttonWidth, buttonHeight, Text.translatable("button.entity-outliner.done"), (button) -> { + // this.client.setScreen(null); + // })); + + this.addDrawableChild( + ButtonWidget.builder( + Text.translatable("button.entity-outliner.done"), + (button) -> { this.client.setScreen(null); } + ).size(buttonWidth, buttonHeight).position(buttonOffset + (buttonWidth + buttonInterval) * 3, buttonY).build() + ); + + this.setInitialFocus(this.searchField); + this.onSearchFieldUpdate(this.searchField.getText()); + } + + // Initializes the prefix tree used for searching in the entity selector screen + private void initializePrefixTree() { + EntitySelector.searcher = new HashMap<>(); + + // Initialize no-text results + List> allResults = new ArrayList>(); + EntitySelector.searcher.put("", allResults); + + // Get sorted list of entity types + List> entityTypes = new ArrayList<>(); + for (EntityType entityType : Registries.ENTITY_TYPE) { + entityTypes.add(entityType); + } + entityTypes.sort(new Comparator>() { + @Override + public int compare(EntityType o1, EntityType o2) { + return o1.getName().getString().compareTo(o2.getName().getString()); + } + }); + + // Add each entity type to everywhere it belongs in the prefix "tree" + for (EntityType entityType : entityTypes) { + + String name = entityType.getName().getString().toLowerCase(); + allResults.add(entityType); + + List prefixes = new ArrayList<>(); + prefixes.add(""); + + // By looping over the name's length, we add to every possible prefix + for (int i = 0; i < name.length(); i++) { + char character = name.charAt(i); + + // Loop over every prefix + for (int p = 0; p < prefixes.size(); p++) { + String prefix = prefixes.get(p) + character; + prefixes.set(p, prefix); + + // Get results for current prefix + List> results; + if (EntitySelector.searcher.containsKey(prefix)) { + results = EntitySelector.searcher.get(prefix); + } else { + results = new ArrayList>(); + EntitySelector.searcher.put(prefix, results); + } + + results.add(entityType); + } + + // Add another prefix to allow searching by second/third/... word + if (Character.isWhitespace(character)) { + prefixes.add(""); + } + } + } + } + + // Callback provided to TextFieldWidget triggered when its text updates + private void onSearchFieldUpdate(String text) { + searchText = text; + text = text.toLowerCase().trim(); + + this.list.clearListEntries(); + + if (searcher.containsKey(text)) { + List> results = searcher.get(text); + + // Splits results into categories and separates them with headers + if (groupByCategory) { + HashMap>> resultsByCategory = new HashMap<>(); + + for (EntityType entityType : results) { + SpawnGroup category = entityType.getSpawnGroup(); + if (!resultsByCategory.containsKey(category)) { + resultsByCategory.put(category, new ArrayList<>()); + } + + resultsByCategory.get(category).add(entityType); + } + + for (SpawnGroup category : SpawnGroup.values()) { + if (resultsByCategory.containsKey(category)) { + this.list.addListEntry(EntityListWidget.HeaderEntry.create(category, this.client.textRenderer, this.width, 25)); + + for (EntityType entityType : resultsByCategory.get(category)) { + this.list.addListEntry(EntityListWidget.EntityEntry.create(entityType, this.width)); + } + + } + } + + } else { + for (EntityType entityType : results) { + this.list.addListEntry(EntityListWidget.EntityEntry.create(entityType, this.width)); + } + } + } else { // If there are no results, let the user know + this.list.addListEntry(EntityListWidget.HeaderEntry.create(null, this.client.textRenderer, this.width, 25)); + } + + // This prevents an overscroll when the user is already scrolled down and the results list is shortened + this.list.setScrollAmount(this.list.getScrollAmount()); + } + + // Called when config screen is escaped + public void removed() { + EntityOutliner.saveConfig(); + } + + public void tick() { + this.searchField.tick(); + } + + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + // Render dirt background + this.renderBackground(context); + + // Render scrolling list + this.list.render(context, mouseX, mouseY, delta); + + // Render our search bar + this.setFocused(this.searchField); + this.searchField.render(context, mouseX, mouseY, delta); + + // Render buttons + super.render(context, mouseX, mouseY, delta); + } + + // Sends mouseDragged event to the scrolling list + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return this.list.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } +} diff --git a/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java b/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java new file mode 100644 index 0000000..5ed0ffd --- /dev/null +++ b/src/main/java/net/entityoutliner/ui/ModMenuIntegration.java @@ -0,0 +1,11 @@ +package net.entityoutliner.ui; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +public class ModMenuIntegration implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return EntitySelector::new; + } +} \ No newline at end of file diff --git a/src/main/resources/assets/entityoutliner/icon.png b/src/main/resources/assets/entityoutliner/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..036b6f86e23b516c04f0380400ede5561d1f7018 GIT binary patch literal 11147 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 Ib4q9e00}m*6#xJL literal 0 HcmV?d00001 diff --git a/src/main/resources/entityoutliner.mixins.json b/src/main/resources/entityoutliner.mixins.json new file mode 100644 index 0000000..d9dab59 --- /dev/null +++ b/src/main/resources/entityoutliner.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.entityoutliner.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + ], + "client": [ + "MixinMinecraftClient", + "MixinWorldRenderer" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..0dcf3c3 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,44 @@ +{ + "schemaVersion": 1, + "id": "entityoutliner", + "version": "${version}", + + "name": "Entity Outliner", + "description": "Allows you to select entity types to outline, making them visible through all obstructions within render distance.", + "authors": [ + "adamviola" + ], + "contact": { + "homepage": "https://github.com/adamviola/EntityOutliner", + "sources": "https://github.com/adamviola/EntityOutliner" + }, + + "license": "MIT", + "icon": "assets/entityoutliner/icon.png", + + "environment": "client", + "entrypoints": { + "client": [ + "net.entityoutliner.EntityOutliner" + ], + "modmenu": [ + "net.entityoutliner.ui.ModMenuIntegration" + ] + }, + "mixins": [ + { + "config": "entityoutliner.mixins.json", + "environment": "client" + } + ], + + "depends": { + "fabricloader": ">=0.14.17", + "fabric-api": "*", + "minecraft": "~1.20", + "java": ">=17" + }, + "suggests": { + "flamingo": "*" + } +} From e9c7b34528aaef29138214917bb90e92dcebb83f Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Sat, 17 Jun 2023 10:33:57 +0300 Subject: [PATCH 3/7] Update gradle.properties changed to 1.20 --- gradle.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index 7bb54f7..3a924c9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,13 +3,13 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.19.3 - yarn_mappings=1.19.3+build.5 - loader_version=0.14.13 + minecraft_version=1.20 + yarn_mappings=1.20+build.1 + loader_version=0.14.21 # Mod Properties - mod_version = 1.2.6 + mod_version = 1.2.6_1.20 maven_group = net.entityoutliner archives_base_name = entity-outliner @@ -17,5 +17,5 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.73.0+1.19.3 + fabric_version=0.83.0+1.20 modmenu_version=5.0.2 From cd8ef0c96efbe6f9b296041937b7a4d63ded8bb5 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Sat, 17 Jun 2023 10:36:33 +0300 Subject: [PATCH 4/7] Update gradle.properties --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3a924c9..2e7a21e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api fabric_version=0.83.0+1.20 - modmenu_version=5.0.2 + modmenu_version=7.0.1 From 6f08460fe82fcbb7f2d45c2f7a28909869098e79 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Sun, 26 Nov 2023 23:05:37 +0300 Subject: [PATCH 5/7] Update fabric.mod.json --- src/main/resources/fabric.mod.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0dcf3c3..ea4f3c9 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -33,9 +33,9 @@ ], "depends": { - "fabricloader": ">=0.14.17", + "fabricloader": ">=0.14.22", "fabric-api": "*", - "minecraft": "~1.20", + "minecraft": "1.20.2", "java": ">=17" }, "suggests": { From d0146b4d4bad13970a5e18582929dee9161421f2 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Sun, 26 Nov 2023 23:06:12 +0300 Subject: [PATCH 6/7] Update gradle.properties --- gradle.properties | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2e7a21e..ffdf232 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,13 +3,13 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.20 - yarn_mappings=1.20+build.1 - loader_version=0.14.21 + minecraft_version=1.20.2 + yarn_mappings=1.20.2+build.4 + loader_version=0.14.24 # Mod Properties - mod_version = 1.2.6_1.20 + mod_version = 1.2.6_1.20.2 maven_group = net.entityoutliner archives_base_name = entity-outliner @@ -17,5 +17,6 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.83.0+1.20 + fabric_version=0.91.0+1.20.2 modmenu_version=7.0.1 + From 33f6ee6d97c282cd33f0f97f42164b52e2abadd6 Mon Sep 17 00:00:00 2001 From: mocksonline <99143323+mocksonline@users.noreply.github.com> Date: Sun, 26 Nov 2023 23:07:59 +0300 Subject: [PATCH 7/7] Update EntitySelector.java --- src/main/java/net/entityoutliner/ui/EntitySelector.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/entityoutliner/ui/EntitySelector.java b/src/main/java/net/entityoutliner/ui/EntitySelector.java index 1b7b091..4036840 100644 --- a/src/main/java/net/entityoutliner/ui/EntitySelector.java +++ b/src/main/java/net/entityoutliner/ui/EntitySelector.java @@ -236,12 +236,12 @@ public void removed() { } public void tick() { - this.searchField.tick(); + //this.searchField.tick(); //WTF is it?? } public void render(DrawContext context, int mouseX, int mouseY, float delta) { // Render dirt background - this.renderBackground(context); + this.renderBackground(context, mouseX, mouseY, delta); // Render scrolling list this.list.render(context, mouseX, mouseY, delta);