How can I set ItemStack to ConfigurationNode?

sponge 8.0

How can I set/load ItemStack to ConfigurationNode ?

please help me.

In the same way you shouldnt be setting a full player (as it contains live data), you shouldnt be setting a ItemStack, but instead a ItemStackSnapshot

Setting

ConfigNode node;
ItemStack stack;

node.set(stack.createSnapshot(), itemStackSnapshot.class);

Receiving

node.ger(ItemStackSnapshot.class);
1 Like

error.

org.spongepowered.configurate.serialize.SerializationException: [item] of type org.spongepowered.api.item.inventory.ItemStackSnapshot: No serializer available for type interface org.spongepowered.api.item.inventory.ItemStackSnapshot

Ah taking a look at the default values … there isnt anything for sponge. Not sure if this is a bug.

But anyway, ive built a work around.

First of all we need a way to serialize the raw data of the item. Most objects in Sponge use a DataView to store the data (All objects that use NBT will have a DataView). And this is what we will use to store our item

public static final TypeSerializer<DataContainer> DATA_CONTAINER_SERIALIZER = new TypeSerializer<DataContainer>() {

                @Override
                public DataContainer deserialize(Type type, ConfigurationNode node) throws SerializationException {
                    DataContainer container = DataContainer.createNew();
                    for (ConfigurationNode query : node.childrenMap().values()) {
                        Map<List<String>, Object> values = findValue(query, new ArrayList<>());
                        for (Map.Entry<List<String>, Object> entry : values.entrySet()) {
                            DataQuery valueQuery = DataQuery.of(entry.getKey());
                            container = container.set(valueQuery, entry.getValue());
                        }
                    }
                    return container;
                }

                @Override
                public void serialize(Type type, @Nullable DataContainer obj, ConfigurationNode node) throws SerializationException {
                    if (obj == null) {
                        node.set(null);
                        return;
                    }
                    for (DataQuery key : obj.keys(true)) {
                        Optional<Object> opValue = obj.get(key);
                        if (!opValue.isPresent()) {
                            System.err.println("Skipping '" + key + "'. Could not read value");
                            continue;
                        }
                        Object[] nodes = key.parts().stream().map(s -> (Object) s).toArray();
                        Object value = opValue.get();

                        node.node(nodes).node("value").set(value);
                        node.node(nodes).node("type").set(value.getClass().getTypeName());
                    }
                }

                private Map<List<String>, Object> findValue(ConfigurationNode node, List<String> path) {
                    List<String> newPath = new ArrayList<>(path);
                    Map<List<String>, Object> newMap = new HashMap<>();
                    newPath.add(node.key().toString());
                    if (node.node("type").isNull()) {
                        for (ConfigurationNode child : node.childrenList()) {
                            Map<List<String>, Object> returnedMap = findValue(child, newPath);
                            newMap.putAll(returnedMap);
                        }
                        return newMap;
                    }
                    String type = node.node("type").getString();
                    Class<?> clazz;
                    try {
                        clazz = Class.forName(type);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                    try {
                        Object value = node.node("value").get(clazz);
                        newMap.put(newPath, value);
                        return newMap;
                    } catch (SerializationException e) {
                        throw new RuntimeException(e);
                    }
                }
            };

Then loading your config, you need to apply this serializer

            HoconConfigurationLoader loader = HoconConfigurationLoader
                    .builder()
                    .file(new File("test.conf"))
                    .defaultOptions((objs) -> objs.serializers((builder) -> builder.register(DataContainer.class, DATA_CONTAINER_SERIALIZER)))
                    .build();

then you should be able to set with

ItemStack stack;
ConfigurationNode node;

node.set(DataContainer.class, stack.createSnapshot().asContainer());

and load with

ConfigurationNode node;

DataContainer container = node.get(DataContainer.class);
ItemStack stack = ItemStack.builder().fromContainer(container),build();

bit long winded I know. But when i get to rewriting the config section on the docs, ill make sure to provide the proper way there

2 Likes

Thank for you care!