sponge 8.0
How can I set/load ItemStack to ConfigurationNode ?
please help me.
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);
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
Thank for you care!