/* This file is a part of the SteamWar software. Copyright (C) 2021 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.steamwar.fightsystem.utils; import com.comphenix.tinyprotocol.Reflection; import com.mojang.datafixers.util.Pair; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.record.REntity; import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak; import net.minecraft.world.entity.EntityTypes; import net.minecraft.world.level.block.entity.TileEntityTypes; import net.minecraft.world.level.block.state.IBlockData; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; import java.util.function.BiFunction; import java.util.function.UnaryOperator; public class ProtocolWrapper18 implements ProtocolWrapper { private static final Reflection.FieldAccessor equipmentStack = Reflection.getField(REntity.equipmentPacket, List.class, 0); @Override public void setEquipmentPacketStack(Object packet, String slot, Object stack) { equipmentStack.set(packet, Collections.singletonList(new Pair<>(getSlot(slot), stack))); } private static final Reflection.FieldAccessor spawnType = Reflection.getField(REntity.spawnPacket, EntityTypes.class, 0); @Override public void setSpawnPacketType(Object packet, EntityType type) { switch(type) { case PRIMED_TNT: spawnType.set(packet, EntityTypes.as); break; case ARROW: spawnType.set(packet, EntityTypes.d); break; case FIREBALL: spawnType.set(packet, EntityTypes.S); break; } } private static final Class enumItemSlot = Reflection.getClass("{nms.world.entity}.EnumItemSlot"); private static final Object[] itemSlots = enumItemSlot.getEnumConstants(); private static Object getSlot(String slot) { switch(slot){ case "HEAD": return itemSlots[5]; case "CHEST": return itemSlots[4]; case "LEGS": return itemSlots[3]; case "FEET": return itemSlots[2]; case "OFFHAND": return itemSlots[1]; case "MAINHAND": default: return itemSlots[0]; } } private static final Class sectionPosition = Reflection.getClass("{nms.core}.SectionPosition"); private static final Reflection.FieldAccessor multiBlockChangeChunk = Reflection.getField(TechHider.multiBlockChangePacket, sectionPosition, 0); private static final Class iBlockDataArray = Reflection.getClass("[L{nms.world.level.block.state}.IBlockData;"); private static final Reflection.FieldAccessor multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, iBlockDataArray, 0); private static final BiFunction, Object> iBlockDataArrayCloner = ProtocolAPI.arrayCloneGenerator(TechHider.iBlockData); @Override public Object multiBlockChangeHider(Player p, Object packet) { Object chunkCoords = multiBlockChangeChunk.get(packet); if(TechHider.bypass(p, TechHider.blockPositionX.get(chunkCoords), TechHider.blockPositionZ.get(chunkCoords))) return packet; Object modpacket = TechHider.multiBlockChangeCloner.apply(packet); multiBlockChangeBlocks.set(modpacket, iBlockDataArrayCloner.apply(multiBlockChangeBlocks.get(modpacket), block -> Config.HiddenBlocks.contains(TechHider.getMaterialByIBlockData(block).name().toLowerCase()) ? TechHider.obfuscateIBlockData : block)); return modpacket; } private static final Reflection.FieldAccessor tileEntityType = Reflection.getField(TechHider.tileEntityDataPacket, TileEntityTypes.class, 0); @Override public boolean unfilteredTileEntityDataAction(Object packet) { return tileEntityType.get(packet) != TileEntityTypes.h; } @Override public BiFunction blockBreakHiderGenerator(Class blockBreakPacket) { return (p, packet) -> { PacketPlayOutBlockBreak breakPacket = (PacketPlayOutBlockBreak) packet; if(TechHider.bypass(p, TechHider.posToChunk(TechHider.blockPositionX.get(breakPacket.b())), TechHider.posToChunk(TechHider.blockPositionZ.get(breakPacket.b())))) return packet; if(!Config.HiddenBlocks.contains(TechHider.getMaterialByIBlockData(breakPacket.c()).name().toLowerCase())) return packet; return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) TechHider.obfuscateIBlockData, breakPacket.d(), breakPacket.a()); }; } }