Package org.kitteh.tag.api

Source Code of org.kitteh.tag.api.PacketHandlerNetty$DisposalCrew

/*
* Copyright 2012-2014 Matt Baxter
*
* 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.kitteh.tag.api;

import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelOutboundHandlerAdapter;
import net.minecraft.util.io.netty.channel.ChannelPipeline;
import net.minecraft.util.io.netty.channel.ChannelPromise;
import org.bukkit.entity.Player;

import java.lang.reflect.Field;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public abstract class PacketHandlerNetty extends PacketHandlerBase {

    private class DisposalCrew extends Thread {
        private int count = 0;
        private boolean finished = false;
        private final Queue<ChannelPipeline> junkHeap = new ConcurrentLinkedQueue<ChannelPipeline>();

        @Override
        public void run() {
            while (!this.finished || !this.junkHeap.isEmpty()) {
                long destination = System.currentTimeMillis() + 3333; // THREE
                while (this.junkHeap.isEmpty()) {
                    if (System.currentTimeMillis() > destination) {
                        System.out.println("TagAPI just failed miserably to clean up.. Report this to mbaxter: [Remaining: " + this.junkHeap.size() + "+, Total:" + this.count + "]");
                        return;
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
                clean();
            }
        }

        private void clean() {
            ChannelPipeline trash;
            while ((trash = this.junkHeap.poll()) != null) {
                trash.remove(TagAPIChannelOutboundHandler.class);
            }
        }

        private void dispose(ChannelPipeline pipeline) {
            this.junkHeap.add(pipeline);
            this.count++;
        }

        private void finished() {
            this.finished = true;
        }
    }

    /**
     * Must be public to remove from netty pipeline
     */
    public class TagAPIChannelOutboundHandler extends ChannelOutboundHandlerAdapter {

        private final Player player;

        private TagAPIChannelOutboundHandler(Player player) {
            this.player = player;
        }

        @Override
        public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
            try {
                PacketHandlerNetty.this.handlePacket(packet, this.player);
            } catch (final Exception e) {
                // TODO: Panic
            }
            super.write(ctx, packet, promise);
        }

    }

    private DisposalCrew disposalCrew;

    public PacketHandlerNetty(TagHandler handler) throws PacketHandlerException {
        super(handler);
        Field field = this.getChannelField();
        if (!Channel.class.isAssignableFrom(field.getType())) {
            throw new PacketHandlerException(field.getDeclaringClass().getSimpleName() + "'s " + field.getName() + " field is not of type Channel");
        }
    }

    private void dispose(ChannelPipeline pipeline) {
        if (this.disposalCrew == null) {
            this.disposalCrew = new DisposalCrew();
            this.disposalCrew.start();
        }
        this.disposalCrew.dispose(pipeline);
    }

    protected ChannelPipeline getPipeline(Player player) {
        Channel channel;
        try {
            channel = (Channel) this.getChannelField().get(this.getNetworkManager(player));
        } catch (final Exception e) {
            e.printStackTrace();
            return null;
        }
        return channel.pipeline();
    }

    @Override
    protected void hookPlayer(Player player) {
        final ChannelPipeline pipeline = this.getPipeline(player);
        if (pipeline != null) {
            pipeline.addLast(new TagAPIChannelOutboundHandler(player));
        }
    }

    @Override
    protected void releasePlayer(Player player) {
        final ChannelPipeline pipeline = this.getPipeline(player);
        if ((pipeline != null) && (pipeline.get(TagAPIChannelOutboundHandler.class) != null)) {
            this.dispose(pipeline);
        }
    }

    @Override
    public void shutdown() {
        super.shutdown();
        if (this.disposalCrew != null) {
            this.disposalCrew.finished();
        }
    }

    protected abstract Field getChannelField();

    protected abstract Object getNetworkManager(Player player);

    protected abstract void handlePacket(Object packet, Player destination) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException;

}
TOP

Related Classes of org.kitteh.tag.api.PacketHandlerNetty$DisposalCrew

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.