1
0
mirror of https://github.com/GeyserMC/Rainbow.git synced 2025-12-19 14:59:16 +00:00

Proper attachable scripts (I think)

This commit is contained in:
Eclipse
2025-07-04 18:53:08 +00:00
parent 90414cbb88
commit 95f3f3acd8
4 changed files with 76 additions and 8 deletions

View File

@@ -1,8 +1,12 @@
package org.geysermc.packgenerator.pack.attachable; package org.geysermc.packgenerator.pack.attachable;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.StringRepresentable; import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
import org.geysermc.packgenerator.CodecUtil; import org.geysermc.packgenerator.CodecUtil;
@@ -10,6 +14,7 @@ import org.geysermc.packgenerator.PackConstants;
import org.geysermc.packgenerator.mapping.geyser.GeyserSingleDefinition; import org.geysermc.packgenerator.mapping.geyser.GeyserSingleDefinition;
import org.geysermc.packgenerator.pack.BedrockTextures; import org.geysermc.packgenerator.pack.BedrockTextures;
import org.geysermc.packgenerator.pack.BedrockVersion; import org.geysermc.packgenerator.pack.BedrockVersion;
import org.geysermc.packgenerator.pack.geometry.BedrockGeometry;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
@@ -19,6 +24,8 @@ import java.util.EnumMap;
import java.util.HashMap; 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.stream.Stream;
public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo info) { public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo info) {
public static final Codec<BedrockAttachable> CODEC = RecordCodecBuilder.create(instance -> public static final Codec<BedrockAttachable> CODEC = RecordCodecBuilder.create(instance ->
@@ -46,8 +53,8 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
default -> ""; default -> "";
}; };
return builder(identifier) return builder(identifier)
.withMaterial(DisplaySlot.DEFAULT, "armor") .withMaterial(DisplaySlot.DEFAULT, VanillaMaterials.ARMOR)
.withMaterial(DisplaySlot.ENCHANTED, "armor_enchanted") .withMaterial(DisplaySlot.ENCHANTED, VanillaMaterials.ARMOR_ENCHANTED)
.withTexture(DisplaySlot.DEFAULT, texture) .withTexture(DisplaySlot.DEFAULT, texture)
.withTexture(DisplaySlot.ENCHANTED, VanillaTextures.ENCHANTED_ACTOR_GLINT) .withTexture(DisplaySlot.ENCHANTED, VanillaTextures.ENCHANTED_ACTOR_GLINT)
.withGeometry(DisplaySlot.DEFAULT, VanillaGeometries.fromEquipmentSlot(slot)) .withGeometry(DisplaySlot.DEFAULT, VanillaGeometries.fromEquipmentSlot(slot))
@@ -56,13 +63,25 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
.build(); .build();
} }
public static BedrockAttachable geometry(ResourceLocation identifier, BedrockGeometry.GeometryDefinition geometry, String texture) {
// TODO animations to make it look right
return builder(identifier)
.withMaterial(DisplaySlot.DEFAULT, VanillaMaterials.ENTITY)
.withMaterial(DisplaySlot.ENCHANTED, VanillaMaterials.ENTITY_ALPHATEST_GLINT)
.withTexture(DisplaySlot.DEFAULT, texture)
.withTexture(DisplaySlot.ENCHANTED, VanillaTextures.ENCHANTED_ITEM_GLINT)
.withGeometry(DisplaySlot.DEFAULT, geometry.info().identifier())
.withRenderController(VanillaRenderControllers.ITEM_DEFAULT)
.build();
}
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);
private final EnumMap<DisplaySlot, String> textures = 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 EnumMap<DisplaySlot, String> geometries = new EnumMap<>(DisplaySlot.class);
private final Map<String, String> animations = new HashMap<>(); private final Map<String, String> animations = new HashMap<>();
private final Map<String, String> scripts = new HashMap<>(); private final Map<String, List<Script>> scripts = new HashMap<>();
private final List<String> renderControllers = new ArrayList<>(); private final List<String> renderControllers = new ArrayList<>();
public Builder(ResourceLocation identifier) { public Builder(ResourceLocation identifier) {
@@ -89,11 +108,19 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
return this; return this;
} }
public Builder withScript(String key, String script) { public Builder withScript(String key, Script script) {
scripts.put(key, script); scripts.merge(key, List.of(script), (scripts, newScript) -> Stream.concat(scripts.stream(), newScript.stream()).toList());
return this; return this;
} }
public Builder withScript(String key, String script, String condition) {
return withScript(key, new Script(script, Optional.of(condition)));
}
public Builder withScript(String key, String script) {
return withScript(key, new Script(script, Optional.empty()));
}
public Builder withRenderController(String controller) { public Builder withRenderController(String controller) {
renderControllers.add(controller); renderControllers.add(controller);
return this; return this;
@@ -101,7 +128,8 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
public BedrockAttachable build() { public BedrockAttachable build() {
return new BedrockAttachable(PackConstants.ENGINE_VERSION, return new BedrockAttachable(PackConstants.ENGINE_VERSION,
new AttachableInfo(identifier, verifyDefault(materials), verifyDefault(textures), verifyDefault(geometries), Map.copyOf(animations), Map.copyOf(scripts), List.copyOf(renderControllers))); new AttachableInfo(identifier, verifyDefault(materials), verifyDefault(textures), verifyDefault(geometries), Map.copyOf(animations),
new Scripts(Map.copyOf(scripts)), List.copyOf(renderControllers)));
} }
private static DisplayMap verifyDefault(EnumMap<DisplaySlot, String> map) { private static DisplayMap verifyDefault(EnumMap<DisplaySlot, String> map) {
@@ -113,7 +141,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
} }
public record AttachableInfo(ResourceLocation identifier, DisplayMap materials, DisplayMap textures, public record AttachableInfo(ResourceLocation identifier, DisplayMap materials, DisplayMap textures,
DisplayMap geometry, Map<String, String> animations, Map<String, String> scripts, DisplayMap geometry, Map<String, String> animations, Scripts scripts,
List<String> renderControllers) { List<String> renderControllers) {
private static final Codec<Map<String, String>> STRING_MAP_CODEC = Codec.unboundedMap(Codec.STRING, Codec.STRING); 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 -> public static final Codec<AttachableInfo> CODEC = RecordCodecBuilder.create(instance ->
@@ -123,7 +151,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
DisplayMap.CODEC.fieldOf("textures").forGetter(AttachableInfo::textures), DisplayMap.CODEC.fieldOf("textures").forGetter(AttachableInfo::textures),
DisplayMap.CODEC.fieldOf("geometry").forGetter(AttachableInfo::geometry), DisplayMap.CODEC.fieldOf("geometry").forGetter(AttachableInfo::geometry),
STRING_MAP_CODEC.optionalFieldOf("animations", Map.of()).forGetter(AttachableInfo::animations), STRING_MAP_CODEC.optionalFieldOf("animations", Map.of()).forGetter(AttachableInfo::animations),
STRING_MAP_CODEC.optionalFieldOf("scripts", Map.of()).forGetter(AttachableInfo::scripts), Scripts.CODEC.optionalFieldOf("scripts", Scripts.EMPTY).forGetter(AttachableInfo::scripts),
Codec.STRING.listOf().optionalFieldOf("render_controllers", List.of()).forGetter(AttachableInfo::renderControllers) Codec.STRING.listOf().optionalFieldOf("render_controllers", List.of()).forGetter(AttachableInfo::renderControllers)
).apply(instance, AttachableInfo::new) ).apply(instance, AttachableInfo::new)
); );
@@ -151,4 +179,40 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
return name; return name;
} }
} }
public record Scripts(Map<String, List<Script>> scripts) {
public static final Codec<Scripts> CODEC = Codec.unboundedMap(Codec.STRING, ExtraCodecs.compactListCodec(Script.CODEC)).xmap(Scripts::new, Scripts::scripts);
public static final Scripts EMPTY = new Scripts(Map.of());
}
public record Script(String script, Optional<String> condition) {
private static final Codec<Script> SCRIPT_WITH_CONDITION_CODEC = Codec.unboundedMap(Codec.STRING, Codec.STRING).flatXmap(
scriptMap -> {
if (scriptMap.size() != 1) {
return DataResult.error(() -> "Script with condition must have exactly one key-value pair");
}
String script = scriptMap.keySet().iterator().next();
return DataResult.success(new Script(script, Optional.of(scriptMap.get(script))));
},
script -> script.condition.map(condition -> DataResult.success(Map.of(script.script, condition)))
.orElse(DataResult.error(() -> "Script must have a condition"))
);
public static final Codec<Script> CODEC = SCRIPT_WITH_CONDITION_CODEC.mapResult(new Codec.ResultFunction<Script>() {
@Override
public <T> DataResult<Pair<Script, T>> apply(DynamicOps<T> ops, T input, DataResult<Pair<Script, T>> decoded) {
if (decoded.isError()) {
return Codec.STRING.map(script -> new Script(script, Optional.empty())).decode(ops, input);
}
return decoded;
}
@Override
public <T> DataResult<T> coApply(DynamicOps<T> ops, Script input, DataResult<T> encoded) {
if (encoded.isError()) {
return Codec.STRING.encodeStart(ops, input.script);
}
return encoded;
}
});
}
} }

View File

@@ -3,4 +3,6 @@ package org.geysermc.packgenerator.pack.attachable;
public class VanillaMaterials { public class VanillaMaterials {
public static final String ARMOR = "armor"; public static final String ARMOR = "armor";
public static final String ARMOR_ENCHANTED = "armor_enchanted"; public static final String ARMOR_ENCHANTED = "armor_enchanted";
public static final String ENTITY = "entity";
public static final String ENTITY_ALPHATEST_GLINT = "entity_alphatest_glint";
} }

View File

@@ -2,4 +2,5 @@ package org.geysermc.packgenerator.pack.attachable;
public class VanillaRenderControllers { public class VanillaRenderControllers {
public static final String ARMOR = "controller.render.armor"; public static final String ARMOR = "controller.render.armor";
public static final String ITEM_DEFAULT = "controller.render.item_default";
} }

View File

@@ -2,4 +2,5 @@ package org.geysermc.packgenerator.pack.attachable;
public class VanillaTextures { public class VanillaTextures {
public static final String ENCHANTED_ACTOR_GLINT = "misc/enchanted_actor_glint"; public static final String ENCHANTED_ACTOR_GLINT = "misc/enchanted_actor_glint";
public static final String ENCHANTED_ITEM_GLINT = "misc/enchanted_item_glint";
} }