Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/
path: |
**/build/libs/
*/build/libs/
4 changes: 3 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/
path: |
**/build/libs/
*/build/libs/
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@

ForcePack facilitates forcing users to accept your resource pack, with utilities such as live reloading, SHA-1 generation, and per-server support via velocity.

You can find the Spigot resource at: https://www.spigotmc.org/resources/forcepack.45439/
Available to download on:
- [Modrinth](https://modrinth.com/plugin/forcepack)
- [Spigot](https://www.spigotmc.org/resources/forcepack.45439)

## Features
- Support for Spigot/Paper/Folia, Velocity, Sponge
- Support for 1.20.3+ multiple resource packs
- Ability to set resource packs on a per-version basis
- Local webserver resource pack hosting
Expand Down
2 changes: 1 addition & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
plugins {
id("buildlogic.java-common-conventions")
`maven-publish`
}


repositories {
maven("https://repo.opencollab.dev/main/")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ public interface ForcePackAPI {
* @return true if the player was successfully exempted, false if they were already on the exemption list.
*/
boolean exemptNextResourcePackSend(UUID uuid);

}
123 changes: 123 additions & 0 deletions api/src/main/java/com/convallyria/forcepack/api/ForcePackPlatform.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.convallyria.forcepack.api;

import com.convallyria.forcepack.api.resourcepack.PackFormatResolver;
import com.convallyria.forcepack.api.resourcepack.ResourcePack;
import com.convallyria.forcepack.api.resourcepack.ResourcePackVersion;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

public interface ForcePackPlatform extends ForcePackAPI {

/**
* Gets whether the specified URL is a default hosted one.
* @param url the url to check
* @return true if site is a default host
*/
default boolean isDefaultHost(String url) {
List<String> warnForHost = List.of("convallyria.com");
for (String host : warnForHost) {
if (url.contains(host)) {
return true;
}
}
return false;
}

/**
* Gets, if there is one, the blacklisted site within a URL
* @param url the url to check
* @return an {@link Optional<String>} possibly containing the URL of the blacklisted site found
*/
default Optional<String> getBlacklistedSite(String url) {
List<String> blacklisted = List.of("mediafire.com");
for (String blacklistedSite : blacklisted) {
if (url.contains(blacklistedSite)) {
return Optional.of(url);
}
}
return Optional.empty();
}

/**
* Gets whether the specified URL has a valid ending
* @param url the url to check
* @return true if URL ends with a valid extension
*/
default boolean isValidEnding(String url) {
List<String> validUrlEndings = Arrays.asList(".zip", "dl=1");
boolean hasEnding = false;
for (String validUrlEnding : validUrlEndings) {
if (url.endsWith(validUrlEnding)) {
hasEnding = true;
break;
}
}
return hasEnding;
}

default ResourcePackVersion getVersionFromId(String versionId) {
if (versionId.equals("all")) {
return null;
}

try {
// One version?
final int fixedVersion = Integer.parseInt(versionId);
return ResourcePackVersion.of(fixedVersion, fixedVersion);
} catch (NumberFormatException ignored) {
try {
// Version range?
final String[] ranged = versionId.split("-");
final int min = Integer.parseInt(ranged[0]);
final int max = Integer.parseInt(ranged[1]);
return ResourcePackVersion.of(min, max);
} catch (NumberFormatException | IndexOutOfBoundsException ignored2) {}
}

throw new IllegalArgumentException("Invalid version id: " + versionId);
}

default Set<ResourcePack> getPacksForVersion(int protocolVersion) {
final int packFormat = PackFormatResolver.getPackFormat(protocolVersion);

log("Searching for a resource pack with pack version " + packFormat);

ResourcePack anyVersionPack = null;
Set<ResourcePack> validPacks = new HashSet<>();
for (ResourcePack resourcePack : getResourcePacks()) {
final Optional<ResourcePackVersion> version = resourcePack.getVersion();
log("Trying resource pack " + resourcePack.getURL() + " (" + (version.isEmpty() ? version.toString() : version.get().toString()) + ")");

if (version.isEmpty()) {
if (anyVersionPack == null) anyVersionPack = resourcePack; // Pick first all-version resource pack
validPacks.add(resourcePack); // This is still a valid pack that we want to apply.
continue;
}

if (version.get().inVersion(packFormat)) {
validPacks.add(resourcePack);
log("Added resource pack " + resourcePack.getURL());
if (protocolVersion < 765) { // If < 1.20.3, only one pack can be applied.
break;
}
}
}

if (!validPacks.isEmpty()) {
log("Found multiple valid resource packs (" + validPacks.size() + ")");
for (ResourcePack validPack : validPacks) {
log("Chosen resource pack " + validPack.getURL());
}
return validPacks;
}

log("Chosen resource pack is " + (anyVersionPack == null ? "null" : anyVersionPack.getURL()));
return anyVersionPack == null ? Set.of() : Set.of(anyVersionPack);
}

void log(String info, Object... format);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@

import com.convallyria.forcepack.api.verification.ResourcePackURLData;
import jakarta.xml.bind.DatatypeConverter;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.function.Consumer;

public class HashingUtil {

public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ default TriConsumer<T, U, V> andThen(TriConsumer<? super T, ? super U, ? super V
after.accept(a, b, c);
};
}
}
}
21 changes: 21 additions & 0 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This project uses @Incubating APIs which are subject to change.
*/

plugins {
// Support convention plugins written in Kotlin. Convention plugins are build scripts in 'src/main' that automatically become available as plugins in the main build.
`kotlin-dsl`
}

repositories {
// Use the plugin portal to apply community plugins in convention plugins.
gradlePluginPortal()
mavenCentral()
}

dependencies {
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.0.0-beta12")
implementation("com.diffplug.spotless:spotless-plugin-gradle:7.0.3")
}
15 changes: 15 additions & 0 deletions build-logic/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This settings file is used to specify which projects to include in your build-logic build.
* This project uses @Incubating APIs which are subject to change.
*/

dependencyResolutionManagement {
// Reuse version catalog from the main build.
versionCatalogs {
create("libs", { from(files("../gradle/libs.versions.toml")) })
}
}

rootProject.name = "build-logic"
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
plugins {
// Apply the java Plugin to add support for Java.
java
id("com.gradleup.shadow")
id("com.diffplug.spotless")
}

spotless {
java {
endWithNewline()
removeUnusedImports()
// indentWithTabs(4)
trimTrailingWhitespace()
targetExclude("build/generated/**/*")
}

kotlinGradle {
endWithNewline()
leadingTabsToSpaces(4)
trimTrailingWhitespace()
}
}

repositories {
mavenCentral()
maven("https://erethon.de/repo/")
maven("https://repo.convallyria.com/snapshots")
maven("https://repo.viaversion.com")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.codemc.io/repository/maven-releases/")
maven("https://oss.sonatype.org/content/groups/public/")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}

project.version = "1.3.71"

java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
disableAutoTargetJvm()
}

testing {
suites {
// Configure the built-in test suite
val test by getting(JvmTestSuite::class) {
// Use JUnit Jupiter test framework
useJUnitJupiter("5.10.1")
}
}
}

tasks {
compileJava {
options.encoding = "UTF-8"

// Set the release flag. This configures what version bytecode the compiler will emit, as well as what JDK APIs are usable.
// See https://openjdk.java.net/jeps/247 for more information.
options.release.set(11)
}

build {
dependsOn(spotlessApply)
dependsOn(shadowJar)
}

shadowJar {
archiveBaseName.set("forcepack")
archiveClassifier.set(project.name)
mergeServiceFiles()
relocate("me.lucko.jarrelocator", "forcepack.libs.relocator")
relocate("org.glassfish.jaxb", "forcepack.libs.jaxb")
relocate("org.objectweb.asm", "forcepack.libs.asm")
relocate("jakarta.xml.bind", "forcepack.libs.jakarta.xml.bind")
relocate("jakarta.activation", "forcepack.libs.jakarta.activation")
relocate("com.sun.xml.txw2", "forcepack.libs.sun.xml")
relocate("com.sun.istack", "forcepack.libs.sun.istack")
relocate("com.github.retrooper.packetevents", "forcepack.libs.pe.api")
relocate("io.github.retrooper.packetevents", "forcepack.libs.pe.impl")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
id("buildlogic.java-common-conventions")
}

dependencies {
implementation("org.incendo:cloud-annotations:${properties["cloud_version"]}") {
exclude("org.checkerframework")
exclude("io.leangen.geantyref")
}
annotationProcessor("org.incendo:cloud-annotations:${properties["cloud_version"]}") {
exclude("org.checkerframework")
exclude("io.leangen.geantyref")
}
}

tasks {
shadowJar {
val prefix = "forcepack.libs.${project.name}"
relocate("org.incendo.cloud", "${prefix}.cloud")
}
}
Loading
Loading