Skip to content

Commit e57460b

Browse files
Include PackConverter & Creative, create Creative pack wrapper for Minecraft's ResourceManager
1 parent 31acd52 commit e57460b

File tree

9 files changed

+651
-0
lines changed

9 files changed

+651
-0
lines changed

build.gradle.kts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ val loaderVersion = properties["loader_version"]!! as String
99
val modVersion = properties["mod_version"]!! as String
1010
val supportedVersions = properties["supported_versions"]!! as String
1111
val archivesBaseName = properties["archives_base_name"]!! as String
12+
1213
val fabricVersion = properties["fabric_version"]!! as String
14+
val packConverterVersion = properties["pack_converter_version"]!! as String
1315

1416
val targetJavaVersion = 21
1517

@@ -18,6 +20,16 @@ repositories {
1820
name = "ParchmentMC"
1921
url = uri("https://maven.parchmentmc.org")
2022
}
23+
24+
maven {
25+
name = "Jitpack"
26+
url = uri("https://jitpack.io")
27+
}
28+
29+
maven {
30+
name = "Open Collaboration"
31+
url = uri("https://repo.opencollab.dev/main")
32+
}
2133
}
2234

2335
dependencies {
@@ -30,6 +42,10 @@ dependencies {
3042
modImplementation("net.fabricmc:fabric-loader:${loaderVersion}")
3143

3244
modImplementation("net.fabricmc.fabric-api:fabric-api:${fabricVersion}")
45+
46+
include(implementation("com.github.GeyserMC.unnamed-creative:creative-api:817fa982c4")!!)
47+
include(implementation("com.github.GeyserMC.unnamed-creative:creative-serializer-minecraft:817fa982c4")!!)
48+
include(implementation("org.geysermc.pack:converter:${packConverterVersion}")!!)
3349
}
3450

3551
tasks {

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ archives_base_name=rainbow
1313

1414
# Dependencies
1515
fabric_version=0.135.0+1.21.10
16+
pack_converter_version=3.4.1-SNAPSHOT
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.geysermc.rainbow;
2+
3+
import net.kyori.adventure.key.Key;
4+
import net.minecraft.resources.ResourceLocation;
5+
6+
@SuppressWarnings("PatternValidation")
7+
public interface KeyUtil {
8+
9+
static Key resourceLocationToKey(ResourceLocation location) {
10+
return Key.key(location.getNamespace(), location.getPath());
11+
}
12+
13+
static ResourceLocation keyToResourceLocation(Key key) {
14+
return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value());
15+
}
16+
}

src/main/java/org/geysermc/rainbow/Rainbow.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,39 @@
22

33
import com.mojang.logging.LogUtils;
44
import net.fabricmc.api.ClientModInitializer;
5+
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
56
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
67
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
78
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
9+
import net.fabricmc.loader.api.FabricLoader;
10+
import net.minecraft.client.Minecraft;
811
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
12+
import net.minecraft.network.chat.Component;
913
import net.minecraft.resources.ResourceLocation;
14+
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
15+
import org.geysermc.pack.converter.PackConversionContext;
16+
import org.geysermc.pack.converter.PackConverter;
17+
import org.geysermc.pack.converter.converter.ActionListener;
18+
import org.geysermc.pack.converter.converter.Converter;
19+
import org.geysermc.pack.converter.converter.base.PackManifestConverter;
20+
import org.geysermc.pack.converter.converter.lang.LangConverter;
21+
import org.geysermc.pack.converter.converter.misc.SplashTextConverter;
22+
import org.geysermc.pack.converter.converter.model.ModelConverter;
23+
import org.geysermc.pack.converter.data.ConversionData;
24+
import org.geysermc.pack.converter.util.DefaultLogListener;
25+
import org.geysermc.pack.converter.util.LogListener;
1026
import org.geysermc.rainbow.command.CommandSuggestionsArgumentType;
1127
import org.geysermc.rainbow.command.PackGeneratorCommand;
28+
import org.geysermc.rainbow.creative.MinecraftCreativeResourcePack;
1229
import org.geysermc.rainbow.mapper.PackMapper;
1330
import org.slf4j.Logger;
1431

32+
import javax.imageio.ImageIO;
33+
import java.io.IOException;
34+
import java.nio.file.Path;
35+
import java.util.ArrayList;
36+
import java.util.List;
37+
1538
public class Rainbow implements ClientModInitializer {
1639

1740
public static final String MOD_ID = "rainbow";
@@ -29,6 +52,58 @@ public void onInitializeClient() {
2952

3053
ArgumentTypeRegistry.registerArgumentType(getModdedLocation("command_suggestions"),
3154
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
55+
56+
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> {
57+
dispatcher.register(ClientCommandManager.literal("debugtest")
58+
.executes(context -> {
59+
60+
PackConverter packConverter = new PackConverter()
61+
.packName("RAINBOW-TEST")
62+
.output(FabricLoader.getInstance().getGameDir().resolve("pack-convert-out"));
63+
Path tmpDir = FabricLoader.getInstance().getGameDir().resolve("pack-convert-temp");
64+
65+
ImageIO.scanForPlugins();
66+
MinecraftCreativeResourcePack resourcePack = new MinecraftCreativeResourcePack(Minecraft.getInstance().getResourceManager());
67+
BedrockResourcePack bedrockResourcePack = new BedrockResourcePack(tmpDir);
68+
69+
LogListener logListener = new DefaultLogListener();
70+
final Converter.ConversionDataCreationContext conversionDataCreationContext = new Converter.ConversionDataCreationContext(
71+
packConverter, logListener, null, tmpDir, resourcePack, resourcePack
72+
);
73+
74+
75+
List<Converter<?>> converters = new ArrayList<>();
76+
converters.add(new PackManifestConverter());
77+
converters.add(new LangConverter());
78+
converters.add(new ModelConverter());
79+
80+
int errors = 0;
81+
for (Converter converter : converters) {
82+
ConversionData data = converter.createConversionData(conversionDataCreationContext);
83+
PackConversionContext<?> conversionContext = new PackConversionContext<>(data, packConverter, resourcePack, bedrockResourcePack, logListener);
84+
85+
List<ActionListener<?>> actionListeners = List.of();
86+
try {
87+
actionListeners.forEach(actionListener -> actionListener.preConvert((PackConversionContext) conversionContext));
88+
converter.convert(conversionContext);
89+
actionListeners.forEach(actionListener -> actionListener.postConvert((PackConversionContext) conversionContext));
90+
} catch (Throwable t) {
91+
logListener.error("Error converting pack!", t);
92+
errors++;
93+
}
94+
}
95+
96+
try {
97+
bedrockResourcePack.export();
98+
} catch (IOException e) {
99+
throw new RuntimeException(e);
100+
}
101+
context.getSource().sendFeedback(Component.literal("exporting, " + errors + " errors"));
102+
103+
return 0;
104+
})
105+
);
106+
});
32107
}
33108

34109
public static ResourceLocation getModdedLocation(String path) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.geysermc.rainbow.creative;
2+
3+
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
4+
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
5+
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
6+
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
7+
import net.kyori.adventure.key.Key;
8+
import net.kyori.adventure.key.Keyed;
9+
import org.jetbrains.annotations.NotNull;
10+
import org.jetbrains.annotations.Nullable;
11+
import team.unnamed.creative.part.ResourcePackPart;
12+
import team.unnamed.creative.serialize.minecraft.ResourceCategory;
13+
import team.unnamed.creative.sound.SoundRegistry;
14+
import team.unnamed.creative.texture.Texture;
15+
16+
@SuppressWarnings("UnstableApiUsage")
17+
public abstract class CachingStreamResourceContainer implements StreamResourceContainer {
18+
private final Reference2ObjectMap<ResourceCategory<?>, Object2ObjectMap<Key, Object>> cache = new Reference2ObjectOpenHashMap<>();
19+
private final Object2ObjectMap<String, SoundRegistry> soundRegistryCache = new Object2ObjectOpenHashMap<>();
20+
private final Object2ObjectMap<Key, Texture> textureCache = new Object2ObjectOpenHashMap<>();
21+
22+
@SuppressWarnings("unchecked")
23+
private <T extends Keyed & ResourcePackPart> T cacheOrDeserialize(ResourceCategory<T> deserializer, Key key) {
24+
Object2ObjectMap<Key, Object> deserializerCache = cache.computeIfAbsent(deserializer, cacheKey -> new Object2ObjectOpenHashMap<>());
25+
return (T) deserializerCache.computeIfAbsent(key, cacheKey -> StreamResourceContainer.super.deserialize(deserializer, key));
26+
}
27+
28+
@Override
29+
public <T extends Keyed & ResourcePackPart> @Nullable T deserialize(ResourceCategory<T> deserializer, Key key) {
30+
return cacheOrDeserialize(deserializer, key);
31+
}
32+
33+
@Override
34+
public @Nullable SoundRegistry soundRegistry(@NotNull String namespace) {
35+
return soundRegistryCache.computeIfAbsent(namespace, cacheNamespace -> StreamResourceContainer.super.soundRegistry(namespace));
36+
}
37+
38+
@Override
39+
public @Nullable Texture texture(@NotNull Key key) {
40+
return textureCache.computeIfAbsent(key, cacheKey -> StreamResourceContainer.super.texture(key));
41+
}
42+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package org.geysermc.rainbow.creative;
2+
3+
import net.kyori.adventure.key.Key;
4+
import org.jetbrains.annotations.NotNull;
5+
import team.unnamed.creative.atlas.Atlas;
6+
import team.unnamed.creative.base.Writable;
7+
import team.unnamed.creative.blockstate.BlockState;
8+
import team.unnamed.creative.equipment.Equipment;
9+
import team.unnamed.creative.font.Font;
10+
import team.unnamed.creative.item.Item;
11+
import team.unnamed.creative.lang.Language;
12+
import team.unnamed.creative.model.Model;
13+
import team.unnamed.creative.overlay.ResourceContainer;
14+
import team.unnamed.creative.resources.MergeStrategy;
15+
import team.unnamed.creative.sound.Sound;
16+
import team.unnamed.creative.sound.SoundRegistry;
17+
import team.unnamed.creative.texture.Texture;
18+
19+
@SuppressWarnings("NonExtendableApiUsage")
20+
public interface ImmutableResourceContainer extends ResourceContainer {
21+
22+
private static <T> T thr() {
23+
throw new UnsupportedOperationException("ResourceContainer is immutable");
24+
}
25+
26+
@Override
27+
default void atlas(@NotNull Atlas atlas) {
28+
thr();
29+
}
30+
31+
@Override
32+
default boolean removeAtlas(@NotNull Key key) {
33+
return thr();
34+
}
35+
36+
@Override
37+
default void blockState(@NotNull BlockState state) {
38+
thr();
39+
}
40+
41+
@Override
42+
default boolean removeBlockState(@NotNull Key key) {
43+
return thr();
44+
}
45+
46+
@Override
47+
default void equipment(@NotNull Equipment equipment) {
48+
thr();
49+
}
50+
51+
@Override
52+
default boolean removeEquipment(@NotNull Key key) {
53+
return thr();
54+
}
55+
56+
@Override
57+
default void font(@NotNull Font font) {
58+
thr();
59+
}
60+
61+
@Override
62+
default boolean removeFont(@NotNull Key key) {
63+
return thr();
64+
}
65+
66+
@Override
67+
default void item(@NotNull Item item) {
68+
thr();
69+
}
70+
71+
@Override
72+
default boolean removeItem(@NotNull Key key) {
73+
return thr();
74+
}
75+
76+
@Override
77+
default void language(@NotNull Language language) {
78+
thr();
79+
}
80+
81+
@Override
82+
default boolean removeLanguage(@NotNull Key key) {
83+
return thr();
84+
}
85+
86+
@Override
87+
default void model(@NotNull Model model) {
88+
thr();
89+
}
90+
91+
@Override
92+
default boolean removeModel(@NotNull Key key) {
93+
return thr();
94+
}
95+
96+
@Override
97+
default void soundRegistry(@NotNull SoundRegistry soundRegistry) {
98+
thr();
99+
}
100+
101+
@Override
102+
default boolean removeSoundRegistry(@NotNull String namespace) {
103+
return thr();
104+
}
105+
106+
@Override
107+
default void sound(@NotNull Sound sound) {
108+
thr();
109+
}
110+
111+
@Override
112+
default boolean removeSound(@NotNull Key key) {
113+
return thr();
114+
}
115+
116+
@Override
117+
default void texture(@NotNull Texture texture) {
118+
thr();
119+
}
120+
121+
@Override
122+
default boolean removeTexture(@NotNull Key key) {
123+
return thr();
124+
}
125+
126+
@Override
127+
default void unknownFile(@NotNull String path, @NotNull Writable data) {
128+
thr();
129+
}
130+
131+
@Override
132+
default boolean removeUnknownFile(@NotNull String path) {
133+
return thr();
134+
}
135+
136+
@Override
137+
default void merge(@NotNull ResourceContainer other, @NotNull MergeStrategy strategy) {
138+
thr();
139+
}
140+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.geysermc.rainbow.creative;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
5+
import team.unnamed.creative.ResourcePack;
6+
import team.unnamed.creative.base.Writable;
7+
import team.unnamed.creative.metadata.Metadata;
8+
import team.unnamed.creative.metadata.sodium.SodiumMeta;
9+
import team.unnamed.creative.overlay.Overlay;
10+
11+
@SuppressWarnings("NonExtendableApiUsage")
12+
public interface ImmutableResourcePack extends ResourcePack, ImmutableResourceContainer {
13+
14+
private static void thr() {
15+
throw new UnsupportedOperationException("ResourcePack is immutable");
16+
}
17+
18+
@Override
19+
default void icon(@Nullable Writable icon) {
20+
thr();
21+
}
22+
23+
@Override
24+
default void metadata(@NotNull Metadata metadata) {
25+
thr();
26+
}
27+
28+
@Override
29+
default void overlay(@NotNull Overlay overlay) {
30+
thr();
31+
}
32+
33+
@Override
34+
default void sodiumMeta(@NotNull SodiumMeta sodiumMeta) {
35+
thr();
36+
}
37+
}

0 commit comments

Comments
 (0)