c = this.collectBlocks();
61 | ScanController.renderQueue.clear();
62 | ScanController.renderQueue.addAll(c);
63 | isScanning.set(false);
64 | RenderOutlines.requestedRefresh.set(true);
65 | }
66 |
67 | /**
68 | * This is an "exact" copy from the forge version of the mod but with the optimisations that the
69 | * rewrite (Fabric) version has brought like chunk location based cache, etc.
70 | *
71 | * This is only run if the cache is invalidated.
72 | *
73 | * @implNote Using the {@link BlockPos#betweenClosed(BlockPos, BlockPos)} may be a better system for the
74 | * scanning.
75 | */
76 | private Set collectBlocks() {
77 | Set blocks = BlockStore.getInstance().getCache().get();
78 |
79 | // If we're not looking for blocks, don't run.
80 | if (blocks.isEmpty() && !SettingsStore.getInstance().get().isShowLava()) {
81 | if (!ScanController.renderQueue.isEmpty()) {
82 | ScanController.renderQueue.clear();
83 | }
84 | return new HashSet<>();
85 | }
86 |
87 | Minecraft instance = Minecraft.getInstance();
88 |
89 | final Level world = instance.level;
90 | final Player player = instance.player;
91 |
92 | // Just stop if we can't get the player or world.
93 | if (world == null || player == null) {
94 | return new HashSet<>();
95 | }
96 |
97 | final Set renderQueue = new HashSet<>();
98 |
99 | int cX = player.chunkPosition().x;
100 | int cZ = player.chunkPosition().z;
101 |
102 | int range = StateSettings.getHalfRange();
103 |
104 | for (int i = cX - range; i <= cX + range; i++) {
105 | int chunkStartX = i << 4;
106 | for (int j = cZ - range; j <= cZ + range; j++) {
107 | int chunkStartZ = j << 4;
108 |
109 | for (int k = chunkStartX; k < chunkStartX + 16; k++) {
110 | for (int l = chunkStartZ; l < chunkStartZ + 16; l++) {
111 | for (int m = world.getMinY(); m < world.getMaxY() + (1 << 4); m++) {
112 | BlockPos pos = new BlockPos(k, m, l);
113 | BasicColor validBlock = isValidBlock(pos, world, blocks);
114 | if (validBlock != null) {
115 | renderQueue.add(new BlockPosWithColor(pos, validBlock));
116 | }
117 | }
118 | }
119 | }
120 | }
121 | }
122 |
123 | return renderQueue;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/StateSettings.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray;
2 |
3 | import net.minecraft.util.Mth;
4 | import pro.mikey.fabric.xray.storage.SettingsStore;
5 |
6 | public class StateSettings {
7 | private static final int maxStepsToScan = 5;
8 |
9 | private transient boolean isActive;
10 | private boolean showLava;
11 | private int range;
12 | private boolean showOverlay;
13 |
14 | public StateSettings() {
15 | this.isActive = false;
16 | this.showLava = false;
17 | this.showOverlay = true;
18 | this.range = 3;
19 | }
20 |
21 | public boolean isActive() {
22 | return this.isActive;
23 | }
24 |
25 | void setActive(boolean active) {
26 | this.isActive = active;
27 | }
28 |
29 | public boolean isShowLava() {
30 | return this.showLava;
31 | }
32 |
33 | public void setShowLava(boolean showLava) {
34 | this.showLava = showLava;
35 | }
36 |
37 | public static int getRadius() {
38 | return Mth.clamp(SettingsStore.getInstance().get().range, 0, maxStepsToScan) * 3;
39 | }
40 |
41 | public static int getHalfRange() {
42 | return Math.max(0, getRadius() / 2);
43 | }
44 |
45 | public static int getVisualRadius() {
46 | return Math.max(1, getRadius());
47 | }
48 |
49 | public void increaseRange() {
50 | if (SettingsStore.getInstance().get().range < maxStepsToScan)
51 | SettingsStore.getInstance().get().range = SettingsStore.getInstance().get().range + 1;
52 | else
53 | SettingsStore.getInstance().get().range = 0;
54 | }
55 |
56 | public void decreaseRange() {
57 | if (SettingsStore.getInstance().get().range > 0)
58 | SettingsStore.getInstance().get().range = SettingsStore.getInstance().get().range - 1;
59 | else
60 | SettingsStore.getInstance().get().range = maxStepsToScan;
61 | }
62 |
63 | public boolean showOverlay() {
64 | return this.showOverlay;
65 | }
66 |
67 | public void setShowOverlay(boolean showOverlay) {
68 | this.showOverlay = showOverlay;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/Utils.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray;
2 |
3 | import net.minecraft.resources.ResourceLocation;
4 |
5 | public class Utils {
6 | public static ResourceLocation rl(String path) {
7 | return ResourceLocation.fromNamespaceAndPath(XRay.MOD_ID, path);
8 | }
9 |
10 | public static ResourceLocation rlFull(String namespaceAndPath) {
11 | return ResourceLocation.tryParse(namespaceAndPath);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/XRay.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray;
2 |
3 | import net.fabricmc.api.ClientModInitializer;
4 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
5 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
6 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
7 | import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
8 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
9 | import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
10 | import net.minecraft.ChatFormatting;
11 | import net.minecraft.client.KeyMapping;
12 | import net.minecraft.client.Minecraft;
13 | import net.minecraft.network.chat.Component;
14 | import org.apache.logging.log4j.LogManager;
15 | import org.apache.logging.log4j.Logger;
16 | import org.lwjgl.glfw.GLFW;
17 | import pro.mikey.fabric.xray.render.RenderOutlines;
18 | import pro.mikey.fabric.xray.screens.forge.GuiOverlay;
19 | import pro.mikey.fabric.xray.screens.forge.GuiSelectionScreen;
20 | import pro.mikey.fabric.xray.storage.BlockStore;
21 | import pro.mikey.fabric.xray.storage.SettingsStore;
22 |
23 | public class XRay implements ClientModInitializer {
24 | public static final String MOD_ID = "advanced-xray-fabric";
25 | public static final String PREFIX_GUI = String.format("%s:textures/gui/", MOD_ID);
26 | public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
27 |
28 | private final KeyMapping xrayButton = new KeyMapping("keybinding.enable_xray", GLFW.GLFW_KEY_BACKSLASH, "category.xray");
29 |
30 | private final KeyMapping guiButton = new KeyMapping("keybinding.open_gui", GLFW.GLFW_KEY_G, "category.xray");
31 |
32 | @Override
33 | public void onInitializeClient() {
34 | LOGGER.info("XRay mod has been initialized");
35 |
36 | ClientTickEvents.END_CLIENT_TICK.register(this::clientTickEvent);
37 | ClientLifecycleEvents.CLIENT_STOPPING.register(this::gameClosing);
38 | ClientLifecycleEvents.CLIENT_STARTED.register(this::started);
39 | HudRenderCallback.EVENT.register(GuiOverlay::RenderGameOverlayEvent);
40 |
41 | WorldRenderEvents.LAST.register(RenderOutlines::render);
42 | PlayerBlockBreakEvents.AFTER.register(ScanController::blockBroken);
43 |
44 | KeyBindingHelper.registerKeyBinding(this.xrayButton);
45 | KeyBindingHelper.registerKeyBinding(this.guiButton);
46 |
47 | }
48 |
49 | private void started(Minecraft minecraft) {
50 | LOGGER.info("Client started, setting up xray store");
51 | }
52 |
53 | /**
54 | * Upon game closing, attempt to save our json stores. This means we can be a little lazy with how
55 | * we go about saving throughout the rest of the mod
56 | */
57 | private void gameClosing(Minecraft client) {
58 | SettingsStore.getInstance().write();
59 | BlockStore.getInstance().write();
60 | }
61 |
62 | /**
63 | * Used to handle keybindings and fire off threaded scanning tasks
64 | */
65 | private void clientTickEvent(Minecraft mc) {
66 | if (mc.player == null || mc.level == null || mc.screen != null) {
67 | return;
68 | }
69 |
70 | // Try and run the task :D
71 | ScanController.runTask(false);
72 |
73 | while (this.guiButton.consumeClick()) {
74 | mc.setScreen(new GuiSelectionScreen());
75 | }
76 |
77 | while (this.xrayButton.consumeClick()) {
78 | BlockStore.getInstance().updateCache();
79 |
80 | StateSettings stateSettings = SettingsStore.getInstance().get();
81 | stateSettings.setActive(!stateSettings.isActive());
82 |
83 | ScanController.runTask(true);
84 |
85 | mc.player.displayClientMessage(Component.translatable("message.xray_" + (!stateSettings.isActive() ? "deactivate" : "active")).withStyle(stateSettings.isActive() ? ChatFormatting.GREEN : ChatFormatting.RED), true);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/cache/BlockSearchCache.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.cache;
2 |
3 | import pro.mikey.fabric.xray.records.BlockEntry;
4 | import pro.mikey.fabric.xray.records.BlockGroup;
5 |
6 | import java.util.HashSet;
7 | import java.util.List;
8 | import java.util.Set;
9 | import java.util.stream.Collectors;
10 |
11 | /**
12 | * Physical representation of what we're searching for. Contains the actual state, Scraps unneeded
13 | * data and cleans up some logic along the way.
14 | *
15 | * I control when this list is populated and has changes through the first load and the gui.
16 | */
17 | public class BlockSearchCache {
18 | private Set cache = new HashSet<>();
19 |
20 | public void processGroupedList(List blockEntries) {
21 | if (blockEntries == null || blockEntries.isEmpty()) {
22 | return;
23 | }
24 |
25 | // Flatten the grouped list down to a single cacheable list
26 | this.cache =
27 | blockEntries.stream()
28 | .flatMap(
29 | e ->
30 | e.entries().stream()
31 | .filter(BlockEntry::isActive)
32 | .map(a -> new BlockSearchEntry(a.getState(), a.getHex(), a.isDefault())))
33 | .collect(Collectors.toSet());
34 | }
35 |
36 | public Set get() {
37 | return this.cache;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/cache/BlockSearchEntry.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.cache;
2 |
3 | import com.google.common.base.MoreObjects;
4 | import com.google.common.base.Objects;
5 | import com.mojang.brigadier.exceptions.CommandSyntaxException;
6 | import net.minecraft.core.registries.BuiltInRegistries;
7 | import net.minecraft.nbt.CompoundTag;
8 | import net.minecraft.nbt.NbtUtils;
9 | import net.minecraft.nbt.TagParser;
10 | import net.minecraft.world.level.block.Blocks;
11 | import net.minecraft.world.level.block.state.BlockState;
12 | import pro.mikey.fabric.xray.records.BasicColor;
13 |
14 | public class BlockSearchEntry {
15 | private final BlockState state;
16 | private final BasicColor color;
17 | private final boolean isDefault;
18 |
19 | BlockSearchEntry(BlockState state, BasicColor color, boolean isDefault) {
20 | this.state = state;
21 | this.color = color;
22 | this.isDefault = isDefault;
23 | }
24 |
25 | public static BlockState blockStateFromStringNBT(String nbt) {
26 | CompoundTag tag;
27 | try {
28 | tag = TagParser.parseCompoundFully(nbt);
29 | } catch (CommandSyntaxException e) {
30 | e.printStackTrace();
31 | return Blocks.AIR.defaultBlockState();
32 | }
33 |
34 | return NbtUtils.readBlockState(BuiltInRegistries.BLOCK, tag);
35 | }
36 |
37 | public static String blockStateToStringNBT(BlockState state) {
38 | return NbtUtils.writeBlockState(state).toString();
39 | }
40 |
41 | public BlockState getState() {
42 | return this.state;
43 | }
44 |
45 | public BasicColor getColor() {
46 | return this.color;
47 | }
48 |
49 | public boolean isDefault() {
50 | return this.isDefault;
51 | }
52 |
53 | // We don't care about the color and isDefault
54 | @Override
55 | public boolean equals(Object o) {
56 | if (this == o) {
57 | return true;
58 | }
59 | if (o == null || this.getClass() != o.getClass()) {
60 | return false;
61 | }
62 | BlockSearchEntry that = (BlockSearchEntry) o;
63 | return Objects.equal(this.state, that.state);
64 | }
65 |
66 | @Override
67 | public int hashCode() {
68 | return Objects.hashCode(this.state);
69 | }
70 |
71 | @Override
72 | public String toString() {
73 | return MoreObjects.toStringHelper(this)
74 | .add("state", this.state)
75 | .add("color", this.color)
76 | .add("isDefault", this.isDefault)
77 | .toString();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/mixins/MixinBlockItem.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.mixins;
2 |
3 | import net.minecraft.world.InteractionResult;
4 | import net.minecraft.world.item.BlockItem;
5 | import net.minecraft.world.item.context.BlockPlaceContext;
6 | import org.spongepowered.asm.mixin.Mixin;
7 | import org.spongepowered.asm.mixin.injection.At;
8 | import org.spongepowered.asm.mixin.injection.Inject;
9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
10 | import pro.mikey.fabric.xray.ScanController;
11 |
12 | // Thanks to architectury
13 | @Mixin(BlockItem.class)
14 | public abstract class MixinBlockItem {
15 | @Inject(method = "place", at = @At("TAIL"))
16 | private void place(BlockPlaceContext context, CallbackInfoReturnable cir) {
17 | if (context.getLevel().isClientSide) {
18 | ScanController.blockPlaced(context);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/records/BasicColor.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.records;
2 |
3 | import java.awt.*;
4 |
5 | public record BasicColor(
6 | int red,
7 | int green,
8 | int blue
9 | ) {
10 | public static BasicColor of(String hex) {
11 | if (!hex.startsWith("#")) {
12 | return new BasicColor(0, 0, 0);
13 | }
14 |
15 | Color color = Color.decode(hex);
16 | return new BasicColor(color.getRed(), color.getGreen(), color.getBlue());
17 | }
18 |
19 | String toHex() {
20 | return String.format("#%02x%02x%02x", this.red, this.green, this.blue);
21 | }
22 |
23 | /**
24 | * Convert the color to an int along with a alpha value of 255
25 | */
26 | public int toInt() {
27 | return (255 << 24) + (this.red << 16) + (this.green << 8) + this.blue;
28 | }
29 |
30 | public int toInt(int alpha) {
31 | return (alpha << 24) + (this.red << 16) + (this.green << 8) + this.blue;
32 | }
33 |
34 | public static int rgbaToInt(int red, int green, int blue, float alpha) {
35 | return ((int) (alpha * 255) << 24) + (red << 16) + (green << 8) + blue;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/records/BlockEntry.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.records;
2 |
3 | import com.google.gson.*;
4 | import net.minecraft.nbt.NbtUtils;
5 | import net.minecraft.world.item.ItemStack;
6 | import net.minecraft.world.level.block.state.BlockState;
7 | import pro.mikey.fabric.xray.cache.BlockSearchEntry;
8 |
9 | import java.lang.reflect.Type;
10 |
11 | public class BlockEntry {
12 | private BlockState state;
13 | private ItemStack stack;
14 | private String name;
15 | private BasicColor color;
16 | private int order;
17 | private boolean isDefault;
18 | private boolean active;
19 |
20 | public BlockEntry(BlockState state, String name, BasicColor color, int order, boolean isDefault, boolean active) {
21 | this.state = state;
22 | this.stack = new ItemStack(this.state.getBlock());
23 | this.name = name;
24 | this.color = color;
25 | this.order = order;
26 | this.isDefault = isDefault;
27 | this.active = active;
28 | }
29 |
30 | public BlockState getState() {
31 | return this.state;
32 | }
33 |
34 | public void setState(BlockState state) {
35 | this.state = state;
36 | }
37 |
38 | public String getName() {
39 | return this.name;
40 | }
41 |
42 | public void setName(String name) {
43 | this.name = name;
44 | }
45 |
46 | public BasicColor getHex() {
47 | return this.color;
48 | }
49 |
50 | public int getOrder() {
51 | return this.order;
52 | }
53 |
54 | public void setOrder(int order) {
55 | this.order = order;
56 | }
57 |
58 | public boolean isDefault() {
59 | return this.isDefault;
60 | }
61 |
62 | public void setDefault(boolean aDefault) {
63 | this.isDefault = aDefault;
64 | }
65 |
66 | public boolean isActive() {
67 | return this.active;
68 | }
69 |
70 | public void setActive(boolean active) {
71 | this.active = active;
72 | }
73 |
74 | public ItemStack getStack() {
75 | return this.stack;
76 | }
77 |
78 | public void setStack(ItemStack stack) {
79 | this.stack = stack;
80 | }
81 |
82 | public void setColor(BasicColor color) {
83 | this.color = color;
84 | }
85 |
86 | public static class Serializer implements JsonSerializer, JsonDeserializer {
87 | @Override
88 | public BlockEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
89 | JsonObject asJsonObject = json.getAsJsonObject();
90 | return new BlockEntry(
91 | BlockSearchEntry.blockStateFromStringNBT(asJsonObject.get("state").getAsString()),
92 | asJsonObject.get("name").getAsString(),
93 | BasicColor.of(asJsonObject.get("color").getAsString()),
94 | asJsonObject.get("order").getAsInt(),
95 | asJsonObject.get("isDefault").getAsBoolean(),
96 | asJsonObject.get("active").getAsBoolean());
97 | }
98 |
99 | @Override
100 | public JsonElement serialize(BlockEntry src, Type typeOfSrc, JsonSerializationContext context) {
101 | JsonObject object = new JsonObject();
102 | object.addProperty("state", NbtUtils.writeBlockState(src.getState()).toString());
103 | object.addProperty("name", src.name);
104 | object.addProperty("color", src.color.toHex());
105 | object.addProperty("order", src.order);
106 | object.addProperty("isDefault", src.isDefault);
107 | object.addProperty("active", src.active);
108 | return object;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/records/BlockGroup.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.records;
2 |
3 | import java.util.List;
4 | import java.util.Objects;
5 |
6 | public final class BlockGroup {
7 | private String name;
8 | private List entries;
9 | private int order;
10 | private boolean active;
11 |
12 | public BlockGroup(
13 | String name,
14 | List entries,
15 | int order,
16 | boolean active
17 | ) {
18 | this.name = name;
19 | this.entries = entries;
20 | this.order = order;
21 | this.active = active;
22 | }
23 |
24 | public String name() {
25 | return name;
26 | }
27 |
28 | public List entries() {
29 | return entries;
30 | }
31 |
32 | public int order() {
33 | return order;
34 | }
35 |
36 | public boolean active() {
37 | return active;
38 | }
39 |
40 | public String getName() {
41 | return name;
42 | }
43 |
44 | public void setName(String name) {
45 | this.name = name;
46 | }
47 |
48 | public List getEntries() {
49 | return entries;
50 | }
51 |
52 | public void setEntries(List entries) {
53 | this.entries = entries;
54 | }
55 |
56 | public int getOrder() {
57 | return order;
58 | }
59 |
60 | public void setOrder(int order) {
61 | this.order = order;
62 | }
63 |
64 | public boolean isActive() {
65 | return active;
66 | }
67 |
68 | public void setActive(boolean active) {
69 | this.active = active;
70 | }
71 |
72 | @Override
73 | public boolean equals(Object obj) {
74 | if (obj == this) return true;
75 | if (obj == null || obj.getClass() != this.getClass()) return false;
76 | var that = (BlockGroup) obj;
77 | return Objects.equals(this.name, that.name) &&
78 | Objects.equals(this.entries, that.entries) &&
79 | this.order == that.order &&
80 | this.active == that.active;
81 | }
82 |
83 | @Override
84 | public int hashCode() {
85 | return Objects.hash(name, entries, order, active);
86 | }
87 |
88 | @Override
89 | public String toString() {
90 | return "BlockGroup[" +
91 | "name=" + name + ", " +
92 | "entries=" + entries + ", " +
93 | "order=" + order + ", " +
94 | "active=" + active + ']';
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/records/BlockPosWithColor.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.records;
2 |
3 | import net.minecraft.core.BlockPos;
4 |
5 | public record BlockPosWithColor(
6 | BlockPos pos,
7 | BasicColor color
8 | ) {
9 | }
10 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/records/BlockWithStack.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.records;
2 |
3 | import net.minecraft.world.item.ItemStack;
4 | import net.minecraft.world.level.block.Block;
5 |
6 | public record BlockWithStack(
7 | Block block,
8 | ItemStack stack
9 | ) {
10 | }
11 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/render/RenderOutlines.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.render;
2 |
3 | import com.mojang.blaze3d.buffers.BufferType;
4 | import com.mojang.blaze3d.buffers.BufferUsage;
5 | import com.mojang.blaze3d.buffers.GpuBuffer;
6 | import com.mojang.blaze3d.pipeline.BlendFunction;
7 | import com.mojang.blaze3d.pipeline.RenderTarget;
8 | import com.mojang.blaze3d.platform.DepthTestFunction;
9 | import com.mojang.blaze3d.shaders.UniformType;
10 | import com.mojang.blaze3d.systems.RenderPass;
11 | import com.mojang.blaze3d.systems.RenderSystem;
12 | import com.mojang.blaze3d.pipeline.RenderPipeline;
13 | import com.mojang.blaze3d.vertex.*;
14 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
15 | import net.minecraft.client.Minecraft;
16 | import net.minecraft.client.renderer.RenderPipelines;
17 | import net.minecraft.client.renderer.ShapeRenderer;
18 | import net.minecraft.resources.ResourceLocation;
19 | import net.minecraft.world.phys.Vec3;
20 | import org.joml.Matrix4fStack;
21 | import pro.mikey.fabric.xray.ScanController;
22 | import pro.mikey.fabric.xray.XRay;
23 | import pro.mikey.fabric.xray.records.BlockPosWithColor;
24 | import pro.mikey.fabric.xray.storage.SettingsStore;
25 |
26 | import java.util.OptionalDouble;
27 | import java.util.OptionalInt;
28 | import java.util.concurrent.atomic.AtomicBoolean;
29 |
30 | public class RenderOutlines {
31 | private static GpuBuffer vertexBuffer;
32 | private static int indexCount = 0;
33 | private static final RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.LINES);
34 | public static AtomicBoolean requestedRefresh = new AtomicBoolean(false);
35 |
36 | public static RenderPipeline LINES_NO_DEPTH = RenderPipeline.builder(RenderPipelines.MATRICES_COLOR_SNIPPET)
37 | .withLocation("pipeline/xray_lines")
38 | .withVertexShader("core/rendertype_lines")
39 | .withFragmentShader(ResourceLocation.fromNamespaceAndPath(XRay.MOD_ID, "frag/rendertype_lines_unaffected"))
40 | .withUniform("LineWidth", UniformType.FLOAT)
41 | .withUniform("ScreenSize", UniformType.VEC2)
42 | .withBlend(BlendFunction.TRANSLUCENT)
43 | .withCull(false)
44 | .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL, VertexFormat.Mode.LINES)
45 | .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
46 | .build();
47 |
48 | public static synchronized void render(WorldRenderContext context) {
49 |
50 | if (ScanController.renderQueue.isEmpty() || !SettingsStore.getInstance().get().isActive()) {
51 | return;
52 | }
53 |
54 | RenderPipeline pipeline = LINES_NO_DEPTH;
55 | if (vertexBuffer == null || requestedRefresh.get()) {
56 | requestedRefresh.set(false);
57 |
58 | if (vertexBuffer != null) {
59 | vertexBuffer.close();
60 | }
61 |
62 | BufferBuilder bufferBuilder = Tesselator.getInstance().begin(
63 | pipeline.getVertexFormatMode(), pipeline.getVertexFormat()
64 | );
65 |
66 | for (BlockPosWithColor blockProps : ScanController.renderQueue) {
67 | PoseStack poseStack = context.matrixStack();
68 | if (blockProps == null || poseStack == null) {
69 | continue;
70 | }
71 |
72 | final float size = 1.0f;
73 | final int x = blockProps.pos().getX(), y = blockProps.pos().getY(), z = blockProps.pos().getZ();
74 |
75 | final float red = (blockProps.color().red()) / 255f;
76 | final float green = (blockProps.color().green()) / 255f;
77 | final float blue = (blockProps.color().blue()) / 255f;
78 |
79 | ShapeRenderer.renderLineBox(poseStack, bufferBuilder, x, y, z, x + size, y + size, z + size, red, green, blue, 1f);
80 | }
81 |
82 | try (MeshData meshData = bufferBuilder.buildOrThrow()) {
83 | vertexBuffer = RenderSystem.getDevice()
84 | .createBuffer(() -> "Outline vertex buffer", BufferType.VERTICES, BufferUsage.STATIC_WRITE, meshData.vertexBuffer());
85 | indexCount = meshData.drawState().indexCount();
86 | }
87 | }
88 |
89 | if (indexCount != 0) {
90 | Vec3 playerPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition().reverse();
91 | RenderTarget renderTarget = Minecraft.getInstance().getMainRenderTarget();
92 |
93 | if (renderTarget.getColorTexture() == null) {
94 | return;
95 | }
96 |
97 | GpuBuffer gpuBuffer = indices.getBuffer(indexCount);
98 |
99 | try (RenderPass renderPass = RenderSystem.getDevice()
100 | .createCommandEncoder()
101 | .createRenderPass(renderTarget.getColorTexture(), OptionalInt.empty(), renderTarget.getDepthTexture(), OptionalDouble.empty())) {
102 |
103 | Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack();
104 | matrix4fStack.pushMatrix();
105 | matrix4fStack.translate((float) playerPos.x(), (float) playerPos.y(), (float) playerPos.z());
106 | renderPass.setPipeline(pipeline);
107 | renderPass.setIndexBuffer(gpuBuffer, indices.type());
108 | renderPass.setVertexBuffer(0, vertexBuffer);
109 | renderPass.drawIndexed(0, indexCount);
110 |
111 | matrix4fStack.popMatrix();
112 | }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/AbstractScreen.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens;
2 |
3 | import com.mojang.blaze3d.systems.RenderSystem;
4 | import com.mojang.blaze3d.vertex.PoseStack;
5 | import net.minecraft.client.gui.GuiGraphics;
6 | import net.minecraft.client.gui.screens.Screen;
7 | import net.minecraft.client.renderer.RenderType;
8 | import net.minecraft.network.chat.Component;
9 | import net.minecraft.resources.ResourceLocation;
10 | import pro.mikey.fabric.xray.Utils;
11 |
12 | public abstract class AbstractScreen extends Screen {
13 | private static final ResourceLocation TEXTURE = Utils.rlFull("textures/gui/recipe_book.png");
14 |
15 | AbstractScreen(Component title) {
16 | super(title);
17 | }
18 |
19 | @Override
20 | public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
21 | super.render(guiGraphics, mouseX, mouseY, delta);
22 |
23 | RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
24 | int i = (this.width - 147) / 2;
25 | int j = (this.height - 166) / 2;
26 |
27 | guiGraphics.blit(RenderType::guiTextured, TEXTURE, i, j, 1, 1, 147, 166, 256, 256);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/MainScreen.java:
--------------------------------------------------------------------------------
1 | //package pro.mikey.fabric.xray.screens;
2 | //
3 | //import com.mojang.blaze3d.vertex.PoseStack;
4 | //import net.minecraft.client.gui.GuiGraphics;
5 | //import net.minecraft.network.chat.Component;
6 | //import net.minecraft.world.item.ItemStack;
7 | //import net.minecraft.world.item.Items;
8 | //import pro.mikey.fabric.xray.records.BlockEntry;
9 | //import pro.mikey.fabric.xray.records.BlockGroup;
10 | //import pro.mikey.fabric.xray.storage.BlockStore;
11 | //
12 | //import java.util.ArrayList;
13 | //import java.util.List;
14 | //
15 | //public class MainScreen extends AbstractScreen {
16 | // private final List blocks = new ArrayList<>();
17 | //
18 | // public MainScreen() {
19 | // super(Component.empty());
20 | //
21 | // List read = BlockStore.getInstance().read();
22 | // if (read != null) {
23 | // this.blocks.addAll(read);
24 | // }
25 | // }
26 | //
27 | //// @Override
28 | //// public void init(MinecraftClient client, int width, int height) {
29 | //// super.init(client, width, height);
30 | //// }
31 | //
32 | // @Override
33 | // public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
34 | // super.render(guiGraphics, mouseX, mouseY, delta);
35 | //
36 | // int y = 50;
37 | // for (BlockGroup group : this.blocks) {
38 | // guiGraphics.drawString(this.font, "Hello", this.width / 2 - 40, y, 0xFFFFFF);
39 | //
40 | // y += this.font.lineHeight + 10;
41 | // for (BlockEntry entry : group.entries()) {
42 | // drawString(matrices, this.font, entry.getName(), this.width / 2 - 40, y, 0xFFFFFF);
43 | //
44 | // matrices.pushPose();
45 | // matrices.translate(this.width / 2f - 60, y - 5, 0);
46 | // matrices.scale(.8f, .8f, .8f);
47 | // this.itemRenderer.renderAndDecorateFakeItem(matrices, new ItemStack(Items.GOLD_BLOCK), 0, 0);
48 | // matrices.popPose();
49 | //
50 | // y += this.font.lineHeight + 10;
51 | // }
52 | //
53 | // y += 10;
54 | // }
55 | // }
56 | //
57 | // @Override
58 | // public boolean isPauseScreen() {
59 | // return false;
60 | // }
61 | //
62 | // @Override
63 | // public void onClose() {
64 | // this.blocks.clear();
65 | // super.onClose();
66 | // }
67 | //}
68 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiAddBlock.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.platform.Lighting;
4 | import net.minecraft.client.gui.GuiGraphics;
5 | import net.minecraft.client.gui.components.Button;
6 | import net.minecraft.client.gui.components.EditBox;
7 | import net.minecraft.client.resources.language.I18n;
8 | import net.minecraft.network.chat.Component;
9 | import net.minecraft.world.item.ItemStack;
10 | import net.minecraft.world.level.block.state.BlockState;
11 | import pro.mikey.fabric.xray.records.BasicColor;
12 | import pro.mikey.fabric.xray.records.BlockEntry;
13 | import pro.mikey.fabric.xray.records.BlockGroup;
14 | import pro.mikey.fabric.xray.storage.BlockStore;
15 |
16 | import java.util.ArrayList;
17 | import java.util.Objects;
18 | import java.util.function.Supplier;
19 |
20 | public class GuiAddBlock extends GuiBase {
21 | private final ItemStack itemStack;
22 | private final Supplier previousScreenCallback;
23 | private BlockState selectBlock;
24 | private EditBox oreName;
25 | private Button addBtn;
26 | private RatioSliderWidget redSlider;
27 | private RatioSliderWidget greenSlider;
28 | private RatioSliderWidget blueSlider;
29 | private Button changeDefaultState;
30 | private BlockState lastState;
31 | private boolean oreNameCleared = false;
32 |
33 | GuiAddBlock(BlockState selectedBlock, Supplier previousScreenCallback) {
34 | super(false);
35 | this.selectBlock = selectedBlock;
36 | this.lastState = null;
37 | this.previousScreenCallback = previousScreenCallback;
38 | this.itemStack = new ItemStack(this.selectBlock.getBlock(), 1);
39 | }
40 |
41 | @Override
42 | public void init() {
43 | // Called when the gui should be (re)created
44 | boolean isDefaultState = this.selectBlock == this.selectBlock.getBlock().defaultBlockState();
45 | this.addRenderableWidget(this.changeDefaultState = new Button.Builder(Component.literal(isDefaultState ? "Already scanning for all states" : "Scan for all block states"), button -> {
46 | this.lastState = this.selectBlock;
47 | this.selectBlock = this.selectBlock.getBlock().defaultBlockState();
48 | button.active = false;
49 | }).pos(this.getWidth() / 2 - 100, this.getHeight() / 2 + 60).size(202,20).build());
50 |
51 | if (isDefaultState) {
52 | this.changeDefaultState.active = false;
53 | }
54 |
55 | this.addRenderableWidget(this.addBtn = new Button.Builder(Component.translatable("xray.single.add"), button -> {
56 | this.onClose();
57 |
58 | BlockGroup group = BlockStore.getInstance().get().size() >= 1 ? BlockStore.getInstance().get().get(0) : new BlockGroup("default", new ArrayList<>(), 1, true);
59 | group.entries().add(new BlockEntry(this.selectBlock, this.oreName.getValue(), new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255)), group.entries().size() + 1, this.selectBlock == this.selectBlock.getBlock().defaultBlockState(), true));
60 |
61 | if (BlockStore.getInstance().get().size() > 0) {
62 | BlockStore.getInstance().get().set(0, group);
63 | } else {
64 | BlockStore.getInstance().get().add(group);
65 | }
66 | BlockStore.getInstance().write();
67 | BlockStore.getInstance().updateCache();
68 |
69 | this.getMinecraft().setScreen(new GuiSelectionScreen());
70 | }).pos(this.getWidth() / 2 - 100, this.getHeight() / 2 + 85).size(128, 20).build());
71 | this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.cancel"), b -> {
72 | this.onClose();
73 | this.getMinecraft().setScreen(this.previousScreenCallback.get());
74 | }).pos(this.getWidth() / 2 + 30,this.getHeight() / 2 + 85).size(72, 20).build());
75 |
76 | this.addRenderableWidget(this.redSlider = new RatioSliderWidget(this.getWidth() / 2 - 100, this.getHeight() / 2 - 40, 100, 20, Component.translatable("xray.color.red"), 0));
77 | this.addRenderableWidget(this.greenSlider = new RatioSliderWidget(this.getWidth() / 2 - 100, this.getHeight() / 2 - 18, 100, 20, Component.translatable("xray.color.green"), 0));
78 |
79 | this.addRenderableWidget(this.blueSlider = new RatioSliderWidget(this.getWidth() / 2 - 100, this.getHeight() / 2 + 4, 100, 20, Component.translatable("xray.color.blue"), 0));
80 |
81 | this.oreName = new EditBox(this.getMinecraft().font, this.getWidth() / 2 - 100, this.getHeight() / 2 - 70, 202, 20, Component.empty());
82 |
83 | this.oreName.setValue(this.selectBlock.getBlock().getName().getString());
84 | this.addRenderableWidget(this.oreName);
85 | this.addRenderableWidget(this.redSlider);
86 | this.addRenderableWidget(this.greenSlider);
87 | this.addRenderableWidget(this.blueSlider);
88 | this.addRenderableWidget(this.changeDefaultState);
89 | }
90 |
91 | @Override
92 | public void tick() {
93 | super.tick();
94 | // this.oreName.tick();
95 | }
96 |
97 | @Override
98 | public void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
99 | int color = (255 << 24) | ((int) (this.redSlider.getValue() * 255) << 16) | ((int) (this.greenSlider.getValue() * 255) << 8) | (int) (this.blueSlider.getValue() * 255);
100 |
101 | guiGraphics.fill(this.getWidth() / 2 + 2, this.getHeight() / 2 - 40, (this.getWidth() / 2 + 2) + 100, (this.getHeight() / 2 - 40) + 64, color);
102 |
103 | guiGraphics.drawString(this.font, this.selectBlock.getBlock().getName().getString(), this.getWidth() / 2 - 100, this.getHeight() / 2 - 90, 0xffffff);
104 |
105 | this.oreName.render(guiGraphics, x, y, partialTicks);
106 |
107 | guiGraphics.drawString(this.font, "Color", this.getWidth() / 2 + 10, this.getHeight() / 2 - 35, 0xffffff);
108 |
109 | // Lighting.setupFor3DItems();
110 | guiGraphics.renderItem(this.itemStack, this.getWidth() / 2 + 85, this.getHeight() / 2 - 105);
111 | // Lighting.setupForFlatItems();
112 | }
113 |
114 | @Override
115 | public boolean mouseClicked(double x, double y, int mouse) {
116 | if (this.oreName.mouseClicked(x, y, mouse)) {
117 | this.setFocused(this.oreName);
118 | }
119 |
120 | if (this.oreName.isFocused() && !this.oreNameCleared) {
121 | this.oreName.setValue("");
122 | this.oreNameCleared = true;
123 | }
124 |
125 | if (!this.oreName.isFocused() && this.oreNameCleared && Objects.equals(this.oreName.getValue(), "")) {
126 | this.oreNameCleared = false;
127 | this.oreName.setValue(I18n.get("xray.input.gui"));
128 | }
129 |
130 | return super.mouseClicked(x, y, mouse);
131 | }
132 |
133 | @Override
134 | public boolean mouseReleased(double x, double y, int mouse) {
135 | return super.mouseReleased(x, y, mouse);
136 | }
137 |
138 | @Override
139 | public boolean hasTitle() {
140 | return true;
141 | }
142 |
143 | @Override
144 | public String title() {
145 | return I18n.get("xray.title.config");
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiBase.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.vertex.PoseStack;
4 | import net.minecraft.client.Minecraft;
5 | import net.minecraft.client.gui.Font;
6 | import net.minecraft.client.gui.GuiGraphics;
7 | import net.minecraft.client.gui.components.Renderable;
8 | import net.minecraft.client.gui.screens.Screen;
9 | import net.minecraft.client.renderer.RenderType;
10 | import net.minecraft.network.chat.Component;
11 | import net.minecraft.resources.ResourceLocation;
12 | import pro.mikey.fabric.xray.Utils;
13 | import pro.mikey.fabric.xray.XRay;
14 |
15 | public abstract class GuiBase extends Screen {
16 | static final ResourceLocation BG_LARGE = Utils.rlFull(XRay.PREFIX_GUI + "bg-help.png");
17 | private static final ResourceLocation BG_NORMAL = Utils.rlFull(XRay.PREFIX_GUI + "bg.png");
18 | private final boolean hasSide;
19 | private String sideTitle = "";
20 | private int backgroundWidth = 229;
21 | private int backgroundHeight = 235;
22 |
23 | GuiBase(boolean hasSide) {
24 | super(Component.empty());
25 | this.hasSide = hasSide;
26 | }
27 |
28 | abstract void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks);
29 |
30 | @Override
31 | public boolean charTyped(char keyTyped, int __unknown) {
32 | super.charTyped(keyTyped, __unknown);
33 |
34 | if (keyTyped == 1 && this.getMinecraft().player != null) {
35 | this.getMinecraft().player.clientSideCloseContainer();
36 | }
37 |
38 | return false;
39 | }
40 |
41 | @Override
42 | public void render(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
43 | super.render(guiGraphics, x, y, partialTicks);
44 | this.renderExtra(guiGraphics, x, y, partialTicks);
45 |
46 | this.renderBackground(guiGraphics, x, y, partialTicks);
47 | int width = this.width;
48 | int height = this.height;
49 | if (this.hasSide) {
50 | guiGraphics.blit(RenderType::guiTextured, this.getBackground(), width / 2 + 60, height / 2 - 180 / 2, 0, 0, 150, 180, 150, 180);
51 | guiGraphics.blit(
52 | RenderType::guiTextured,
53 | this.getBackground(),
54 | width / 2 - 150,
55 | height / 2 - 118,
56 | 0,
57 | 0,
58 | this.backgroundWidth,
59 | this.backgroundHeight,
60 | this.backgroundWidth,
61 | this.backgroundHeight
62 | );
63 | }
64 |
65 | if (!this.hasSide) {
66 | guiGraphics.blit(
67 | RenderType::guiTextured,
68 | this.getBackground(),
69 | width / 2 - this.backgroundWidth / 2 + 1,
70 | height / 2 - this.backgroundHeight / 2,
71 | 0,
72 | 0,
73 | this.backgroundWidth,
74 | this.backgroundHeight,
75 | this.backgroundWidth,
76 | this.backgroundHeight
77 | );
78 | }
79 |
80 | PoseStack pose = guiGraphics.pose();
81 | pose.pushPose();
82 | for (Renderable renderable : this.renderables) {
83 | renderable.render(guiGraphics, x, y, partialTicks);
84 | }
85 | pose.popPose();
86 |
87 | this.renderExtra(guiGraphics, x, y, partialTicks);
88 |
89 | if (this.hasTitle()) {
90 | if (this.hasSide) {
91 | guiGraphics.drawString(
92 | this.font, this.title(), width / 2 - 138, height / 2 - 105, 0xffff00);
93 | } else {
94 | guiGraphics.drawString(
95 | this.font,
96 | this.title(),
97 | width / 2 - ( this.backgroundWidth / 2) + 14,
98 | height / 2 - ( this.backgroundHeight / 2) + 13,
99 | 0xffff00
100 | );
101 | }
102 | }
103 |
104 | if (this.hasSide && this.hasSideTitle()) {
105 | guiGraphics.drawString(this.font, this.sideTitle, width / 2 + 80, height / 2 - 77, 0xffff00);
106 | }
107 | }
108 |
109 | public ResourceLocation getBackground() {
110 | return BG_NORMAL;
111 | }
112 |
113 | public boolean hasTitle() {
114 | return false;
115 | }
116 |
117 | public String title() {
118 | return "";
119 | }
120 |
121 | private boolean hasSideTitle() {
122 | return !this.sideTitle.isEmpty();
123 | }
124 |
125 | void setSideTitle(String title) {
126 | this.sideTitle = title;
127 | }
128 |
129 | void setSize(int width, int height) {
130 | this.backgroundWidth = width;
131 | this.backgroundHeight = height;
132 | }
133 |
134 | Font getFontRender() {
135 | return this.getMinecraft().font;
136 | }
137 |
138 | int getWidth() {
139 | return this.width;
140 | }
141 |
142 | int getHeight() {
143 | return this.height;
144 | }
145 |
146 | @Override
147 | public boolean isPauseScreen() {
148 | return false;
149 | }
150 |
151 | public Minecraft getMinecraft() {
152 | return this.minecraft;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiBlockList.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.vertex.PoseStack;
4 | import net.minecraft.client.gui.Font;
5 | import net.minecraft.client.gui.GuiGraphics;
6 | import net.minecraft.client.gui.components.AbstractSelectionList;
7 | import net.minecraft.client.gui.components.Button;
8 | import net.minecraft.client.gui.components.EditBox;
9 | import net.minecraft.core.registries.BuiltInRegistries;
10 | import net.minecraft.network.chat.Component;
11 | import net.minecraft.resources.ResourceLocation;
12 | import net.minecraft.world.item.BlockItem;
13 | import net.minecraft.world.item.ItemStack;
14 | import net.minecraft.world.item.Items;
15 | import net.minecraft.world.level.block.Block;
16 | import pro.mikey.fabric.xray.records.BasicColor;
17 | import pro.mikey.fabric.xray.records.BlockWithStack;
18 |
19 | import java.awt.*;
20 | import java.util.List;
21 | import java.util.stream.Collectors;
22 |
23 | public class GuiBlockList extends GuiBase {
24 | private final List blocks;
25 | private ScrollingBlockList blockList;
26 | private EditBox search;
27 | private String lastSearched = "";
28 |
29 | GuiBlockList() {
30 | super(false);
31 | this.blocks = BuiltInRegistries.ITEM.stream().filter(item -> item instanceof BlockItem && item != Items.AIR).map(item -> new BlockWithStack(Block.byItem(item), new ItemStack(item))).toList();
32 | }
33 |
34 | @Override
35 | public void init() {
36 | this.blockList = new ScrollingBlockList((this.getWidth() / 2) + 1, this.getHeight() / 2 - 12, 202, 185, this.blocks);
37 | this.addRenderableWidget(this.blockList);
38 |
39 | this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 100, this.getHeight() / 2 + 85, 140, 18, Component.empty());
40 | this.search.setFocused(true);
41 | this.setFocused(this.search);
42 |
43 | this.addRenderableWidget(this.search);
44 | this.addRenderableWidget(this.blockList);
45 |
46 | this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.cancel"), b -> {
47 | assert this.getMinecraft() != null;
48 | this.getMinecraft().setScreen(new GuiSelectionScreen());
49 | }).pos(this.getWidth() / 2 + 43, this.getHeight() / 2 + 84).size(60, 20).build());
50 | }
51 |
52 | @Override
53 | public void tick() {
54 | // this.search.tick
55 | if (!this.search.getValue().equals(this.lastSearched)) {
56 | this.reloadBlocks();
57 | }
58 |
59 | super.tick();
60 | }
61 |
62 | private void reloadBlocks() {
63 | if (this.lastSearched.equals(this.search.getValue())) {
64 | return;
65 | }
66 |
67 | this.blockList.updateEntries(this.search.getValue().isEmpty() ? this.blocks : this.blocks.stream().filter(e -> e.stack().getHoverName().getString().toLowerCase().contains(this.search.getValue().toLowerCase())).collect(Collectors.toList()));
68 |
69 | this.lastSearched = this.search.getValue();
70 | this.blockList.setScrollAmount(0);
71 | }
72 |
73 | @Override
74 | public void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
75 | // this.search.render(guiGraphics, x, y, partialTicks);
76 | // this.blockList.render(guiGraphics, x, y, partialTicks);
77 | }
78 |
79 | @Override
80 | public boolean mouseClicked(double x, double y, int button) {
81 | if (this.search.mouseClicked(x, y, button)) {
82 | this.setFocused(this.search);
83 | }
84 |
85 | return super.mouseClicked(x, y, button);
86 | }
87 |
88 | // @Override
89 | // public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
90 | // this.blockList.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_);
91 | // return super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_);
92 | // }
93 |
94 | static class ScrollingBlockList extends ScrollingList {
95 | static final int SLOT_HEIGHT = 35;
96 |
97 | ScrollingBlockList(int x, int y, int width, int height, List blocks) {
98 | super(x, y, width, height, SLOT_HEIGHT);
99 | this.updateEntries(blocks);
100 | }
101 |
102 | @Override
103 | public void setSelected(BlockSlot entry) {
104 | if (entry == null) {
105 | return;
106 | }
107 |
108 | assert this.minecraft.player != null;
109 | this.minecraft.setScreen(new GuiAddBlock(entry.getBlock().block().defaultBlockState(), GuiBlockList::new));
110 | }
111 |
112 | void updateEntries(List blocks) {
113 | this.clearEntries();
114 | blocks.forEach(block -> this.addEntry(new BlockSlot(block, this)));
115 | }
116 |
117 | public static class BlockSlot extends AbstractSelectionList.Entry {
118 | BlockWithStack block;
119 | ScrollingBlockList parent;
120 |
121 | BlockSlot(BlockWithStack block, ScrollingBlockList parent) {
122 | this.block = block;
123 | this.parent = parent;
124 | }
125 |
126 | BlockWithStack getBlock() {
127 | return this.block;
128 | }
129 |
130 | @Override
131 | public void render(GuiGraphics graphics, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) {
132 | Font font = this.parent.minecraft.font;
133 |
134 | ResourceLocation resource = BuiltInRegistries.BLOCK.getKey(this.block.block());
135 | graphics.drawString(font, this.block.stack().getItem().getName().getString(), left + 35, top + 7, Color.WHITE.getRGB());
136 | graphics.drawString(font, resource.getNamespace(), left + 35, top + 17, Color.WHITE.getRGB());
137 |
138 | graphics.renderItem(this.block.stack(), left + 10, top + 7);
139 | }
140 |
141 | @Override
142 | public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
143 | this.parent.setSelected(this);
144 | return false;
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiEdit.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.platform.Lighting;
4 | import net.minecraft.client.gui.Gui;
5 | import net.minecraft.client.gui.GuiGraphics;
6 | import net.minecraft.client.gui.components.Button;
7 | import net.minecraft.client.gui.components.EditBox;
8 | import net.minecraft.client.resources.language.I18n;
9 | import net.minecraft.network.chat.Component;
10 | import net.minecraft.world.level.block.state.BlockState;
11 | import pro.mikey.fabric.xray.records.BasicColor;
12 | import pro.mikey.fabric.xray.records.BlockEntry;
13 | import pro.mikey.fabric.xray.storage.BlockStore;
14 |
15 | public class GuiEdit extends GuiBase {
16 | private final BlockEntry block;
17 | private EditBox oreName;
18 | private RatioSliderWidget redSlider;
19 | private RatioSliderWidget greenSlider;
20 | private RatioSliderWidget blueSlider;
21 | private Button changeDefaultState;
22 | private BlockState lastState;
23 |
24 | GuiEdit(BlockEntry block) {
25 | super(true); // Has a sidebar
26 | this.setSideTitle(I18n.get("xray.single.tools"));
27 |
28 | this.block = block;
29 | }
30 |
31 | @Override
32 | public void init() {
33 | this.addRenderableWidget(this.changeDefaultState = new Button.Builder( Component.literal(this.block.isDefault() ? "Already scanning for all states" : "Scan for all block states"), button -> {
34 | this.lastState = this.block.getState();
35 | this.block.setState(this.block.getState().getBlock().defaultBlockState());
36 | button.active = false;
37 | }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 60).size(202, 20).build());
38 |
39 | if (this.block.isDefault()) {
40 | this.changeDefaultState.active = false;
41 | }
42 |
43 | this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.delete"), b -> {
44 | try {
45 | BlockStore.getInstance().get().get(0).entries().remove(this.block);
46 | BlockStore.getInstance().write();
47 | BlockStore.getInstance().updateCache();
48 | } catch (Exception e) {
49 | }
50 | this.getMinecraft().setScreen(new GuiSelectionScreen());
51 | }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 - 60).size(120, 20).build());
52 |
53 | this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.cancel"), b -> {
54 | this.getMinecraft().setScreen(new GuiSelectionScreen());
55 | }).pos((this.getWidth() / 2) + 78, this.getHeight() / 2 + 58).size(120, 20).build());
56 | this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.save"), b -> {
57 | try {
58 | int index = BlockStore.getInstance().get().get(0).entries().indexOf(this.block);
59 | BlockEntry entry = BlockStore.getInstance().get().get(0).entries().get(index);
60 | entry.setName(this.oreName.getValue());
61 | entry.setColor(new BasicColor((int) (this.redSlider.getValue() * 255), (int) (this.greenSlider.getValue() * 255), (int) (this.blueSlider.getValue() * 255)));
62 | entry.setState(this.block.getState());
63 | entry.setDefault(this.lastState != null);
64 | BlockStore.getInstance().get().get(0).entries().set(index, entry);
65 | BlockStore.getInstance().write();
66 | BlockStore.getInstance().updateCache();
67 | } catch (Exception ignored) {
68 | } // lazy catching for basic failures
69 |
70 | this.getMinecraft().setScreen(new GuiSelectionScreen());
71 | }).pos(this.getWidth() / 2 - 138, this.getHeight() / 2 + 83).size(202, 20).build());
72 |
73 | this.addRenderableWidget(this.redSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 - 40, 100, 20, Component.translatable("xray.color.red"), 0));
74 | this.addRenderableWidget(this.greenSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 - 18, 100, 20, Component.translatable("xray.color.green"), 0));
75 | this.addRenderableWidget(this.blueSlider = new RatioSliderWidget(this.getWidth() / 2 - 138, this.getHeight() / 2 + 4, 100, 20, Component.translatable("xray.color.blue"), 0));
76 |
77 | this.oreName = new EditBox(this.getMinecraft().font, this.getWidth() / 2 - 138, this.getHeight() / 2 - 63, 202, 20, Component.empty());
78 | this.oreName.setValue(this.block.getName());
79 | this.addRenderableWidget(this.oreName);
80 | this.addRenderableWidget(this.redSlider);
81 | this.addRenderableWidget(this.greenSlider);
82 | this.addRenderableWidget(this.blueSlider);
83 |
84 | this.redSlider.setValue(this.block.getHex().red() / 255f);
85 | this.greenSlider.setValue(this.block.getHex().green() / 255f);
86 | this.blueSlider.setValue(this.block.getHex().blue() / 255f);
87 | }
88 |
89 | @Override
90 | public void tick() {
91 | super.tick();
92 | // this.oreName.tick();
93 | }
94 |
95 | @Override
96 | public void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
97 | guiGraphics.drawString(this.font, this.block.getName(), this.getWidth() / 2 - 138, this.getHeight() / 2 - 90, 0xffffff);
98 |
99 | this.oreName.render(guiGraphics, x, y, partialTicks);
100 |
101 | int color = (255 << 24) | ((int) (this.redSlider.getValue() * 255) << 16) | ((int) (this.greenSlider.getValue() * 255) << 8) | (int) (this.blueSlider.getValue() * 255);
102 |
103 | guiGraphics.fill(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40, (this.getWidth() / 2 - 35) + 100, (this.getHeight() / 2 - 40) + 64, color);
104 |
105 | guiGraphics.drawString(this.font, "Color", this.getWidth() / 2 - 30, this.getHeight() / 2 - 35, 0xffffff);
106 | // Lighting.setupFor3DItems();
107 | // TODO: Check
108 | guiGraphics.renderItem(this.block.getStack(), this.getWidth() / 2 + 50, this.getHeight() / 2 - 105);
109 | // Lighting.setupForFlatItems();
110 | }
111 |
112 | @Override
113 | public boolean mouseClicked(double x, double y, int mouse) {
114 | if (this.oreName.mouseClicked(x, y, mouse)) {
115 | this.setFocused(this.oreName);
116 | }
117 |
118 | return super.mouseClicked(x, y, mouse);
119 | }
120 |
121 | @Override
122 | public boolean mouseReleased(double x, double y, int mouse) {
123 | return super.mouseReleased(x, y, mouse);
124 | }
125 |
126 | @Override
127 | public boolean hasTitle() {
128 | return true;
129 | }
130 |
131 | @Override
132 | public String title() {
133 | return I18n.get("xray.title.edit");
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiHelp.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import net.minecraft.client.gui.GuiGraphics;
4 | import net.minecraft.client.gui.components.Button;
5 | import net.minecraft.client.resources.language.I18n;
6 | import net.minecraft.network.chat.Component;
7 | import net.minecraft.resources.ResourceLocation;
8 |
9 | import java.awt.*;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class GuiHelp extends GuiBase {
14 | private final List areas = new ArrayList<>();
15 |
16 | public GuiHelp() {
17 | super(false);
18 | this.setSize(380, 210);
19 | }
20 |
21 | @Override
22 | public void init() {
23 | super.init();
24 |
25 | this.areas.clear();
26 | this.areas.add(new LinedText("xray.message.help.gui"));
27 | this.areas.add(new LinedText("xray.message.help.warning"));
28 |
29 | this.addRenderableWidget(
30 | new Button.Builder(
31 | Component.translatable("xray.single.close"),
32 | b -> {
33 | this.getMinecraft().setScreen(new GuiSelectionScreen());
34 | }).pos((this.getWidth() / 2) - 100,
35 | (this.getHeight() / 2) + 80).size(200,
36 | 20).build());
37 | }
38 |
39 | @Override
40 | public void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
41 | int lineY = (this.getHeight() / 2) - 85;
42 | for (LinedText linedText : this.areas) {
43 | for (String line : linedText.getLines()) {
44 | lineY += 12;
45 | guiGraphics.drawString(this.font, line, (this.getWidth() / 2) - 176, lineY, Color.WHITE.getRGB());
46 | }
47 | lineY += 10;
48 | }
49 | }
50 |
51 | @Override
52 | public boolean hasTitle() {
53 | return true;
54 | }
55 |
56 | @Override
57 | public ResourceLocation getBackground() {
58 | return BG_LARGE;
59 | }
60 |
61 | @Override
62 | public String title() {
63 | return I18n.get("xray.single.help");
64 | }
65 |
66 | private static class LinedText {
67 | private final String[] lines;
68 |
69 | LinedText(String key) {
70 | this.lines = I18n.get(key).split("\\R");
71 | }
72 |
73 | String[] getLines() {
74 | return this.lines;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiOverlay.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.systems.GpuDevice;
4 | import com.mojang.blaze3d.systems.RenderSystem;
5 | import net.minecraft.client.DeltaTracker;
6 | import net.minecraft.client.Minecraft;
7 | import net.minecraft.client.gui.GuiGraphics;
8 | import net.minecraft.client.renderer.RenderType;
9 | import net.minecraft.client.resources.language.I18n;
10 | import net.minecraft.resources.ResourceLocation;
11 | import pro.mikey.fabric.xray.Utils;
12 | import pro.mikey.fabric.xray.XRay;
13 | import pro.mikey.fabric.xray.storage.SettingsStore;
14 |
15 | public class GuiOverlay {
16 | private static final ResourceLocation circle = Utils.rlFull(XRay.PREFIX_GUI + "circle.png");
17 |
18 | public static void RenderGameOverlayEvent(GuiGraphics guiGraphics, DeltaTracker counter) {
19 | // Draw Indicator
20 | if (!SettingsStore.getInstance().get().isActive() || !SettingsStore.getInstance().get().showOverlay()) {
21 | return;
22 | }
23 |
24 | GpuDevice gpuDevice = RenderSystem.tryGetDevice();
25 | boolean renderDebug = gpuDevice != null && gpuDevice.isDebuggingEnabled();
26 |
27 | int x = 5, y = 5;
28 | if (renderDebug) {
29 | x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - 10;
30 | y = Minecraft.getInstance().getWindow().getGuiScaledHeight() - 10;
31 | }
32 |
33 | guiGraphics.blit(RenderType::guiTextured, circle, x, y, 0f, 0f, 5, 5, 5, 5, 0xFF00FF00);
34 |
35 | int width = Minecraft.getInstance().font.width(I18n.get("xray.overlay"));
36 | guiGraphics.drawString(Minecraft.getInstance().font, I18n.get("xray.overlay"), x + (!renderDebug ? 10 : -width - 5), y - (!renderDebug ? 1 : 2), 0xff00ff00);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/GuiSelectionScreen.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import com.mojang.blaze3d.platform.Lighting;
4 | import com.mojang.blaze3d.vertex.PoseStack;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.client.gui.Font;
7 | import net.minecraft.client.gui.GuiGraphics;
8 | import net.minecraft.client.gui.components.AbstractSelectionList;
9 | import net.minecraft.client.gui.components.Button;
10 | import net.minecraft.client.gui.components.EditBox;
11 | import net.minecraft.client.gui.components.Tooltip;
12 | import net.minecraft.client.gui.components.events.GuiEventListener;
13 | import net.minecraft.client.player.LocalPlayer;
14 | import net.minecraft.client.renderer.RenderType;
15 | import net.minecraft.client.renderer.entity.ItemRenderer;
16 | import net.minecraft.client.resources.language.I18n;
17 | import net.minecraft.network.chat.Component;
18 | import net.minecraft.resources.ResourceLocation;
19 | import net.minecraft.world.InteractionHand;
20 | import net.minecraft.world.item.BlockItem;
21 | import net.minecraft.world.item.ItemStack;
22 | import net.minecraft.world.level.block.Block;
23 | import net.minecraft.world.level.block.Blocks;
24 | import net.minecraft.world.level.block.state.BlockState;
25 | import net.minecraft.world.phys.BlockHitResult;
26 | import net.minecraft.world.phys.HitResult;
27 | import pro.mikey.fabric.xray.ScanController;
28 | import pro.mikey.fabric.xray.StateSettings;
29 | import pro.mikey.fabric.xray.Utils;
30 | import pro.mikey.fabric.xray.XRay;
31 | import pro.mikey.fabric.xray.records.BasicColor;
32 | import pro.mikey.fabric.xray.records.BlockEntry;
33 | import pro.mikey.fabric.xray.records.BlockGroup;
34 | import pro.mikey.fabric.xray.storage.BlockStore;
35 | import pro.mikey.fabric.xray.storage.SettingsStore;
36 |
37 | import java.awt.*;
38 | import java.util.List;
39 | import java.util.*;
40 | import java.util.concurrent.atomic.AtomicInteger;
41 | import java.util.stream.Collectors;
42 |
43 | public class GuiSelectionScreen extends GuiBase {
44 | private static final List ORE_TAGS = List.of(Blocks.GOLD_ORE, Blocks.IRON_ORE, Blocks.DIAMOND_ORE, Blocks.REDSTONE_ORE, Blocks.LAPIS_ORE, Blocks.COAL_ORE, Blocks.EMERALD_ORE, Blocks.COPPER_ORE, Blocks.DEEPSLATE_GOLD_ORE, Blocks.DEEPSLATE_IRON_ORE, Blocks.DEEPSLATE_DIAMOND_ORE, Blocks.DEEPSLATE_REDSTONE_ORE, Blocks.DEEPSLATE_LAPIS_ORE, Blocks.DEEPSLATE_COAL_ORE, Blocks.DEEPSLATE_EMERALD_ORE, Blocks.DEEPSLATE_COPPER_ORE, Blocks.NETHER_GOLD_ORE, Blocks.ANCIENT_DEBRIS);
45 |
46 | private static final ResourceLocation CIRCLE = Utils.rlFull(XRay.PREFIX_GUI + "circle.png");
47 | private final List originalList;
48 | public ItemRenderer render;
49 | private Button distButtons;
50 | private EditBox search;
51 | private String lastSearch = "";
52 | private List itemList;
53 | private ScrollingBlockList scrollList;
54 |
55 | public GuiSelectionScreen() {
56 | super(true);
57 | this.setSideTitle(I18n.get("xray.single.tools"));
58 |
59 | populateDefault();
60 |
61 | this.itemList = BlockStore.getInstance().get().size() >= 1 ? BlockStore.getInstance().get().get(0).entries() : new ArrayList<>();
62 | this.itemList.sort(Comparator.comparingInt(BlockEntry::getOrder));
63 |
64 | this.originalList = this.itemList;
65 | }
66 |
67 | private void populateDefault() {
68 | if (BlockStore.getInstance().justCreated && BlockStore.getInstance().get().size() == 0) {
69 | AtomicInteger order = new AtomicInteger();
70 | Random random = new Random();
71 |
72 | BlockStore.getInstance().get().add(new BlockGroup("default", ORE_TAGS.stream().map(e ->
73 | new BlockEntry(e.defaultBlockState(), e.asItem().getName().getString(), new BasicColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)), order.getAndIncrement(), true, true)).collect(Collectors.toList()), 0, true)
74 | );
75 |
76 | BlockStore.getInstance().updateCache();
77 | }
78 | }
79 |
80 | @Override
81 | public void init() {
82 | if (this.minecraft.player == null) {
83 | return;
84 | }
85 |
86 | this.render = Minecraft.getInstance().getItemRenderer();
87 | // this.buttons.clear();
88 |
89 | this.search = new EditBox(this.getFontRender(), this.getWidth() / 2 - 137, this.getHeight() / 2 - 105, 202, 18, Component.empty());
90 | this.search.setCanLoseFocus(true);
91 |
92 | this.addRenderableWidget(this.search);
93 |
94 | // sidebar buttons
95 | this.addRenderableWidget(Button.builder( Component.translatable("xray.input.add"), button -> {
96 | this.minecraft.setScreen(new GuiBlockList());
97 | })
98 | .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 - 60)
99 | .size( 120, 20)
100 | .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block")))
101 | .build());
102 |
103 | this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_hand"), button -> {
104 | ItemStack handItem = this.minecraft.player.getItemInHand(InteractionHand.MAIN_HAND);
105 |
106 | // Check if the hand item is a block or not
107 | if (!(handItem.getItem() instanceof BlockItem)) {
108 | this.minecraft.player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.invalid_hand", handItem.getHoverName().getString())), false);
109 | return;
110 | }
111 |
112 | this.minecraft.setScreen(new GuiAddBlock(((BlockItem) handItem.getItem()).getBlock().defaultBlockState(), GuiSelectionScreen::new));
113 | })
114 | .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 38)
115 | .size( 120, 20)
116 | .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_in_hand")))
117 | .build());
118 |
119 | this.addRenderableWidget(Button.builder(Component.translatable("xray.input.add_look"), button -> {
120 | LocalPlayer player = this.minecraft.player;
121 | if (this.minecraft.level == null || player == null) {
122 | return;
123 | }
124 |
125 | this.onClose();
126 | try {
127 | HitResult look = player.pick(100, 1f, false);
128 |
129 | if (look.getType() == BlockHitResult.Type.BLOCK) {
130 | BlockState state = this.minecraft.level.getBlockState(((BlockHitResult) look).getBlockPos());
131 |
132 | this.minecraft.setScreen(new GuiAddBlock(state, GuiSelectionScreen::new));
133 | } else {
134 | player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.nothing_infront")), false);
135 | }
136 | } catch (NullPointerException ex) {
137 | player.displayClientMessage(Component.literal("[XRay] " + I18n.get("xray.message.thats_odd")), false);
138 | }
139 | })
140 | .pos(this.getWidth() / 2 + 79, this.getHeight() / 2 - 16)
141 | .size(120, 20)
142 | .tooltip(Tooltip.create(Component.translatable("xray.tooltips.add_block_looking_at")))
143 | .build());
144 |
145 | this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava()), button -> {
146 | SettingsStore.getInstance().get().setShowLava(!SettingsStore.getInstance().get().isShowLava());
147 | ScanController.runTask(true);
148 | button.setMessage(Component.translatable("xray.input.show-lava", SettingsStore.getInstance().get().isShowLava()));
149 | })
150 | .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 + 6)
151 | .size(120, 20)
152 | .tooltip(Tooltip.create(Component.translatable("xray.tooltips.show_lava")))
153 | .build());
154 |
155 | this.addRenderableWidget(this.distButtons = Button.builder(Component.translatable("xray.input.distance", StateSettings.getVisualRadius()), button -> {
156 | SettingsStore.getInstance().get().increaseRange();
157 | button.setMessage(Component.translatable("xray.input.distance", StateSettings.getVisualRadius()));
158 | })
159 | .pos((this.getWidth() / 2) + 79, this.getHeight() / 2 + 36)
160 | .size(120, 20)
161 | .tooltip(Tooltip.create(Component.translatable("xray.tooltips.distance")))
162 | .build());
163 |
164 | this.addRenderableWidget(new Button.Builder( Component.translatable("xray.single.help"), button -> {
165 | this.minecraft.setScreen(new GuiHelp());
166 | }).pos(this.getWidth() / 2 + 79, this.getHeight() / 2 + 58).size(60,20).build());
167 | this.addRenderableWidget(new Button.Builder(Component.translatable("xray.single.close"), button -> this.onClose()).pos((this.getWidth() / 2 + 79) + 62, this.getHeight() / 2 + 58).size(59,20).build());
168 |
169 | this.scrollList = new ScrollingBlockList((this.getWidth() / 2) - 37, this.getHeight() / 2 + 10, 203, 185, this.itemList, this);
170 | this.addRenderableWidget(this.scrollList);
171 | }
172 |
173 | private void updateSearch() {
174 | if (this.lastSearch.equals(this.search.getValue())) {
175 | return;
176 | }
177 |
178 | if (this.search.getValue().equals("")) {
179 | this.itemList = this.originalList;
180 | this.scrollList.updateEntries(this.itemList);
181 | this.lastSearch = "";
182 | return;
183 | }
184 |
185 | this.itemList = this.originalList.stream().filter(b -> b.getName().toLowerCase().contains(this.search.getValue().toLowerCase())).collect(Collectors.toCollection(ArrayList::new));
186 |
187 | this.itemList.sort(Comparator.comparingInt(BlockEntry::getOrder));
188 |
189 | this.scrollList.updateEntries(this.itemList);
190 | this.lastSearch = this.search.getValue();
191 | }
192 |
193 | @Override
194 | public void tick() {
195 | super.tick();
196 | this.updateSearch();
197 | }
198 |
199 | @Override
200 | public boolean mouseClicked(double x, double y, int mouse) {
201 | if (this.search.mouseClicked(x, y, mouse)) {
202 | this.setFocused(this.search);
203 | }
204 |
205 | if (mouse == 1 && this.distButtons.isMouseOver(x, y)) {
206 | SettingsStore.getInstance().get().decreaseRange();
207 |
208 | this.distButtons.setMessage(Component.translatable("xray.input.distance", StateSettings.getVisualRadius()));
209 | this.distButtons.playDownSound(this.minecraft.getSoundManager());
210 | }
211 |
212 | return super.mouseClicked(x, y, mouse);
213 | }
214 |
215 | @Override
216 | public void renderExtra(GuiGraphics guiGraphics, int x, int y, float partialTicks) {
217 | if (!this.search.isFocused() && this.search.getValue().equals("")) {
218 | guiGraphics.drawString(this.font, I18n.get("xray.single.search"), this.getWidth() / 2 - 130, this.getHeight() / 2 - 101, Color.GRAY.getRGB());
219 | }
220 |
221 | PoseStack pose = guiGraphics.pose();
222 | pose.pushPose();
223 | pose.translate(this.getWidth() / 2f - 140, ((this.getHeight() / 2f) - 3) + 120, 0);
224 | pose.scale(0.75f, 0.75f, 0.75f);
225 | guiGraphics.drawString(this.font, Component.translatable("xray.tooltips.edit1"), 0, 0, Color.GRAY.getRGB());
226 | pose.translate(0, 12, 0);
227 | guiGraphics.drawString(this.font, Component.translatable("xray.tooltips.edit2"), 0, 0, Color.GRAY.getRGB());
228 | pose.popPose();
229 | }
230 |
231 | @Override
232 | public void onClose() {
233 | SettingsStore.getInstance().write();
234 | BlockStore.getInstance().write();
235 | BlockStore.getInstance().updateCache();
236 |
237 | ScanController.runTask(true);
238 |
239 | super.onClose();
240 | }
241 |
242 | public static class ScrollingBlockList extends ScrollingList {
243 | static final int SLOT_HEIGHT = 35;
244 | GuiSelectionScreen parent;
245 |
246 | ScrollingBlockList(int x, int y, int width, int height, List blocks, GuiSelectionScreen parent) {
247 | super(x, y, width, height, SLOT_HEIGHT);
248 | this.updateEntries(blocks);
249 | this.parent = parent;
250 | }
251 |
252 | void setSelected(BlockSlot entry, int mouse) {
253 | if (entry == null) {
254 | return;
255 | }
256 |
257 | if (GuiSelectionScreen.hasShiftDown()) {
258 | this.minecraft.setScreen(new GuiEdit(entry.block));
259 | return;
260 | }
261 |
262 | try {
263 | int index = BlockStore.getInstance().get().get(0).entries().indexOf(entry.getBlock());
264 | BlockEntry blockEntry = BlockStore.getInstance().get().get(0).entries().get(index);
265 | blockEntry.setActive(!blockEntry.isActive());
266 | BlockStore.getInstance().get().get(0).entries().set(index, blockEntry);
267 | BlockStore.getInstance().write();
268 | BlockStore.getInstance().updateCache();
269 | } catch (Exception ignored) {
270 | }
271 | }
272 |
273 | void updateEntries(List blocks) {
274 | this.clearEntries();
275 | blocks.forEach(block -> this.addEntry(new BlockSlot(block, this))); // @mcp: func_230513_b_ = addEntry
276 | }
277 |
278 |
279 | public class BlockSlot extends AbstractSelectionList.Entry {
280 | BlockEntry block;
281 | ScrollingBlockList parent;
282 |
283 | BlockSlot(BlockEntry block, ScrollingBlockList parent) {
284 | this.block = block;
285 | this.parent = parent;
286 | }
287 |
288 | public BlockEntry getBlock() {
289 | return this.block;
290 | }
291 |
292 | @Override
293 | public void render(GuiGraphics guiGraphics, int entryIdx, int top, int left, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean p_194999_5_, float partialTicks) {
294 | BlockEntry blockData = this.block;
295 |
296 | Font font = this.parent.minecraft.font;
297 |
298 | guiGraphics.drawString(font, blockData.getName(), left + 35, top + 7, 0xFFFFFF);
299 | guiGraphics.drawString(font, blockData.isActive() ? "Enabled" : "Disabled", left + 35, top + 17, blockData.isActive() ? Color.GREEN.getRGB() : Color.RED.getRGB());
300 |
301 | guiGraphics.renderItem(blockData.getStack(), left + 10, top + 7);
302 |
303 | guiGraphics.blit(RenderType::guiTextured, GuiSelectionScreen.CIRCLE, (left + entryWidth) - 17, (int) (top + (entryHeight / 2f) - 9), 0, 0, 14, 14, 14, 14, BasicColor.rgbaToInt(0, 0, 0, .5f));
304 | guiGraphics.blit(RenderType::guiTextured, GuiSelectionScreen.CIRCLE, (left + entryWidth) - 15, (int) (top + (entryHeight / 2f) - 7), 0, 0, 10, 10, 10, 10, blockData.getHex().toInt());
305 | }
306 |
307 | @Override
308 | public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int mouse) {
309 | this.parent.setSelected(this, mouse);
310 | return false;
311 | }
312 | }
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/RatioSliderWidget.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import net.minecraft.client.gui.components.AbstractSliderButton;
4 | import net.minecraft.network.chat.Component;
5 |
6 | public class RatioSliderWidget extends AbstractSliderButton {
7 | private final Component message;
8 |
9 | RatioSliderWidget(int x, int y, int width, int height, Component text, double value) {
10 | super(x, y, width, height, text, value);
11 | this.message = text;
12 | this.updateMessage();
13 | }
14 |
15 | @Override
16 | protected void applyValue() {}
17 |
18 | @Override
19 | protected void updateMessage() {
20 | this.setMessage(Component.literal(this.message.getString() + ((int) (this.value * 255))));
21 | }
22 |
23 | double getValue() {
24 | return this.value;
25 | }
26 |
27 | void setValue(double value) {
28 | this.value = Math.max(0, Math.min(1, value));
29 | this.updateMessage();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/screens/forge/ScrollingList.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.screens.forge;
2 |
3 | import net.minecraft.client.Minecraft;
4 | import net.minecraft.client.gui.GuiGraphics;
5 | import net.minecraft.client.gui.components.AbstractSelectionList;
6 | import net.minecraft.client.gui.narration.NarrationElementOutput;
7 |
8 | public class ScrollingList> extends AbstractSelectionList {
9 | ScrollingList(int x, int y, int width, int height, int slotHeightIn) {
10 | super(
11 | Minecraft.getInstance(),
12 | width,
13 | height,
14 | y - (height / 2),
15 | slotHeightIn);
16 | this.setX(x - (width / 2));
17 | }
18 |
19 | @Override
20 | public void renderWidget(GuiGraphics stack, int mouseX, int mouseY, float partialTicks) {
21 | super.renderWidget(stack, mouseX, mouseY, partialTicks);
22 | }
23 |
24 | @Override
25 | protected int scrollBarX() {
26 | return (this.getX() + this.width) - 6;
27 | }
28 |
29 | @Override
30 | protected void updateWidgetNarration(NarrationElementOutput narrationElementOutput) {
31 |
32 | }
33 |
34 | @Override
35 | public int getRowWidth() {
36 | return this.width - 10;
37 | }
38 |
39 | @Override
40 | public int getRowLeft() {
41 | return this.getX();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/storage/BlockStore.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.storage;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import com.google.gson.reflect.TypeToken;
6 | import pro.mikey.fabric.xray.cache.BlockSearchCache;
7 | import pro.mikey.fabric.xray.records.BlockEntry;
8 | import pro.mikey.fabric.xray.records.BlockGroup;
9 |
10 | import java.lang.reflect.Type;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class BlockStore extends Store> {
15 | private static BlockStore instance;
16 | private final BlockSearchCache cache = new BlockSearchCache();
17 | private final List blockEntries;
18 |
19 | private BlockStore() {
20 | super("blocks");
21 |
22 | this.blockEntries = this.read();
23 | this.updateCache(this.blockEntries); // ensure the cache is up to date
24 | }
25 |
26 | public static BlockStore getInstance() {
27 | if (instance == null) {
28 | instance = new BlockStore();
29 | }
30 |
31 | return instance;
32 | }
33 |
34 | public void updateCache() {
35 | this.updateCache(this.get());
36 | }
37 |
38 | private void updateCache(List data) {
39 | this.cache.processGroupedList(data);
40 | }
41 |
42 | public BlockSearchCache getCache() {
43 | return this.cache;
44 | }
45 |
46 | @Override
47 | public List get() {
48 | return this.blockEntries;
49 | }
50 |
51 | @Override
52 | public Gson getGson() {
53 | return new GsonBuilder()
54 | .registerTypeAdapter(BlockEntry.class, new BlockEntry.Serializer())
55 | .setPrettyPrinting()
56 | .create();
57 | }
58 |
59 | @Override
60 | public List providedDefault() {
61 | return new ArrayList<>();
62 | }
63 |
64 | @Override
65 | Type getType() {
66 | return new TypeToken>() {
67 | }.getType();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/storage/SettingsStore.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.storage;
2 |
3 | import pro.mikey.fabric.xray.StateSettings;
4 |
5 | import java.lang.reflect.Type;
6 |
7 | public class SettingsStore extends Store {
8 | private static SettingsStore instance;
9 | private final StateSettings settings;
10 |
11 | private SettingsStore() {
12 | super("settings");
13 | this.settings = this.read();
14 | }
15 |
16 | public static SettingsStore getInstance() {
17 | if (instance == null) {
18 | instance = new SettingsStore();
19 | }
20 |
21 | return instance;
22 | }
23 |
24 | @Override
25 | public StateSettings providedDefault() {
26 | return new StateSettings();
27 | }
28 |
29 | @Override
30 | public StateSettings get() {
31 | return this.settings;
32 | }
33 |
34 | @Override
35 | Type getType() {
36 | return StateSettings.class;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/client/java/pro/mikey/fabric/xray/storage/Store.java:
--------------------------------------------------------------------------------
1 | package pro.mikey.fabric.xray.storage;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import com.google.gson.JsonIOException;
6 | import com.google.gson.JsonSyntaxException;
7 | import net.minecraft.client.Minecraft;
8 | import pro.mikey.fabric.xray.XRay;
9 |
10 | import java.io.*;
11 | import java.lang.reflect.Type;
12 |
13 | public abstract class Store {
14 | private static final String CONFIG_PATH = String.format("%s/config/%s", Minecraft.getInstance().gameDirectory, XRay.MOD_ID);
15 |
16 | private final String name;
17 | private final String file;
18 |
19 | public boolean justCreated = false;
20 |
21 | Store(String name) {
22 | this.name = name;
23 | this.file = String.format("%s/%s.json", CONFIG_PATH, this.name);
24 |
25 | this.read();
26 | }
27 |
28 | public Gson getGson() {
29 | return new GsonBuilder().setPrettyPrinting().create();
30 | }
31 |
32 | public T read() {
33 | Gson gson = this.getGson();
34 |
35 | try {
36 | try {
37 | return gson.fromJson(new FileReader(this.file), this.getType());
38 | } catch (JsonIOException | JsonSyntaxException e) {
39 | XRay.LOGGER.fatal("Fatal error with json loading on {}.json", this.name, e);
40 | }
41 | } catch (FileNotFoundException ignored) {
42 | this.justCreated = true;
43 |
44 | // Write a blank version of the file
45 | if (new File(CONFIG_PATH).mkdirs()) {
46 | this.write(true);
47 | }
48 | }
49 |
50 | return this.providedDefault();
51 | }
52 |
53 | public void write() {
54 | this.write(false);
55 | }
56 |
57 | private void write(Boolean firstWrite) {
58 | Gson gson = this.getGson();
59 |
60 | try {
61 | try (FileWriter writer = new FileWriter(this.file)) {
62 | gson.toJson(firstWrite ? this.providedDefault() : this.get(), writer);
63 | writer.flush();
64 | }
65 | } catch (IOException | JsonIOException e) {
66 | XRay.LOGGER.catching(e);
67 | }
68 | }
69 |
70 | public abstract T providedDefault();
71 |
72 | public abstract T get();
73 |
74 | abstract Type getType();
75 | }
76 |
--------------------------------------------------------------------------------
/src/client/resources/advanced-xray-fabric.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "pro.mikey.fabric.xray.mixins",
5 | "compatibilityLevel": "JAVA_17",
6 | "mixins": [
7 | ],
8 | "client": [
9 | "MixinBlockItem"
10 | ],
11 | "injectors": {
12 | "defaultRequire": 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/resources/advanced-xray-fabric.accesswidener:
--------------------------------------------------------------------------------
1 | accessWidener v1 named
2 | accessible class net/minecraft/client/gui/components/AbstractSelectionList$Entry
3 | accessible field net/minecraft/client/gui/screens/Screen renderables Ljava/util/List;
4 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AdvancedXRay/XRay-Fabric/e2a29ae4caf36df9e9d32ed51340050fbd360ff3/src/main/resources/assets/advanced-xray-fabric/icon.png
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/lang/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "category.xray": "Advanced XRay",
3 | "keybinding.enable_xray": "Enable XRay",
4 | "keybinding.open_gui": "Open Gui",
5 | "message.xray_active": "XRay activated",
6 | "message.xray_deactivate": "XRay deactivated",
7 | "spacer": "-------------------------------------------------------",
8 | "comment_forge": "Forge mod old lang stuff, please never translate",
9 | "xray.single.cancel": "Cancel",
10 | "xray.single.add": "Add",
11 | "xray.single.delete": "Delete",
12 | "xray.single.save": "Save",
13 | "xray.single.tools": "Tools",
14 | "xray.single.close": "Close",
15 | "xray.single.search": "Search",
16 | "xray.single.help": "Help",
17 | "xray.overlay": "XRay Active",
18 | "xray.color.red": "Red: ",
19 | "xray.color.green": "Green: ",
20 | "xray.color.blue": "Blue: ",
21 | "xray.input.gui": "GUI Name",
22 | "xray.input.add": "Add Block",
23 | "xray.input.add_hand": "Add Block in hand",
24 | "xray.input.add_look": "Add Looking at",
25 | "xray.input.distance": "Distance: %s",
26 | "xray.input.show-lava": "Show Lava: %s",
27 | "xray.input.toggle_oredict": "Use Dictionary",
28 | "xray.title.config": "Configure Block",
29 | "xray.title.edit": "Edit Block",
30 | "xray.title.edit_meta": "Edit Meta",
31 | "xray.message.missing_input": "You need to have all the inputs filled in",
32 | "xray.message.already_exists": "This block has already been added to the block list",
33 | "xray.message.added_block": "Successfully added %s.",
34 | "xray.message.updated_block": "Entry Updated",
35 | "xray.message.remove_block": "%s has been removed",
36 | "xray.message.block_exists": "%s already exists. Please enter a different name.",
37 | "xray.message.unknown": "Looks like the block you've tried to edit doesn't exist.",
38 | "xray.message.removed": "Successfully removed %s.",
39 | "xray.message.config_missing": "Config file not found. Creating now.",
40 | "xray.message.invalid_hand": "%s needs to be a block",
41 | "xray.message.thats_odd": "Something went wrong? Sorry about that. Make an issue if this continues to happen",
42 | "xray.message.nothing_infront": "You're not looking at anything are you?",
43 | "xray.message.not_a_number": "{%s} is not a number. Please use a number for your meta",
44 | "xray.message.meta_not_supported": "{%s} isn't a valid meta data for {%s}",
45 | "xray.message.state_warning": "Warning, this will limit you to default\nblocks. Use looking at or in hand to get\nthe absolute block you require.\nIn some cases (chests) this may be what you need to do\nif that's the case then this is the right option.",
46 | "xray.tooltips.add_block": "Select a block to add to the XRay'd blocks\nThis uses block defaults, if you require a specific block\nthen use 'Add Looking At'.",
47 | "xray.tooltips.add_block_in_hand": "Automatically selects the block you've\ngot in your hand to add to the list.",
48 | "xray.tooltips.add_block_looking_at": "Automatically selects the block you're\nlooking at to add to the list.",
49 | "xray.tooltips.show_lava": "Displays lava in RED like a normal block.\nWatch out! It's hot.",
50 | "xray.tooltips.distance": "This is the amount of chunks around the player.",
51 | "xray.tooltips.edit1": "Click to enable / disable",
52 | "xray.tooltips.edit2": "Hold shift and click to edit.",
53 | "xray.message.help.gui": "To edit a block simply shift click on the block you wish to edit.\nIf you want to enable / disable a block then click on a block\n and it'll toggle on and off.",
54 | "xray.message.help.warning": "As a warning, using any distance over 64 will cause FPS drops due\nto the vast amount of blocks that we have to scan. (It's like 256^3)"
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/lang/fr_fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "category.xray": "Advanced XRay",
3 | "keybinding.enable_xray": "Activer XRay",
4 | "keybinding.open_gui": "Ouvrir le menu",
5 |
6 | "message.xray_active": "XRay activé",
7 | "message.xray_deactivate": "XRay désactivé"
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/lang/ja_jp.json:
--------------------------------------------------------------------------------
1 | {
2 | "category.xray": "Advanced XRay",
3 | "keybinding.enable_xray": "XRayを有効化",
4 | "keybinding.open_gui": "GUIを開く",
5 |
6 | "message.xray_active": "XRayを有効化しました",
7 | "message.xray_deactivate": "XRayを無効化しました"
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/lang/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "category.xray": "高级 X 射线",
3 | "keybinding.enable_xray": "启用 X 射线",
4 | "keybinding.open_gui": "打开图像界面",
5 | "message.xray_active": "启动 X 射线",
6 | "message.xray_deactivate": "停用 X 射线",
7 | "spacer": "-------------------------------------------------------",
8 | "comment_forge": "Forge mod old lang stuff, please never translate",
9 | "xray.single.cancel": "取消",
10 | "xray.single.add": "添加",
11 | "xray.single.delete": "删除",
12 | "xray.single.save": "删除",
13 | "xray.single.tools": "工具",
14 | "xray.single.close": "关闭",
15 | "xray.single.search": "搜索",
16 | "xray.single.help": "帮助",
17 | "xray.overlay": "X射线活性",
18 | "xray.color.red": "红色: ",
19 | "xray.color.green": "绿色: ",
20 | "xray.color.blue": "蓝色: ",
21 | "xray.input.gui": "GUI Name",
22 | "xray.input.add": "添加区块",
23 | "xray.input.add_hand": "添加手中的方块",
24 | "xray.input.add_look": "添加查看",
25 | "xray.input.distance": "加载区块: %s",
26 | "xray.input.show-lava": "显示 岩浆: %s",
27 | "xray.input.toggle_oredict": "使用词典",
28 | "xray.title.config": "配置块",
29 | "xray.title.edit": "编辑区块",
30 | "xray.title.edit_meta": "编辑元数据",
31 | "xray.message.missing_input": "您需要填写所有输入",
32 | "xray.message.already_exists": "此阻止已添加到阻止列表",
33 | "xray.message.added_block": "添加成功 %s.",
34 | "xray.message.updated_block": "条目已更新",
35 | "xray.message.remove_block": "%s 已被删除",
36 | "xray.message.block_exists": "%s 已存在。请输入其他名称。",
37 | "xray.message.unknown": "您尝试编辑的方块似乎不存在。",
38 | "xray.message.removed": "已成功移除 %s.",
39 | "xray.message.config_missing": "未找到配置文件。立即创建.",
40 | "xray.message.invalid_hand": "%s 需要成为一个块",
41 | "xray.message.thats_odd": "好像出问题了,如果这个问题不是第一次出现,请反馈到https://github.com/AdvancedXRay/XRay-Fabric/issues",
42 | "xray.message.nothing_infront": "你什么也没看吧?",
43 | "xray.message.not_a_number": "{%s} 不是数字。请使用数字作为您的元信息",
44 | "xray.message.meta_not_supported": "{%s} 不是有效的元数据 {%s}",
45 | "xray.message.state_warning": "警告,这会将您限制为默认\n方块。使用查看或手中的方块来获取\n您所需的绝对方块。\n在某些情况下(箱子)这可能是您需要做的\n如果是这种情况,那么这是正确的选择.",
46 | "xray.tooltips.add_block": "选着一个方块加入到追踪列表中\n这里面基本是原生的方块,如果你要特殊方块\n需要点击“添加查看”。",
47 | "xray.tooltips.add_block_in_hand": "将右手拿的方块添加到追踪列表中。",
48 | "xray.tooltips.add_block_looking_at": "自动选择您正在查看的块以添加到列表中.",
49 | "xray.tooltips.show_lava": "显示岩浆(包括源和流动),如果是当前加载过的区块,可能存在数据更新不及时,只需要重新开关即可.",
50 | "xray.tooltips.distance": "加载玩家周围的区块数量(是个正方形,如果是1就行1*1区块,3就是3*3区块).",
51 | "xray.tooltips.edit1": "点击启用/禁用",
52 | "xray.tooltips.edit2": "按住 Shift 并单击以编辑.",
53 | "xray.message.help.gui": "如果要修改已经在追踪列表中的数据只需要按住shift然后点击对应的条目即可。\n如果你只是想开关,只要鼠标左键点击就行。",
54 | "xray.message.help.warning": "需要注意的是\n不要将范围调太大,会掉fps,因为我需要扫描所有的方块"
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/shaders/frag/rendertype_lines_unaffected.fsh:
--------------------------------------------------------------------------------
1 | #version 150
2 |
3 | in vec4 vertexColor;
4 | out vec4 fragColor;
5 |
6 | void main() {
7 | fragColor = vertexColor;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/textures/gui/bg-help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AdvancedXRay/XRay-Fabric/e2a29ae4caf36df9e9d32ed51340050fbd360ff3/src/main/resources/assets/advanced-xray-fabric/textures/gui/bg-help.png
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/textures/gui/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AdvancedXRay/XRay-Fabric/e2a29ae4caf36df9e9d32ed51340050fbd360ff3/src/main/resources/assets/advanced-xray-fabric/textures/gui/bg.png
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/textures/gui/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AdvancedXRay/XRay-Fabric/e2a29ae4caf36df9e9d32ed51340050fbd360ff3/src/main/resources/assets/advanced-xray-fabric/textures/gui/circle.png
--------------------------------------------------------------------------------
/src/main/resources/assets/advanced-xray-fabric/textures/gui/color-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AdvancedXRay/XRay-Fabric/e2a29ae4caf36df9e9d32ed51340050fbd360ff3/src/main/resources/assets/advanced-xray-fabric/textures/gui/color-bg.png
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "advanced-xray-fabric",
4 | "version": "${version}",
5 | "name": "Advanced XRay (Fabric)",
6 | "description": "An Advanced XRay mod for Fabric with all your block finding needs baked right in!",
7 | "authors": [
8 | "ErrorMikey"
9 | ],
10 | "contact": {
11 | "homepage": "https://github.com/AdvancedXRay/xray-fabric",
12 | "sources": "https://github.com/AdvancedXRay/xray-fabric"
13 | },
14 | "license": "MIT",
15 | "icon": "assets/advanced-xray-fabric/icon.png",
16 | "environment": "client",
17 | "entrypoints": {
18 | "client": [
19 | "pro.mikey.fabric.xray.XRay"
20 | ]
21 | },
22 | "mixins": [
23 | {
24 | "config": "advanced-xray-fabric.mixins.json",
25 | "environment": "client"
26 | }
27 | ],
28 | "depends": {
29 | "fabricloader": ">=0.16.9",
30 | "fabric-api": "*",
31 | "minecraft": ">=1.21.1"
32 | },
33 | "accessWidener": "advanced-xray-fabric.accesswidener"
34 | }
35 |
--------------------------------------------------------------------------------