Add FTB NBT editor shortcuts
This commit is contained in:
parent
7041633e1b
commit
30f4dc4933
8 changed files with 263 additions and 0 deletions
59
client/src/main/java/dev/quorate/client/nbt/NbtKeys.java
Normal file
59
client/src/main/java/dev/quorate/client/nbt/NbtKeys.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package dev.quorate.client.nbt;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public final class NbtKeys {
|
||||
private static final KeyMapping OPEN =
|
||||
new KeyMapping(
|
||||
"key.saltatory_client.nbt",
|
||||
InputConstants.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_N,
|
||||
"key.categories.misc");
|
||||
|
||||
private NbtKeys() {}
|
||||
|
||||
@EventBusSubscriber(modid = "saltatory_client", value = Dist.CLIENT)
|
||||
public static final class ModEvents {
|
||||
@SubscribeEvent
|
||||
public static void register(RegisterKeyMappingsEvent event) {
|
||||
if (NbtPlugin.supported()) event.register(OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
@EventBusSubscriber(modid = "saltatory_client", value = Dist.CLIENT)
|
||||
public static final class GameEvents {
|
||||
@SubscribeEvent
|
||||
public static void tick(ClientTickEvent.Post event) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
while (OPEN.consumeClick()) {
|
||||
if (!NbtPlugin.supported()
|
||||
|| mc.player == null
|
||||
|| mc.screen != null
|
||||
|| mc.getConnection() == null) continue;
|
||||
String target = "item";
|
||||
if (mc.hitResult instanceof EntityHitResult hit) {
|
||||
String kind = hit.getEntity() instanceof Player ? "player " : "entity ";
|
||||
target = kind + hit.getEntity().getStringUUID();
|
||||
} else if (mc.hitResult instanceof BlockHitResult hit
|
||||
&& mc.level.getBlockEntity(hit.getBlockPos()) != null) {
|
||||
var pos = hit.getBlockPos();
|
||||
target = "block " + pos.getX() + " " + pos.getY() + " " + pos.getZ();
|
||||
}
|
||||
mc.getConnection().sendCommand("ftblibrary nbtedit " + target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
client/src/main/java/dev/quorate/client/nbt/NbtPlugin.java
Normal file
45
client/src/main/java/dev/quorate/client/nbt/NbtPlugin.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package dev.quorate.client.nbt;
|
||||
|
||||
import dev.quorate.client.mixin.ModRanges;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public final class NbtPlugin implements IMixinConfigPlugin {
|
||||
static final String FTB = "[2101.1.37]";
|
||||
|
||||
public static boolean supported() {
|
||||
return ModRanges.loaded("ftblibrary", FTB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String target, String mixin) {
|
||||
return supported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> targets, Set<String> others) {}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String target, ClassNode node, String mixin, IMixinInfo info) {}
|
||||
|
||||
@Override
|
||||
public void postApply(String target, ClassNode node, String mixin, IMixinInfo info) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package dev.quorate.client.nbt.mixin;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen;
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen.ButtonNBT;
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen.ButtonNBTCollection;
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen.ButtonNBTMap;
|
||||
import dev.ftb.mods.ftblibrary.ui.input.Key;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(value = NBTEditorScreen.class, remap = false)
|
||||
public abstract class EditorMixin {
|
||||
@Shadow private ButtonNBT selected;
|
||||
|
||||
@Shadow
|
||||
private void setSelected(ButtonNBT node) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Inject(method = "keyPressed", at = @At("RETURN"), cancellable = true)
|
||||
private void saltatory$keys(Key key, CallbackInfoReturnable<Boolean> result) {
|
||||
if (result.getReturnValue() || !key.modifiers.control()) return;
|
||||
if (key.is(GLFW.GLFW_KEY_C)) {
|
||||
saltatory$copy();
|
||||
result.setReturnValue(true);
|
||||
} else if (key.is(GLFW.GLFW_KEY_V)) {
|
||||
saltatory$paste();
|
||||
result.setReturnValue(true);
|
||||
} else if (key.is(GLFW.GLFW_KEY_D) || key.is(GLFW.GLFW_KEY_X)) {
|
||||
NodeAccess node = (NodeAccess) selected;
|
||||
ButtonNBTCollection parent = node.saltatory$parent();
|
||||
if (parent != null) {
|
||||
if (key.is(GLFW.GLFW_KEY_X)) saltatory$copy();
|
||||
parent.setTag(node.saltatory$key(), null);
|
||||
parent.updateChildren(false);
|
||||
setSelected(parent);
|
||||
parent.getGui().refreshWidgets();
|
||||
}
|
||||
result.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void saltatory$copy() {
|
||||
NodeAccess node = (NodeAccess) selected;
|
||||
ButtonNBTCollection parent = node.saltatory$parent();
|
||||
CompoundTag copied = new CompoundTag();
|
||||
if (parent == null && selected instanceof ButtonNBTMap root) {
|
||||
for (String name : root.children.keySet()) {
|
||||
copied.put(name, root.getTag(name).copy());
|
||||
}
|
||||
} else if (parent != null) {
|
||||
copied.put(node.saltatory$key(), parent.getTag(node.saltatory$key()).copy());
|
||||
}
|
||||
Minecraft.getInstance().keyboardHandler.setClipboard(copied.toString());
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void saltatory$paste() {
|
||||
if (!(selected instanceof ButtonNBTCollection target)) return;
|
||||
CompoundTag copied;
|
||||
try {
|
||||
copied = TagParser.parseTag(Minecraft.getInstance().keyboardHandler.getClipboard());
|
||||
} catch (CommandSyntaxException e) {
|
||||
Minecraft.getInstance()
|
||||
.player
|
||||
.displayClientMessage(Component.literal("Invalid NBT clipboard"), true);
|
||||
return;
|
||||
}
|
||||
byte elementType = 0;
|
||||
for (String name : copied.getAllKeys()) {
|
||||
Tag tag = copied.get(name);
|
||||
if (!target.canCreateNew(tag.getId())
|
||||
|| (!(target instanceof ButtonNBTMap)
|
||||
&& elementType != 0
|
||||
&& elementType != tag.getId())) {
|
||||
Minecraft.getInstance()
|
||||
.player
|
||||
.displayClientMessage(
|
||||
Component.literal("NBT type does not fit selection"), true);
|
||||
return;
|
||||
}
|
||||
elementType = tag.getId();
|
||||
}
|
||||
for (String name : copied.getAllKeys()) {
|
||||
target.setTag(target instanceof ButtonNBTMap ? name : "-1", copied.get(name).copy());
|
||||
}
|
||||
target.updateChildren(false);
|
||||
target.getGui().refreshWidgets();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package dev.quorate.client.nbt.mixin;
|
||||
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen.ButtonNBT;
|
||||
import dev.ftb.mods.ftblibrary.nbtedit.NBTEditorScreen.ButtonNBTCollection;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(value = ButtonNBT.class, remap = false)
|
||||
public interface NodeAccess {
|
||||
@Accessor("parent")
|
||||
ButtonNBTCollection saltatory$parent();
|
||||
|
||||
@Accessor("key")
|
||||
String saltatory$key();
|
||||
}
|
||||
|
|
@ -14,6 +14,9 @@ config="client.mixins.json"
|
|||
[[mixins]]
|
||||
config="client.jemi.mixins.json"
|
||||
|
||||
[[mixins]]
|
||||
config="client.nbt.mixins.json"
|
||||
|
||||
[[dependencies.saltatory_client]]
|
||||
modId="neoforge"
|
||||
type="required"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"key.saltatory_client.nbt": "Edit targeted NBT"
|
||||
}
|
||||
9
client/src/main/resources/client.nbt.mixins.json
Normal file
9
client/src/main/resources/client.nbt.mixins.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8.7",
|
||||
"package": "dev.quorate.client.nbt.mixin",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"plugin": "dev.quorate.client.nbt.NbtPlugin",
|
||||
"client": ["NodeAccess", "EditorMixin"],
|
||||
"injectors": {"defaultRequire": 1}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package dev.quorate.client.nbt;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import dev.quorate.client.mixin.ModRanges;
|
||||
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class NbtPluginTest {
|
||||
@Test
|
||||
void targetsOnlyInspectedFtbVersion() {
|
||||
assertTrue(ModRanges.contains(new DefaultArtifactVersion("2101.1.37"), NbtPlugin.FTB));
|
||||
assertFalse(ModRanges.contains(new DefaultArtifactVersion("2101.1.36"), NbtPlugin.FTB));
|
||||
assertFalse(ModRanges.contains(new DefaultArtifactVersion("2101.1.38"), NbtPlugin.FTB));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue