Skip to content

Commit 37ac514

Browse files
Add vanilla json patching system (#68)
* Add json patching renderer * Make minecraft:trial_spawner_detection particle have parity * Oops meant to keep this * Move Arrow, Rabbit and Illusioner entity to new json patches * Move to .patch.json system * Bump pack version * Update title visibility condition to only hide blank text * Use nicer json format * Change to .kts, fix trial_spawner_detection_ominous particle --------- Co-authored-by: chris <[email protected]>
1 parent 730cf0c commit 37ac514

31 files changed

+435
-338
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ Download: [GeyserOptionalPack.mcpack](https://download.geysermc.org/v2/projects/
2323
### Manually compiling the pack
2424

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

3029
### Legal
3130

build.gradle

Lines changed: 0 additions & 26 deletions
This file was deleted.

build.gradle.kts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
plugins {
2+
java
3+
application
4+
}
5+
6+
group = "org.geysermc.optionalpack"
7+
version = "1.0-SNAPSHOT"
8+
9+
repositories {
10+
mavenCentral()
11+
}
12+
13+
dependencies {
14+
implementation("com.google.code.gson:gson:2.13.1")
15+
implementation("org.reflections:reflections:0.10.2")
16+
}
17+
18+
tasks {
19+
jar {
20+
archiveFileName = "GeyserOptionalPackCompiler.jar"
21+
manifest.attributes["Main-Class"] = application.mainClass
22+
}
23+
}
24+
25+
application {
26+
mainClass.set("org.geysermc.optionalpack.OptionalPack")
27+
}

developer_documentation.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ The GeyserOptionalPack is compiled using a program written in Java. It contains
2626

2727
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.
2828

29+
### Patches
30+
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.
31+
32+
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`.
33+
2934
### Armor stands
3035

3136
#### Part visibility and rotation encoding

settings.gradle

Lines changed: 0 additions & 2 deletions
This file was deleted.

settings.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
rootProject.name = "GeyserOptionalPackCompiler"
2+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.geysermc.optionalpack;
2+
3+
import java.io.InputStream;
4+
5+
public class BedrockResourcesWrapper {
6+
private static final String BEDROCK_RESOURCES_URL = "https://raw.githubusercontent.com/Mojang/bedrock-samples/refs/tags/v" + Constants.BEDROCK_TARGET_VERSION + "/resource_pack/%s";
7+
8+
public static String getResourceAsString(String path) {
9+
return WebUtils.getAsString(BEDROCK_RESOURCES_URL.formatted(path));
10+
}
11+
12+
public static InputStream getResource(String path) {
13+
return WebUtils.request(BEDROCK_RESOURCES_URL.formatted(path));
14+
}
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.geysermc.optionalpack;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.GsonBuilder;
5+
6+
public class Constants {
7+
public static final String JAVA_TARGET_VERSION = "1.21.8";
8+
public static final String BEDROCK_TARGET_VERSION = "1.21.100.6";
9+
10+
public static final Gson GSON = new GsonBuilder()
11+
.setPrettyPrinting()
12+
.disableHtmlEscaping()
13+
.create();
14+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.geysermc.optionalpack;
2+
3+
import java.io.File;
4+
import java.io.FileOutputStream;
5+
import java.io.IOException;
6+
import java.nio.file.FileVisitResult;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.nio.file.SimpleFileVisitor;
10+
import java.nio.file.attribute.BasicFileAttributes;
11+
import java.util.zip.ZipEntry;
12+
import java.util.zip.ZipOutputStream;
13+
14+
public class FileUtils {
15+
/**
16+
* Delete a directory and all files within it
17+
* From: https://www.geeksforgeeks.org/java/java-program-to-delete-a-directory/
18+
*
19+
* @param directory The directory to remove
20+
*/
21+
public static void deleteDirectory(File directory) {
22+
File[] files = directory.listFiles();
23+
if (files != null) {
24+
for (File subfile : directory.listFiles()) {
25+
if (subfile.isDirectory()) {
26+
deleteDirectory(subfile);
27+
}
28+
subfile.delete();
29+
}
30+
}
31+
32+
directory.delete();
33+
}
34+
35+
/**
36+
* @see #deleteDirectory(File)
37+
*/
38+
public static void deleteDirectory(Path directory) {
39+
deleteDirectory(directory.toFile());
40+
}
41+
42+
/**
43+
* Zip a folder
44+
* From: https://stackoverflow.com/a/57997601
45+
*
46+
* @param sourceFolderPath Folder to zip
47+
* @param zipPath Output path for the zip
48+
*/
49+
public static void zipFolder(Path sourceFolderPath, Path zipPath) throws Exception {
50+
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));
51+
Files.walkFileTree(sourceFolderPath, new SimpleFileVisitor<>() {
52+
@Override
53+
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
54+
zos.putNextEntry(new ZipEntry(sourceFolderPath.relativize(file).toString()));
55+
Files.copy(file, zos);
56+
zos.closeEntry();
57+
return FileVisitResult.CONTINUE;
58+
}
59+
});
60+
zos.close();
61+
}
62+
}

src/main/java/org/geysermc/optionalpack/JavaResources.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import javax.imageio.ImageIO;
2929
import java.awt.image.BufferedImage;
30+
import java.io.File;
3031
import java.io.IOException;
3132
import java.io.InputStream;
3233
import java.nio.charset.Charset;
@@ -60,12 +61,15 @@ public static void extract(ZipFile clientJar) {
6061
String assetFileName = Path.of(jarAssetPath).toFile().getName();
6162
Path destination = OptionalPack.WORKING_PATH.resolve(destinationPath).resolve(assetFileName);
6263

63-
if (destination.toFile().mkdirs()) {
64-
Files.copy(asset, destination, StandardCopyOption.REPLACE_EXISTING);
65-
}
66-
else {
67-
OptionalPack.log("Could not make directories for copying " + jarAssetPath + " to " + destinationPath + "!");
64+
File destinationFolder = OptionalPack.WORKING_PATH.resolve(destinationPath).toFile();
65+
if (!destinationFolder.exists()) {
66+
if (!destinationFolder.mkdirs()) {
67+
OptionalPack.log("Could not make directories for copying " + jarAssetPath + " to " + destinationPath + "!");
68+
continue;
69+
}
6870
}
71+
72+
Files.copy(asset, destination, StandardCopyOption.REPLACE_EXISTING);
6973
}
7074

7175
} catch (IOException e) {

0 commit comments

Comments
 (0)