package openmods.sync.drops; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Maps; import java.lang.reflect.Field; import java.util.Map; import javax.annotation.Nonnull; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import openmods.reflection.FieldAccess; import openmods.sync.ISyncableObject; import openmods.utils.ItemUtils; public class DropTagSerializer { private final Map<String, ISyncableObject> objects = Maps.newHashMap(); public void addObject(String name, ISyncableObject object) { ISyncableObject prev = objects.put(name, object); Preconditions.checkState(prev == null, "Duplicate on name %s, values = '%s' -> '%s'", name, prev, object); } public void addFields(Object target) { Class<?> cls = target.getClass(); while (cls != Object.class) { for (Field field : cls.getDeclaredFields()) { StoreOnDrop marker = field.getAnnotation(StoreOnDrop.class); if (marker == null) continue; Preconditions.checkArgument(ISyncableObject.class.isAssignableFrom(field.getType()), "Field '%s' has SyncableDrop annotation, but isn't ISyncableObject", field); final FieldAccess<ISyncableObject> wrappedField = FieldAccess.create(field); final ISyncableObject obj = wrappedField.get(target); Preconditions.checkNotNull(obj, "Field '%s' contains null", field); final String suggestedName = field.getName(); final String name = Strings.isNullOrEmpty(marker.name())? suggestedName : marker.name(); addObject(name, obj); } cls = cls.getSuperclass(); } } public void write(NBTTagCompound tag) { for (Map.Entry<String, ISyncableObject> e : objects.entrySet()) e.getValue().writeToNBT(tag, e.getKey()); } public void read(NBTTagCompound tag, boolean skipEmpty) { for (Map.Entry<String, ISyncableObject> e : objects.entrySet()) { final String key = e.getKey(); if (!skipEmpty || tag.hasKey(key)) e.getValue().readFromNBT(tag, key); } } @Nonnull public ItemStack write(ItemStack stack) { NBTTagCompound tag = ItemUtils.getItemTag(stack); write(tag); return stack; } @Nonnull public void read(ItemStack stack, boolean skipEmpty) { NBTTagCompound tag = ItemUtils.getItemTag(stack); read(tag, skipEmpty); } }