Last active
September 3, 2016 15:41
-
-
Save copygirl/53f94373c0f6901a87b9dad0b934423c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** Represents arbitrary data that can be added to any object that implements IComponentsProvider. | |
| * For example: Block, Item, Entity, ItemStack, Enchantment, Biome, ... | |
| * | |
| * Components are required to have an empty public constructor so they can be loaded / saved and | |
| * getOrCreate can be used. */ | |
| public interface IComponent { | |
| /** Serializes (saves) this component as an NBT tag. | |
| * If null is returned, the component won't be saved. */ | |
| Tag serialize() { return null; } | |
| /** Deserializes (loads) this component from an NBT tag. | |
| * If false is returned, the component will be dropped. */ | |
| boolean deserialize(Tag tag) { return false; } | |
| } | |
| /** Holds the components for an IComponentsProvider. */ | |
| public class ComponentContainer implements Iterable<IComponent> { | |
| public static final String TAG_NAME = "fabric:components"; | |
| private final IComponentsProvider owner; | |
| private final Map<Class<? extends IComponent>, IComponent> map; | |
| public ComponentContainer(IComponentsProvider owner) { | |
| this.owner = owner; | |
| this.map = new HashMap<>(); | |
| } | |
| /** Gets a component of type T or null if it's not present. */ | |
| public <T extends IComponent> T get(Class<T> componentClass) { | |
| return map.get(componentClass); | |
| } | |
| /** Sets a component of type T, returning the previous value, null if none. */ | |
| public <T extends IComponent> T set(Class<T> componentClass, @Nullable T component) { | |
| IComponent previous = ((component != null) | |
| ? map.put(componentClass, component) | |
| : map.remove(componentClass)); | |
| if (previous != null) owner.onComponentRemoved(previous); | |
| if (component != null) owner.onComponentAdded(component); | |
| return previous; | |
| } | |
| /** Adds a component of type T, returning the previous value, null if none. */ | |
| public <T extends IComponent> T add(T component) { | |
| return set((Class<T>)component.getClass(), component); | |
| } | |
| /** Removes a component of type T, returning the previous value, null if none. */ | |
| public <T extends IComponent> T remove(Class<T> componentClass) { | |
| return set(componentClass, null); | |
| } | |
| /** Gets a component of type T or creates one if it's not present. */ | |
| public <T extends IComponent> T getOrCreate(Class<T> componentClass) { | |
| T component = get<T>(componentClass); | |
| if (component == null) | |
| component = componentClass.newInstance(); // TODO: Wrap with try/catch. | |
| return component; | |
| } | |
| public void serializeTag(TagCompound root) { | |
| TagCompound compound = new TagCompound(); | |
| for (Map.Entry<Class, IComponent> entry : map.entrySet()) { | |
| String className = entry.getKey().getClass().getName(); | |
| IComponent component = entry.getValue(); | |
| try { | |
| Tag componentTag = component.serialize(); | |
| if (componentTag == null) continue; | |
| compound.setTag(className, componentTag); | |
| } catch (Exception ex) { | |
| // TODO: Failed to save component. | |
| } | |
| } | |
| if (!compound.isEmpty) | |
| root.setTag(TAG_NAME, compound); | |
| } | |
| public void deserializeTag(TagCompound root) { | |
| Tag tag = root.getTag(TAG_NAME); | |
| if ((tag == null) || (tag.getType() != 10)) return; | |
| TagCompound compound = (TagCompound)tag; | |
| for (String className : compound.getKeys()) { | |
| Tag componentTag = component.getTag(className); | |
| try { | |
| Class componentClass = Class.forName(className); | |
| IComponent component = (IComponent)componentClass.newInstance(); | |
| if (!component.deserialize(componentTag)) continue; | |
| components.put(className, component); | |
| } catch (Exception ex) { | |
| // TODO: Failed to load component. | |
| } | |
| } | |
| } | |
| public Iterator<IComponent> iterator() { | |
| return map.valueSet().iterator(); | |
| } | |
| } | |
| public interface IComponentsProvider { | |
| /** Gets this IComponentsProvider's components. */ | |
| ComponentContainer components(); | |
| /** Called when a component is added to this IComponentsProvider. */ | |
| void onComponentAdded(IComponent component); | |
| /** Called when a component is removed from this IComponentsProvider. */ | |
| void onComponentRemoved(IComponent component); | |
| } | |
| public class ComponentsProviderMixin implements IComponentsProvider { | |
| private final ComponentContainer components; | |
| public ComponentsProviderMixin() { components = new ComponentContainer(this); } | |
| public ComponentContainer components() { return components; } | |
| public void onComponentAdded(IComponent component) { } | |
| public void onComponentRemoved(IComponent component) { } | |
| } | |
| /* ======================= * | |
| * [[ Example Component ]] * | |
| * ======================= */ | |
| public class BackpackComponent implements IComponent { | |
| private ItemStack backpack; | |
| public Tag serialize() { | |
| TagCompound compound = new TagCompound(); | |
| compound.setTag("backpack", backpack.serialize(new TagCompound())); | |
| return compound; | |
| } | |
| public boolean deserialize(Tag tag) { | |
| TagCompound compound = (TagCompound)tag; | |
| backpack = new ItemStack(compound.getTag("backpack")); | |
| return true; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment