mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Support writing legacy definitions
This commit is contained in:
@@ -34,4 +34,8 @@ public class Rainbow implements ClientModInitializer {
|
||||
public static ResourceLocation getModdedLocation(String path) {
|
||||
return ResourceLocation.fromNamespaceAndPath(MOD_ID, path);
|
||||
}
|
||||
|
||||
public static String fileSafeResourceLocation(ResourceLocation location) {
|
||||
return location.toString().replace(':', '.').replace('/', '_');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.geysermc.rainbow.mapping.attachable.AttachableMapper;
|
||||
import org.geysermc.rainbow.mapping.geometry.BedrockGeometryContext;
|
||||
import org.geysermc.rainbow.mapping.geometry.GeometryMapper;
|
||||
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
|
||||
import org.geysermc.rainbow.mapping.geyser.GeyserBaseDefinition;
|
||||
import org.geysermc.rainbow.mapping.geyser.GeyserMappings;
|
||||
import org.geysermc.rainbow.mapping.geyser.GeyserSingleDefinition;
|
||||
import org.geysermc.rainbow.mapping.geyser.predicate.GeyserConditionPredicate;
|
||||
@@ -78,14 +79,17 @@ public class BedrockItemMapper {
|
||||
}
|
||||
|
||||
mapItem(model, displayName, protectionValue, stack.getComponentsPatch(), reporter,
|
||||
mapping -> mappings.map(stack.getItemHolder(), mapping), packPath, itemConsumer, additionalTextureConsumer);
|
||||
packPath, mapping -> mappings.map(stack.getItemHolder(), new GeyserSingleDefinition(mapping, Optional.of(model))),
|
||||
itemConsumer, additionalTextureConsumer);
|
||||
}
|
||||
|
||||
public static void mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter,
|
||||
Consumer<GeyserSingleDefinition> mappingConsumer, Path packPath, BedrockItemConsumer itemConsumer, Consumer<ResourceLocation> additionalTextureConsumer) {
|
||||
Path packPath, Consumer<GeyserBaseDefinition> mappingConsumer, BedrockItemConsumer itemConsumer,
|
||||
Consumer<ResourceLocation> additionalTextureConsumer) {
|
||||
ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation);
|
||||
MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch,
|
||||
reporter.forChild(() -> "client item definition " + modelLocation + " "), mappingConsumer, itemConsumer, packPath, additionalTextureConsumer);
|
||||
MappingContext context = new MappingContext(List.of(), displayName, protectionValue, componentPatch,
|
||||
reporter.forChild(() -> "client item definition " + modelLocation + " "),
|
||||
packPath, mappingConsumer, itemConsumer, additionalTextureConsumer);
|
||||
mapItem(model, context);
|
||||
}
|
||||
|
||||
@@ -153,8 +157,8 @@ public class BedrockItemMapper {
|
||||
mapItem(onFalse, context.with(new GeyserConditionPredicate(predicateProperty, false), "condition on false "));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> void mapSelectModel(SelectItemModel<T> model, MappingContext context) {
|
||||
//noinspection unchecked
|
||||
SelectItemModelProperty<T> property = ((SelectItemModelAccessor<T>) model).getProperty();
|
||||
Function<T, GeyserMatchPredicate.MatchPredicateData> dataConstructor = switch (property) {
|
||||
case Charge ignored -> chargeType -> new GeyserMatchPredicate.ChargeType((CrossbowItem.ChargeType) chargeType);
|
||||
@@ -165,7 +169,6 @@ public class BedrockItemMapper {
|
||||
default -> null;
|
||||
};
|
||||
|
||||
//noinspection unchecked
|
||||
Object2ObjectMap<T, ItemModel> cases = ((SelectItemModelCasesAccessor<T>) model).rainbow$getCases();
|
||||
|
||||
if (dataConstructor == null) {
|
||||
@@ -186,24 +189,24 @@ public class BedrockItemMapper {
|
||||
mapItem(cases.defaultReturnValue(), context.child("select fallback case "));
|
||||
}
|
||||
|
||||
private record MappingContext(List<GeyserPredicate> predicateStack, ResourceLocation model, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter,
|
||||
Consumer<GeyserSingleDefinition> mappingConsumer, BedrockItemConsumer itemConsumer, Path packPath,
|
||||
private record MappingContext(List<GeyserPredicate> predicateStack, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter,
|
||||
Path packPath, Consumer<GeyserBaseDefinition> mappingConsumer, BedrockItemConsumer itemConsumer,
|
||||
Consumer<ResourceLocation> additionalTextureConsumer) {
|
||||
|
||||
public MappingContext with(GeyserPredicate predicate, String childName) {
|
||||
return new MappingContext(Stream.concat(predicateStack.stream(), Stream.of(predicate)).toList(), model, displayName, protectionValue, componentPatch,
|
||||
reporter.forChild(() -> childName), mappingConsumer, itemConsumer, packPath, additionalTextureConsumer);
|
||||
return new MappingContext(Stream.concat(predicateStack.stream(), Stream.of(predicate)).toList(), displayName, protectionValue, componentPatch,
|
||||
reporter.forChild(() -> childName), packPath, mappingConsumer, itemConsumer, additionalTextureConsumer);
|
||||
}
|
||||
|
||||
public MappingContext child(String childName) {
|
||||
return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName),
|
||||
mappingConsumer, itemConsumer, packPath, additionalTextureConsumer);
|
||||
return new MappingContext(predicateStack, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName),
|
||||
packPath, mappingConsumer, itemConsumer, additionalTextureConsumer);
|
||||
}
|
||||
|
||||
public void create(ResourceLocation bedrockIdentifier, ResourceLocation texture, boolean displayHandheld,
|
||||
Optional<ResolvedModel> customModel) {
|
||||
GeyserSingleDefinition definition = new GeyserSingleDefinition(Optional.of(model), bedrockIdentifier, Optional.of(displayName), predicateStack,
|
||||
new GeyserSingleDefinition.BedrockOptions(Optional.empty(), true, displayHandheld, protectionValue), componentPatch);
|
||||
GeyserBaseDefinition definition = new GeyserBaseDefinition(bedrockIdentifier, Optional.of(displayName), predicateStack,
|
||||
new GeyserBaseDefinition.BedrockOptions(Optional.empty(), true, displayHandheld, protectionValue), componentPatch);
|
||||
try {
|
||||
mappingConsumer.accept(definition);
|
||||
} catch (Exception exception) {
|
||||
@@ -221,7 +224,7 @@ public class BedrockItemMapper {
|
||||
boolean exportTexture = true;
|
||||
if (customModel.isPresent()) {
|
||||
ItemStack fakeItem = new ItemStack(Items.FLINT);
|
||||
fakeItem.set(DataComponents.ITEM_MODEL, model);
|
||||
//fakeItem.set(DataComponents.ITEM_MODEL, model); TODO
|
||||
|
||||
texture = texture.withPath(path -> path + "_icon");
|
||||
GeometryRenderer.render(fakeItem, packPath.resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png"));
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.geysermc.rainbow.mapping.geyser;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.geysermc.rainbow.Rainbow;
|
||||
import org.geysermc.rainbow.mapping.geyser.predicate.GeyserPredicate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
// TODO other keys, etc.
|
||||
// TODO sometimes still includes components key when patch before filtering is not empty but after is
|
||||
// TODO display name can be a component
|
||||
public record GeyserBaseDefinition(ResourceLocation bedrockIdentifier, Optional<String> displayName,
|
||||
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) {
|
||||
private static final List<DataComponentType<?>> SUPPORTED_COMPONENTS = List.of(DataComponents.CONSUMABLE, DataComponents.EQUIPPABLE, DataComponents.FOOD,
|
||||
DataComponents.MAX_DAMAGE, DataComponents.MAX_STACK_SIZE, DataComponents.USE_COOLDOWN, DataComponents.ENCHANTABLE, DataComponents.ENCHANTMENT_GLINT_OVERRIDE);
|
||||
|
||||
private static final Codec<DataComponentPatch> FILTERED_COMPONENT_MAP_CODEC = DataComponentPatch.CODEC.xmap(Function.identity(), patch -> {
|
||||
DataComponentPatch.Builder filtered = DataComponentPatch.builder();
|
||||
patch.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().isEmpty() || SUPPORTED_COMPONENTS.contains(entry.getKey()))
|
||||
.forEach(entry -> {
|
||||
if (entry.getValue().isPresent()) {
|
||||
filtered.set((DataComponentType) entry.getKey(), entry.getValue().orElseThrow());
|
||||
} else {
|
||||
filtered.remove(entry.getKey());
|
||||
}
|
||||
});
|
||||
return filtered.build();
|
||||
});
|
||||
|
||||
public static final MapCodec<GeyserBaseDefinition> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserBaseDefinition::bedrockIdentifier),
|
||||
Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserBaseDefinition::displayName),
|
||||
GeyserPredicate.LIST_CODEC.optionalFieldOf("predicate", List.of()).forGetter(GeyserBaseDefinition::predicates),
|
||||
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserBaseDefinition::bedrockOptions),
|
||||
FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserBaseDefinition::components)
|
||||
).apply(instance, GeyserBaseDefinition::new)
|
||||
);
|
||||
|
||||
public boolean conflictsWith(GeyserBaseDefinition other) {
|
||||
if (predicates.size() == other.predicates.size()) {
|
||||
boolean predicatesAreEqual = true;
|
||||
for (GeyserPredicate predicate : predicates) {
|
||||
if (!other.predicates.contains(predicate)) {
|
||||
predicatesAreEqual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return predicatesAreEqual;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String textureName() {
|
||||
return bedrockOptions.icon.orElse(Rainbow.fileSafeResourceLocation(bedrockIdentifier));
|
||||
}
|
||||
|
||||
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) {
|
||||
public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Codec.STRING.optionalFieldOf("icon").forGetter(BedrockOptions::icon),
|
||||
Codec.BOOL.optionalFieldOf("allow_offhand", true).forGetter(BedrockOptions::allowOffhand),
|
||||
Codec.BOOL.optionalFieldOf("display_handheld", false).forGetter(BedrockOptions::displayHandheld),
|
||||
Codec.INT.optionalFieldOf("protection_value", 0).forGetter(BedrockOptions::protectionValue)
|
||||
).apply(instance, BedrockOptions::new)
|
||||
);
|
||||
public static final BedrockOptions DEFAULT = new BedrockOptions(Optional.empty(), true, false, 0);
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,16 @@ public record GeyserGroupDefinition(Optional<ResourceLocation> model, List<Geyse
|
||||
return new GeyserGroupDefinition(model, Stream.concat(definitions.stream(), Stream.of(mapping)).toList());
|
||||
}
|
||||
|
||||
public boolean isFor(ResourceLocation model) {
|
||||
return this.model.isPresent() && this.model.get().equals(model);
|
||||
public boolean isFor(Optional<ResourceLocation> model) {
|
||||
return this.model.isPresent() && model.isPresent() && this.model.get().equals(model.get());
|
||||
}
|
||||
|
||||
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserSingleDefinition other) {
|
||||
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
|
||||
Optional<ResourceLocation> thisModel = model.or(() -> parentModel);
|
||||
for (GeyserMapping definition : definitions) {
|
||||
if (definition instanceof GeyserGroupDefinition group && group.conflictsWith(thisModel, other)) {
|
||||
return true;
|
||||
} else if (definition instanceof GeyserSingleDefinition single && single.conflictsWith(thisModel, other)) {
|
||||
} else if (definition instanceof GeyserItemDefinition item && item.conflictsWith(thisModel, other)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.geysermc.rainbow.mapping.geyser;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface GeyserItemDefinition extends GeyserMapping {
|
||||
|
||||
GeyserBaseDefinition base();
|
||||
|
||||
boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.geysermc.rainbow.mapping.geyser;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public record GeyserLegacyDefinition(GeyserBaseDefinition base, int customModelData) implements GeyserItemDefinition {
|
||||
|
||||
public static final MapCodec<GeyserLegacyDefinition> CODEC = RecordCodecBuilder.mapCodec(instance ->
|
||||
instance.group(
|
||||
GeyserBaseDefinition.MAP_CODEC.forGetter(GeyserLegacyDefinition::base),
|
||||
Codec.INT.fieldOf("custom_model_data").forGetter(GeyserLegacyDefinition::customModelData)
|
||||
).apply(instance, GeyserLegacyDefinition::new)
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
|
||||
if (other instanceof GeyserLegacyDefinition otherLegacy) {
|
||||
return customModelData == otherLegacy.customModelData && base.conflictsWith(otherLegacy.base);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type type() {
|
||||
return Type.LEGACY;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public interface GeyserMapping {
|
||||
|
||||
enum Type implements StringRepresentable {
|
||||
SINGLE("definition", GeyserSingleDefinition.CODEC),
|
||||
LEGACY("legacy", GeyserLegacyDefinition.CODEC),
|
||||
GROUP("group", GeyserGroupDefinition.CODEC);
|
||||
|
||||
public static final Codec<Type> CODEC = StringRepresentable.fromEnum(Type::values);
|
||||
|
||||
@@ -36,8 +36,8 @@ public class GeyserMappings {
|
||||
}
|
||||
}
|
||||
|
||||
public void map(Holder<Item> item, GeyserSingleDefinition mapping) {
|
||||
ResourceLocation model = mapping.model().orElseThrow();
|
||||
public void map(Holder<Item> item, GeyserItemDefinition mapping) {
|
||||
Optional<ResourceLocation> model = mapping instanceof GeyserSingleDefinition single ? Optional.of(single.model().orElseThrow()) : Optional.empty();
|
||||
Optional<GeyserGroupDefinition> modelGroup = Optional.empty();
|
||||
|
||||
Collection<GeyserMapping> existingMappings = new ArrayList<>(mappings.get(item));
|
||||
@@ -48,19 +48,22 @@ public class GeyserMappings {
|
||||
}
|
||||
modelGroup = Optional.of(existingGroup);
|
||||
break;
|
||||
} else if (existing instanceof GeyserSingleDefinition single) {
|
||||
if (single.conflictsWith(Optional.empty(), mapping)) {
|
||||
throw new IllegalArgumentException("Mapping conflicts with existing single mapping");
|
||||
} else if (model.equals(single.model().orElseThrow())) {
|
||||
mappings.remove(item, single);
|
||||
modelGroup = Optional.of(new GeyserGroupDefinition(Optional.of(model), List.of(single.withoutModel())));
|
||||
} else if (existing instanceof GeyserItemDefinition itemDefinition) {
|
||||
if (itemDefinition.conflictsWith(Optional.empty(), mapping)) {
|
||||
throw new IllegalArgumentException("Mapping conflicts with existing item mapping");
|
||||
} else if (model.isPresent() && itemDefinition instanceof GeyserSingleDefinition single && model.get().equals(single.model().orElseThrow())) {
|
||||
mappings.remove(item, itemDefinition);
|
||||
modelGroup = Optional.of(new GeyserGroupDefinition(model, List.of(single.withoutModel())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modelGroup.isPresent()) {
|
||||
mappings.remove(item, modelGroup.get());
|
||||
mappings.put(item, modelGroup.get().with(mapping.withoutModel()));
|
||||
|
||||
// We're only putting mappings in groups when they're single definitions - legacy mappings always go ungrouped
|
||||
assert mapping instanceof GeyserSingleDefinition;
|
||||
mappings.put(item, modelGroup.get().with(((GeyserSingleDefinition) mapping).withoutModel()));
|
||||
} else {
|
||||
mappings.put(item, mapping);
|
||||
}
|
||||
|
||||
@@ -1,96 +1,35 @@
|
||||
package org.geysermc.rainbow.mapping.geyser;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.geysermc.rainbow.mapping.geyser.predicate.GeyserPredicate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
// TODO other keys, etc.
|
||||
// TODO sometimes still includes components key when patch before filtering is not empty but after is
|
||||
// TODO display name can be a component
|
||||
public record GeyserSingleDefinition(Optional<ResourceLocation> model, ResourceLocation bedrockIdentifier, Optional<String> displayName,
|
||||
List<GeyserPredicate> predicates, BedrockOptions bedrockOptions, DataComponentPatch components) implements GeyserMapping {
|
||||
private static final List<DataComponentType<?>> SUPPORTED_COMPONENTS = List.of(DataComponents.CONSUMABLE, DataComponents.EQUIPPABLE, DataComponents.FOOD,
|
||||
DataComponents.MAX_DAMAGE, DataComponents.MAX_STACK_SIZE, DataComponents.USE_COOLDOWN, DataComponents.ENCHANTABLE, DataComponents.ENCHANTMENT_GLINT_OVERRIDE);
|
||||
|
||||
private static final Codec<DataComponentPatch> FILTERED_COMPONENT_MAP_CODEC = DataComponentPatch.CODEC.xmap(Function.identity(), patch -> {
|
||||
DataComponentPatch.Builder filtered = DataComponentPatch.builder();
|
||||
patch.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().isEmpty() || SUPPORTED_COMPONENTS.contains(entry.getKey()))
|
||||
.forEach(entry -> {
|
||||
if (entry.getValue().isPresent()) {
|
||||
filtered.set((DataComponentType) entry.getKey(), entry.getValue().orElseThrow());
|
||||
} else {
|
||||
filtered.remove(entry.getKey());
|
||||
}
|
||||
});
|
||||
return filtered.build();
|
||||
});
|
||||
|
||||
public record GeyserSingleDefinition(GeyserBaseDefinition base, Optional<ResourceLocation> model) implements GeyserItemDefinition {
|
||||
public static final MapCodec<GeyserSingleDefinition> CODEC = RecordCodecBuilder.mapCodec(instance ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC.optionalFieldOf("model").forGetter(GeyserSingleDefinition::model),
|
||||
ResourceLocation.CODEC.fieldOf("bedrock_identifier").forGetter(GeyserSingleDefinition::bedrockIdentifier),
|
||||
Codec.STRING.optionalFieldOf("display_name").forGetter(GeyserSingleDefinition::displayName),
|
||||
GeyserPredicate.LIST_CODEC.optionalFieldOf("predicate", List.of()).forGetter(GeyserSingleDefinition::predicates),
|
||||
BedrockOptions.CODEC.optionalFieldOf("bedrock_options", BedrockOptions.DEFAULT).forGetter(GeyserSingleDefinition::bedrockOptions),
|
||||
FILTERED_COMPONENT_MAP_CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(GeyserSingleDefinition::components)
|
||||
GeyserBaseDefinition.MAP_CODEC.forGetter(GeyserSingleDefinition::base),
|
||||
ResourceLocation.CODEC.optionalFieldOf("model").forGetter(GeyserSingleDefinition::model)
|
||||
).apply(instance, GeyserSingleDefinition::new)
|
||||
);
|
||||
|
||||
public String textureName() {
|
||||
return bedrockOptions.icon.orElse(iconFromResourceLocation(bedrockIdentifier));
|
||||
}
|
||||
|
||||
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserSingleDefinition other) {
|
||||
@Override
|
||||
public boolean conflictsWith(Optional<ResourceLocation> parentModel, GeyserItemDefinition other) {
|
||||
if (other instanceof GeyserSingleDefinition otherSingle) {
|
||||
ResourceLocation thisModel = model.or(() -> parentModel).orElseThrow();
|
||||
ResourceLocation otherModel = other.model.or(() -> parentModel).orElseThrow();
|
||||
if (!thisModel.equals(otherModel)) {
|
||||
return false;
|
||||
} else if (predicates.size() == other.predicates.size()) {
|
||||
boolean predicatesAreEqual = true;
|
||||
for (GeyserPredicate predicate : predicates) {
|
||||
if (!other.predicates.contains(predicate)) {
|
||||
predicatesAreEqual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return predicatesAreEqual;
|
||||
ResourceLocation otherModel = otherSingle.model.or(() -> parentModel).orElseThrow();
|
||||
return thisModel.equals(otherModel) && base.conflictsWith(other.base());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public GeyserSingleDefinition withoutModel() {
|
||||
return new GeyserSingleDefinition(Optional.empty(), bedrockIdentifier, displayName, predicates, bedrockOptions, components);
|
||||
return new GeyserSingleDefinition(base, Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type type() {
|
||||
return Type.SINGLE;
|
||||
}
|
||||
|
||||
public record BedrockOptions(Optional<String> icon, boolean allowOffhand, boolean displayHandheld, int protectionValue) {
|
||||
public static final Codec<BedrockOptions> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Codec.STRING.optionalFieldOf("icon").forGetter(BedrockOptions::icon),
|
||||
Codec.BOOL.optionalFieldOf("allow_offhand", true).forGetter(BedrockOptions::allowOffhand),
|
||||
Codec.BOOL.optionalFieldOf("display_handheld", false).forGetter(BedrockOptions::displayHandheld),
|
||||
Codec.INT.optionalFieldOf("protection_value", 0).forGetter(BedrockOptions::protectionValue)
|
||||
).apply(instance, BedrockOptions::new)
|
||||
);
|
||||
public static final BedrockOptions DEFAULT = new BedrockOptions(Optional.empty(), true, false, 0);
|
||||
}
|
||||
|
||||
// TODO this method is used in other places too now, maybe move it
|
||||
public static String iconFromResourceLocation(ResourceLocation location) {
|
||||
return location.toString().replace(':', '.').replace('/', '_');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.geysermc.rainbow.pack;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.geysermc.rainbow.mapping.geyser.GeyserSingleDefinition;
|
||||
import org.geysermc.rainbow.Rainbow;
|
||||
import org.geysermc.rainbow.pack.animation.BedrockAnimation;
|
||||
import org.geysermc.rainbow.pack.attachable.BedrockAttachable;
|
||||
import org.geysermc.rainbow.pack.geometry.BedrockGeometry;
|
||||
@@ -21,7 +21,7 @@ public record BedrockItem(ResourceLocation identifier, String textureName, Resou
|
||||
geometry.get().save(geometryDirectory);
|
||||
}
|
||||
if (animation.isPresent()) {
|
||||
animation.get().save(animationDirectory, GeyserSingleDefinition.iconFromResourceLocation(identifier));
|
||||
animation.get().save(animationDirectory, Rainbow.fileSafeResourceLocation(identifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import org.geysermc.rainbow.CodecUtil;
|
||||
import org.geysermc.rainbow.PackConstants;
|
||||
import org.geysermc.rainbow.mapping.geyser.GeyserSingleDefinition;
|
||||
import org.geysermc.rainbow.Rainbow;
|
||||
import org.geysermc.rainbow.pack.BedrockTextures;
|
||||
import org.geysermc.rainbow.pack.BedrockVersion;
|
||||
import org.geysermc.rainbow.pack.geometry.BedrockGeometry;
|
||||
@@ -37,7 +37,7 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf
|
||||
|
||||
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"));
|
||||
CodecUtil.trySaveJson(CODEC, this, attachablesDirectory.resolve(Rainbow.fileSafeResourceLocation(info.identifier) + ".json"));
|
||||
}
|
||||
|
||||
public static Builder builder(ResourceLocation identifier) {
|
||||
|
||||
Reference in New Issue
Block a user