135 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.client.renderer.item;
 | |
| 
 | |
| import com.mojang.serialization.Codec;
 | |
| import com.mojang.serialization.MapCodec;
 | |
| import com.mojang.serialization.codecs.RecordCodecBuilder;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Arrays;
 | |
| import java.util.Comparator;
 | |
| import java.util.List;
 | |
| import java.util.Optional;
 | |
| import net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import net.minecraft.client.multiplayer.ClientLevel;
 | |
| import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperties;
 | |
| import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperty;
 | |
| import net.minecraft.client.resources.model.ResolvableModel;
 | |
| import net.minecraft.world.entity.LivingEntity;
 | |
| import net.minecraft.world.item.ItemDisplayContext;
 | |
| import net.minecraft.world.item.ItemStack;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| public class RangeSelectItemModel implements ItemModel {
 | |
| 	private static final int LINEAR_SEARCH_THRESHOLD = 16;
 | |
| 	private final RangeSelectItemModelProperty property;
 | |
| 	private final float scale;
 | |
| 	private final float[] thresholds;
 | |
| 	private final ItemModel[] models;
 | |
| 	private final ItemModel fallback;
 | |
| 
 | |
| 	RangeSelectItemModel(RangeSelectItemModelProperty property, float scale, float[] thresholds, ItemModel[] models, ItemModel fallback) {
 | |
| 		this.property = property;
 | |
| 		this.thresholds = thresholds;
 | |
| 		this.models = models;
 | |
| 		this.fallback = fallback;
 | |
| 		this.scale = scale;
 | |
| 	}
 | |
| 
 | |
| 	private static int lastIndexLessOrEqual(float[] thresholds, float value) {
 | |
| 		if (thresholds.length < 16) {
 | |
| 			for (int i = 0; i < thresholds.length; i++) {
 | |
| 				if (thresholds[i] > value) {
 | |
| 					return i - 1;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return thresholds.length - 1;
 | |
| 		} else {
 | |
| 			int ix = Arrays.binarySearch(thresholds, value);
 | |
| 			if (ix < 0) {
 | |
| 				int j = ~ix;
 | |
| 				return j - 1;
 | |
| 			} else {
 | |
| 				return ix;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void update(
 | |
| 		ItemStackRenderState renderState,
 | |
| 		ItemStack stack,
 | |
| 		ItemModelResolver itemModelResolver,
 | |
| 		ItemDisplayContext displayContext,
 | |
| 		@Nullable ClientLevel level,
 | |
| 		@Nullable LivingEntity entity,
 | |
| 		int seed
 | |
| 	) {
 | |
| 		renderState.appendModelIdentityElement(this);
 | |
| 		float f = this.property.get(stack, level, entity, seed) * this.scale;
 | |
| 		ItemModel itemModel;
 | |
| 		if (Float.isNaN(f)) {
 | |
| 			itemModel = this.fallback;
 | |
| 		} else {
 | |
| 			int i = lastIndexLessOrEqual(this.thresholds, f);
 | |
| 			itemModel = i == -1 ? this.fallback : this.models[i];
 | |
| 		}
 | |
| 
 | |
| 		itemModel.update(renderState, stack, itemModelResolver, displayContext, level, entity, seed);
 | |
| 	}
 | |
| 
 | |
| 	@Environment(EnvType.CLIENT)
 | |
| 	public record Entry(float threshold, ItemModel.Unbaked model) {
 | |
| 		public static final Codec<RangeSelectItemModel.Entry> CODEC = RecordCodecBuilder.create(
 | |
| 			instance -> instance.group(
 | |
| 					Codec.FLOAT.fieldOf("threshold").forGetter(RangeSelectItemModel.Entry::threshold),
 | |
| 					ItemModels.CODEC.fieldOf("model").forGetter(RangeSelectItemModel.Entry::model)
 | |
| 				)
 | |
| 				.apply(instance, RangeSelectItemModel.Entry::new)
 | |
| 		);
 | |
| 		public static final Comparator<RangeSelectItemModel.Entry> BY_THRESHOLD = Comparator.comparingDouble(RangeSelectItemModel.Entry::threshold);
 | |
| 	}
 | |
| 
 | |
| 	@Environment(EnvType.CLIENT)
 | |
| 	public record Unbaked(RangeSelectItemModelProperty property, float scale, List<RangeSelectItemModel.Entry> entries, Optional<ItemModel.Unbaked> fallback)
 | |
| 		implements ItemModel.Unbaked {
 | |
| 		public static final MapCodec<RangeSelectItemModel.Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(
 | |
| 			instance -> instance.group(
 | |
| 					RangeSelectItemModelProperties.MAP_CODEC.forGetter(RangeSelectItemModel.Unbaked::property),
 | |
| 					Codec.FLOAT.optionalFieldOf("scale", 1.0F).forGetter(RangeSelectItemModel.Unbaked::scale),
 | |
| 					RangeSelectItemModel.Entry.CODEC.listOf().fieldOf("entries").forGetter(RangeSelectItemModel.Unbaked::entries),
 | |
| 					ItemModels.CODEC.optionalFieldOf("fallback").forGetter(RangeSelectItemModel.Unbaked::fallback)
 | |
| 				)
 | |
| 				.apply(instance, RangeSelectItemModel.Unbaked::new)
 | |
| 		);
 | |
| 
 | |
| 		@Override
 | |
| 		public MapCodec<RangeSelectItemModel.Unbaked> type() {
 | |
| 			return MAP_CODEC;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public ItemModel bake(ItemModel.BakingContext context) {
 | |
| 			float[] fs = new float[this.entries.size()];
 | |
| 			ItemModel[] itemModels = new ItemModel[this.entries.size()];
 | |
| 			List<RangeSelectItemModel.Entry> list = new ArrayList(this.entries);
 | |
| 			list.sort(RangeSelectItemModel.Entry.BY_THRESHOLD);
 | |
| 
 | |
| 			for (int i = 0; i < list.size(); i++) {
 | |
| 				RangeSelectItemModel.Entry entry = (RangeSelectItemModel.Entry)list.get(i);
 | |
| 				fs[i] = entry.threshold;
 | |
| 				itemModels[i] = entry.model.bake(context);
 | |
| 			}
 | |
| 
 | |
| 			ItemModel itemModel = (ItemModel)this.fallback.map(unbaked -> unbaked.bake(context)).orElse(context.missingItemModel());
 | |
| 			return new RangeSelectItemModel(this.property, this.scale, fs, itemModels, itemModel);
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void resolveDependencies(ResolvableModel.Resolver resolver) {
 | |
| 			this.fallback.ifPresent(unbaked -> unbaked.resolveDependencies(resolver));
 | |
| 			this.entries.forEach(entry -> entry.model.resolveDependencies(resolver));
 | |
| 		}
 | |
| 	}
 | |
| }
 |