/* * Copyright (c) 2015 NOVA, All rights reserved. * This library is free software, licensed under GNU Lesser General Public License version 3 * * This file is part of NOVA. * * NOVA is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NOVA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NOVA. If not, see <http://www.gnu.org/licenses/>. */package nova.core.network; import nova.core.entity.component.Player; import nova.core.network.NetworkTarget.Side; import nova.core.network.handler.BlockPacket; import nova.core.network.handler.EntityPacket; import nova.core.network.handler.PacketHandler; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * A central network manager. * * @author Calclavia */ public abstract class NetworkManager { private final List<PacketHandler<?>> handlers = new ArrayList<>(); public NetworkManager() { register(new BlockPacket()); register(new EntityPacket()); } /** * Register a packet type. A packet type handles * a specific packet handler type. * * @param type An ID is assigned to the packet handler */ public int register(PacketHandler<?> type) { handlers.add(type); return handlers.size() - 1; } /** * @return A new empty packet */ public abstract Packet newPacket(); public PacketHandler<?> getPacketType(int id) { return handlers.get(id); } public int getPacketTypeID(PacketHandler<?> type) { return handlers.indexOf(type); } /** * Gets the packet type that handles a PacketHandler * * @param handler The packet handler * @return The packet type for the packet handler */ public PacketHandler<?> getPacketType(Object handler) { Optional<PacketHandler<?>> first = handlers .stream() .filter(type -> type.isHandlerFor(handler)) .findFirst(); if (first.isPresent()) { return first.get(); } else { throw new NetworkException("Invalid packet sender: " + handler); } } /** * Sends a packet based on a sender. * * @param sender The packet handler sending the packet * @param packet The packet to send */ public void sendPacket(Object sender, Packet packet) { writePacket(sender, packet); sendPacket(packet); } /** * Sends a new custom packet without any overhead. * This method directly sends the packet. It will not write the PacketType ID, which will cause an error unless the ID is written to the packet already. * * @param packet The packet to send */ public abstract void sendPacket(Packet packet); public Packet writePacket(Object sender, Packet packet) { int packetTypeID = getPacketTypeID(getPacketType(sender)); packet.writeInt(packetTypeID); packet.writeInt(packet.getID()); ((PacketHandler) getPacketType(sender)).write(sender, packet); return packet; } /** * Syncs a PacketHandler between server and client. * * @param sender {@link Syncable} */ public final void sync(Object sender) { sync(0, sender); } /** * Syncs a PacketHandler between server and client, with a specific packet ID * * @param id The packet ID * @param sender sender {@link Syncable} */ public void sync(int id, Object sender) { Packet packet = newPacket(); packet.setID(id); sendPacket(sender, packet); } public abstract void sendChat(Player player, String message); /** * Use {@link Side#get()} instead. * * @return active side */ public final Side getSide() { return isClient() ? Side.CLIENT : Side.SERVER; } /** * Use {@link Side#get()}{@link Side#isClient() .isClient()} instead. * * @return true if the active side is {@link Side#CLIENT} */ public final boolean isClient() { return !isServer(); } /** * Use {@link Side#get()}{@link Side#isServer() .isServer()} instead. * * @return true if the active side is {@link Side#SERVER} */ public abstract boolean isServer(); }