Skip to content

Commit

Permalink
Added command to help setting heads
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro270707 committed Feb 10, 2024
1 parent 03e5dc4 commit bc5e46f
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 193 deletions.
370 changes: 205 additions & 165 deletions src/client/java/net/pedroricardo/HeadedRewrittenClient.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package net.pedroricardo.content;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import io.wispforest.owo.config.Option;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
import net.pedroricardo.HeadedRewritten;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;

public class HeadOptionArgumentType implements ArgumentType<Option<Object>> {
public static final DynamicCommandExceptionType INVALID_HEAD_OPTION_EXCEPTION = new DynamicCommandExceptionType((head) -> Text.stringifiedTranslatable("argument." + HeadedRewritten.MOD_ID + ".head_option.invalid", head));

public static HeadOptionArgumentType head() {
return new HeadOptionArgumentType();
}

public static Option<Object> getHeadOption(CommandContext<?> context, String name) {
return (Option<Object>) context.getArgument(name, Option.class);
}

@Override
public Option<Object> parse(StringReader reader) throws CommandSyntaxException {
String string = reader.readUnquotedString();
Option<Object> option = HeadedRewritten.CONFIG.optionForKey(new Option.Key(string));
if (option == null) {
throw INVALID_HEAD_OPTION_EXCEPTION.create(string);
}
return option;
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
Collection<String> collection = new ArrayList<>();
HeadedRewritten.CONFIG.allOptions().forEach((key, value) -> {
if (key.asString().startsWith("headURLs.")) collection.add(key.asString());
});
return CommandSource.suggestMatching(collection, builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
import net.pedroricardo.HeadedRewrittenClient;

import java.util.Map;
import java.util.function.Supplier;

public class HeadedCreativeTab {
private static final RegistryKey<ItemGroup> ITEM_GROUP_REGISTRY_KEY = RegistryKey.of(RegistryKeys.ITEM_GROUP, new Identifier(HeadedRewritten.MOD_ID, "headed_rewritten"));
public static final ItemGroup ITEM_GROUP = Registry.register(Registries.ITEM_GROUP, ITEM_GROUP_REGISTRY_KEY, FabricItemGroup.builder().icon(() -> new ItemStack(Items.PLAYER_HEAD))
.displayName(Text.translatable("itemGroup.headed-rewritten"))
.entries((ctx, entries) -> {
for (Map.Entry<String, HeadedHead> entry : TextureToHeadMap.MAP.entrySet()) {
for (Map.Entry<Supplier<String>, HeadedHead> entry : TextureToHeadMap.MAP.entrySet()) {
if (entry.getValue().addToItemGroup()) entries.add(entry.getValue().toStack());
}
})
Expand Down
15 changes: 8 additions & 7 deletions src/client/java/net/pedroricardo/content/HeadedHead.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import java.util.Collections;
import java.util.Random;
import java.util.function.Function;
import java.util.function.Supplier;

public class HeadedHead {
private final String originalTexture;
private final Supplier<String> originalTexture;
private final Function<EntityModelLoader, SkullBlockEntityModel> modelFunction;
private final RenderLayer renderLayer;
private final Collection<Function<EntityModelLoader, HeadedFeatureRenderer>> featureRenderers;
Expand All @@ -30,7 +31,7 @@ public class HeadedHead {

private final boolean addToItemGroup;

public HeadedHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound, Collection<Function<EntityModelLoader, HeadedFeatureRenderer>> featureRenderers, boolean addToItemGroup) {
public HeadedHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound, Collection<Function<EntityModelLoader, HeadedFeatureRenderer>> featureRenderers, boolean addToItemGroup) {
this.originalTexture = originalTexture;
this.modelFunction = modelFunction;
this.renderLayer = renderLayer;
Expand All @@ -40,19 +41,19 @@ public HeadedHead(String originalTexture, Function<EntityModelLoader, SkullBlock
this.addToItemGroup = addToItemGroup;
}

public HeadedHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound, Collection<Function<EntityModelLoader, HeadedFeatureRenderer>> featureRenderers) {
public HeadedHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound, Collection<Function<EntityModelLoader, HeadedFeatureRenderer>> featureRenderers) {
this(originalTexture, modelFunction, renderLayer, name, noteBlockSound, featureRenderers, true);
}

public HeadedHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound) {
public HeadedHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, @Nullable String name, @Nullable String noteBlockSound) {
this(originalTexture, modelFunction, renderLayer, name, noteBlockSound, Collections.emptyList());
}

public HeadedHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer texture, @Nullable String name, @Nullable String noteBlockSound, boolean addToItemGroup) {
public HeadedHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer texture, @Nullable String name, @Nullable String noteBlockSound, boolean addToItemGroup) {
this(originalTexture, modelFunction, texture, name, noteBlockSound, Collections.emptyList(), addToItemGroup);
}

public String getOriginalTexture() {
public Supplier<String> getOriginalTexture() {
return this.originalTexture;
}

Expand Down Expand Up @@ -85,7 +86,7 @@ public ItemStack toStack() {
NbtCompound propertyTextures = new NbtCompound();
NbtList list = new NbtList();
NbtCompound textureValueCompound = new NbtCompound();
textureValueCompound.putString("Value", Base64.encodeBase64String(("{\"textures\":{\"SKIN\":{\"url\":\"" + this.getOriginalTexture() + "\"}}}").getBytes(StandardCharsets.UTF_8)));
textureValueCompound.putString("Value", Base64.encodeBase64String(("{\"textures\":{\"SKIN\":{\"url\":\"" + this.getOriginalTexture().get() + "\"}}}").getBytes(StandardCharsets.UTF_8)));
list.add(textureValueCompound);
propertyTextures.put("textures", list);
skullOwner.put("Properties", propertyTextures);
Expand Down
27 changes: 22 additions & 5 deletions src/client/java/net/pedroricardo/content/TextureToHeadMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,45 @@
import net.minecraft.client.render.block.entity.SkullBlockEntityModel;
import net.minecraft.client.render.entity.model.EntityModelLoader;
import net.pedroricardo.content.features.HeadedFeatureRenderer;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

public class TextureToHeadMap {
public static final LinkedHashMap<String, HeadedHead> MAP = new LinkedHashMap<>();
public static final LinkedHashMap<Supplier<String>, HeadedHead> MAP = new LinkedHashMap<>();

public static HeadedHead addHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound) {
public static HeadedHead addHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound) {
return MAP.put(originalTexture, new HeadedHead(originalTexture, modelFunction, renderLayer, name, noteBlockSound));
}

@SafeVarargs
public static HeadedHead addHead(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound, Function<EntityModelLoader, HeadedFeatureRenderer>... featureRenderers) {
public static HeadedHead addHead(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound, Function<EntityModelLoader, HeadedFeatureRenderer>... featureRenderers) {
return MAP.put(originalTexture, new HeadedHead(originalTexture, modelFunction, renderLayer, name, noteBlockSound, Arrays.asList(featureRenderers)));
}

public static HeadedHead addHeadNotInGroup(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound) {
public static HeadedHead addHeadNotInGroup(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound) {
return MAP.put(originalTexture, new HeadedHead(originalTexture, modelFunction, renderLayer, name, noteBlockSound, false));
}

@SafeVarargs
public static HeadedHead addHeadNotInGroup(String originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound, Function<EntityModelLoader, HeadedFeatureRenderer>... featureRenderers) {
public static HeadedHead addHeadNotInGroup(Supplier<String> originalTexture, Function<EntityModelLoader, SkullBlockEntityModel> modelFunction, RenderLayer renderLayer, String name, String noteBlockSound, Function<EntityModelLoader, HeadedFeatureRenderer>... featureRenderers) {
return MAP.put(originalTexture, new HeadedHead(originalTexture, modelFunction, renderLayer, name, noteBlockSound, Arrays.asList(featureRenderers), false));
}

public static boolean contains(String texture) {
for (Supplier<String> supplier : MAP.keySet()) {
if (supplier.get().equals(texture)) return true;
}
return false;
}

@Nullable
public static HeadedHead get(String texture) {
for (Map.Entry<Supplier<String>, HeadedHead> entry : MAP.entrySet()) {
if (entry.getKey().get().equals(texture)) return entry.getValue();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
public class HeadCollisionMixin {
@Inject(method = "getOutlineShape", at = @At("HEAD"), cancellable = true)
private void headedrewritten$getAccurateOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, CallbackInfoReturnable<VoxelShape> cir) {
if (HeadedRewritten.CONFIG.changeHeadCollisions() && world.getBlockEntity(pos) instanceof SkullBlockEntity blockEntity && blockEntity.getOwner() != null && blockEntity.getOwner().getProperties().containsKey("textures") && TextureToHeadMap.MAP.containsKey(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl())) {
SkullBlockEntityModel model = TextureToHeadMap.MAP.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
if (HeadedRewritten.CONFIG.changeHeadCollisions() && world.getBlockEntity(pos) instanceof SkullBlockEntity blockEntity && blockEntity.getOwner() != null && blockEntity.getOwner().getProperties().containsKey("textures") && TextureToHeadMap.contains(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl())) {
SkullBlockEntityModel model = TextureToHeadMap.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
Vector3f boxSize;
if (model instanceof HeadedRewrittenModel headedRewrittenModel) {
boxSize = headedRewrittenModel.getHeadSizeInPixels();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
public class RenderHeadedHeadItemMixin {
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/entity/SkullBlockEntityRenderer;renderSkull(Lnet/minecraft/util/math/Direction;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/block/entity/SkullBlockEntityModel;Lnet/minecraft/client/render/RenderLayer;)V"), index = 6)
private SkullBlockEntityModel headedrewritten$replaceItemModel(SkullBlockEntityModel model, @Local(ordinal = 0) AbstractSkullBlock block, @Local(ordinal = 0) GameProfile gameProfile) {
if (block.getSkullType() == SkullBlock.Type.PLAYER && gameProfile != null && gameProfile.getProperties().containsKey("textures") && TextureToHeadMap.MAP.containsKey(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(gameProfile).textureUrl())) {
if (block.getSkullType() == SkullBlock.Type.PLAYER && gameProfile != null && gameProfile.getProperties().containsKey("textures") && TextureToHeadMap.contains(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(gameProfile).textureUrl())) {
HeadedContext.currentProfile = gameProfile;
return TextureToHeadMap.MAP.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(gameProfile).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
return TextureToHeadMap.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(gameProfile).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
}
return model;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ public class RenderHeadedHeadMixin {
@ModifyArg(method = "render(Lnet/minecraft/block/entity/SkullBlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;II)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/entity/SkullBlockEntityRenderer;renderSkull(Lnet/minecraft/util/math/Direction;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/block/entity/SkullBlockEntityModel;Lnet/minecraft/client/render/RenderLayer;)V"), index = 6)
private SkullBlockEntityModel headedrewritten$replaceModel(SkullBlockEntityModel model, @Local(ordinal = 0) SkullBlock.SkullType skullType, @Local(ordinal = 0) SkullBlockEntity blockEntity) {
HeadedContext.currentProfile = blockEntity.getOwner();
if (skullType == SkullBlock.Type.PLAYER && blockEntity.getOwner() != null && blockEntity.getOwner().getProperties().containsKey("textures") && TextureToHeadMap.MAP.containsKey(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl())) {
return TextureToHeadMap.MAP.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
if (skullType == SkullBlock.Type.PLAYER && blockEntity.getOwner() != null && blockEntity.getOwner().getProperties().containsKey("textures") && TextureToHeadMap.contains(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl())) {
return TextureToHeadMap.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(blockEntity.getOwner()).textureUrl()).getModel(MinecraftClient.getInstance().getEntityModelLoader());
}
return model;
}

@Inject(method = "getRenderLayer", at = @At(value = "HEAD"), cancellable = true)
private static void headedrewritten$replaceTexture(SkullBlock.SkullType type, GameProfile profile, CallbackInfoReturnable<RenderLayer> cir) {
if (type == SkullBlock.Type.PLAYER && profile != null && profile.getProperties().containsKey("textures") && TextureToHeadMap.MAP.containsKey(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(profile).textureUrl())) {
cir.setReturnValue(TextureToHeadMap.MAP.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(profile).textureUrl()).getRenderLayer());
if (type == SkullBlock.Type.PLAYER && profile != null && profile.getProperties().containsKey("textures") && TextureToHeadMap.contains(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(profile).textureUrl())) {
cir.setReturnValue(TextureToHeadMap.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(profile).textureUrl()).getRenderLayer());
}
}

Expand All @@ -61,8 +61,8 @@ public class RenderHeadedHeadMixin {

@Inject(method = "renderSkull", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V", shift = At.Shift.AFTER))
private static void headedrewritten$renderFeatures(Direction direction, float yaw, float animationProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, SkullBlockEntityModel model, RenderLayer renderLayer, CallbackInfo ci) {
if (HeadedContext.currentProfile != null && HeadedContext.currentProfile.getProperties().containsKey("textures") && TextureToHeadMap.MAP.containsKey(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(HeadedContext.currentProfile).textureUrl())) {
HeadedHead head = TextureToHeadMap.MAP.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(HeadedContext.currentProfile).textureUrl());
if (HeadedContext.currentProfile != null && HeadedContext.currentProfile.getProperties().containsKey("textures") && TextureToHeadMap.contains(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(HeadedContext.currentProfile).textureUrl())) {
HeadedHead head = TextureToHeadMap.get(MinecraftClient.getInstance().getSkinProvider().getSkinTextures(HeadedContext.currentProfile).textureUrl());
HeadedContext.currentProfile = null;
for (Function<EntityModelLoader, HeadedFeatureRenderer> featureRenderer : head.getFeatureRenderers()) {
featureRenderer.apply(MinecraftClient.getInstance().getEntityModelLoader()).render(direction, yaw, animationProgress, matrices, vertexConsumers, light);
Expand Down
Loading

0 comments on commit bc5e46f

Please sign in to comment.