Package org.terasology.persistence.serializers

Source Code of org.terasology.persistence.serializers.PrefabSerializer

/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.terasology.persistence.serializers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.asset.AssetType;
import org.terasology.asset.Assets;
import org.terasology.entitySystem.Component;
import org.terasology.entitySystem.metadata.ComponentLibrary;
import org.terasology.entitySystem.metadata.ComponentMetadata;
import org.terasology.entitySystem.prefab.Prefab;
import org.terasology.entitySystem.prefab.PrefabData;
import org.terasology.module.Module;
import org.terasology.persistence.ModuleContext;
import org.terasology.persistence.typeHandling.TypeSerializationLibrary;
import org.terasology.protobuf.EntityData;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* Provides the ability to serialize and deserialize prefabs to the EntityData.Prefab proto buffer format.
* <p/>
* As with the component serializer, a component id mapping can be provided to have components serialized against
* ids rather than name strings.
* <p/>
* It is also possible to set whether entity ids will be handled or ignored - if ignored then deserialized entities will
* be given new ids.
*
* @author Immortius
*/
public class PrefabSerializer {
    private static final Logger logger = LoggerFactory.getLogger(PrefabSerializer.class);

    private ComponentSerializer componentSerializer;
    private ComponentLibrary componentLibrary;

    public PrefabSerializer(ComponentLibrary componentLibrary, TypeSerializationLibrary typeSerializationLibrary) {
        this.componentLibrary = componentLibrary;
        this.componentSerializer = new ComponentSerializer(componentLibrary, typeSerializationLibrary);
    }

    /**
     * Sets the mapping between component classes and the ids that are used for serialization
     *
     * @param table
     */
    public void setComponentIdMapping(Map<Class<? extends Component>, Integer> table) {
        componentSerializer.setIdMapping(table);
    }

    /**
     * Clears the mapping between component classes and ids. This causes components to be serialized with their component
     * class name instead.
     */
    public void removeComponentIdMapping() {
        componentSerializer.removeIdMapping();
    }

    /**
     * @param prefab
     * @return The serialized prefab
     */
    public EntityData.Prefab serialize(Prefab prefab) {
        EntityData.Prefab.Builder prefabData = EntityData.Prefab.newBuilder();
        prefabData.setName(prefab.getName());
        if (prefab.getParent() != null) {
            prefabData.setParentName(prefab.getParent().getName());
        }
        prefabData.setAlwaysRelevant(prefab.isAlwaysRelevant());
        prefabData.setPersisted(prefab.isPersisted());

        // Delta off the parent
        for (Component component : prefab.iterateComponents()) {
            if (prefab.getParent() != null && prefab.getParent().hasComponent(component.getClass())) {
                EntityData.Component serializedComponent = componentSerializer.serialize(prefab.getParent().getComponent(component.getClass()), component);
                if (serializedComponent != null) {
                    prefabData.addComponent(serializedComponent);
                }
            } else {
                prefabData.addComponent(componentSerializer.serialize(component));
            }
        }
        if (prefab.getParent() != null) {
            for (Component parentComp : prefab.getParent().iterateComponents()) {
                if (!prefab.hasComponent(parentComp.getClass())) {
                    prefabData.addRemovedComponent(componentLibrary.getMetadata(parentComp).getUri().toString());
                }
            }
        }
        return prefabData.build();
    }

    /**
     * Deserializes a prefab
     *
     * @param prefabData
     * @return The deserialized prefab
     */
    public PrefabData deserialize(EntityData.Prefab prefabData) {
        return deserialize(prefabData, Collections.<EntityData.Prefab>emptyList());
    }

    /**
     * Deserializes a prefab
     *
     * @param prefabData
     * @param
     * @return The deserialized prefab
     */
    public PrefabData deserialize(EntityData.Prefab prefabData, List<EntityData.Prefab> deltas) {
        Module context = ModuleContext.getContext();
        PrefabData result = new PrefabData();
        deserializeCommonData(prefabData, result);
        for (EntityData.Prefab delta : deltas) {
            applyCommonDataDelta(delta, result);
        }

        addInheritedComponents(result);

        applyComponentChanges(context, prefabData, result);
        for (EntityData.Prefab delta : deltas) {
            applyComponentChanges(context, delta, result);
        }

        return result;
    }

    private void applyComponentChanges(Module context, EntityData.Prefab prefabData, PrefabData result) {
        for (String removedComponent : prefabData.getRemovedComponentList()) {
            ComponentMetadata<?> metadata = componentLibrary.resolve(removedComponent, context);
            if (metadata != null) {
                result.removeComponent(metadata.getType());
            }
        }
        for (EntityData.Component componentData : prefabData.getComponentList()) {
            ComponentMetadata<?> metadata = componentLibrary.resolve(componentData.getType(), context);
            if (metadata != null) {
                Component existing = result.getComponent(metadata.getType());
                if (existing != null) {
                    componentSerializer.deserializeOnto(existing, componentData, context);
                } else {
                    Component newComponent = componentSerializer.deserialize(componentData, context);
                    if (newComponent != null) {
                        result.addComponent(newComponent);
                    }
                }
            } else if (componentData.hasType()) {
                logger.error("Prefab contains unknown component '{}'", componentData.getType());
            }
        }
    }

    private void addInheritedComponents(PrefabData result) {
        if (result.getParent() != null) {
            for (Component comp : result.getParent().iterateComponents()) {
                result.addComponent(componentLibrary.copy(comp));
            }
        }
    }

    private void applyCommonDataDelta(EntityData.Prefab delta, PrefabData result) {
        if (delta.hasPersisted()) {
            result.setPersisted(delta.getPersisted());
        }
        if (delta.hasAlwaysRelevant()) {
            result.setAlwaysRelevant(delta.getAlwaysRelevant());
        }
        if (delta.hasParentName()) {
            Prefab parent = Assets.get(AssetType.PREFAB, delta.getParentName(), Prefab.class);
            result.setParent(parent);
        }
    }

    private void deserializeCommonData(EntityData.Prefab prefabData, PrefabData result) {
        result.setPersisted((prefabData.hasPersisted()) ? prefabData.getPersisted() : true);
        result.setAlwaysRelevant(prefabData.hasAlwaysRelevant() ? prefabData.getAlwaysRelevant() : false);
        if (prefabData.hasParentName()) {
            Prefab parent = Assets.get(AssetType.PREFAB, prefabData.getParentName(), Prefab.class);
            result.setParent(parent);
        }
    }
}
TOP

Related Classes of org.terasology.persistence.serializers.PrefabSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.