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 ?