Api data problème

Bonjour
j’ai un petit problème avec l’api Data. Je ne suis pas un professionnel du java^^.

Je sauvegarde un Vector3d, mais au redémarrage du serveur les données sont écraser et valent (0,0,0) à cause de la méthode create().
Comment je peux faire pour ne pas les réinitialiser ?

Le Code
import com.flowpowered.math.vector.Vector3d;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.DataHolder;
import org.spongepowered.api.data.DataView;
import org.spongepowered.api.data.key.Key;
import org.spongepowered.api.data.manipulator.DataManipulatorBuilder;
import org.spongepowered.api.data.manipulator.immutable.common.AbstractImmutableSingleData;
import org.spongepowered.api.data.manipulator.mutable.common.AbstractSingleData;
import org.spongepowered.api.data.merge.MergeFunction;
import org.spongepowered.api.data.persistence.AbstractDataBuilder;
import org.spongepowered.api.data.persistence.InvalidDataException;
import org.spongepowered.api.data.value.BaseValue;
import org.spongepowered.api.data.value.immutable.ImmutableValue;
import org.spongepowered.api.data.value.mutable.Value;

import java.util.Optional;

public class MyVector3dData extends AbstractSingleData<Vector3d, MyVector3dData, MyVector3dData.Immutable> {

    public MyVector3dData(Vector3d value, Key<? extends Value<Vector3d>> usedKey) {
        super(usedKey, value);
    }

    @Override
    public Value<Vector3d> getValueGetter() {
        return Sponge.getRegistry().getValueFactory().createValue(ToolKeys.VECTOR3D, getValue());
    }

    public Value<Vector3d> blockstate() {
        return getValueGetter();
    }

    @Override
    public Optional<MyVector3dData> fill(DataHolder dataHolder, MergeFunction overlap) {
        Optional<MyVector3dData> data_ = dataHolder.get(MyVector3dData.class);
        if (data_.isPresent()) {
            MyVector3dData data = data_.get();
            MyVector3dData finalData = overlap.merge(this, data);
            setValue(finalData.getValue());
        }
        return Optional.of(this);
    }

    @Override
    public Optional<MyVector3dData> from(DataContainer container) {
        return Optional.of(this);
    }

    @Override
    public MyVector3dData copy() {
        return new MyVector3dData(getValue(), ToolKeys.VECTOR3D);
    }

    @Override
    public Immutable asImmutable() {
        return new Immutable(ToolKeys.VECTOR3D, getValue());
    }

    @Override
    public int getContentVersion() {
        return 1;
    }

    public class Immutable extends AbstractImmutableSingleData<Vector3d, Immutable, MyVector3dData> {

        public Immutable(Key<? extends Value<Vector3d>> usedKey, Vector3d value) {
            super(usedKey, value);
        }

        @Override
        public <E> Optional<Immutable> with(Key<? extends BaseValue<E>> key, E value) {
            if(this.supports(key)) {
                return Optional.of(asMutable().set(key, value).asImmutable());
            } else {
                return Optional.empty();
            }
        }

        @Override
        protected ImmutableValue<?> getValueGetter() {
            return Sponge.getRegistry().getValueFactory().createValue(ToolKeys.VECTOR3D, getValue()).asImmutable();
        }

        @Override
        public MyVector3dData asMutable() {
            return new MyVector3dData(getValue(), ToolKeys.VECTOR3D);
        }

        @Override
        public int getContentVersion() {
            return 1;
        }
    }
    public static class Builder extends AbstractDataBuilder<MyVector3dData> implements DataManipulatorBuilder<MyVector3dData, Immutable> {
        public Builder() {
            super(MyVector3dData.class, 1);
        }

        @Override
        public MyVector3dData create() {
            return new MyVector3dData(new Vector3d(0, 0, 0), ToolKeys.VECTOR3D);
        }

        @Override
        public Optional<MyVector3dData> createFrom(DataHolder dataHolder) {
            return create().fill(dataHolder);
        }

        @Override
        protected Optional<MyVector3dData> buildContent(DataView container) throws InvalidDataException {
            return Optional.of(create());
        }
    }
}

J’ai utiliser cet exemple:

Requested from an eminent user :

Hi,
I have kind of a trouble with Data API. I am not a pro with java.

I save a Vector3D but when rebooting the server datas get erased and are set to (0,0,0) because of the create() method.

How can I do to avoid reset of datas ?

I used that example

(Mais je ne saurais pas te répondre, désolé !)

There are three comments at the top saying what kind of example it is. The one you need to pay attention to is the one that says “non-persistent data” - this is data that will not persist through a server restart. The repository contains other examples, including ones that are persistent, and the difference between them is whether they override toContainer and provide a meaningful implementation in from. Look at the other examples in the project for how to do that.

Je n’y arrive pas, je peux avoir un autre exemple SVP?

[Google translate]
I can not do it, can I have another example?

Merci ^^, j’avais mal fait la première fois que j’ai essayé l’exemple MyStandardData, maintenant cela fonctionne

[translate.google]
Thank you ^^, I had done wrong the first time I tried the MyStandardData example, now it works

Bonjour,
j’ai créé une nouvelle key qui ne fonctionne pas bien , je ne comprends pas savez vous d’ou peut venir le problème ?

[translate.google.fr]
Hello,
I created a new key that does not work well, I do not understand you know where can the problem come from?

Key.builder()
public static final Key<MapValue<Integer, ItemStack>> INVENTORY = Key.builder()
        .type(new TypeToken<MapValue<Integer, ItemStack>>() {})
        .id("inventory_id")
        .name("Inventory ID")
        .query(DataQuery.of('.', "inventory_id.name"))
        .build();
GameRegistryEvent.Register<Key<?>>

@Listener
public void GameRegistryEventRegisterKey(GameRegistryEvent.Register<Key<?>> event) {
event.register(ToolKeys.INVENTORY);
}

DataRegistration

@Listener
public void GamePreInitialization(GamePreInitializationEvent event) throws IOException {
DataRegistration.builder()
.name(“My Inventory Data”)
.id(“inventory_data”) // prefix is added for you and you can’t add it yourself
.dataClass(MyInventoryData.class)
.immutableClass(MyImmutableInventoryData.class)
.builder(new MyInventoryDataBuilder()).build();
}

MyImmutableInventoryData

public class MyImmutableInventoryData extends AbstractImmutableData<MyImmutableInventoryData, MyInventoryData> {
private Map<Integer, ItemStack> inventory;

    public MyImmutableInventoryData(Map<Integer, ItemStack> inventory) {
        this.inventory = inventory;
        registerGetters();
    }

    @Override
    protected void registerGetters() {
        registerFieldGetter(ToolKeys.INVENTORY, () -> this.inventory);
        registerKeyValue(ToolKeys.INVENTORY, this::inventory);
    }

    public ImmutableMapValue<Integer, ItemStack> inventory() {
        return Sponge.getRegistry().getValueFactory().createMapValue(ToolKeys.INVENTORY, inventory).asImmutable();
    }

    @Override
    public MyInventoryData asMutable() {
        return new MyInventoryData(inventory);
    }

    @Override
    public int getContentVersion() {
        return 1;
    }

    @Override
    public DataContainer toContainer() {
        return super.toContainer()
                .set(ToolKeys.INVENTORY.getQuery(), this.inventory);
    }
}
MyInventoryData
public class MyInventoryData extends AbstractData<MyInventoryData, MyImmutableInventoryData> {
    private Map<Integer, ItemStack> inventory;


    public MyInventoryData(Map<Integer, ItemStack> inventory) {
        this.inventory = inventory;

        // you must call this!
        registerGettersAndSetters();
    }

    @Override
    protected void registerGettersAndSetters() {
        registerFieldGetter(ToolKeys.INVENTORY, () -> this.inventory);
        registerFieldSetter(ToolKeys.INVENTORY, inventory -> this.inventory = inventory);
        registerKeyValue(ToolKeys.INVENTORY, this::inventory);
    }

    public MapValue<Integer, ItemStack> inventory() {
        return Sponge.getRegistry().getValueFactory().createMapValue(ToolKeys.INVENTORY, inventory);
    }

    @Override
    public Optional<MyInventoryData> fill(DataHolder dataHolder, MergeFunction overlap) {
        Optional<MyInventoryData> otherData_ = dataHolder.get(MyInventoryData.class);
        if (otherData_.isPresent()) {
            MyInventoryData otherData = otherData_.get();
            MyInventoryData finalData = overlap.merge(this, otherData);
            this.inventory = finalData.inventory;
        }
        return Optional.of(this);
    }

    // the double method isn't strictly necessary but makes implementing the builder easier
    @Override
    public Optional<MyInventoryData> from(DataContainer container) {
        return from((DataView) container);
    }

    public Optional<MyInventoryData> from(DataView view) {
        if (view.contains(ToolKeys.INVENTORY.getQuery())) {
//            Optional<DataSerializable> v = view.getSerializable(ToolKeys.INVENTORY.getQuery(), DataSerializable.class);
//            DataSerializable v2 = v.get();

            this.inventory = (Map<Integer, ItemStack>) view.getMap(ToolKeys.INVENTORY.getQuery()).get();
//            this.inventory = view.getObject(ToolKeys.INVENTORY.getQuery(), HashMap.class).get();
            return Optional.of(this);
        } else {
            return Optional.empty();
        }
    }

    @Override
    public MyInventoryData copy() {
        return new MyInventoryData(this.inventory);
    }

    @Override
    public MyImmutableInventoryData asImmutable() {
        return new MyImmutableInventoryData(this.inventory);
    }

    @Override
    public int getContentVersion() {
        return 1;
    }

    // IMPORTANT this is what causes your data to be written to NBT
    @Override
    public DataContainer toContainer() {
        return super.toContainer()
                .set(ToolKeys.INVENTORY.getQuery(), this.inventory);
    }
}
MyInventoryDataBuilder
public class MyInventoryDataBuilder extends AbstractDataBuilder<MyInventoryData> implements DataManipulatorBuilder<MyInventoryData, MyImmutableInventoryData> {
    public MyInventoryDataBuilder() {
        super(MyInventoryData.class, 1);
    }

    @Override
    public MyInventoryData create() {
        HashMap<Integer, ItemStack> inventory = new HashMap<Integer, ItemStack>();
        return new MyInventoryData(inventory);
    }

    @Override
    public Optional<MyInventoryData> createFrom(DataHolder dataHolder) {
        return create().fill(dataHolder);
    }

    @Override
    protected Optional<MyInventoryData> buildContent(DataView container) throws InvalidDataException {
        return create().from(container);
    }
}

Map extraction does not work well. You cannot simply cast it. I recommend not using getMap, instead doing it yourself with getKeys(false)/getView.

Je peux a voir un exemple ? Merci

[ translate.google.fr ]
Can I see an example? Thank you

DataView invView = view.getView(ToolKeys.INVENTORY.getQuery());
Map<Integer, ItemStack> map = new HashMap<>();
for (DataQuery query : invView.getKeys(false)) {
    ItemStack stack = invView.getSerializable(query, ItemStack.class).get();
    int key = Integer.parseInt(query.toString());
    map.put(key, stack);
}
this.inventory = map;

[fr]
Encore moi, pourquoi quand je sauvegarde un ItemStack ces key ne sont plus active quand on le récupère alors que tout est dans le fichier ?

translate.google.fr:
Still me, why when I save an ItemStack these key are no longer active when it is recovered while everything is in the file?

Code
                for (Map.Entry<Object, ? extends ConfigurationNode> entry : conf.getConfig().getChildrenMap().entrySet()) {
                    String key = (String) entry.getKey();
                    ItemStack itemStackConf = null;
                    try {
                        itemStackConf = entry.getValue().getValue(new TypeToken<ItemStack>() {});

                        if(itemStackConf.get(ToolKeys.INVENTORY).isPresent()) {
                            Tool.getLogger().info("INVENTORY!!!");
                        } else {
                            Tool.getLogger().info("!INVENTORY ");
                        }
                    } catch (ObjectMappingException e) {
                        e.printStackTrace();
                    }
                }

EDIT:

                        Optional<MyInventoryData> myInventoryDataOptional = itemStackConf.getOrCreate(MyInventoryData.class);
                        if(myInventoryDataOptional.isPresent()) {
                            MyInventoryData myInventoryData = myInventoryDataOptional.get();
                            Tool.getLogger().info("size: " + myInventoryData.inventory().size()+"");
                            for(Map.Entry<Integer, ItemStack> inventoryevent : myInventoryData.inventory().entrySet()){
                                ItemStack inventoryeventItemStack = inventoryevent.getValue();
                                Tool.getLogger().info("=> " +inventoryeventItemStack.toString());
                            }
                        } else {
                            Tool.getLogger().info("!INVENTORY");
                        }

return: size: 0


[fr]
Toute les données ont leur valeurs par défaut. comment je dois faire ?

translate.google.fr:
All data has default values. How should I do ?

Personne a une solution ?

translate.google.fr:
Nobody has a solution?

:frowning::frowning:

My code: MyImmutableInventoryData - Pastebin.com
MyInventoryData - Pastebin.com
MyInventoryDataBuilder - Pastebin.com
event - Pastebin.com
sav/load - Pastebin.com
json: json conf - Pastebin.com