/* * Copyright 2015 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.nameTags; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.entity.lifecycleEvents.OnActivatedComponent; import org.terasology.entitySystem.entity.lifecycleEvents.OnChangedComponent; import org.terasology.entitySystem.event.ReceiveEvent; import org.terasology.entitySystem.systems.BaseComponentSystem; import org.terasology.entitySystem.systems.RegisterMode; import org.terasology.entitySystem.systems.RegisterSystem; import org.terasology.logic.characters.CharacterComponent; import org.terasology.logic.common.DisplayNameComponent; import org.terasology.network.ClientComponent; import org.terasology.network.ClientInfoComponent; import org.terasology.network.ColorComponent; import org.terasology.network.NetworkSystem; import org.terasology.registry.In; import org.terasology.rendering.nui.Color; /** * Creates name tags for characters controlled by players based on their name. * * Once there is the intention to implement multiple different name tag generation rules for players feel free to move * this system into a module so that it isn't always enabled. */ @RegisterSystem(RegisterMode.CLIENT) public class PlayerNameTagSystem extends BaseComponentSystem { private static final Logger logger = LoggerFactory.getLogger(NameTagClientSystem.class); @In private NetworkSystem networkSystem; /** * Listening for {@link org.terasology.logic.players.event.OnPlayerSpawnedEvent} does not work, as it is an * authority event that does not get processed at clients. That is why we listen for the activation. */ @ReceiveEvent(components = CharacterComponent.class) public void onCharacterActivation(OnActivatedComponent event, EntityRef characterEntity, CharacterComponent characterComponent) { EntityRef ownerEntity = networkSystem.getOwnerEntity(characterEntity); if (ownerEntity == null) { return; // NPC } ClientComponent clientComponent = ownerEntity.getComponent(ClientComponent.class); if (clientComponent == null) { logger.warn("Can't create player based name tag for character as owner has no client component"); return; } if (clientComponent.local) { return; // the character belongs to the local player and does not need a name tag } EntityRef clientInfoEntity = clientComponent.clientInfo; DisplayNameComponent displayNameComponent = clientInfoEntity.getComponent(DisplayNameComponent.class); if (displayNameComponent == null) { logger.error("Can't create player based name tag for character as client info has no DisplayNameComponent"); return; } String name = displayNameComponent.name; float yOffset = characterComponent.nameTagOffset; Color color = Color.WHITE; ColorComponent colorComponent = clientInfoEntity.getComponent(ColorComponent.class); if (colorComponent != null) { color = colorComponent.color; } NameTagComponent nameTagComponent = characterEntity.getComponent(NameTagComponent.class); boolean newComponent = nameTagComponent == null; if (nameTagComponent == null) { nameTagComponent = new NameTagComponent(); } nameTagComponent.text = name; nameTagComponent.textColor = color; nameTagComponent.yOffset = yOffset; if (newComponent) { characterEntity.addComponent(nameTagComponent); } else { characterEntity.saveComponent(nameTagComponent); } } /** * The player entity may currently become "local" afterh the player has been activated. * * To address this issue the name tag component will be removed again when a client turns out to be local * afterwards. */ @ReceiveEvent public void onClientComponentChange(OnChangedComponent event, EntityRef clientEntity, ClientComponent clientComponent) { if (clientComponent.local) { EntityRef character = clientComponent.character; if (character.exists() && character.hasComponent(NameTagComponent.class)) { character.removeComponent(NameTagComponent.class); } } } @ReceiveEvent public void onDisplayNameChange(OnChangedComponent event, EntityRef clientInfoEntity, DisplayNameComponent displayNameComponent) { ClientInfoComponent clientInfoComp = clientInfoEntity.getComponent(ClientInfoComponent.class); if (clientInfoComp == null) { return; // not a client info object } EntityRef clientEntity = clientInfoComp.client; if (!clientEntity.exists()) { return; // offline players aren't visible: nothing to do } ClientComponent clientComponent = clientEntity.getComponent(ClientComponent.class); if (clientComponent == null) { logger.warn("Can't update name tag as client entity lacks ClietnComponent"); return; } EntityRef characterEntity = clientComponent.character; if (characterEntity == null || !characterEntity.exists()) { return; // player has no character, nothing to do } NameTagComponent nameTagComponent = characterEntity.getComponent(NameTagComponent.class); if (nameTagComponent == null) { return; // local players don't have a name tag } nameTagComponent.text = displayNameComponent.name; characterEntity.saveComponent(nameTagComponent); } }