/*
* 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.network.serialization;
import com.google.common.collect.Lists;
import gnu.trove.list.TIntList;
import org.terasology.entitySystem.entity.EntityRef;
import org.terasology.math.geom.Vector3i;
import org.terasology.network.NetworkComponent;
import org.terasology.network.internal.NetworkSystemImpl;
import org.terasology.persistence.typeHandling.DeserializationContext;
import org.terasology.persistence.typeHandling.PersistedData;
import org.terasology.persistence.typeHandling.PersistedDataArray;
import org.terasology.persistence.typeHandling.SerializationContext;
import org.terasology.persistence.typeHandling.TypeHandler;
import org.terasology.world.BlockEntityRegistry;
import org.terasology.world.block.BlockComponent;
import java.util.Collection;
import java.util.List;
/**
* This type handler encodes EntityRef for network transferals. For normal entities, the Network Id of the entity is used.
* For block entities the block position is used instead (this allows overriding simulated block entities).
*
*/
public class NetEntityRefTypeHandler implements TypeHandler<EntityRef> {
private NetworkSystemImpl networkSystem;
private BlockEntityRegistry blockEntityRegistry;
public NetEntityRefTypeHandler(NetworkSystemImpl networkSystem, BlockEntityRegistry blockEntityRegistry) {
this.networkSystem = networkSystem;
this.blockEntityRegistry = blockEntityRegistry;
}
@Override
public PersistedData serialize(EntityRef value, SerializationContext context) {
BlockComponent blockComponent = value.getComponent(BlockComponent.class);
if (blockComponent != null) {
Vector3i pos = blockComponent.getPosition();
return context.create(pos.x, pos.y, pos.z);
}
NetworkComponent netComponent = value.getComponent(NetworkComponent.class);
if (netComponent != null) {
return context.create(netComponent.getNetworkId());
}
return context.createNull();
}
@Override
public EntityRef deserialize(PersistedData data, DeserializationContext context) {
if (data.isArray()) {
PersistedDataArray array = data.getAsArray();
if (array.isNumberArray() && array.size() == 3) {
TIntList items = data.getAsArray().getAsIntegerArray();
Vector3i pos = new Vector3i(items.get(0), items.get(1), items.get(2));
return blockEntityRegistry.getBlockEntityAt(pos);
}
}
if (data.isNumber()) {
return networkSystem.getEntity(data.getAsInteger());
}
return EntityRef.NULL;
}
@Override
public PersistedData serializeCollection(Collection<EntityRef> value, SerializationContext context) {
List<PersistedData> items = Lists.newArrayList();
for (EntityRef ref : value) {
BlockComponent blockComponent = ref.getComponent(BlockComponent.class);
if (blockComponent != null) {
Vector3i blockPos = blockComponent.getPosition();
items.add(context.create(blockPos.x, blockPos.y, blockPos.z));
} else {
NetworkComponent netComponent = ref.getComponent(NetworkComponent.class);
if (netComponent != null) {
items.add(context.create(netComponent.getNetworkId()));
} else {
items.add(context.createNull());
}
}
}
return context.create(items);
}
@Override
public List<EntityRef> deserializeCollection(PersistedData data, DeserializationContext context) {
List<EntityRef> result = Lists.newArrayListWithCapacity(data.getAsArray().size());
for (PersistedData item : data.getAsArray()) {
result.add(deserialize(item, context));
}
return result;
}
}