Skip to content

Commit

Permalink
Merge pull request #31 from SammyForReal/1.21
Browse files Browse the repository at this point in the history
Usage of Item Components instead of raw NBT data in ShardCreatorGuiDescription
  • Loading branch information
sisby-folk authored Dec 6, 2024
2 parents c04b766 + b41a8ae commit 8c5b63d
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 13 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ dependencies {
include libs.fpapi
}

loom {
accessWidenerPath = file("src/main/resources/${modId}.accesswidener")
}

processResources {
final Map<String, String> meta = [
version : version,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package net.modfest.scatteredshards.client.screen;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
import io.github.cottonmc.cotton.gui.client.CottonClientScreen;
Expand All @@ -14,12 +16,18 @@
import io.github.cottonmc.cotton.gui.widget.data.Axis;
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
import io.github.cottonmc.cotton.gui.widget.data.Insets;
import it.unimi.dsi.fastutil.objects.ReferenceArraySet;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.argument.ItemStringReader;
import net.minecraft.component.ComponentChanges;
import net.minecraft.component.ComponentMap;
import net.minecraft.component.ComponentType;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.StringNbtReader;
import net.minecraft.registry.Registries;
import net.minecraft.resource.Resource;
import net.minecraft.text.Text;
Expand All @@ -37,6 +45,7 @@

import java.util.Objects;
import java.util.Optional;
import java.util.Set;

public class ShardCreatorGuiDescription extends LightweightGuiDescription {
public static final Text TITLE_TEXT = Text.translatable("gui.scattered_shards.creator.title");
Expand All @@ -47,12 +56,10 @@ public class ShardCreatorGuiDescription extends LightweightGuiDescription {
public static final Text ICON_TEXTURE_TEXT = Text.translatable("gui.scattered_shards.creator.icon.texture");
public static final Text ICON_ITEM_TEXT = Text.translatable("gui.scattered_shards.creator.icon.item");
public static final Text ITEM_TEXT = Text.translatable("gui.scattered_shards.creator.field.item.id");
public static final Text NBT_TEXT = Text.translatable("gui.scattered_shards.creator.field.item.nbt");
public static final Text COMPONENT_TEXT = Text.translatable("gui.scattered_shards.creator.field.item.component");
public static final Text USE_MOD_ICON_TEXT = Text.translatable("gui.scattered_shards.creator.toggle.mod_icon");
public static final Text SAVE_TEXT = Text.translatable("gui.scattered_shards.creator.button.save");

private static final Gson GSON = new Gson();

private Identifier shardId;
private Shard shard;
private Identifier modIcon;
Expand Down Expand Up @@ -118,18 +125,15 @@ public static Identifier parseTexture(String path) {
updateItemIcon();
});

public WProtectableField nbtField = new WProtectableField(NBT_TEXT)
public WProtectableField componentField = new WProtectableField(COMPONENT_TEXT)
.setChangedListener((it) -> {
try {
this.itemComponents = ComponentMap.EMPTY;
JsonElement json = GSON.fromJson(it, JsonElement.class);
this.itemComponents = ComponentMap.CODEC.decode(JsonOps.INSTANCE, json).getOrThrow().getFirst();
updateComponents(new StringReader(it));
} catch (Exception ignored) {
}
updateItemIcon();
});


public WButton saveButton = new WButton(SAVE_TEXT)
.setOnClick(() -> ClientPlayNetworking.send(new C2SModifyShard(shardId, shard)));

Expand All @@ -138,6 +142,74 @@ public static Identifier parseTexture(String path) {
private Identifier iconPath = null;


private <T> void updateComponents(StringReader reader) throws CommandSyntaxException {
ComponentChanges.Builder changesBuilder = ComponentChanges.builder();
Set<ComponentType<?>> known = new ReferenceArraySet<>();

// Begin of component list
reader.expect('[');
reader.skipWhitespace();

// Body of component list
while (reader.canRead() && reader.peek() != ']') {
boolean negation = false;

if (reader.peek() == '!') {
// Negate incoming block
reader.skip();
negation = true;
}

// Component Type
@SuppressWarnings("unchecked") // We could avoid this with a separate method for getting the values but eh
ComponentType<T> componentType = (ComponentType<T>) ItemStringReader.Reader.readComponentType(reader);
reader.skipWhitespace();
if (!known.add(componentType))
throw new SimpleCommandExceptionType(Text.literal("Same component cannot appear twice")).create();

if (negation)
changesBuilder.remove(componentType);
else {
reader.expect('=');
reader.skipWhitespace();

// Component Value

int index = reader.getCursor();

NbtElement nbtElement = new StringNbtReader(reader).parseElement();
DataResult<T> dataResult = componentType.getCodecOrThrow().parse(NbtOps.INSTANCE, nbtElement);

changesBuilder.add(componentType, dataResult.getOrThrow(error -> {
reader.setCursor(index);
return new SimpleCommandExceptionType(Text.literal("Component is malformed")).create();
}));

reader.skipWhitespace();
}

// List separation

if (!reader.canRead() || reader.peek() != ',')
break;

reader.skip();
reader.skipWhitespace();
if (!reader.canRead())
throw new SimpleCommandExceptionType(Text.literal("Expected component")).create();
}

// End of components list
reader.expect(']');

ComponentChanges componentChanges = changesBuilder.build();

ComponentMap.Builder mapBuilder = ComponentMap.builder();
mapBuilder.addAll(componentChanges.toAddedRemovedPair().added());

this.itemComponents = mapBuilder.build();
}

private void updateItemIcon() {
if (item == null) {
shard.setIcon(Shard.MISSING_ICON);
Expand Down Expand Up @@ -190,7 +262,7 @@ public ShardCreatorGuiDescription(Identifier shardId, Shard shard, String modId)
this.itemField.setText(Registries.ITEM.getId(a.getItem()).toString());
String nbt = componentJson.toString();
if ("{}".equals(nbt)) nbt = "";
this.nbtField.setText(nbt);
this.componentField.setText(nbt);
}));

shardPanel.setShard(shard);
Expand Down Expand Up @@ -226,7 +298,7 @@ public ShardCreatorGuiDescription(Identifier shardId) {
textureIconPanel.add(textureToggle);

itemIconPanel.add(itemField);
itemIconPanel.add(nbtField);
itemIconPanel.add(componentField);

editorPanel.add(saveButton);

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/assets/scattered_shards/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"gui.scattered_shards.creator.icon.texture": "Texture Icon",
"gui.scattered_shards.creator.icon.item": "Item Icon",
"gui.scattered_shards.creator.field.item.id": "Item ID...",
"gui.scattered_shards.creator.field.item.nbt": "Item NBT...",
"gui.scattered_shards.creator.field.item.component": "Item Components...",
"gui.scattered_shards.creator.field.texture": "Texture path...",
"gui.scattered_shards.creator.toggle.mod_icon": "Use mod icon",
"gui.scattered_shards.creator.button.save": "Save",
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"libgui": ">=${libgui}",
"fabric-permissions-api-v0": ">=${fpapi}"
},
"accessWidener": "${modId}.accesswidener",
"entrypoints": {
"main": [
"net.modfest.scatteredshards.ScatteredShards"
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/scattered_shards.accesswidener
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
accessWidener v2 named

accessible class net/minecraft/command/argument/ItemStringReader$Reader

0 comments on commit 8c5b63d

Please sign in to comment.