/* * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion * Copyright (C) 2016-2024 ViaVersion and contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.viaversion.viaversion.api.protocol.remapper; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.type.Type; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.logging.Level; public abstract class PacketHandlers implements PacketHandler { private final List packetHandlers = new ArrayList<>(); protected PacketHandlers() { register(); } static PacketHandler fromRemapper(List valueRemappers) { final PacketHandlers handlers = new PacketHandlers() { @Override public void register() { } }; handlers.packetHandlers.addAll(valueRemappers); return handlers; } /** * Reads and writes the given type. * * @param type type to map */ public void map(Type type) { handler(wrapper -> wrapper.write(type, wrapper.read(type))); } /** * Reads the first given type and writes the second given type. * * @param oldType old type * @param newType new type */ public void map(Type oldType, Type newType) { handler(wrapper -> wrapper.write(newType, wrapper.read(oldType))); } /** * Maps a type from an old type to a transformed new type. * * @param old value type * @param new value type * @param oldType old type * @param newType new type * @param transformer transformer to produce the new type */ public void map(Type oldType, Type newType, Function transformer) { map(oldType, new ValueTransformer(newType) { @Override public T2 transform(PacketWrapper wrapper, T1 inputValue) { return transformer.apply(inputValue); } }); } /** * Maps a type from an old type to a transformed new type based on their input type. * * @param old value type * @param new value type * @param transformer transformer to produce the new type */ public void map(ValueTransformer transformer) { if (transformer.getInputType() == null) { throw new IllegalArgumentException("Use map(Type, ValueTransformer) for value transformers without specified input type!"); } map(transformer.getInputType(), transformer); } /** * Maps a type from an old type to a transformed new type. * * @param old value type * @param new value type * @param oldType old type * @param transformer transformer to produce the new type */ public void map(Type oldType, ValueTransformer transformer) { map(new TypeRemapper<>(oldType), transformer); } /** * Maps a type using a basic ValueReader to a ValueWriter. * * @param inputReader reader to read with * @param outputWriter writer to write with * @param read/write type */ public void map(ValueReader inputReader, ValueWriter outputWriter) { handler(wrapper -> outputWriter.write(wrapper, inputReader.read(wrapper))); } /** * Adds a packet handler. * * @param handler packet handler */ public void handler(PacketHandler handler) { packetHandlers.add(handler); } /** * Adds a packet handler which will suppress any exceptions thrown by the handler. * * @param handler packet handler */ public void handlerSoftFail(PacketHandler handler) { packetHandlers.add(h -> { try { handler.handle(h); } catch (Exception e) { if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) { Via.getPlatform().getLogger().log(Level.WARNING, "Failed to handle packet", e); } h.cancel(); } }); } /** * Writes a value. * * @param type type to write * @param value value to write */ public void create(Type type, T value) { handler(wrapper -> wrapper.write(type, value)); } /** * Reads (and thus removes) the given type. * * @param type type to read */ public void read(Type type) { handler(wrapper -> wrapper.read(type)); } /** * Registers the handlers for this packet. */ protected abstract void register(); @Override public final void handle(PacketWrapper wrapper) throws Exception { for (PacketHandler handler : packetHandlers) { handler.handle(wrapper); } } public int handlersSize() { return packetHandlers.size(); } }