mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Bedrock geometry builders
This commit is contained in:
@@ -28,6 +28,11 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
|
|||||||
).apply(instance, BedrockAttachable::new)
|
).apply(instance, BedrockAttachable::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public void save(Path attachablesDirectory) throws IOException {
|
||||||
|
// Get a safe attachable path by using Geyser's way of getting icons
|
||||||
|
CodecUtil.trySaveJson(CODEC, this, attachablesDirectory.resolve(GeyserSingleDefinition.iconFromResourceLocation(info.identifier) + ".json"));
|
||||||
|
}
|
||||||
|
|
||||||
public static Builder builder(ResourceLocation identifier) {
|
public static Builder builder(ResourceLocation identifier) {
|
||||||
return new Builder(identifier);
|
return new Builder(identifier);
|
||||||
}
|
}
|
||||||
@@ -51,11 +56,6 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(Path attachablesPath) throws IOException {
|
|
||||||
// Get a safe attachable path by using Geyser's way of getting icons
|
|
||||||
CodecUtil.trySaveJson(CODEC, this, attachablesPath.resolve(GeyserSingleDefinition.iconFromResourceLocation(info.identifier) + ".json"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private final ResourceLocation identifier;
|
private final ResourceLocation identifier;
|
||||||
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
private final EnumMap<DisplaySlot, String> materials = new EnumMap<>(DisplaySlot.class);
|
||||||
|
|||||||
@@ -4,15 +4,22 @@ import com.mojang.serialization.Codec;
|
|||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.util.ExtraCodecs;
|
import net.minecraft.util.ExtraCodecs;
|
||||||
|
import org.geysermc.packgenerator.CodecUtil;
|
||||||
import org.geysermc.packgenerator.pack.BedrockVersion;
|
import org.geysermc.packgenerator.pack.BedrockVersion;
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinition> definitions) {
|
public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinition> definitions) {
|
||||||
|
public static final BedrockVersion FORMAT_VERSION = BedrockVersion.of(1, 21, 0);
|
||||||
public static final Vector3f VECTOR3F_ZERO = new Vector3f();
|
public static final Vector3f VECTOR3F_ZERO = new Vector3f();
|
||||||
|
|
||||||
public static final Codec<BedrockGeometry> CODEC = RecordCodecBuilder.create(instance ->
|
public static final Codec<BedrockGeometry> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
@@ -22,6 +29,83 @@ public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinit
|
|||||||
).apply(instance, BedrockGeometry::new)
|
).apply(instance, BedrockGeometry::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public void save(Path geometryDirectory) throws IOException {
|
||||||
|
CodecUtil.trySaveJson(CODEC, this, geometryDirectory.resolve(definitions.getFirst().info.identifier + ".geo.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BedrockGeometry of(GeometryDefinition... definitions) {
|
||||||
|
return new BedrockGeometry(FORMAT_VERSION, Arrays.asList(definitions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder(String identifier) {
|
||||||
|
return new Builder(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bone.Builder bone(String name) {
|
||||||
|
return new Bone.Builder(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Cube.Builder cube(Vector3f origin, Vector3f size) {
|
||||||
|
return new Cube.Builder(origin, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private final String identifier;
|
||||||
|
private final List<Bone> bones = new ArrayList<>();
|
||||||
|
|
||||||
|
private Optional<Float> visibleBoundsWidth = Optional.empty();
|
||||||
|
private Optional<Float> visibleBoundsHeight = Optional.empty();
|
||||||
|
private Optional<Vector3f> visibleBoundsOffset = Optional.empty();
|
||||||
|
private Optional<Integer> textureWidth = Optional.empty();
|
||||||
|
private Optional<Integer> textureHeight = Optional.empty();
|
||||||
|
|
||||||
|
public Builder(String identifier) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withVisibleBoundsWidth(float visibleBoundsWidth) {
|
||||||
|
this.visibleBoundsWidth = Optional.of(visibleBoundsWidth);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withVisibleBoundsHeight(float visibleBoundsHeight) {
|
||||||
|
this.visibleBoundsHeight = Optional.of(visibleBoundsHeight);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withVisibleBoundsOffset(Vector3f visibleBoundsOffset) {
|
||||||
|
this.visibleBoundsOffset = Optional.of(visibleBoundsOffset);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withTextureWidth(int textureWidth) {
|
||||||
|
this.textureWidth = Optional.of(textureWidth);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withTextureHeight(int textureHeight) {
|
||||||
|
this.textureHeight = Optional.of(textureHeight);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withBone(Bone bone) {
|
||||||
|
if (bones.stream().anyMatch(existing -> existing.name.equals(bone.name))) {
|
||||||
|
throw new IllegalArgumentException("Duplicate bone with name " + bone.name);
|
||||||
|
}
|
||||||
|
bones.add(bone);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withBone(Bone.Builder builder) {
|
||||||
|
return withBone(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BedrockGeometry build() {
|
||||||
|
return BedrockGeometry.of(new GeometryDefinition(
|
||||||
|
new GeometryInfo(identifier, visibleBoundsWidth, visibleBoundsHeight, visibleBoundsOffset, textureWidth, textureHeight), List.copyOf(bones)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public record GeometryDefinition(GeometryInfo info, List<Bone> bones) {
|
public record GeometryDefinition(GeometryInfo info, List<Bone> bones) {
|
||||||
public static final Codec<GeometryDefinition> CODEC = RecordCodecBuilder.create(instance ->
|
public static final Codec<GeometryDefinition> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
instance.group(
|
instance.group(
|
||||||
@@ -58,6 +142,59 @@ public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinit
|
|||||||
Cube.CODEC.listOf().optionalFieldOf("cubes", List.of()).forGetter(Bone::cubes)
|
Cube.CODEC.listOf().optionalFieldOf("cubes", List.of()).forGetter(Bone::cubes)
|
||||||
).apply(instance, Bone::new)
|
).apply(instance, Bone::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private final String name;
|
||||||
|
private final List<Cube> cubes = new ArrayList<>();
|
||||||
|
|
||||||
|
private Optional<String> parent = Optional.empty();
|
||||||
|
private Vector3f pivot = VECTOR3F_ZERO;
|
||||||
|
private Vector3f rotation = VECTOR3F_ZERO;
|
||||||
|
private boolean mirror = false;
|
||||||
|
private float inflate = 0.0F;
|
||||||
|
|
||||||
|
public Builder(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withParent(String parent) {
|
||||||
|
this.parent = Optional.of(parent);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withPivot(Vector3f pivot) {
|
||||||
|
this.pivot = pivot;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withRotation(Vector3f rotation) {
|
||||||
|
this.rotation = rotation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mirror() {
|
||||||
|
this.mirror = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withInflate(float inflate) {
|
||||||
|
this.inflate = inflate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withCube(Cube cube) {
|
||||||
|
this.cubes.add(cube);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withCube(Cube.Builder builder) {
|
||||||
|
return withCube(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bone build() {
|
||||||
|
return new Bone(name, parent, pivot, rotation, mirror, inflate, List.copyOf(cubes));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Cube(Vector3f origin, Vector3f size, Vector3f rotation, Vector3f pivot, float inflate, boolean mirror,
|
public record Cube(Vector3f origin, Vector3f size, Vector3f rotation, Vector3f pivot, float inflate, boolean mirror,
|
||||||
@@ -65,8 +202,8 @@ public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinit
|
|||||||
private static final Codec<Map<Direction, Face>> FACE_MAP_CODEC = Codec.unboundedMap(Direction.CODEC, Face.CODEC);
|
private static final Codec<Map<Direction, Face>> FACE_MAP_CODEC = Codec.unboundedMap(Direction.CODEC, Face.CODEC);
|
||||||
public static final Codec<Cube> CODEC = RecordCodecBuilder.create(instance ->
|
public static final Codec<Cube> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
instance.group(
|
instance.group(
|
||||||
ExtraCodecs.VECTOR3F.fieldOf("origin").forGetter(Cube::origin),
|
ExtraCodecs.VECTOR3F.fieldOf("uvOrigin").forGetter(Cube::origin),
|
||||||
ExtraCodecs.VECTOR3F.fieldOf("size").forGetter(Cube::size),
|
ExtraCodecs.VECTOR3F.fieldOf("uvSize").forGetter(Cube::size),
|
||||||
ExtraCodecs.VECTOR3F.optionalFieldOf("rotation", VECTOR3F_ZERO).forGetter(Cube::size),
|
ExtraCodecs.VECTOR3F.optionalFieldOf("rotation", VECTOR3F_ZERO).forGetter(Cube::size),
|
||||||
ExtraCodecs.VECTOR3F.optionalFieldOf("pivot", VECTOR3F_ZERO).forGetter(Cube::pivot),
|
ExtraCodecs.VECTOR3F.optionalFieldOf("pivot", VECTOR3F_ZERO).forGetter(Cube::pivot),
|
||||||
Codec.FLOAT.optionalFieldOf("inflate", 0.0F).forGetter(Cube::inflate),
|
Codec.FLOAT.optionalFieldOf("inflate", 0.0F).forGetter(Cube::inflate),
|
||||||
@@ -74,13 +211,61 @@ public record BedrockGeometry(BedrockVersion formatVersion, List<GeometryDefinit
|
|||||||
FACE_MAP_CODEC.optionalFieldOf("uv", Map.of()).forGetter(Cube::faces)
|
FACE_MAP_CODEC.optionalFieldOf("uv", Map.of()).forGetter(Cube::faces)
|
||||||
).apply(instance, Cube::new)
|
).apply(instance, Cube::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private final Vector3f origin;
|
||||||
|
private final Vector3f size;
|
||||||
|
private final Map<Direction, Face> faces = new HashMap<>();
|
||||||
|
|
||||||
|
private Vector3f rotation = VECTOR3F_ZERO;
|
||||||
|
private Vector3f pivot = VECTOR3F_ZERO;
|
||||||
|
private float inflate = 0.0F;
|
||||||
|
private boolean mirror = false;
|
||||||
|
|
||||||
|
public Builder(Vector3f origin, Vector3f size) {
|
||||||
|
this.origin = origin;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withRotation(Vector3f rotation) {
|
||||||
|
this.rotation = rotation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withPivot(Vector3f pivot) {
|
||||||
|
this.pivot = pivot;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withInflate(float inflate) {
|
||||||
|
this.inflate = inflate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mirror() {
|
||||||
|
this.mirror = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder withFace(Direction direction, Vector2f uvOrigin, Vector2f uvSize) {
|
||||||
|
if (faces.containsKey(direction)) {
|
||||||
|
throw new IllegalArgumentException("Already added a face for direction " + direction);
|
||||||
|
}
|
||||||
|
faces.put(direction, new Face(uvOrigin, uvSize));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cube build() {
|
||||||
|
return new Cube(origin, size, rotation, pivot, inflate, mirror, Map.copyOf(faces));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Face(Vector2f origin, Vector2f size) {
|
public record Face(Vector2f uvOrigin, Vector2f uvSize) {
|
||||||
public static final Codec<Face> CODEC = RecordCodecBuilder.create(instance ->
|
public static final Codec<Face> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
instance.group(
|
instance.group(
|
||||||
ExtraCodecs.VECTOR2F.fieldOf("uv").forGetter(Face::origin),
|
ExtraCodecs.VECTOR2F.fieldOf("uv").forGetter(Face::uvOrigin),
|
||||||
ExtraCodecs.VECTOR2F.fieldOf("uv_size").forGetter(Face::size)
|
ExtraCodecs.VECTOR2F.fieldOf("uv_size").forGetter(Face::uvSize)
|
||||||
).apply(instance, Face::new)
|
).apply(instance, Face::new)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user