/* * Copyright 2012 Benjamin Glatzel <benjamin.glatzel@me.com> * * 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.logic.world; import java.util.List; import java.util.Map; import java.util.Queue; import org.terasology.components.HealthComponent; import org.terasology.components.world.BlockComponent; import org.terasology.entitySystem.EntityManager; import org.terasology.entitySystem.EntityRef; import org.terasology.entitySystem.EventHandlerSystem; import org.terasology.entitySystem.ReceiveEvent; import org.terasology.entitySystem.event.AddComponentEvent; import org.terasology.entitySystem.event.RemovedComponentEvent; import org.terasology.events.BlockChangedEvent; import org.terasology.game.CoreRegistry; import org.terasology.math.Vector3i; import org.terasology.teraspout.TeraBlock; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Queues; /** * @author Immortius */ public class EntityAwareWorldProvider extends AbstractWorldProviderDecorator implements BlockEntityRegistry, EventHandlerSystem { private EntityManager entityManager; // TODO: Perhaps a better datastructure for spatial lookups // TODO: Or perhaps a build in indexing system for entities private Map<Vector3i, EntityRef> blockComponentLookup = Maps.newHashMap(); private List<EntityRef> tempBlocks = Lists.newArrayList(); private Thread mainThread; private Queue<BlockChangedEvent> eventQueue = Queues.newConcurrentLinkedQueue(); public EntityAwareWorldProvider(WorldProviderCore base) { super(base); mainThread = Thread.currentThread(); } @Override public void initialise() { this.entityManager = CoreRegistry.get(EntityManager.class); for (EntityRef blockComp : entityManager.iteratorEntities(BlockComponent.class)) { BlockComponent comp = blockComp.getComponent(BlockComponent.class); blockComponentLookup.put(new Vector3i(comp.getPosition()), blockComp); } for (EntityRef entity : entityManager.iteratorEntities(BlockComponent.class)) { BlockComponent blockComp = entity.getComponent(BlockComponent.class); if (blockComp.temporary) { HealthComponent health = entity.getComponent(HealthComponent.class); if (health == null || health.currentHealth == health.maxHealth || health.currentHealth == 0) { entity.destroy(); } } } } @Override public void shutdown() { } @Override public boolean setBlock(int x, int y, int z, TeraBlock type, TeraBlock oldType) { if (super.setBlock(x, y, z, type, oldType)) { if (Thread.currentThread().equals(mainThread)) { getOrCreateEntityAt(new Vector3i(x, y, z)).send(new BlockChangedEvent(new Vector3i(x, y, z), type, oldType)); } else { eventQueue.add(new BlockChangedEvent(new Vector3i(x, y, z), type, oldType)); } return true; } return false; } @Override public EntityRef getEntityAt(Vector3i blockPosition) { EntityRef result = blockComponentLookup.get(blockPosition); return (result == null) ? EntityRef.NULL : result; } @Override public EntityRef getOrCreateEntityAt(Vector3i blockPosition) { EntityRef blockEntity = blockComponentLookup.get(blockPosition); if (blockEntity == null || !blockEntity.exists()) { TeraBlock block = getBlock(blockPosition.x, blockPosition.y, blockPosition.z); if (block.getId() == 0) return EntityRef.NULL; blockEntity = entityManager.create(block.getEntityPrefab()); if (block.isEntityTemporary()) { tempBlocks.add(blockEntity); } blockEntity.addComponent(new BlockComponent(blockPosition, block.isEntityTemporary())); // TODO: Get regen and wait from block config? if (block.isDestructible()) { blockEntity.addComponent(new HealthComponent(block.getHardness(), 2.0f, 1.0f)); } } return blockEntity; } @ReceiveEvent(components = {BlockComponent.class}) public void onCreate(AddComponentEvent event, EntityRef entity) { BlockComponent block = entity.getComponent(BlockComponent.class); blockComponentLookup.put(new Vector3i(block.getPosition()), entity); } @ReceiveEvent(components = {BlockComponent.class}) public void onDestroy(RemovedComponentEvent event, EntityRef entity) { BlockComponent block = entity.getComponent(BlockComponent.class); blockComponentLookup.remove(new Vector3i(block.getPosition())); } }