I’m trying to make a crates plugin that I made be able to interface with a ‘command vouchers’ plugin. The core of both plugins is usable on their own, but I found that when trying to serialize custom data into the file the crates will be stored in, the custom data gets stripped. leaving me with a useless item when it comes out the other end.
DataManipulator:
package io.github.redrield.commandvouchers.data
import org.spongepowered.api.Sponge
import org.spongepowered.api.data.DataContainer
import org.spongepowered.api.data.DataHolder
import org.spongepowered.api.data.DataView
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.value.immutable.ImmutableValue
import org.spongepowered.api.data.value.mutable.Value
import java.util.Optional
class VoucherData(command: String) : AbstractSingleData<String, VoucherData, VoucherData.Immutable>(command, VoucherKeys.VOUCHER_COMMAND){
override fun copy(): VoucherData = VoucherData(value)
override fun compareTo(other: VoucherData?): Int = 0
override fun getContentVersion(): Int = 1
override fun fill(dataHolder: DataHolder, overlap: MergeFunction): Optional<VoucherData> {
return Optional.of(overlap.merge(this, dataHolder.get(VoucherData::class.java).orElse(null)))
}
override fun from(container: DataContainer): Optional<VoucherData> {
this.value = container.getString(VoucherKeys.VOUCHER_COMMAND.query).orElse(null) ?: return Optional.empty<VoucherData>()
return Optional.of(this)
}
override fun getValueGetter(): Value<*> = Sponge.getRegistry().valueFactory.createValue(VoucherKeys.VOUCHER_COMMAND, value)
override fun asImmutable(): Immutable = Immutable(value)
override fun toContainer(): DataContainer = super.toContainer().set(VoucherKeys.VOUCHER_COMMAND, value)
class Immutable(command: String) : AbstractImmutableSingleData<String, Immutable, VoucherData>(command, VoucherKeys.VOUCHER_COMMAND) {
override fun getValueGetter(): ImmutableValue<*> = Sponge.getRegistry().valueFactory.createValue(VoucherKeys.VOUCHER_COMMAND, value).asImmutable()
override fun compareTo(other: Immutable?): Int = 0
override fun getContentVersion(): Int = 1
override fun asMutable(): VoucherData = VoucherData(value)
}
class Builder : AbstractDataBuilder<VoucherData>(VoucherData::class.java, 1), DataManipulatorBuilder<VoucherData, Immutable> {
override fun create(): VoucherData = VoucherData("")
override fun createFrom(dataHolder: DataHolder) = VoucherData("").fill(dataHolder)
override fun buildContent(container: DataView): Optional<VoucherData> {
val data = VoucherData("")
container.getString(VoucherKeys.VOUCHER_COMMAND.query).ifPresent {
data.value = it
}
return Optional.of(data)
}
}
}
Reward class:
package io.github.redrield.spongycrates.data
import ninja.leaping.configurate.objectmapping.Setting
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable
import org.spongepowered.api.item.ItemTypes
import org.spongepowered.api.item.inventory.ItemStack
@ConfigSerializable data class Reward(@Setting("reward") val stack: ItemStack,
@Setting("chance") var percent: Int) {
constructor(): this(ItemStack.of(ItemTypes.APPLE, 1), 0)
}
Where the data is serialized:
package io.github.redrield.spongycrates.commands
import com.google.common.collect.Lists
import com.google.common.reflect.TypeToken
import io.github.redrield.spongycrates.SpongyCrates
import io.github.redrield.spongycrates.data.Reward
import org.spongepowered.api.command.CommandException
import org.spongepowered.api.command.CommandResult
import org.spongepowered.api.command.CommandSource
import org.spongepowered.api.command.args.CommandContext
import org.spongepowered.api.command.spec.CommandExecutor
import org.spongepowered.api.entity.living.player.Player
import org.spongepowered.api.text.Text
import org.spongepowered.api.text.format.TextColors
import java.util.ArrayList
class AddDropCommand(private val plugin: SpongyCrates) : CommandExecutor {
@Throws(CommandException::class)
override fun execute(src: CommandSource, args: CommandContext): CommandResult {
if(src !is Player) {
throw CommandException(Text.of(TextColors.RED, "You must be a player to use this command!"))
}
val name = args.getOne<String>("name").get()
val percent = args.getOne<Int>("percent").get()
if(!src.itemInHand.isPresent) {
throw CommandException(Text.of(TextColors.RED, "You need to be holding an item in your hand to use this command!"))
}
if(plugin.crates.getNode(name).isVirtual) {
throw CommandException(Text.of(TextColors.RED, "The crate you have specified does not exist!"))
}
val reward = Reward(src.itemInHand.get(), percent)
val rewards = Lists.newArrayList(plugin.crates.getNode(name, "drops").getList(TypeToken.of(Reward::class.java)))
rewards.add(reward)
plugin.crates.getNode(name, "drops").setValue(object : TypeToken<ArrayList<Reward>>() {}, rewards)
plugin.cratesLoader.save(plugin.crates)
src.sendMessage(Text.of(TextColors.GREEN, "That drop has been added!"))
return CommandResult.success()
}
}
(Ignore terrible formatting on the first paste)