/* * Copyright 2014 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.world.block.structure; import com.google.common.collect.Sets; import org.terasology.entitySystem.entity.EntityManager; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.event.ReceiveEvent; import org.terasology.entitySystem.prefab.PrefabManager; import org.terasology.entitySystem.systems.BaseComponentSystem; import org.terasology.entitySystem.systems.RegisterSystem; import org.terasology.logic.health.DestroyEvent; import org.terasology.math.Side; import org.terasology.math.geom.Vector3i; import org.terasology.monitoring.PerformanceMonitor; import org.terasology.registry.In; import org.terasology.registry.Share; import org.terasology.world.BlockEntityRegistry; import org.terasology.world.OnChangedBlock; import org.terasology.world.WorldProvider; import org.terasology.world.block.Block; import org.terasology.world.block.BlockComponent; import org.terasology.world.block.entity.placement.PlaceBlocks; import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Set; /** */ @RegisterSystem @Share(BlockStructuralSupportRegistry.class) public class BlockStructuralSupportSystem extends BaseComponentSystem implements BlockStructuralSupportRegistry { @In private WorldProvider worldProvider; @In private BlockEntityRegistry blockEntityRegistry; @In private EntityManager entityManager; @In private PrefabManager prefabManager; private boolean midDestruction; private EntityRef gatheringEntity; private Set<BlockStructuralSupport> supports = Sets.newTreeSet( new Comparator<BlockStructuralSupport>() { @Override public int compare(BlockStructuralSupport o1, BlockStructuralSupport o2) { return o1.getPriority() - o2.getPriority(); } }); @Override public void preBegin() { registerBlockStructuralSupport(new AttachSupportRequired()); registerBlockStructuralSupport(new BlockDefSupportRequired()); registerBlockStructuralSupport(new SideBlockSupportRequired()); } @Override public void registerBlockStructuralSupport(BlockStructuralSupport blockStructuralSupport) { supports.add(blockStructuralSupport); } @ReceiveEvent(components = {BlockComponent.class}) public void checkForSupportRemoved(OnChangedBlock event, EntityRef entity) { PerformanceMonitor.startActivity("StructuralCheck"); try { for (Side side : Side.values()) { validateSupportForBlockOnSide(event.getBlockPosition(), side); } } finally { PerformanceMonitor.endActivity(); } } @ReceiveEvent public void preventInvalidPlacement(PlaceBlocks placeBlocks, EntityRef world) { final Map<Vector3i, Block> blocksMap = placeBlocks.getBlocks(); for (BlockStructuralSupport support : supports) { for (Map.Entry<Vector3i, Block> blockEntry : blocksMap.entrySet()) { final Vector3i position = blockEntry.getKey(); if (!support.isSufficientlySupported(position, Collections.unmodifiableMap(blocksMap))) { placeBlocks.consume(); return; } } } } private void validateSupportForBlockOnSide(Vector3i replacedBlockPosition, Side side) { final Vector3i blockPosition = side.getAdjacentPos(replacedBlockPosition); if (worldProvider.isBlockRelevant(blockPosition)) { final Side sideReverse = side.reverse(); for (BlockStructuralSupport support : supports) { if (support.shouldBeRemovedDueToChange(blockPosition, sideReverse)) { blockEntityRegistry.getBlockEntityAt(blockPosition).send(new DestroyEvent(gatheringEntity, EntityRef.NULL, prefabManager.getPrefab("engine:supportRemovedDamage"))); break; } } } } }