/* * Copyright 2016 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.logic.health; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import org.terasology.utilities.Assets; import org.terasology.entitySystem.entity.EntityManager; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.systems.BaseComponentSystem; import org.terasology.entitySystem.systems.RegisterMode; import org.terasology.entitySystem.systems.RegisterSystem; import org.terasology.entitySystem.systems.RenderSystem; import org.terasology.math.geom.Vector3i; import org.terasology.registry.In; import org.terasology.rendering.assets.texture.Texture; import org.terasology.rendering.assets.texture.TextureRegionAsset; import org.terasology.rendering.world.selection.BlockSelectionRenderer; import org.terasology.world.block.BlockComponent; import org.terasology.world.block.regions.BlockRegionComponent; import java.util.Optional; /** * This system renders damage damaged blocks using the BlockSelectionRenderer. */ @RegisterSystem(RegisterMode.CLIENT) public class BlockDamageRenderer extends BaseComponentSystem implements RenderSystem { BlockSelectionRenderer blockSelectionRenderer; @In private EntityManager entityManager; @Override public void renderOverlay() { if (blockSelectionRenderer == null) { Texture texture = Assets.getTextureRegion("core:blockdamageeffects#1").get().getTexture(); blockSelectionRenderer = new BlockSelectionRenderer(texture); } // group the entities into what texture they will use so that there is less recreating meshes (changing a texture region on the BlockSelectionRenderer // will recreate the mesh to use the different UV coordinates). Also this allows Multimap<Integer, Vector3i> groupedEntitiesByEffect = ArrayListMultimap.create(); for (EntityRef entity : entityManager.getEntitiesWith(HealthComponent.class, BlockComponent.class)) { HealthComponent health = entity.getComponent(HealthComponent.class); if (health.currentHealth == health.maxHealth) { continue; } BlockComponent blockComponent = entity.getComponent(BlockComponent.class); groupedEntitiesByEffect.put(getEffectsNumber(health), blockComponent.getPosition()); } for (EntityRef entity : entityManager.getEntitiesWith(BlockRegionComponent.class, HealthComponent.class)) { HealthComponent health = entity.getComponent(HealthComponent.class); if (health.currentHealth == health.maxHealth) { continue; } BlockRegionComponent blockRegion = entity.getComponent(BlockRegionComponent.class); for (Vector3i blockPos : blockRegion.region) { groupedEntitiesByEffect.put(getEffectsNumber(health), blockPos); } } // we know that the texture will be the same for each block effect, just differnt UV coordinates. Bind the texture already blockSelectionRenderer.beginRenderOverlay(); for (Integer effectsNumber : groupedEntitiesByEffect.keySet()) { Optional<TextureRegionAsset> texture = Assets.getTextureRegion("core:blockdamageeffects#" + effectsNumber); if (texture.isPresent()) { blockSelectionRenderer.setEffectsTexture(texture.get()); for (Vector3i position : groupedEntitiesByEffect.get(effectsNumber)) { blockSelectionRenderer.renderMark(position); } } } blockSelectionRenderer.endRenderOverlay(); } private Integer getEffectsNumber(HealthComponent health) { return java.lang.Math.round((1f - (float) health.currentHealth / health.maxHealth) * 10.0f); } @Override public void renderFirstPerson() { } @Override public void renderShadows() { } @Override public void renderOpaque() { } @Override public void renderAlphaBlend() { } }