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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ Download: [GeyserOptionalPack.mcpack](https://download.geysermc.org/v2/projects/
### Manually compiling the pack

1. Clone the repo to your computer
2. Run `gradlew build`.
3. Run the pack compiler using `java -jar build/libs/GeyserOptionalPackCompiler.jar`
4. When it finishes compiling, it will output the `GeyserOptionalPack.mcpack`.
2. Run `gradlew run`.
3. When it finishes compiling, it will output the `GeyserOptionalPack.mcpack`.

### Legal

Expand Down
26 changes: 0 additions & 26 deletions build.gradle

This file was deleted.

27 changes: 27 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
plugins {
java
application
}

group = "org.geysermc.optionalpack"
version = "1.0-SNAPSHOT"

repositories {
mavenCentral()
}

dependencies {
implementation("com.google.code.gson:gson:2.13.1")
implementation("org.reflections:reflections:0.10.2")
}

tasks {
jar {
archiveFileName = "GeyserOptionalPackCompiler.jar"
manifest.attributes["Main-Class"] = application.mainClass
}
}

application {
mainClass.set("org.geysermc.optionalpack.OptionalPack")
}
5 changes: 5 additions & 0 deletions developer_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ The GeyserOptionalPack is compiled using a program written in Java. It contains

Entity data and entity flags (known as queries in Molang) are pieces of metadata that store various pieces of information about an entity on the Bedrock Edition of Minecraft. You can query for an entity's health, for example (a number query or an entity data), and can query for if an entity is angry (an entity flag, which is either 1.0 or 0.0 in Molang). Not all entities use every query, but every entity has access to most queries, though Bedrock by default ignores these. These queries can be sent by Geyser and change how an entity looks. We use this to our advantage in this resource pack.

### Patches
There is a system within the compiler to apply patches to the vanilla Bedrock json files. This is done by placing a `.patch.json` in the `patches` resource folder, with the same path as the file you want to patch. The patch file will be merged with the original file, replacing any existing keys. This is useful for small changes to vanilla files, such as adding an extra texture to an entity.

The source for these files is https://github.com/Mojang/bedrock-samples/tree/main/resource_pack with each patch being the same name and path as the original file but with `.json` replaced with `.patch.json`.

### Armor stands

#### Part visibility and rotation encoding
Expand Down
2 changes: 0 additions & 2 deletions settings.gradle

This file was deleted.

2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rootProject.name = "GeyserOptionalPackCompiler"

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.geysermc.optionalpack;

import java.io.InputStream;

public class BedrockResourcesWrapper {
private static final String BEDROCK_RESOURCES_URL = "https://raw.githubusercontent.com/Mojang/bedrock-samples/refs/tags/v" + Constants.BEDROCK_TARGET_VERSION + "/resource_pack/%s";

public static String getResourceAsString(String path) {
return WebUtils.getAsString(BEDROCK_RESOURCES_URL.formatted(path));
}

public static InputStream getResource(String path) {
return WebUtils.request(BEDROCK_RESOURCES_URL.formatted(path));
}
}
14 changes: 14 additions & 0 deletions src/main/java/org/geysermc/optionalpack/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.geysermc.optionalpack;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Constants {
public static final String JAVA_TARGET_VERSION = "1.21.8";
public static final String BEDROCK_TARGET_VERSION = "1.21.100.6";

public static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
}
62 changes: 62 additions & 0 deletions src/main/java/org/geysermc/optionalpack/FileUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.geysermc.optionalpack;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileUtils {
/**
* Delete a directory and all files within it
* From: https://www.geeksforgeeks.org/java/java-program-to-delete-a-directory/
*
* @param directory The directory to remove
*/
public static void deleteDirectory(File directory) {
File[] files = directory.listFiles();
if (files != null) {
for (File subfile : directory.listFiles()) {
if (subfile.isDirectory()) {
deleteDirectory(subfile);
}
subfile.delete();
}
}

directory.delete();
}

/**
* @see #deleteDirectory(File)
*/
public static void deleteDirectory(Path directory) {
deleteDirectory(directory.toFile());
}

/**
* Zip a folder
* From: https://stackoverflow.com/a/57997601
*
* @param sourceFolderPath Folder to zip
* @param zipPath Output path for the zip
*/
public static void zipFolder(Path sourceFolderPath, Path zipPath) throws Exception {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));
Files.walkFileTree(sourceFolderPath, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
zos.putNextEntry(new ZipEntry(sourceFolderPath.relativize(file).toString()));
Files.copy(file, zos);
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
});
zos.close();
}
}
14 changes: 9 additions & 5 deletions src/main/java/org/geysermc/optionalpack/JavaResources.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
Expand Down Expand Up @@ -60,12 +61,15 @@ public static void extract(ZipFile clientJar) {
String assetFileName = Path.of(jarAssetPath).toFile().getName();
Path destination = OptionalPack.WORKING_PATH.resolve(destinationPath).resolve(assetFileName);

if (destination.toFile().mkdirs()) {
Files.copy(asset, destination, StandardCopyOption.REPLACE_EXISTING);
}
else {
OptionalPack.log("Could not make directories for copying " + jarAssetPath + " to " + destinationPath + "!");
File destinationFolder = OptionalPack.WORKING_PATH.resolve(destinationPath).toFile();
if (!destinationFolder.exists()) {
if (!destinationFolder.mkdirs()) {
OptionalPack.log("Could not make directories for copying " + jarAssetPath + " to " + destinationPath + "!");
continue;
}
}

Files.copy(asset, destination, StandardCopyOption.REPLACE_EXISTING);
}

} catch (IOException e) {
Expand Down
17 changes: 5 additions & 12 deletions src/main/java/org/geysermc/optionalpack/LauncherMetaWrapper.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.geysermc.optionalpack;

import com.google.gson.Gson;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -10,24 +8,21 @@
import java.util.Map;

public class LauncherMetaWrapper {
private static final String TARGET_VERSION = "1.21.8";

private static final Path CLIENT_JAR = OptionalPack.TEMP_PATH.resolve("client.jar");
private static final String LAUNCHER_META_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
private static final Gson GSON = new Gson();

public static Path getLatest() {
OptionalPack.log("Downloading " + TARGET_VERSION + " client.jar from Mojang...");
OptionalPack.log("Downloading " + Constants.JAVA_TARGET_VERSION + " client.jar from Mojang...");

VersionManifest versionManifest = GSON.fromJson(HTTP.getAsString(LAUNCHER_META_URL), VersionManifest.class);
VersionManifest versionManifest = Constants.GSON.fromJson(WebUtils.getAsString(LAUNCHER_META_URL), VersionManifest.class);

for (Version version : versionManifest.versions()) {
if (version.id().equals(TARGET_VERSION)) {
VersionInfo versionInfo = GSON.fromJson(HTTP.getAsString(version.url()), VersionInfo.class);
if (version.id().equals(Constants.JAVA_TARGET_VERSION)) {
VersionInfo versionInfo = Constants.GSON.fromJson(WebUtils.getAsString(version.url()), VersionInfo.class);
VersionDownload client = versionInfo.downloads().get("client");
if (!Files.exists(CLIENT_JAR) || !client.sha1.equals(getSha1(CLIENT_JAR))) {
// Download the client jar
try (InputStream in = HTTP.request(client.url())) {
try (InputStream in = WebUtils.request(client.url())) {
Files.copy(in, CLIENT_JAR);
} catch (Exception e) {
throw new RuntimeException("Could not download client jar", e);
Expand Down Expand Up @@ -62,8 +57,6 @@ private static String getSha1(Path path) {
}
}



public record VersionManifest(
LatestVersion latest,
List<Version> versions
Expand Down
Loading