# IPaintingAPI The platform-neutral interface implemented by both Paper and Velocity plugins. Retrieved via `PaintingAPI.get()`. --- ## Source ```java package gg.lode.paintingapi; import gg.lode.paintingapi.api.model.PackDefinition; import gg.lode.paintingapi.api.model.ServerEntry; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; public interface IPaintingAPI { boolean isEnabled(); @NotNull List<PackDefinition> getPackDefinitions(); @Nullable PackDefinition getPackDefinition(@NotNull String name); @NotNull List<ServerEntry> getServerEntries(); boolean isRequiredForServer(@NotNull String serverName); void reload(); void resendPacksToOnlinePlayers(); void resendPacksToPlayer(@NotNull UUID playerId); /** * Re-checks every configured pack URL and rewrites any hash that moved. * * <p>Runs off the server thread. Unforced calls are throttled and deduped * against the periodic refresh, so calling this on a hot path is cheap: * a run that happened within {@code hash-refresh-throttle} seconds is * reused rather than repeated. * * @param force bypass the throttle and re-download every pack * @return how many variant hashes changed */ default @NotNull CompletableFuture<Integer> refreshPackHashes(boolean force) { throw new UnsupportedOperationException("refreshPackHashes is not supported by this Painting build"); } /** * SHA-1 of a pack, from an {@code http(s)} URL or from a file on disk — * whichever {@code source} turns out to be. * * <p>The source is validated before anything is read: only http/https, * redirects followed by hand with every hop re-checked, a byte cap on the * body, and file paths resolved through their symlinks and confined to the * server directory. Limits come from the {@code hash-security} block in * Painting's config; the future completes exceptionally with a * {@link SecurityException} when the source falls outside them. * * @param source pack URL, or a path relative to the Painting data folder / * the server directory * @return hex SHA-1, ready to drop into a {@code hash:} field */ default @NotNull CompletableFuture<String> computeHash(@NotNull String source) { throw new UnsupportedOperationException("computeHash is not supported by this Painting build"); } /** As {@link #computeHash(String)}, refusing anything that is not an http(s) URL. */ default @NotNull CompletableFuture<String> computeHashFromUrl(@NotNull String url) { throw new UnsupportedOperationException("computeHashFromUrl is not supported by this Painting build"); } /** As {@link #computeHash(String)}, refusing anything that is not a file inside the server directory. */ default @NotNull CompletableFuture<String> computeHashFromFile(@NotNull String path) { throw new UnsupportedOperationException("computeHashFromFile is not supported by this Painting build"); } } ``` --- ## Related Pages - [[Painting/API/PaintingAPI]] — static accessor that delegates to this interface - [[Painting/API/PackDefinition]] — returned by `getPackDefinition` - [[Painting/API/ServerEntry]] — returned by `getServerEntries` - [[Painting/API/Hash/PackHasher]] — what the `computeHash` methods call - [[Painting/API/Hash/HashPolicy]] — the limits those methods apply