Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ public DataView update(final DataView content) {
final String type = content.getString(Constants.ItemStack.V2.TYPE).get();

final DataContainer updated = DataContainer.createNew();
updated.set(Constants.ItemStack.TYPE, type);
updated.set(Constants.ItemStack.COUNT, count);
updated.set(Constants.ItemStack.V3.TYPE, type);
updated.set(Constants.ItemStack.V3.COUNT, count);

final DataContainer components = DataContainer.createNew();
content.getInt(Constants.ItemStack.V2.DAMAGE_VALUE).filter(dmg -> dmg != 0).ifPresent(dmg -> components.set(Constants.ItemStack.DAMAGE, dmg));
content.getInt(Constants.ItemStack.V2.DAMAGE_VALUE).filter(dmg -> dmg != 0).ifPresent(dmg -> components.set(Constants.ItemStack.V3.DAMAGE, dmg));

content.getView(Constants.Sponge.UNSAFE_NBT).ifPresent(unsafe -> {
// Get unsafe nbt data
Expand All @@ -77,7 +77,7 @@ public DataView update(final DataView content) {
newComponents.values(false).forEach(components::set);
});

updated.set(Constants.ItemStack.COMPONENTS, components);
updated.set(Constants.ItemStack.V3.COMPONENTS, components);
updated.set(Queries.CONTENT_VERSION, this.outputVersion());

return updated;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.item;

import org.spongepowered.api.data.persistence.DataContainer;
import org.spongepowered.api.data.persistence.DataContentUpdater;
import org.spongepowered.api.data.persistence.DataView;
import org.spongepowered.api.data.persistence.Queries;
import org.spongepowered.api.item.ItemTypes;
import org.spongepowered.api.registry.RegistryTypes;
import org.spongepowered.common.util.Constants;

public final class ItemStackDataVersionUpdater implements DataContentUpdater {

public static final DataContentUpdater INSTANCE = new ItemStackDataVersionUpdater();

@Override
public int inputVersion() {
return Constants.ItemStack.Data.DATA_COMPONENTS;
}

@Override
public int outputVersion() {
return Constants.ItemStack.Data.DATA_VERSIONED;
}

@Override
public DataView update(final DataView content) {
final boolean isAir = content.getRegistryValue(Constants.ItemStack.V3.TYPE, RegistryTypes.ITEM_TYPE)
.map(i -> i == ItemTypes.AIR.get())
.orElse(false);

final DataContainer updated = DataContainer.createNew();
updated.set(Queries.CONTENT_VERSION, this.outputVersion());
updated.set(Constants.ItemStack.V4.DATA_VERSION, 3833); // The version from the previous ItemStackDataComponentsUpdater.

if (isAir) {
return updated.set(Constants.ItemStack.V4.DATA, DataContainer.createNew());
}

final DataContainer data = DataContainer.createNew()
.set(Constants.ItemStack.V3.TYPE, content.getString(Constants.ItemStack.V3.TYPE).get())
.set(Constants.ItemStack.V3.COUNT, content.getInt(Constants.ItemStack.V3.COUNT).get());

content.getView(Constants.ItemStack.V3.COMPONENTS)
.ifPresent(components -> data.set(Constants.ItemStack.V3.COMPONENTS, components));

return updated.set(Constants.ItemStack.V4.DATA, data);
}
}
60 changes: 26 additions & 34 deletions src/main/java/org/spongepowered/common/item/SpongeItemStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@


import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Dynamic;
import net.minecraft.SharedConstants;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.RegistryOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.datafix.DataFixers;
import net.minecraft.util.datafix.fixes.References;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.EquipmentSlotGroup;
import net.minecraft.world.entity.ai.attributes.Attribute;
Expand Down Expand Up @@ -64,7 +66,6 @@
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.item.inventory.equipment.EquipmentType;
import org.spongepowered.api.registry.RegistryTypes;
import org.spongepowered.common.SpongeCommon;
import org.spongepowered.common.block.SpongeBlockSnapshot;
import org.spongepowered.common.data.DataUpdaterDelegate;
Expand Down Expand Up @@ -273,20 +274,13 @@ public ItemStack empty() {

@NotNull
public static DataContainer getDataContainer(final net.minecraft.world.item.ItemStack mcStack) {
final ResourceLocation key = BuiltInRegistries.ITEM.getKey(mcStack.getItem());
final DataContainer container = DataContainer.createNew()
.set(Queries.CONTENT_VERSION, ((ItemStack) (Object) mcStack).contentVersion())
.set(Constants.ItemStack.TYPE, key)
.set(Constants.ItemStack.COUNT, mcStack.getCount());
// Cleanup Old Custom Data
SpongeItemStack.cleanupOldCustomData(mcStack);
// Serialize all DataComponents...

var ops = RegistryOps.create(NbtOps.INSTANCE, SpongeCommon.server().registryAccess());
var componentsTag = DataComponentPatch.CODEC.encodeStart(ops, mcStack.getComponentsPatch());
var components = NBTTranslator.INSTANCE.translate((CompoundTag) componentsTag.getOrThrow());
container.set(Constants.ItemStack.COMPONENTS, components);
return container;
final CompoundTag stackData = (CompoundTag) mcStack.saveOptional(SpongeCommon.server().registryAccess());
return DataContainer.createNew()
.set(Queries.CONTENT_VERSION, ((ItemStack) (Object) mcStack).contentVersion())
.set(Constants.ItemStack.V4.DATA_VERSION, SharedConstants.getCurrentVersion().getDataVersion().getVersion())
.set(Constants.ItemStack.V4.DATA, NBTTranslator.INSTANCE.translate(stackData));
}

@NotNull
Expand All @@ -313,7 +307,8 @@ private static void cleanupOldCustomData(final net.minecraft.world.item.ItemStac
// TODO updater for old (maybe V2?) Constants.Sponge.DATA_MANIPULATORS
public static final ImmutableList<DataContentUpdater> STACK_UPDATERS = ImmutableList.of(
ItemStackSnapshotDuplicateManipulatorUpdater.INSTANCE,
ItemStackDataComponentsUpdater.INSTANCE);
ItemStackDataComponentsUpdater.INSTANCE,
ItemStackDataVersionUpdater.INSTANCE);

@NotNull
public static Optional<ItemStack> createItemStack(final DataView container) {
Expand All @@ -333,27 +328,24 @@ public static Optional<ItemStack> createItemStack(final DataView container) {
final DataUpdaterDelegate delegate = new DataUpdaterDelegate(builder.build(), version, Constants.ItemStack.Data.CURRENT_VERSION);
final DataView updatedContainer = delegate.update(container);

// Check if we have valid updated stack
if (!updatedContainer.contains(Constants.ItemStack.TYPE, Constants.ItemStack.COUNT)) {
if (!updatedContainer.contains(Constants.ItemStack.V4.DATA_VERSION, Constants.ItemStack.V4.DATA)) {
return Optional.empty();
}

final int count = updatedContainer.getInt(Constants.ItemStack.COUNT).get();

final ItemType itemType = updatedContainer.getRegistryValue(Constants.ItemStack.TYPE, RegistryTypes.ITEM_TYPE)
.orElseThrow(() -> new IllegalStateException("Unable to find item with id: "));
final var mcStack = new net.minecraft.world.item.ItemStack((Item) itemType, count);
if (!mcStack.isEmpty()) { // ignore components when the stack is empty anyways
// Read and apply components from container to mc stack
mcStack.applyComponents(SpongeItemStack.patchFromData(updatedContainer));
final CompoundTag stackData = updatedContainer.getView(Constants.ItemStack.V4.DATA)
.map(NBTTranslator.INSTANCE::translate)
.orElseThrow(() -> new InvalidDataException("Unable retrieve item stack data"));
if (stackData.isEmpty()) {
return Optional.of(ItemStack.empty());
}
return Optional.of((ItemStack) (Object) mcStack);
}

public static DataComponentPatch patchFromData(final DataView container) {
return container.getView(Constants.ItemStack.COMPONENTS).map(NBTTranslator.INSTANCE::translate).flatMap(compound -> {
var dynamic = new Dynamic<>(RegistryOps.create(NbtOps.INSTANCE, SpongeCommon.server().registryAccess()), compound);
return DataComponentPatch.CODEC.decode(dynamic).result().map(Pair::getFirst);
}).orElse(DataComponentPatch.EMPTY);
final int dataVersion = updatedContainer.getInt(Constants.ItemStack.V4.DATA_VERSION).get();
final Dynamic<Tag> fixedData = DataFixers.getDataFixer().update(
References.ITEM_STACK,
new Dynamic<>(NbtOps.INSTANCE, stackData),
dataVersion,
SharedConstants.getCurrentVersion().getDataVersion().getVersion()
);
return net.minecraft.world.item.ItemStack.parse(SpongeCommon.server().registryAccess(), fixedData.getValue())
.map(ItemStack.class::cast);
}
}
24 changes: 17 additions & 7 deletions src/main/java/org/spongepowered/common/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -1192,12 +1192,6 @@ public static final class Fluids {

public static final class ItemStack {

public static final DataQuery COUNT = of("count");
public static final DataQuery TYPE = of("id");
public static final DataQuery COMPONENTS = of("components");
public static final DataQuery CUSTOM_DATA = of("minecraft:custom_data");
public static final DataQuery DAMAGE = of("minecraft:damage");

@Deprecated
public static final class V2 {

Expand All @@ -1207,13 +1201,29 @@ public static final class V2 {
public static final DataQuery TYPE = of("ItemType");
}

@Deprecated
public static final class V3 {

public static final DataQuery COUNT = of("count");
public static final DataQuery TYPE = of("id");
public static final DataQuery COMPONENTS = of("components");
public static final DataQuery DAMAGE = of("minecraft:damage");
}

public static final class V4 {

public static final DataQuery DATA = of("Data");
public static final DataQuery DATA_VERSION = of("DataVersion");
}

// Previously only ItemStackSnapshot
public static final class Data {

public static final int DUPLICATE_MANIPULATOR_DATA_VERSION = 1;
public static final int REMOVED_DUPLICATE_DATA = 2;
public static final int DATA_COMPONENTS = 3;
public static final int CURRENT_VERSION = Data.DATA_COMPONENTS;
public static final int DATA_VERSIONED = 4;
public static final int CURRENT_VERSION = Data.DATA_VERSIONED;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource;
import net.minecraft.core.component.DataComponentMap;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
Expand Down Expand Up @@ -80,6 +81,7 @@ public abstract class ItemStackMixin_API implements SerializableDataHolder.Mutab
@Shadow public abstract Item shadow$getItem();
@Shadow public abstract net.minecraft.network.chat.Component shadow$getDisplayName();
@Shadow public abstract void shadow$applyComponents(final DataComponentPatch $$0);
@Shadow public abstract void shadow$applyComponents(final DataComponentMap $$0);
@Shadow public abstract DataComponentPatch shadow$getComponentsPatch();
@Shadow @Nullable public abstract <T> T shadow$update(final DataComponentType<T> $$0, final T $$1, final UnaryOperator<T> $$2);

Expand All @@ -100,7 +102,7 @@ public abstract class ItemStackMixin_API implements SerializableDataHolder.Mutab
@Override
public boolean validateRawData(final DataView container) {
Objects.requireNonNull(container);
return false;
return SpongeItemStack.createItemStack(container).isPresent();
}

@Override
Expand All @@ -111,8 +113,12 @@ public void setRawData(final DataView container) throws InvalidDataException {
throw new IllegalArgumentException("Cannot set data on empty item stacks!");
}

final net.minecraft.world.item.ItemStack updated = SpongeItemStack.createItemStack(container)
.map(net.minecraft.world.item.ItemStack.class::cast)
.orElseThrow(() -> new InvalidDataException("Unable to deserialize item stack data"));

try {
this.shadow$applyComponents(SpongeItemStack.patchFromData(container));
this.shadow$applyComponents(updated.getComponents());
} catch (final Exception e) {
throw new InvalidDataException("Unable to set raw data or translate raw data for ItemStack setting", e);
}
Expand Down Expand Up @@ -168,7 +174,7 @@ public SerializableDataHolder.Mutable copy() {

@Override
public int contentVersion() {
return 3;
return 4;
}

@Override
Expand Down
Loading