use of slimeknights.tconstruct.library.materials.IMaterialRegistry in project TinkersConstruct by SlimeKnights.
the class ToolBuildHandler method randomMaterials.
/**
* Gets a list of random materials consistent with the given tool definition data
* @param data Data, primarily used for part requirements
* @param maxTier Max tier of material allowed
* @param allowHidden If true, hidden materials may be used
* @return List of random materials
*/
public static MaterialNBT randomMaterials(ToolDefinitionData data, int maxTier, boolean allowHidden) {
// start by getting a list of materials for each stat type we need
List<PartRequirement> requirements = data.getParts();
// figure out which stat types we need
Map<MaterialStatsId, List<IMaterial>> materialChoices = requirements.stream().map(PartRequirement::getStatType).distinct().collect(Collectors.toMap(Function.identity(), t -> new ArrayList<>()));
IMaterialRegistry registry = MaterialRegistry.getInstance();
registry.getAllMaterials().stream().filter(mat -> (allowHidden || !mat.isHidden()) && mat.getTier() <= maxTier).forEach(mat -> {
for (IMaterialStats stats : registry.getAllStats(mat.getIdentifier())) {
List<IMaterial> list = materialChoices.get(stats.getIdentifier());
if (list != null) {
list.add(mat);
}
}
});
// then randomly choose a material from the lists for each part
MaterialNBT.Builder builder = MaterialNBT.builder();
for (PartRequirement requirement : requirements) {
// if the list has no materials for some reason, skip, null should be impossible but might as well be safe
List<IMaterial> choices = materialChoices.get(requirement.getStatType());
if (choices == null || choices.isEmpty()) {
builder.add(MaterialVariant.UNKNOWN);
TConstruct.LOG.error("Failed to find a {} material of type {} below tier {}", allowHidden ? "non-hidden " : "", requirement.getStatType(), maxTier);
} else {
builder.add(choices.get(TConstruct.RANDOM.nextInt(choices.size())));
}
}
return builder.build();
}
use of slimeknights.tconstruct.library.materials.IMaterialRegistry in project TinkersConstruct by SlimeKnights.
the class ModifierUsageCommand method runForType.
private static int runForType(CommandContext<CommandSourceStack> context, ModifierUsages filter, @Nullable OptionalSlotType slotFilter) {
// recipe modifiers are used in a displayable modifier recipe
HashMultimap<SlotType, Modifier> recipeModifiers = context.getSource().getLevel().getRecipeManager().byType(RecipeTypes.TINKER_STATION).values().stream().filter(r -> r instanceof IModifierRecipe).map(r -> (IModifierRecipe) r).collect(Collector.of(HashMultimap::create, (map, r) -> map.put(r.getSlotType(), r.getModifier()), (m1, m2) -> {
m1.putAll(m2);
return m1;
}));
// material traits are used in material traits (kinda obvious)
IMaterialRegistry matReg = MaterialRegistry.getInstance();
Set<Modifier> materialTraits = matReg.getAllMaterials().stream().flatMap(mat -> {
MaterialId matId = mat.getIdentifier();
return Stream.concat(matReg.getDefaultTraits(matId).stream(), matReg.getAllStats(matId).stream().filter(stat -> matReg.hasUniqueTraits(matId, stat.getIdentifier())).flatMap(stat -> matReg.getTraits(matId, stat.getIdentifier()).stream()));
}).map(ModifierEntry::getModifier).collect(Collectors.toSet());
// finally, tool traits we limit to anything in the modifiable tag
Set<Modifier> toolTraits = TinkerTags.Items.MODIFIABLE.getValues().stream().filter(item -> item instanceof IModifiable).flatMap(item -> ((IModifiable) item).getToolDefinition().getData().getTraits().stream()).map(ModifierEntry::getModifier).collect(Collectors.toSet());
// next, get our list of modifiers
Stream<Modifier> modifierStream;
switch(filter) {
case RECIPE:
// filter to just one type of modifier if requested
if (slotFilter != null) {
modifierStream = recipeModifiers.get(slotFilter.slotType()).stream();
} else {
modifierStream = recipeModifiers.values().stream();
}
break;
case MATERIAL_TRAIT:
modifierStream = materialTraits.stream();
break;
case TOOL_TRAIT:
modifierStream = toolTraits.stream();
break;
default:
modifierStream = TinkerRegistries.MODIFIERS.getValues().stream();
break;
}
// if requested, filter out all
if (filter == ModifierUsages.UNUSED) {
modifierStream = modifierStream.filter(modifier -> !recipeModifiers.containsValue(modifier) && !materialTraits.contains(modifier) && !toolTraits.contains(modifier));
}
// start building the table for output
TablePrinter<ModifierUsageRow> table = new TablePrinter<>();
table.header("ID", r -> r.modifierId().toString());
if (filter != ModifierUsages.UNUSED) {
if (filter != ModifierUsages.RECIPE || slotFilter == null) {
table.header("Recipe", ModifierUsageRow::recipe);
}
if (filter != ModifierUsages.MATERIAL_TRAIT) {
table.header("material Trait", r -> r.materialTrait() ? "Material trait" : "");
}
if (filter != ModifierUsages.TOOL_TRAIT) {
table.header("tool Trait", r -> r.toolTrait() ? "Tool trait" : "");
}
}
StringBuilder logOutput = new StringBuilder();
logOutput.append(filter.logPrefix);
if (slotFilter != null) {
if (slotFilter.slotType() == null) {
logOutput.append(" (slotless)");
} else {
logOutput.append(" (").append(slotFilter.slotType().getName()).append(")");
}
}
logOutput.append(System.lineSeparator());
// for all the modifiers (sorted), add table rows
Collection<Modifier> finalList = modifierStream.sorted(Comparator.comparing(Modifier::getId)).toList();
finalList.forEach(modifier -> {
// determine which recipes use this by slot type
List<String> recipeUsages = SlotType.getAllSlotTypes().stream().filter(type -> recipeModifiers.containsEntry(type, modifier)).map(SlotType::getName).collect(Collectors.toList());
String recipes;
if (recipeUsages.isEmpty()) {
recipes = recipeModifiers.containsEntry(null, modifier) ? "slotless" : "";
} else {
recipes = String.join(", ", recipeUsages);
}
table.add(new ModifierUsageRow(modifier.getId(), recipes, toolTraits.contains(modifier), materialTraits.contains(modifier)));
});
// finally, output the table
table.build(logOutput);
TConstruct.LOG.info(logOutput.toString());
context.getSource().sendSuccess(SUCCESS, true);
return finalList.size();
}
use of slimeknights.tconstruct.library.materials.IMaterialRegistry in project TinkersConstruct by SlimeKnights.
the class TooltipUtil method getDisplayName.
/**
* Gets the display name for a tool including the head material in the name
* @param stack Stack instance
* @param tool Tool instance
* @return Display name including the head material
*/
public static Component getDisplayName(ItemStack stack, @Nullable IToolStackView tool, ToolDefinition toolDefinition) {
List<PartRequirement> components = toolDefinition.getData().getParts();
Component baseName = new TranslatableComponent(stack.getDescriptionId());
if (components.isEmpty()) {
return baseName;
}
// if there is a mismatch in material size, just stop here
if (tool == null)
tool = ToolStack.from(stack);
MaterialNBT materials = tool.getMaterials();
if (materials.size() != components.size()) {
return baseName;
}
// if the tool is not named we use the repair materials for a prefix like thing
// set ensures we don't use the same name twice, specifically a set of components ensures if two variants have the same name we don't use both
Set<Component> nameMaterials = Sets.newLinkedHashSet();
MaterialVariantId firstMaterial = null;
IMaterialRegistry registry = MaterialRegistry.getInstance();
for (int i = 0; i < components.size(); i++) {
if (i < materials.size() && registry.canRepair(components.get(i).getStatType())) {
MaterialVariantId material = materials.get(i).getVariant();
if (!IMaterial.UNKNOWN_ID.equals(material)) {
if (firstMaterial == null) {
firstMaterial = material;
}
nameMaterials.add(MaterialTooltipCache.getDisplayName(material));
}
}
}
// if a single material, use the single material logic
if (nameMaterials.size() == 1) {
return getMaterialItemName(stack, baseName, firstMaterial);
}
// multiple means we mix them together
return getCombinedItemName(baseName, nameMaterials);
}
use of slimeknights.tconstruct.library.materials.IMaterialRegistry in project TinkersConstruct by SlimeKnights.
the class ToolDefinition method getRepairParts.
/**
* Returns a list of part material requirements for repair materials
*/
public int[] getRepairParts() {
if (repairIndices == null) {
// get indices of all head parts
List<PartRequirement> components = getData().getParts();
if (components.isEmpty()) {
repairIndices = new int[0];
} else {
IMaterialRegistry registry = MaterialRegistry.getInstance();
repairIndices = IntStream.range(0, components.size()).filter(i -> registry.getDefaultStats(components.get(i).getStatType()) instanceof IRepairableMaterialStats).toArray();
}
}
return repairIndices;
}
use of slimeknights.tconstruct.library.materials.IMaterialRegistry in project TinkersConstruct by SlimeKnights.
the class MaterialIdNBT method resolveRedirects.
/**
* Resolves all redirects, replacing with material redirects
*/
public MaterialIdNBT resolveRedirects() {
boolean changed = false;
ImmutableList.Builder<MaterialVariantId> builder = ImmutableList.builder();
IMaterialRegistry registry = MaterialRegistry.getInstance();
for (MaterialVariantId id : materials) {
MaterialId original = id.getId();
MaterialId resolved = registry.resolve(original);
if (resolved != original) {
changed = true;
}
builder.add(MaterialVariantId.create(resolved, id.getVariant()));
}
// return a new instance only if things changed
if (changed) {
return new MaterialIdNBT(builder.build());
}
return this;
}
Aggregations