/** * Retrieve a structure modifier that automatically marshalls between NBT wrappers and their NMS * counterpart. * * @param stack - the stack that will store the NBT compound. * @return The structure modifier. */ private static StructureModifier<NbtBase<?>> getStackModifier(ItemStack stack) { Object nmsStack = MinecraftReflection.getMinecraftItemStack(stack); if (itemStackModifier == null) { itemStackModifier = new StructureModifier<Object>(nmsStack.getClass(), Object.class, false); } // Use the first and best NBT tag return itemStackModifier .withTarget(nmsStack) .withType(MinecraftReflection.getNBTBaseClass(), BukkitConverters.getNbtConverter()); }
/** * Create a new NBT wrapper from a given type. * * @param <T> Type * @param type - the NBT type. * @param name - the name of the NBT tag. * @return The new wrapped NBT tag. * @throws FieldAccessException If we're unable to create the underlying tag. */ public static <T> NbtWrapper<T> ofWrapper(NbtType type, String name) { if (type == null) throw new IllegalArgumentException("type cannot be NULL."); if (type == NbtType.TAG_END) throw new IllegalArgumentException("Cannot create a TAG_END."); if (methodCreateTag == null) { Class<?> base = MinecraftReflection.getNBTBaseClass(); // Use the base class try { methodCreateTag = findCreateMethod(base, byte.class, String.class); methodCreateWithName = true; } catch (Exception e) { methodCreateTag = findCreateMethod(base, byte.class); methodCreateWithName = false; } } try { // Delegate to the correct version if (methodCreateWithName) return createTagWithName(type, name); else return createTagSetName(type, name); } catch (Exception e) { // Inform the caller throw new FieldAccessException( String.format("Cannot create NBT element %s (type: %s)", name, type), e); } }
@Override public void injectManager() { if (serverHandlerRef == null) throw new IllegalStateException("Cannot find server handler."); // Don't inject twice if (serverHandlerRef.getValue() instanceof Factory) return; if (!tryInjectManager()) { // Try to override the proxied object if (proxyServerField != null) { serverHandlerRef = new VolatileField(proxyServerField, serverHandler, true); serverHandler = serverHandlerRef.getValue(); if (serverHandler == null) throw new RuntimeException("Cannot hook player: Inner proxy object is NULL."); // Try again if (tryInjectManager()) { // It worked - probably return; } } throw new RuntimeException( "Cannot hook player: Unable to find a valid constructor for the " + MinecraftReflection.getNetServerHandlerClass().getName() + " object."); } }
/** * Retrieves a read/write structure for collections of chunk positions. * * <p>This modifier will automatically marshall between the visible ProtocolLib ChunkPosition and * the internal Minecraft ChunkPosition. * * @return A modifier for ChunkPosition list fields. */ public StructureModifier<List<ChunkPosition>> getPositionCollectionModifier() { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, BukkitConverters.getListConverter( MinecraftReflection.getChunkPositionClass(), ChunkPosition.getConverter())); }
/** * Retrieve the packet ID of a given packet. * * @param packet - the type of packet to check. * @return The ID of the given packet. * @throws IllegalArgumentException If this is not a valid packet. */ public static int getPacketID(Class<?> packet) { if (packet == null) throw new IllegalArgumentException("Packet type class cannot be NULL."); if (!MinecraftReflection.getPacketClass().isAssignableFrom(packet)) throw new IllegalArgumentException("Type must be a packet."); // The registry contains both the overridden and original packets return getPacketToID().get(packet); }
/** * Ensure that the given stack can store arbitrary NBT information. * * @param stack - the stack to check. */ private static void checkItemStack(ItemStack stack) { if (stack == null) throw new IllegalArgumentException("Stack cannot be NULL."); if (!MinecraftReflection.isCraftItemStack(stack)) throw new IllegalArgumentException("Stack must be a CraftItemStack."); if (stack.getType() == Material.AIR) throw new IllegalArgumentException( "ItemStacks representing air cannot store NMS information."); }
/** * Retrieves a read/write structure for collections of watchable objects. * * <p>This modifier will automatically marshall between the visible WrappedWatchableObject and the * internal Minecraft WatchableObject. * * @return A modifier for watchable object list fields. */ public StructureModifier<List<WrappedWatchableObject>> getWatchableCollectionModifier() { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, BukkitConverters.getListConverter( MinecraftReflection.getWatchableObjectClass(), BukkitConverters.getWatchableObjectConverter())); }
private void registerSpigot(DelayedPacketManager delayed) { // Use netty if we have a non-standard ServerConnection class nettyEnabled = !MinecraftReflection.isMinecraftObject( InjectedServerConnection.getServerConnection(reporter, server)); // Switch to the standard manager delayed.setDelegate(buildInternal()); }
/** * Create a new packet filter manager. * * @return A new packet filter manager. */ public InternalManager build() { if (reporter == null) throw new IllegalArgumentException("reporter cannot be NULL."); if (classLoader == null) throw new IllegalArgumentException("classLoader cannot be NULL."); asyncManager = new AsyncFilterManager(reporter, server.getScheduler()); nettyEnabled = false; // Spigot if (SpigotPacketInjector.canUseSpigotListener()) { // If the server hasn't loaded yet - wait if (InjectedServerConnection.getServerConnection(reporter, server) == null) { // We need to delay this until we know if Netty is enabled final DelayedPacketManager delayed = new DelayedPacketManager(reporter, mcVersion); // They must reference each other delayed.setAsynchronousManager(asyncManager); asyncManager.setManager(delayed); Futures.addCallback( BukkitFutures.nextEvent(library, WorldInitEvent.class), new FutureCallback<WorldInitEvent>() { @Override public void onSuccess(WorldInitEvent event) { // Nevermind if (delayed.isClosed()) return; try { registerSpigot(delayed); } catch (Exception e) { onFailure(e); } } @Override public void onFailure(Throwable error) { reporter.reportWarning( PacketFilterBuilder.this, Report.newBuilder(REPORT_TEMPORARY_EVENT_ERROR).error(error)); } }); System.out.println("Delaying due to Spigot"); // Let plugins use this version instead return delayed; } else { nettyEnabled = !MinecraftReflection.isMinecraftObject( InjectedServerConnection.getServerConnection(reporter, server)); } } // Otherwise - construct the packet filter manager right away return buildInternal(); }
/** * Read an ItemStack from a input stream without "scrubbing" the NBT content. * * @param input - the input stream. * @return The deserialized item stack. * @throws IOException If anything went wrong. */ @Override public ItemStack deserializeItemStack(DataInputStream input) throws IOException { ItemStack result = null; short type = input.readShort(); if (type >= 0) { byte amount = input.readByte(); short damage = input.readShort(); result = new ItemStack(type, amount, damage); NbtCompound tag = super.deserializeCompound(input); if (tag != null) { result = MinecraftReflection.getBukkitItemStack(result); NbtFactory.setItemTag(result, tag); } } return result; }
/** * Retrieves a read/write structure for arrays of ItemStacks. * * <p>This modifier will automatically marshall between the Bukkit ItemStack and the internal * Minecraft ItemStack. * * @return A modifier for ItemStack array fields. */ public StructureModifier<ItemStack[]> getItemArrayModifier() { final EquivalentConverter<ItemStack> stackConverter = BukkitConverters.getItemStackConverter(); // Convert to and from the Bukkit wrapper return structureModifier.<ItemStack[]>withType( MinecraftReflection.getItemStackArrayClass(), BukkitConverters.getIgnoreNull( new EquivalentConverter<ItemStack[]>() { public Object getGeneric(Class<?> genericType, ItemStack[] specific) { Class<?> nmsStack = MinecraftReflection.getItemStackClass(); Object[] result = (Object[]) Array.newInstance(nmsStack, specific.length); // Unwrap every item for (int i = 0; i < result.length; i++) { result[i] = stackConverter.getGeneric(nmsStack, specific[i]); } return result; } @Override public ItemStack[] getSpecific(Object generic) { Object[] input = (Object[]) generic; ItemStack[] result = new ItemStack[input.length]; // Add the wrapper for (int i = 0; i < result.length; i++) { result[i] = stackConverter.getSpecific(input[i]); } return result; } @Override public Class<ItemStack[]> getSpecificType() { return ItemStack[].class; } })); }
private Class<?> getFirstMinecraftSuperClass(Class<?> clazz) { if (clazz.getName().startsWith(MinecraftReflection.getMinecraftPackage())) return clazz; else if (clazz.equals(Object.class)) return clazz; else return getFirstMinecraftSuperClass(clazz.getSuperclass()); }
/** * Retrieves a read/write structure for ItemStack. * * <p>This modifier will automatically marshall between the Bukkit ItemStack and the internal * Minecraft ItemStack. * * @return A modifier for ItemStack fields. */ public StructureModifier<ItemStack> getItemModifier() { // Convert to and from the Bukkit wrapper return structureModifier.<ItemStack>withType( MinecraftReflection.getItemStackClass(), BukkitConverters.getItemStackConverter()); }
/** * Retrieves a read/write structure for the world type enum. * * <p>This modifier will automatically marshall between the Bukkit world type and the internal * Minecraft world type. * * @return A modifier for world type fields. */ public StructureModifier<WorldType> getWorldTypeModifier() { // Convert to and from the Bukkit wrapper return structureModifier.<WorldType>withType( MinecraftReflection.getWorldTypeClass(), BukkitConverters.getWorldTypeConverter()); }
/** * Retrieves a read/write structure for data watchers. * * @return A modifier for data watchers. */ public StructureModifier<WrappedDataWatcher> getDataWatcherModifier() { // Convert to and from the Bukkit wrapper return structureModifier.<WrappedDataWatcher>withType( MinecraftReflection.getDataWatcherClass(), BukkitConverters.getDataWatcherConverter()); }
/** * Retrieve the cached fuzzy reflection instance allowing access to the packet registry. * * @return Reflected packet registry. */ private static FuzzyReflection getPacketRegistry() { if (packetRegistry == null) packetRegistry = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true); return packetRegistry; }
/** * Retrieves a read/write structure for chunk positions. * * @return A modifier for a ChunkPosition. */ public StructureModifier<ChunkPosition> getPositionModifier() { // Convert to and from the Bukkit wrapper return structureModifier.withType( MinecraftReflection.getChunkPositionClass(), ChunkPosition.getConverter()); }
/** * Retrieves a read/write structure for NBT classes. * * @return A modifier for NBT classes. */ public StructureModifier<NbtBase<?>> getNbtModifier() { // Allow access to the NBT class in packet 130 return structureModifier.withType( MinecraftReflection.getNBTBaseClass(), BukkitConverters.getNbtConverter()); }