mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Attachable generation?
This commit is contained in:
@@ -14,6 +14,7 @@ public record BedrockTextures(Map<String, String> textures) {
|
||||
.xmap(pairs -> pairs.stream().map(pair -> Pair.of(pair.getFirst(), pair.getSecond().getFirst().getSecond())).collect(Pair.toMap()),
|
||||
map -> map.entrySet().stream().map(entry -> Pair.of(entry.getKey(), List.of(Pair.of("textures", entry.getValue())))).toList())
|
||||
.xmap(BedrockTextures::new, BedrockTextures::textures);
|
||||
public static final String TEXTURES_FOLDER = "textures/";
|
||||
|
||||
public Builder toBuilder() {
|
||||
Builder builder = builder();
|
||||
@@ -26,7 +27,6 @@ public record BedrockTextures(Map<String, String> textures) {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private static final String TEXTURES_FOLDER = "textures/";
|
||||
private final Map<String, String> textures = new HashMap<>();
|
||||
|
||||
public Builder withItemTexture(GeyserMapping mapping, String texturePath) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.geysermc.packgenerator.pack;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -8,6 +9,20 @@ public record BedrockVersion(int major, int minor, int patch) {
|
||||
public static final Codec<BedrockVersion> CODEC = Codec.INT.listOf(3, 3)
|
||||
.xmap(list -> BedrockVersion.of(list.getFirst(), list.get(1), list.getLast()),
|
||||
version -> List.of(version.major, version.minor, version.patch));
|
||||
public static final Codec<BedrockVersion> STRING_CODEC = Codec.STRING.comapFlatMap(string -> {
|
||||
String[] segments = string.split("\.");
|
||||
if (segments.length != 3) {
|
||||
return DataResult.error(() -> "Semantic version must consist of 3 versions");
|
||||
}
|
||||
try {
|
||||
int major = Integer.parseInt(segments[0]);
|
||||
int minor = Integer.parseInt(segments[1]);
|
||||
int patch = Integer.parseInt(segments[2]);
|
||||
return DataResult.success(new BedrockVersion(major, minor, patch));
|
||||
} catch (NumberFormatException exception) {
|
||||
return DataResult.error(() -> "Failed to parse semantic version number");
|
||||
}
|
||||
}, version -> String.format("%d.%d.%d", version.major, version.minor, version.patch));
|
||||
|
||||
public static BedrockVersion of(int patch) {
|
||||
return of(0, 0, patch);
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.geysermc.packgenerator.pack.attachable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import org.geysermc.packgenerator.PackConstants;
|
||||
import org.geysermc.packgenerator.pack.BedrockTextures;
|
||||
import org.geysermc.packgenerator.pack.BedrockVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo info) {
|
||||
public static final Codec<BedrockAttachable> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
BedrockVersion.STRING_CODEC.fieldOf("format_version").forGetter(BedrockAttachable::formatVersion),
|
||||
AttachableInfo.CODEC.fieldOf("description").fieldOf("minecraft:attachable").forGetter(BedrockAttachable::info)
|
||||
).apply(instance, BedrockAttachable::new)
|
||||
);
|
||||
|
||||
public static Builder builder(ResourceLocation identifier) {
|
||||
return new Builder(identifier);
|
||||
}
|
||||
|
||||
public static BedrockAttachable equipment(ResourceLocation identifier, EquipmentSlot slot, String texture) {
|
||||
return builder(identifier)
|
||||
.withMaterial(DisplaySlot.DEFAULT, "armor")
|
||||
.withMaterial(DisplaySlot.ENCHANTED, "armor_enchanted")
|
||||
.withTexture(DisplaySlot.DEFAULT, texture)
|
||||
.withTexture(DisplaySlot.ENCHANTED, VanillaTextures.ENCHANTED_ACTOR_GLINT)
|
||||
.withGeometry(DisplaySlot.DEFAULT, VanillaGeometries.fromEquipmentSlot(slot))
|
||||
.withRenderController(VanillaRenderControllers.ARMOR)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final ResourceLocation identifier;
|
||||
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
||||
private final EnumMap<DisplaySlot, String> textures = new EnumMap<>(DisplaySlot.class);
|
||||
private final EnumMap<DisplaySlot, String> geometries = new EnumMap<>(DisplaySlot.class);
|
||||
private final Map<String, String> animations = new HashMap<>();
|
||||
private final Map<String, String> scripts = new HashMap<>();
|
||||
private final List<String> renderControllers = new ArrayList<>();
|
||||
|
||||
public Builder(ResourceLocation identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public Builder withMaterial(DisplaySlot slot, String material) {
|
||||
materials.put(slot, material);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withTexture(DisplaySlot slot, String texture) {
|
||||
textures.put(slot, BedrockTextures.TEXTURES_FOLDER + texture);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withGeometry(DisplaySlot slot, String geometry) {
|
||||
geometries.put(slot, geometry);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withAnimation(String key, String animation) {
|
||||
animations.put(key, animation);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withScript(String key, String script) {
|
||||
scripts.put(key, script);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withRenderController(String controller) {
|
||||
renderControllers.add(controller);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BedrockAttachable build() {
|
||||
return new BedrockAttachable(PackConstants.ENGINE_VERSION,
|
||||
new AttachableInfo(identifier, verifyDefault(materials), verifyDefault(textures), verifyDefault(geometries), Map.copyOf(animations), Map.copyOf(scripts), List.copyOf(renderControllers)));
|
||||
}
|
||||
|
||||
private static DisplayMap verifyDefault(EnumMap<DisplaySlot, String> map) {
|
||||
if (!map.containsKey(DisplaySlot.DEFAULT)) {
|
||||
throw new IllegalStateException("DisplayMap must have a default key");
|
||||
}
|
||||
return new DisplayMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
public record AttachableInfo(ResourceLocation identifier, DisplayMap materials, DisplayMap textures,
|
||||
DisplayMap geometry, Map<String, String> animations, Map<String, String> scripts,
|
||||
List<String> renderControllers) {
|
||||
private static final Codec<Map<String, String>> STRING_MAP_CODEC = Codec.unboundedMap(Codec.STRING, Codec.STRING);
|
||||
public static final Codec<AttachableInfo> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC.fieldOf("identifier").forGetter(AttachableInfo::identifier),
|
||||
DisplayMap.CODEC.fieldOf("materials").forGetter(AttachableInfo::materials),
|
||||
DisplayMap.CODEC.fieldOf("textures").forGetter(AttachableInfo::textures),
|
||||
DisplayMap.CODEC.fieldOf("geometry").forGetter(AttachableInfo::geometry),
|
||||
STRING_MAP_CODEC.optionalFieldOf("animations", Map.of()).forGetter(AttachableInfo::animations),
|
||||
STRING_MAP_CODEC.optionalFieldOf("scripts", Map.of()).forGetter(AttachableInfo::scripts),
|
||||
Codec.STRING.listOf().optionalFieldOf("render_controllers", List.of()).forGetter(AttachableInfo::renderControllers)
|
||||
).apply(instance, AttachableInfo::new)
|
||||
);
|
||||
}
|
||||
|
||||
public record DisplayMap(EnumMap<DisplaySlot, String> map) {
|
||||
public static final Codec<DisplayMap> CODEC = Codec.unboundedMap(DisplaySlot.CODEC, Codec.STRING)
|
||||
.xmap(map -> map.isEmpty() ? new DisplayMap(new EnumMap<>(DisplaySlot.class)) : new DisplayMap(new EnumMap<>(map)), DisplayMap::map);
|
||||
}
|
||||
|
||||
public enum DisplaySlot implements StringRepresentable {
|
||||
DEFAULT("default"),
|
||||
ENCHANTED("enchanted");
|
||||
|
||||
public static final Codec<DisplaySlot> CODEC = StringRepresentable.fromEnum(DisplaySlot::values);
|
||||
|
||||
private final String name;
|
||||
|
||||
DisplaySlot(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getSerializedName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.geysermc.packgenerator.pack.attachable;
|
||||
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
|
||||
public class VanillaGeometries {
|
||||
public static final String HELMET = "geometry.player.armor.helmet";
|
||||
public static final String CHESTPLATE = "geometry.player.armor.chestplate";
|
||||
public static final String LEGGINGS = "geometry.player.armor.leggings";
|
||||
public static final String BOOTS = "geometry.player.armor.boots";
|
||||
|
||||
public static String fromEquipmentSlot(EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case FEET -> BOOTS;
|
||||
case LEGS -> LEGGINGS;
|
||||
case CHEST -> CHESTPLATE;
|
||||
case HEAD -> HELMET;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.geysermc.packgenerator.pack.attachable;
|
||||
|
||||
public class VanillaMaterials {
|
||||
public static final String ARMOR = "armor";
|
||||
public static final String ARMOR_ENCHANTED = "armor_enchanted";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.geysermc.packgenerator.pack.attachable;
|
||||
|
||||
public class VanillaRenderControllers {
|
||||
public static final String ARMOR = "controller.render.armor";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.geysermc.packgenerator.pack.attachable;
|
||||
|
||||
public class VanillaTextures {
|
||||
public static final String ENCHANTED_ACTOR_GLINT = "misc/enchanted_actor_glint";
|
||||
}
|
||||
Reference in New Issue
Block a user