/*
 * Copyright 2017 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;

import org.terasology.entitySystem.entity.EntityManager;
import org.terasology.entitySystem.entity.EntityRef;
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.entitySystem.systems.UpdateSubscriberSystem;
import org.terasology.logic.players.LocalPlayer;
import org.terasology.network.events.DeactivatePingClientEvent;
import org.terasology.network.events.DeactivatePingServerEvent;
import org.terasology.network.events.DisconnectedEvent;
import org.terasology.network.events.PingFromClientEvent;
import org.terasology.network.events.PingFromServerEvent;
import org.terasology.network.events.PingValueEvent;
import org.terasology.registry.In;

import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;

/**
 * This system implement the server ping to clients on need base.
 * It runs on the server, pings to all clients who subscribe this function.
 */
@RegisterSystem (RegisterMode.AUTHORITY)
public class ServerPingSystem extends BaseComponentSystem implements UpdateSubscriberSystem{

    private static final long pingPeriod = 10000;

    @In
    private EntityManager entityManager;

    @In
    private LocalPlayer localPlayer;

    private HashMap<EntityRef, Instant> startMap = new HashMap<>();

    private HashMap<EntityRef, Instant> endMap = new HashMap<>();

    private HashMap<EntityRef, Long> pingMap = new HashMap<>();

    private Instant lastPingTime;

    @Override
    public void initialise() {
        lastPingTime = Instant.now();
    }

    @Override
    public void update(float delta) {
        long time = Duration.between(lastPingTime, Instant.now()).toMillis();
        if (time > pingPeriod) {

            // Server ping to all clients only if there are clients who subscribe
            if (entityManager.getCountOfEntitiesWith(PingSubscriberComponent.class) != 0) {
                Iterable<EntityRef> clients = entityManager.getEntitiesWith(ClientComponent.class);
                for (EntityRef client : clients) {
                    if (client.equals(localPlayer.getClientEntity())) {
                        continue;
                    }
                    Instant start = Instant.now();
                    startMap.put(client, start);
                    client.send(new PingFromServerEvent());
                }
                lastPingTime = Instant.now();
            }
        }
    }

    @ReceiveEvent(components = ClientComponent.class)
    public void onPingFromClient(PingFromClientEvent event, EntityRef entity) {
        Instant end = Instant.now();
        endMap.put(entity, end);
        updatePing(entity);

        for (EntityRef client : entityManager.getEntitiesWith(PingSubscriberComponent.class)) {
            client.send(new PingValueEvent(entity, pingMap.get(entity)));
        }
    }

    private void updatePing(EntityRef entity) {
        if(startMap.containsKey(entity) && endMap.containsKey(entity)) {
            long pingTime = Duration.between(startMap.get(entity), endMap.get(entity)).toMillis();
            pingMap.put(entity, pingTime);
        }
    }

    @ReceiveEvent(components = ClientComponent.class)
    public void onDeactivatePing(DeactivatePingServerEvent event, EntityRef entity) {
        entity.removeComponent(PingSubscriberComponent.class);
        entity.send(new DeactivatePingClientEvent(entity));
        if (entityManager.getCountOfEntitiesWith(PingSubscriberComponent.class) == 0) {
            startMap.clear();
            endMap.clear();
            pingMap.clear();
        }
    }

    @ReceiveEvent(components = ClientComponent.class)
    public void onDisconnected(DisconnectedEvent event, EntityRef entity) {
        if (entity.hasComponent(PingSubscriberComponent.class)) {

            //clean pingMaps in server and pingMaps in client entity
            startMap.remove(entity);
            endMap.remove(entity);
            pingMap.remove(entity);
            for (EntityRef client : entityManager.getEntitiesWith(PingSubscriberComponent.class)) {
                client.send(new DeactivatePingClientEvent(entity));
            }
        }
    }
}

@@ -4027,131 +4027,8 @@
 ) %7B%0A
-        entity.removeComponent(PingSubscriberComponent.class);%0A        entity.send(new DeactivatePingClientEvent(entity));%0A
     

remove two lines not need